From f067d584a81ae771d301304ea885e55e2de8ee9a Mon Sep 17 00:00:00 2001
From: Chris Lattner Syntax:
- <result> = shl <ty> <op1>, <op2> ; yields {ty}:result
+ <result> = shl <ty> <op1>, <op2> ; yields {ty}:result
+ <result> = shl nuw <ty> <op1>, <op2> ; yields {ty}:result
+ <result> = shl nsw <ty> <op1>, <op2> ; yields {ty}:result
+ <result> = shl nuw nsw <ty> <op1>, <op2> ; yields {ty}:result
Overview:
@@ -3704,6 +3707,14 @@ Instruction
vectors, each vector element of op1 is shifted by the corresponding
shift amount in op2.
If the nuw keyword is present, then the shift produces a + trap value if it shifts out any non-zero bits. If + the nsw keywrod is present, then the shift produces a + trap value if it shifts out any bits that disagree + with the resultant sign bit. As such, NUW/NSW have the same semantics as + they would if the shift were expressed as a mul instruction with the same + nsw/nuw bits in (mul %op1, (shl 1, %op2)).
+<result> = shl i32 4, %var ; yields {i32}: 4 << %var @@ -3723,7 +3734,8 @@ InstructionSyntax:
- <result> = lshr <ty> <op1>, <op2> ; yields {ty}:result + <result> = lshr <ty> <op1>, <op2> ; yields {ty}:result + <result> = lshr exact <ty> <op1>, <op2> ; yields {ty}:resultOverview:
@@ -3743,6 +3755,11 @@ Instruction vectors, each vector element of op1 is shifted by the corresponding shift amount in op2. +If the exact keyword is present, the result value of the + lshr is a trap value if any of the bits + shifted out are non-zero.
+ +Example:
<result> = lshr i32 4, 1 ; yields {i32}:result = 2 @@ -3762,7 +3779,8 @@ InstructionSyntax:
- <result> = ashr <ty> <op1>, <op2> ; yields {ty}:result + <result> = ashr <ty> <op1>, <op2> ; yields {ty}:result + <result> = ashr exact <ty> <op1>, <op2> ; yields {ty}:resultOverview:
@@ -3783,6 +3801,10 @@ Instruction the arguments are vectors, each vector element of op1 is shifted by the corresponding shift amount in op2. +If the exact keyword is present, the result value of the + ashr is a trap value if any of the bits + shifted out are non-zero.
+Example:
<result> = ashr i32 4, 1 ; yields {i32}:result = 2 diff --git a/include/llvm/Constants.h b/include/llvm/Constants.h index b782737d31a..56f39b9b092 100644 --- a/include/llvm/Constants.h +++ b/include/llvm/Constants.h @@ -724,8 +724,12 @@ public: static Constant *getNUWSub(Constant *C1, Constant *C2); static Constant *getNSWMul(Constant *C1, Constant *C2); static Constant *getNUWMul(Constant *C1, Constant *C2); + static Constant *getNSWShl(Constant *C1, Constant *C2); + static Constant *getNUWShl(Constant *C1, Constant *C2); static Constant *getExactSDiv(Constant *C1, Constant *C2); static Constant *getExactUDiv(Constant *C1, Constant *C2); + static Constant *getExactAShr(Constant *C1, Constant *C2); + static Constant *getExactLShr(Constant *C1, Constant *C2); /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Constant); diff --git a/include/llvm/Operator.h b/include/llvm/Operator.h index eaa28ad47fa..ff2a0ad5e4e 100644 --- a/include/llvm/Operator.h +++ b/include/llvm/Operator.h @@ -106,66 +106,14 @@ public: static inline bool classof(const Instruction *I) { return I->getOpcode() == Instruction::Add || I->getOpcode() == Instruction::Sub || - I->getOpcode() == Instruction::Mul; + I->getOpcode() == Instruction::Mul || + I->getOpcode() == Instruction::Shl; } static inline bool classof(const ConstantExpr *CE) { return CE->getOpcode() == Instruction::Add || CE->getOpcode() == Instruction::Sub || - CE->getOpcode() == Instruction::Mul; - } - static inline bool classof(const Value *V) { - return (isa(V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); - } -}; - -/// AddOperator - Utility class for integer addition operators. -/// -class AddOperator : public OverflowingBinaryOperator { - ~AddOperator(); // do not implement -public: - static inline bool classof(const AddOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Add; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Add; - } - static inline bool classof(const Value *V) { - return (isa (V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); - } -}; - -/// SubOperator - Utility class for integer subtraction operators. -/// -class SubOperator : public OverflowingBinaryOperator { - ~SubOperator(); // do not implement -public: - static inline bool classof(const SubOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Sub; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Sub; - } - static inline bool classof(const Value *V) { - return (isa (V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); - } -}; - -/// MulOperator - Utility class for integer multiplication operators. -/// -class MulOperator : public OverflowingBinaryOperator { - ~MulOperator(); // do not implement -public: - static inline bool classof(const MulOperator *) { return true; } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::Mul; - } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::Mul; + CE->getOpcode() == Instruction::Mul || + CE->getOpcode() == Instruction::Shl; } static inline bool classof(const Value *V) { return (isa (V) && classof(cast (V))) || @@ -196,31 +144,40 @@ public: return SubclassOptionalData & IsExact; } + static bool isPossiblyExactOpcode(unsigned OpC) { + return OpC == Instruction::SDiv || + OpC == Instruction::UDiv || + OpC == Instruction::AShr || + OpC == Instruction::LShr; + } static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::SDiv || - CE->getOpcode() == Instruction::UDiv; + return isPossiblyExactOpcode(CE->getOpcode()); } static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::SDiv || - I->getOpcode() == Instruction::UDiv; + return isPossiblyExactOpcode(I->getOpcode()); } static inline bool classof(const Value *V) { return (isa (V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); + (isa (V) && classof(cast (V))); } }; -/// SDivOperator - An Operator with opcode Instruction::SDiv. -/// -class SDivOperator : public PossiblyExactOperator { + + +/// ConcreteOperator - A helper template for defining operators for individual +/// opcodes. +template +class ConcreteOperator : public SuperClass { + ~ConcreteOperator(); // DO NOT IMPLEMENT public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const SDivOperator *) { return true; } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::SDiv; + static inline bool classof(const ConcreteOperator *) { + return true; } static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::SDiv; + return I->getOpcode() == Opc; + } + static inline bool classof(const ConstantExpr *CE) { + return CE->getOpcode() == Opc; } static inline bool classof(const Value *V) { return (isa (V) && classof(cast (V))) || @@ -228,31 +185,33 @@ public: } }; -/// UDivOperator - An Operator with opcode Instruction::UDiv. -/// -class UDivOperator : public PossiblyExactOperator { -public: - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const UDivOperator *) { return true; } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::UDiv; - } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::UDiv; - } - static inline bool classof(const Value *V) { - return (isa (V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); - } -}; +class AddOperator + : public ConcreteOperator {}; +class SubOperator + : public ConcreteOperator {}; +class MulOperator + : public ConcreteOperator {}; +class ShlOperator + : public ConcreteOperator {}; + -class GEPOperator : public Operator { +class SDivOperator + : public ConcreteOperator {}; +class UDivOperator + : public ConcreteOperator {}; +class AShrOperator + : public ConcreteOperator {}; +class LShrOperator + : public ConcreteOperator {}; + + + +class GEPOperator + : public ConcreteOperator { enum { IsInBounds = (1 << 0) }; - ~GEPOperator(); // do not implement - friend class GetElementPtrInst; friend class ConstantExpr; void setIsInBounds(bool B) { @@ -301,8 +260,8 @@ public: /// value, just potentially different types. bool hasAllZeroIndices() const { for (const_op_iterator I = idx_begin(), E = idx_end(); I != E; ++I) { - if (Constant *C = dyn_cast (I)) - if (C->isNullValue()) + if (ConstantInt *C = dyn_cast (I)) + if (C->isZero()) continue; return false; } @@ -319,21 +278,6 @@ public: } return true; } - - - // Methods for support type inquiry through isa, cast, and dyn_cast: - static inline bool classof(const GEPOperator *) { return true; } - static inline bool classof(const GetElementPtrInst *) { return true; } - static inline bool classof(const ConstantExpr *CE) { - return CE->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Instruction *I) { - return I->getOpcode() == Instruction::GetElementPtr; - } - static inline bool classof(const Value *V) { - return (isa (V) && classof(cast (V))) || - (isa (V) && classof(cast (V))); - } }; } // End llvm namespace diff --git a/lib/AsmParser/LLParser.cpp b/lib/AsmParser/LLParser.cpp index 6d71c9e3e60..cb4ddcba72a 100644 --- a/lib/AsmParser/LLParser.cpp +++ b/lib/AsmParser/LLParser.cpp @@ -2286,7 +2286,10 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { case lltok::kw_fdiv: case lltok::kw_urem: case lltok::kw_srem: - case lltok::kw_frem: { + case lltok::kw_frem: + case lltok::kw_shl: + case lltok::kw_lshr: + case lltok::kw_ashr: { bool NUW = false; bool NSW = false; bool Exact = false; @@ -2294,9 +2297,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { Constant *Val0, *Val1; Lex.Lex(); LocTy ModifierLoc = Lex.getLoc(); - if (Opc == Instruction::Add || - Opc == Instruction::Sub || - Opc == Instruction::Mul) { + if (Opc == Instruction::Add || Opc == Instruction::Sub || + Opc == Instruction::Mul || Opc == Instruction::Shl) { if (EatIfPresent(lltok::kw_nuw)) NUW = true; if (EatIfPresent(lltok::kw_nsw)) { @@ -2304,7 +2306,8 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { if (EatIfPresent(lltok::kw_nuw)) NUW = true; } - } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv) { + } else if (Opc == Instruction::SDiv || Opc == Instruction::UDiv || + Opc == Instruction::LShr || Opc == Instruction::AShr) { if (EatIfPresent(lltok::kw_exact)) Exact = true; } @@ -2331,6 +2334,9 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { case Instruction::SDiv: case Instruction::URem: case Instruction::SRem: + case Instruction::Shl: + case Instruction::AShr: + case Instruction::LShr: if (!Val0->getType()->isIntOrIntVectorTy()) return Error(ID.Loc, "constexpr requires integer operands"); break; @@ -2355,9 +2361,6 @@ bool LLParser::ParseValID(ValID &ID, PerFunctionState *PFS) { } // Logical Operations - case lltok::kw_shl: - case lltok::kw_lshr: - case lltok::kw_ashr: case lltok::kw_and: case lltok::kw_or: case lltok::kw_xor: { @@ -3002,55 +3005,38 @@ int LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, // Binary Operators. case lltok::kw_add: case lltok::kw_sub: - case lltok::kw_mul: { - bool NUW = false; - bool NSW = false; + case lltok::kw_mul: + case lltok::kw_shl: { LocTy ModifierLoc = Lex.getLoc(); - if (EatIfPresent(lltok::kw_nuw)) - NUW = true; - if (EatIfPresent(lltok::kw_nsw)) { - NSW = true; - if (EatIfPresent(lltok::kw_nuw)) - NUW = true; - } - bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); - if (!Result) { - if (!Inst->getType()->isIntOrIntVectorTy()) { - if (NUW) - return Error(ModifierLoc, "nuw only applies to integer operations"); - if (NSW) - return Error(ModifierLoc, "nsw only applies to integer operations"); - } - if (NUW) - cast (Inst)->setHasNoUnsignedWrap(true); - if (NSW) - cast (Inst)->setHasNoSignedWrap(true); - } - return Result; + bool NUW = EatIfPresent(lltok::kw_nuw); + bool NSW = EatIfPresent(lltok::kw_nsw); + if (!NUW) NUW = EatIfPresent(lltok::kw_nuw); + + if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true; + + if (NUW) cast (Inst)->setHasNoUnsignedWrap(true); + if (NSW) cast (Inst)->setHasNoSignedWrap(true); + return false; } case lltok::kw_fadd: case lltok::kw_fsub: case lltok::kw_fmul: return ParseArithmetic(Inst, PFS, KeywordVal, 2); case lltok::kw_sdiv: - case lltok::kw_udiv: { - bool Exact = false; - if (EatIfPresent(lltok::kw_exact)) - Exact = true; - bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); - if (!Result) - if (Exact) - cast (Inst)->setIsExact(true); - return Result; + case lltok::kw_udiv: + case lltok::kw_lshr: + case lltok::kw_ashr: { + bool Exact = EatIfPresent(lltok::kw_exact); + + if (ParseArithmetic(Inst, PFS, KeywordVal, 1)) return true; + if (Exact) cast (Inst)->setIsExact(true); + return false; } case lltok::kw_urem: case lltok::kw_srem: return ParseArithmetic(Inst, PFS, KeywordVal, 1); case lltok::kw_fdiv: case lltok::kw_frem: return ParseArithmetic(Inst, PFS, KeywordVal, 2); - case lltok::kw_shl: - case lltok::kw_lshr: - case lltok::kw_ashr: case lltok::kw_and: case lltok::kw_or: case lltok::kw_xor: return ParseLogical(Inst, PFS, KeywordVal); diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index a744d833026..d812a6d465c 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -1085,13 +1085,16 @@ bool BitcodeReader::ParseConstants() { if (Record.size() >= 4) { if (Opc == Instruction::Add || Opc == Instruction::Sub || - Opc == Instruction::Mul) { + Opc == Instruction::Mul || + Opc == Instruction::Shl) { if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP)) Flags |= OverflowingBinaryOperator::NoSignedWrap; if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; } else if (Opc == Instruction::SDiv || - Opc == Instruction::UDiv) { + Opc == Instruction::UDiv || + Opc == Instruction::LShr || + Opc == Instruction::AShr) { if (Record[3] & (1 << bitc::PEO_EXACT)) Flags |= SDivOperator::IsExact; } @@ -1901,13 +1904,16 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { if (OpNum < Record.size()) { if (Opc == Instruction::Add || Opc == Instruction::Sub || - Opc == Instruction::Mul) { + Opc == Instruction::Mul || + Opc == Instruction::Shl) { if (Record[OpNum] & (1 << bitc::OBO_NO_SIGNED_WRAP)) cast (I)->setHasNoSignedWrap(true); if (Record[OpNum] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) cast (I)->setHasNoUnsignedWrap(true); } else if (Opc == Instruction::SDiv || - Opc == Instruction::UDiv) { + Opc == Instruction::UDiv || + Opc == Instruction::LShr || + Opc == Instruction::AShr) { if (Record[OpNum] & (1 << bitc::PEO_EXACT)) cast (I)->setIsExact(true); } diff --git a/lib/VMCore/Constants.cpp b/lib/VMCore/Constants.cpp index d2359e5bcda..b9b7b3f5393 100644 --- a/lib/VMCore/Constants.cpp +++ b/lib/VMCore/Constants.cpp @@ -7,7 +7,7 @@ // //===----------------------------------------------------------------------===// // -// This file implements the Constant* classes. +// This file implements the Constant *classes. // //===----------------------------------------------------------------------===// @@ -72,7 +72,7 @@ Constant *Constant::getNullValue(const Type *Ty) { } } -Constant* Constant::getIntegerValue(const Type *Ty, const APInt &V) { +Constant *Constant::getIntegerValue(const Type *Ty, const APInt &V) { const Type *ScalarTy = Ty->getScalarType(); // Create the base integer constant. @@ -89,7 +89,7 @@ Constant* Constant::getIntegerValue(const Type *Ty, const APInt &V) { return C; } -Constant* Constant::getAllOnesValue(const Type *Ty) { +Constant *Constant::getAllOnesValue(const Type *Ty) { if (const IntegerType *ITy = dyn_cast (Ty)) return ConstantInt::get(Ty->getContext(), APInt::getAllOnesValue(ITy->getBitWidth())); @@ -296,7 +296,7 @@ ConstantInt *ConstantInt::get(LLVMContext &Context, const APInt& V) { return Slot; } -Constant* ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) { +Constant *ConstantInt::get(const Type* Ty, uint64_t V, bool isSigned) { Constant *C = get(cast (Ty->getScalarType()), V, isSigned); @@ -321,7 +321,7 @@ Constant *ConstantInt::getSigned(const Type *Ty, int64_t V) { return get(Ty, V, true); } -Constant* ConstantInt::get(const Type* Ty, const APInt& V) { +Constant *ConstantInt::get(const Type* Ty, const APInt& V) { ConstantInt *C = get(Ty->getContext(), V); assert(C->getType() == Ty->getScalarType() && "ConstantInt type doesn't match the type implied by its value!"); @@ -360,7 +360,7 @@ static const fltSemantics *TypeToFloatSemantics(const Type *Ty) { /// get() - This returns a constant fp for the specified value in the /// specified type. This should only be used for simple constant values like /// 2.0/1.0 etc, that are known-valid both as double and as the target format. -Constant* ConstantFP::get(const Type* Ty, double V) { +Constant *ConstantFP::get(const Type* Ty, double V) { LLVMContext &Context = Ty->getContext(); APFloat FV(V); @@ -378,7 +378,7 @@ Constant* ConstantFP::get(const Type* Ty, double V) { } -Constant* ConstantFP::get(const Type* Ty, StringRef Str) { +Constant *ConstantFP::get(const Type* Ty, StringRef Str) { LLVMContext &Context = Ty->getContext(); APFloat FV(*TypeToFloatSemantics(Ty->getScalarType()), Str); @@ -401,7 +401,7 @@ ConstantFP* ConstantFP::getNegativeZero(const Type* Ty) { } -Constant* ConstantFP::getZeroValueForNegation(const Type* Ty) { +Constant *ConstantFP::getZeroValueForNegation(const Type* Ty) { if (const VectorType *PTy = dyn_cast (Ty)) if (PTy->getElementType()->isFloatingPointTy()) { std::vector zeros(PTy->getNumElements(), @@ -509,7 +509,7 @@ Constant *ConstantArray::get(const ArrayType *Ty, } -Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals, +Constant *ConstantArray::get(const ArrayType* T, Constant *const* Vals, unsigned NumVals) { // FIXME: make this the primary ctor method. return get(T, std::vector (Vals, Vals+NumVals)); @@ -521,7 +521,7 @@ Constant* ConstantArray::get(const ArrayType* T, Constant* const* Vals, /// Otherwise, the length parameter specifies how much of the string to use /// and it won't be null terminated. /// -Constant* ConstantArray::get(LLVMContext &Context, StringRef Str, +Constant *ConstantArray::get(LLVMContext &Context, StringRef Str, bool AddNull) { std::vector ElementVals; ElementVals.reserve(Str.size() + size_t(AddNull)); @@ -557,7 +557,7 @@ ConstantStruct::ConstantStruct(const StructType *T, } // ConstantStruct accessors. -Constant* ConstantStruct::get(const StructType* T, +Constant *ConstantStruct::get(const StructType* T, const std::vector & V) { LLVMContextImpl* pImpl = T->getContext().pImpl; @@ -569,7 +569,7 @@ Constant* ConstantStruct::get(const StructType* T, return ConstantAggregateZero::get(T); } -Constant* ConstantStruct::get(LLVMContext &Context, +Constant *ConstantStruct::get(LLVMContext &Context, const std::vector & V, bool packed) { std::vector StructEls; StructEls.reserve(V.size()); @@ -578,8 +578,8 @@ Constant* ConstantStruct::get(LLVMContext &Context, return get(StructType::get(Context, StructEls, packed), V); } -Constant* ConstantStruct::get(LLVMContext &Context, - Constant* const *Vals, unsigned NumVals, +Constant *ConstantStruct::get(LLVMContext &Context, + Constant *const *Vals, unsigned NumVals, bool Packed) { // FIXME: make this the primary ctor method. return get(Context, std::vector (Vals, Vals+NumVals), Packed); @@ -601,7 +601,7 @@ ConstantVector::ConstantVector(const VectorType *T, } // ConstantVector accessors. -Constant* ConstantVector::get(const VectorType* T, +Constant *ConstantVector::get(const VectorType* T, const std::vector & V) { assert(!V.empty() && "Vectors can't be empty"); LLVMContext &Context = T->getContext(); @@ -629,68 +629,89 @@ Constant* ConstantVector::get(const VectorType* T, return pImpl->VectorConstants.getOrCreate(T, V); } -Constant* ConstantVector::get(const std::vector & V) { +Constant *ConstantVector::get(const std::vector & V) { assert(!V.empty() && "Cannot infer type if V is empty"); return get(VectorType::get(V.front()->getType(),V.size()), V); } -Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) { +Constant *ConstantVector::get(Constant *const* Vals, unsigned NumVals) { // FIXME: make this the primary ctor method. return get(std::vector (Vals, Vals+NumVals)); } -Constant* ConstantExpr::getNSWNeg(Constant* C) { +Constant *ConstantExpr::getNSWNeg(Constant *C) { assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return getNSWSub(ConstantFP::getZeroValueForNegation(C->getType()), C); } -Constant* ConstantExpr::getNUWNeg(Constant* C) { +Constant *ConstantExpr::getNUWNeg(Constant *C) { assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return getNUWSub(ConstantFP::getZeroValueForNegation(C->getType()), C); } -Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNSWAdd(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Add, C1, C2, OverflowingBinaryOperator::NoSignedWrap); } -Constant* ConstantExpr::getNUWAdd(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNUWAdd(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Add, C1, C2, OverflowingBinaryOperator::NoUnsignedWrap); } -Constant* ConstantExpr::getNSWSub(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNSWSub(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Sub, C1, C2, OverflowingBinaryOperator::NoSignedWrap); } -Constant* ConstantExpr::getNUWSub(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNUWSub(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Sub, C1, C2, OverflowingBinaryOperator::NoUnsignedWrap); } -Constant* ConstantExpr::getNSWMul(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNSWMul(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Mul, C1, C2, OverflowingBinaryOperator::NoSignedWrap); } -Constant* ConstantExpr::getNUWMul(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNUWMul(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::Mul, C1, C2, OverflowingBinaryOperator::NoUnsignedWrap); } -Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getNSWShl(Constant *C1, Constant *C2) { + return getTy(C1->getType(), Instruction::Shl, C1, C2, + OverflowingBinaryOperator::NoSignedWrap); +} + +Constant *ConstantExpr::getNUWShl(Constant *C1, Constant *C2) { + return getTy(C1->getType(), Instruction::Shl, C1, C2, + OverflowingBinaryOperator::NoUnsignedWrap); +} + +Constant *ConstantExpr::getExactSDiv(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::SDiv, C1, C2, PossiblyExactOperator::IsExact); } -Constant* ConstantExpr::getExactUDiv(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getExactUDiv(Constant *C1, Constant *C2) { return getTy(C1->getType(), Instruction::UDiv, C1, C2, PossiblyExactOperator::IsExact); } +Constant *ConstantExpr::getExactAShr(Constant *C1, Constant *C2) { + return getTy(C1->getType(), Instruction::AShr, C1, C2, + PossiblyExactOperator::IsExact); +} + +Constant *ConstantExpr::getExactLShr(Constant *C1, Constant *C2) { + return getTy(C1->getType(), Instruction::LShr, C1, C2, + PossiblyExactOperator::IsExact); +} + + // Utility function for determining if a ConstantExpr is a CastOp or not. This // can't be inline because we don't want to #include Instruction.h into // Constant.h @@ -816,7 +837,7 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { /// operands replaced with the specified values. The specified operands must /// match count and type with the existing ones. Constant *ConstantExpr:: -getWithOperands(Constant* const *Ops, unsigned NumOps) const { +getWithOperands(Constant *const *Ops, unsigned NumOps) const { assert(NumOps == getNumOperands() && "Operand count mismatch!"); bool AnyChange = false; for (unsigned i = 0; i != NumOps; ++i) { @@ -1486,7 +1507,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, return getTy(C1->getType(), Opcode, C1, C2, Flags); } -Constant* ConstantExpr::getSizeOf(const Type* Ty) { +Constant *ConstantExpr::getSizeOf(const Type* Ty) { // sizeof is implemented as: (i64) gep (Ty*)null, 1 // Note that a non-inbounds gep is used, as null isn't within any object. Constant *GEPIdx = ConstantInt::get(Type::getInt32Ty(Ty->getContext()), 1); @@ -1496,7 +1517,7 @@ Constant* ConstantExpr::getSizeOf(const Type* Ty) { Type::getInt64Ty(Ty->getContext())); } -Constant* ConstantExpr::getAlignOf(const Type* Ty) { +Constant *ConstantExpr::getAlignOf(const Type* Ty) { // alignof is implemented as: (i64) gep ({i1,Ty}*)null, 0, 1 // Note that a non-inbounds gep is used, as null isn't within any object. const Type *AligningTy = StructType::get(Ty->getContext(), @@ -1510,12 +1531,12 @@ Constant* ConstantExpr::getAlignOf(const Type* Ty) { Type::getInt64Ty(Ty->getContext())); } -Constant* ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) { +Constant *ConstantExpr::getOffsetOf(const StructType* STy, unsigned FieldNo) { return getOffsetOf(STy, ConstantInt::get(Type::getInt32Ty(STy->getContext()), FieldNo)); } -Constant* ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) { +Constant *ConstantExpr::getOffsetOf(const Type* Ty, Constant *FieldNo) { // offsetof is implemented as: (i64) gep (Ty*)null, 0, FieldNo // Note that a non-inbounds gep is used, as null isn't within any object. Constant *GEPIdx[] = { @@ -1823,7 +1844,7 @@ Constant *ConstantExpr::getExtractValue(Constant *Agg, return getExtractValueTy(ReqTy, Agg, IdxList, NumIdx); } -Constant* ConstantExpr::getNeg(Constant* C) { +Constant *ConstantExpr::getNeg(Constant *C) { assert(C->getType()->isIntOrIntVectorTy() && "Cannot NEG a nonintegral value!"); return get(Instruction::Sub, @@ -1831,7 +1852,7 @@ Constant* ConstantExpr::getNeg(Constant* C) { C); } -Constant* ConstantExpr::getFNeg(Constant* C) { +Constant *ConstantExpr::getFNeg(Constant *C) { assert(C->getType()->isFPOrFPVectorTy() && "Cannot FNEG a non-floating-point value!"); return get(Instruction::FSub, @@ -1839,81 +1860,81 @@ Constant* ConstantExpr::getFNeg(Constant* C) { C); } -Constant* ConstantExpr::getNot(Constant* C) { +Constant *ConstantExpr::getNot(Constant *C) { assert(C->getType()->isIntOrIntVectorTy() && "Cannot NOT a nonintegral value!"); return get(Instruction::Xor, C, Constant::getAllOnesValue(C->getType())); } -Constant* ConstantExpr::getAdd(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getAdd(Constant *C1, Constant *C2) { return get(Instruction::Add, C1, C2); } -Constant* ConstantExpr::getFAdd(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getFAdd(Constant *C1, Constant *C2) { return get(Instruction::FAdd, C1, C2); } -Constant* ConstantExpr::getSub(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getSub(Constant *C1, Constant *C2) { return get(Instruction::Sub, C1, C2); } -Constant* ConstantExpr::getFSub(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getFSub(Constant *C1, Constant *C2) { return get(Instruction::FSub, C1, C2); } -Constant* ConstantExpr::getMul(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getMul(Constant *C1, Constant *C2) { return get(Instruction::Mul, C1, C2); } -Constant* ConstantExpr::getFMul(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getFMul(Constant *C1, Constant *C2) { return get(Instruction::FMul, C1, C2); } -Constant* ConstantExpr::getUDiv(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getUDiv(Constant *C1, Constant *C2) { return get(Instruction::UDiv, C1, C2); } -Constant* ConstantExpr::getSDiv(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getSDiv(Constant *C1, Constant *C2) { return get(Instruction::SDiv, C1, C2); } -Constant* ConstantExpr::getFDiv(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getFDiv(Constant *C1, Constant *C2) { return get(Instruction::FDiv, C1, C2); } -Constant* ConstantExpr::getURem(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getURem(Constant *C1, Constant *C2) { return get(Instruction::URem, C1, C2); } -Constant* ConstantExpr::getSRem(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getSRem(Constant *C1, Constant *C2) { return get(Instruction::SRem, C1, C2); } -Constant* ConstantExpr::getFRem(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getFRem(Constant *C1, Constant *C2) { return get(Instruction::FRem, C1, C2); } -Constant* ConstantExpr::getAnd(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getAnd(Constant *C1, Constant *C2) { return get(Instruction::And, C1, C2); } -Constant* ConstantExpr::getOr(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getOr(Constant *C1, Constant *C2) { return get(Instruction::Or, C1, C2); } -Constant* ConstantExpr::getXor(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getXor(Constant *C1, Constant *C2) { return get(Instruction::Xor, C1, C2); } -Constant* ConstantExpr::getShl(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getShl(Constant *C1, Constant *C2) { return get(Instruction::Shl, C1, C2); } -Constant* ConstantExpr::getLShr(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getLShr(Constant *C1, Constant *C2) { return get(Instruction::LShr, C1, C2); } -Constant* ConstantExpr::getAShr(Constant* C1, Constant* C2) { +Constant *ConstantExpr::getAShr(Constant *C1, Constant *C2) { return get(Instruction::AShr, C1, C2); } diff --git a/test/Assembler/2003-05-21-MalformedShiftCrash.ll b/test/Assembler/2003-05-21-MalformedShiftCrash.ll index c661f7c0771..a845d89bb6c 100644 --- a/test/Assembler/2003-05-21-MalformedShiftCrash.ll +++ b/test/Assembler/2003-05-21-MalformedShiftCrash.ll @@ -1,4 +1,4 @@ ; Found by inspection of the code -; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer or integer vector operands} +; RUN: not llvm-as < %s > /dev/null |& grep {constexpr requires integer operands} global i32 ashr (float 1.0, float 2.0) diff --git a/test/Assembler/flags.ll b/test/Assembler/flags.ll index 82b35b5c210..310b807c5d5 100644 --- a/test/Assembler/flags.ll +++ b/test/Assembler/flags.ll @@ -92,6 +92,12 @@ define i64 @mul_both_reversed(i64 %x, i64 %y) { ret i64 %z } +define i64 @shl_both(i64 %x, i64 %y) { +; CHECK: %z = shl nuw nsw i64 %x, %y + %z = shl nuw nsw i64 %x, %y + ret i64 %z +} + define i64 @sdiv_exact(i64 %x, i64 %y) { ; CHECK: %z = sdiv exact i64 %x, %y %z = sdiv exact i64 %x, %y @@ -116,6 +122,29 @@ define i64 @udiv_plain(i64 %x, i64 %y) { ret i64 %z } +define i64 @ashr_plain(i64 %x, i64 %y) { +; CHECK: %z = ashr i64 %x, %y + %z = ashr i64 %x, %y + ret i64 %z +} + +define i64 @ashr_exact(i64 %x, i64 %y) { +; CHECK: %z = ashr exact i64 %x, %y + %z = ashr exact i64 %x, %y + ret i64 %z +} + +define i64 @lshr_plain(i64 %x, i64 %y) { +; CHECK: %z = lshr i64 %x, %y + %z = lshr i64 %x, %y + ret i64 %z +} + +define i64 @lshr_exact(i64 %x, i64 %y) { +; CHECK: %z = lshr exact i64 %x, %y + %z = lshr exact i64 %x, %y + ret i64 %z +} define i64* @gep_nw(i64* %p, i64 %x) { ; CHECK: %z = getelementptr inbounds i64* %p, i64 %x @@ -154,6 +183,16 @@ define i64 @udiv_exact_ce() { ret i64 udiv exact (i64 ptrtoint (i64* @addr to i64), i64 91) } +define i64 @ashr_exact_ce() { +; CHECK: ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9) + ret i64 ashr exact (i64 ptrtoint (i64* @addr to i64), i64 9) +} + +define i64 @lshr_exact_ce() { +; CHECK: ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9) + ret i64 lshr exact (i64 ptrtoint (i64* @addr to i64), i64 9) +} + define i64* @gep_nw_ce() { ; CHECK: ret i64* getelementptr inbounds (i64* @addr, i64 171) ret i64* getelementptr inbounds (i64* @addr, i64 171) @@ -214,6 +253,12 @@ define i64 @mul_signed_ce() { ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91) } +define i64 @shl_signed_ce() { +; CHECK: ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17) + ret i64 shl nsw (i64 ptrtoint (i64* @addr to i64), i64 17) +} + + define i64 @add_unsigned_ce() { ; CHECK: ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91) ret i64 add nuw (i64 ptrtoint (i64* @addr to i64), i64 91)