diff --git a/llvm/include/llvm/Constants.h b/llvm/include/llvm/Constants.h index e79ca543ab37..da6fe96a7726 100644 --- a/llvm/include/llvm/Constants.h +++ b/llvm/include/llvm/Constants.h @@ -571,17 +571,13 @@ protected: // These private methods are used by the type resolution code to create // ConstantExprs in intermediate forms. static Constant *getTy(const Type *Ty, unsigned Opcode, - Constant *C1, Constant *C2, - unsigned Flags = 0); + Constant *C1, Constant *C2); static Constant *getCompareTy(unsigned short pred, Constant *C1, Constant *C2); static Constant *getSelectTy(const Type *Ty, Constant *C1, Constant *C2, Constant *C3); static Constant *getGetElementPtrTy(const Type *Ty, Constant *C, Value* const *Idxs, unsigned NumIdxs); - static Constant *getInBoundsGetElementPtrTy(const Type *Ty, Constant *C, - Value* const *Idxs, - unsigned NumIdxs); static Constant *getExtractElementTy(const Type *Ty, Constant *Val, Constant *Idx); static Constant *getInsertElementTy(const Type *Ty, Constant *Val, @@ -722,8 +718,7 @@ public: /// get - Return a binary or shift operator constant expression, /// folding if possible. /// - static Constant *get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags = 0); + static Constant *get(unsigned Opcode, Constant *C1, Constant *C2); /// @brief Return an ICmp or FCmp comparison operator constant expression. static Constant *getCompare(unsigned short pred, Constant *C1, Constant *C2); diff --git a/llvm/include/llvm/InstrTypes.h b/llvm/include/llvm/InstrTypes.h index 032a1e7f7a19..35d7534e5a34 100644 --- a/llvm/include/llvm/InstrTypes.h +++ b/llvm/include/llvm/InstrTypes.h @@ -200,19 +200,19 @@ public: static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, const Twine &Name = "") { BinaryOperator *BO = CreateAdd(V1, V2, Name); - BO->setHasNoSignedWrap(true); + cast(BO)->setHasNoSignedWrap(true); return BO; } static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { BinaryOperator *BO = CreateAdd(V1, V2, Name, BB); - BO->setHasNoSignedWrap(true); + cast(BO)->setHasNoSignedWrap(true); return BO; } static BinaryOperator *CreateNSWAdd(Value *V1, Value *V2, const Twine &Name, Instruction *I) { BinaryOperator *BO = CreateAdd(V1, V2, Name, I); - BO->setHasNoSignedWrap(true); + cast(BO)->setHasNoSignedWrap(true); return BO; } @@ -221,19 +221,19 @@ public: static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, const Twine &Name = "") { BinaryOperator *BO = CreateSDiv(V1, V2, Name); - BO->setIsExact(true); + cast(BO)->setIsExact(true); return BO; } static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, const Twine &Name, BasicBlock *BB) { BinaryOperator *BO = CreateSDiv(V1, V2, Name, BB); - BO->setIsExact(true); + cast(BO)->setIsExact(true); return BO; } static BinaryOperator *CreateExactSDiv(Value *V1, Value *V2, const Twine &Name, Instruction *I) { BinaryOperator *BO = CreateSDiv(V1, V2, Name, I); - BO->setIsExact(true); + cast(BO)->setIsExact(true); return BO; } @@ -287,21 +287,6 @@ public: /// bool swapOperands(); - /// setHasNoUnsignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. - void setHasNoUnsignedWrap(bool); - - /// setHasNoSignedWrap - Set or clear the nsw flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. - void setHasNoSignedWrap(bool); - - /// setIsExact - Set or clear the exact flag on this instruction, - /// which must be an operator which supports this flag. See LangRef.html - /// for the meaning of this flag. - void setIsExact(bool); - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const BinaryOperator *) { return true; } static inline bool classof(const Instruction *I) { diff --git a/llvm/include/llvm/Instructions.h b/llvm/include/llvm/Instructions.h index 57cff1722131..71f473852897 100644 --- a/llvm/include/llvm/Instructions.h +++ b/llvm/include/llvm/Instructions.h @@ -496,7 +496,7 @@ public: Instruction *InsertBefore = 0) { GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, NameStr, InsertBefore); - GEP->setIsInBounds(true); + cast(GEP)->setIsInBounds(true); return GEP; } template @@ -507,21 +507,21 @@ public: BasicBlock *InsertAtEnd) { GetElementPtrInst *GEP = Create(Ptr, IdxBegin, IdxEnd, NameStr, InsertAtEnd); - GEP->setIsInBounds(true); + cast(GEP)->setIsInBounds(true); return GEP; } static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, const Twine &NameStr = "", Instruction *InsertBefore = 0) { GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertBefore); - GEP->setIsInBounds(true); + cast(GEP)->setIsInBounds(true); return GEP; } static GetElementPtrInst *CreateInBounds(Value *Ptr, Value *Idx, const Twine &NameStr, BasicBlock *InsertAtEnd) { GetElementPtrInst *GEP = Create(Ptr, Idx, NameStr, InsertAtEnd); - GEP->setIsInBounds(true); + cast(GEP)->setIsInBounds(true); return GEP; } @@ -602,10 +602,6 @@ public: /// a constant offset between them. bool hasAllConstantIndices() const; - /// setIsInBounds - Set or clear the inbounds flag on this GEP instruction. - /// See LangRef.html for the meaning of inbounds on a getelementptr. - void setIsInBounds(bool); - // Methods for support type inquiry through isa, cast, and dyn_cast: static inline bool classof(const GetElementPtrInst *) { return true; } static inline bool classof(const Instruction *I) { diff --git a/llvm/include/llvm/Operator.h b/llvm/include/llvm/Operator.h index 06eb243418ec..48ac09d54fc4 100644 --- a/llvm/include/llvm/Operator.h +++ b/llvm/include/llvm/Operator.h @@ -21,8 +21,6 @@ namespace llvm { class GetElementPtrInst; -class BinaryOperator; -class ConstantExpr; /// Operator - This is a utility class that provides an abstraction for the /// common functionality between Instructions and ConstantExprs. @@ -69,37 +67,24 @@ public: /// despite that operator having the potential for overflow. /// class OverflowingBinaryOperator : public Operator { -public: - enum { - NoUnsignedWrap = (1 << 0), - NoSignedWrap = (1 << 1) - }; - -private: ~OverflowingBinaryOperator(); // do not implement - - friend class BinaryOperator; - friend class ConstantExpr; - void setHasNoUnsignedWrap(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~NoUnsignedWrap) | (B * NoUnsignedWrap); - } - void setHasNoSignedWrap(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~NoSignedWrap) | (B * NoSignedWrap); - } - public: /// hasNoUnsignedWrap - Test whether this operation is known to never /// undergo unsigned overflow, aka the nuw property. bool hasNoUnsignedWrap() const { - return SubclassOptionalData & NoUnsignedWrap; + return SubclassOptionalData & (1 << 0); + } + void setHasNoUnsignedWrap(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0); } /// hasNoSignedWrap - Test whether this operation is known to never /// undergo signed overflow, aka the nsw property. bool hasNoSignedWrap() const { - return SubclassOptionalData & NoSignedWrap; + return SubclassOptionalData & (1 << 1); + } + void setHasNoSignedWrap(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~(1 << 1)) | (B << 1); } static inline bool classof(const OverflowingBinaryOperator *) { return true; } @@ -176,25 +161,15 @@ public: /// SDivOperator - An Operator with opcode Instruction::SDiv. /// class SDivOperator : public Operator { -public: - enum { - IsExact = (1 << 0) - }; - -private: ~SDivOperator(); // do not implement - - friend class BinaryOperator; - friend class ConstantExpr; - void setIsExact(bool B) { - SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); - } - public: /// isExact - Test whether this division is known to be exact, with /// zero remainder. bool isExact() const { - return SubclassOptionalData & IsExact; + return SubclassOptionalData & (1 << 0); + } + void setIsExact(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0); } // Methods for support type inquiry through isa, cast, and dyn_cast: @@ -212,24 +187,15 @@ public: }; class GEPOperator : public Operator { - enum { - IsInBounds = (1 << 0) - }; - ~GEPOperator(); // do not implement - - friend class GetElementPtrInst; - friend class ConstantExpr; - void setIsInBounds(bool B) { - SubclassOptionalData = - (SubclassOptionalData & ~IsInBounds) | (B * IsInBounds); - } - public: /// isInBounds - Test whether this is an inbounds GEP, as defined /// by LangRef.html. bool isInBounds() const { - return SubclassOptionalData & IsInBounds; + return SubclassOptionalData & (1 << 0); + } + void setIsInBounds(bool B) { + SubclassOptionalData = (SubclassOptionalData & ~(1 << 0)) | (B << 0); } inline op_iterator idx_begin() { return op_begin()+1; } diff --git a/llvm/include/llvm/Value.h b/llvm/include/llvm/Value.h index 415b8fbb2ba2..fdc3aeb9567a 100644 --- a/llvm/include/llvm/Value.h +++ b/llvm/include/llvm/Value.h @@ -146,6 +146,12 @@ public: // Only use when in type resolution situations! void uncheckedReplaceAllUsesWith(Value *V); + /// clearOptionalData - Clear any optional optimization data from this Value. + /// Transformation passes must call this method whenever changing the IR + /// in a way that would affect the values produced by this Value, unless + /// it takes special care to ensure correctness in some other way. + void clearOptionalData() { SubclassOptionalData = 0; } + //---------------------------------------------------------------------- // Methods for handling the chain of uses of this Value. // @@ -234,13 +240,6 @@ public: return SubclassID; } - /// getRawSubclassOptionalData - Return the raw optional flags value - /// contained in this value. This should only be used when testing two - /// Values for equivalence. - unsigned getRawSubclassOptionalData() const { - return SubclassOptionalData; - } - /// hasSameSubclassOptionalData - Test whether the optional flags contained /// in this value are equal to the optional flags in the given value. bool hasSameSubclassOptionalData(const Value *V) const { diff --git a/llvm/lib/AsmParser/LLParser.cpp b/llvm/lib/AsmParser/LLParser.cpp index b7b95d7ecf05..3ef4aaf64980 100644 --- a/llvm/lib/AsmParser/LLParser.cpp +++ b/llvm/lib/AsmParser/LLParser.cpp @@ -2095,11 +2095,13 @@ bool LLParser::ParseValID(ValID &ID) { if (!Val0->getType()->isIntOrIntVector() && !Val0->getType()->isFPOrFPVector()) return Error(ID.Loc,"constexpr requires integer, fp, or vector operands"); - unsigned Flags = 0; - if (NUW) Flags |= OverflowingBinaryOperator::NoUnsignedWrap; - if (NSW) Flags |= OverflowingBinaryOperator::NoSignedWrap; - if (Exact) Flags |= SDivOperator::IsExact; - Constant *C = ConstantExpr::get(Opc, Val0, Val1, Flags); + Constant *C = ConstantExpr::get(Opc, Val0, Val1); + if (NUW) + cast(C)->setHasNoUnsignedWrap(true); + if (NSW) + cast(C)->setHasNoSignedWrap(true); + if (Exact) + cast(C)->setIsExact(true); ID.ConstantVal = C; ID.Kind = ValID::t_Constant; return false; @@ -2155,12 +2157,10 @@ bool LLParser::ParseValID(ValID &ID) { (Value**)(Elts.data() + 1), Elts.size() - 1)) return Error(ID.Loc, "invalid indices for getelementptr"); - ID.ConstantVal = InBounds ? - ConstantExpr::getInBoundsGetElementPtr(Elts[0], - Elts.data() + 1, - Elts.size() - 1) : - ConstantExpr::getGetElementPtr(Elts[0], - Elts.data() + 1, Elts.size() - 1); + ID.ConstantVal = ConstantExpr::getGetElementPtr(Elts[0], + Elts.data() + 1, Elts.size() - 1); + if (InBounds) + cast(ID.ConstantVal)->setIsInBounds(true); } else if (Opc == Instruction::Select) { if (Elts.size() != 3) return Error(ID.Loc, "expected three operands to select"); @@ -2681,9 +2681,9 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, return Error(ModifierLoc, "nsw only applies to integer operations"); } if (NUW) - cast(Inst)->setHasNoUnsignedWrap(true); + cast(Inst)->setHasNoUnsignedWrap(true); if (NSW) - cast(Inst)->setHasNoSignedWrap(true); + cast(Inst)->setHasNoSignedWrap(true); } return Result; } @@ -2698,7 +2698,7 @@ bool LLParser::ParseInstruction(Instruction *&Inst, BasicBlock *BB, bool Result = ParseArithmetic(Inst, PFS, KeywordVal, 1); if (!Result) if (Exact) - cast(Inst)->setIsExact(true); + cast(Inst)->setIsExact(true); return Result; } @@ -3501,7 +3501,7 @@ bool LLParser::ParseGetElementPtr(Instruction *&Inst, PerFunctionState &PFS) { return Error(Loc, "invalid getelementptr indices"); Inst = GetElementPtrInst::Create(Ptr, Indices.begin(), Indices.end()); if (InBounds) - cast(Inst)->setIsInBounds(true); + cast(Inst)->setIsInBounds(true); return false; } diff --git a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp index 05f7b52292da..9ed75ab1313f 100644 --- a/llvm/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/llvm/lib/Bitcode/Reader/BitcodeReader.cpp @@ -883,6 +883,19 @@ bool BitcodeReader::ResolveGlobalAndAliasInits() { return false; } +static void SetOptimizationFlags(Value *V, uint64_t Flags) { + if (OverflowingBinaryOperator *OBO = + dyn_cast(V)) { + if (Flags & (1 << bitc::OBO_NO_SIGNED_WRAP)) + OBO->setHasNoSignedWrap(true); + if (Flags & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) + OBO->setHasNoUnsignedWrap(true); + } else if (SDivOperator *Div = dyn_cast(V)) { + if (Flags & (1 << bitc::SDIV_EXACT)) + Div->setIsExact(true); + } +} + bool BitcodeReader::ParseConstants() { if (Stream.EnterSubBlock(bitc::CONSTANTS_BLOCK_ID)) return Error("Malformed block record"); @@ -1034,22 +1047,10 @@ bool BitcodeReader::ParseConstants() { } else { Constant *LHS = ValueList.getConstantFwdRef(Record[1], CurTy); Constant *RHS = ValueList.getConstantFwdRef(Record[2], CurTy); - unsigned Flags = 0; - if (Record.size() >= 4) { - if (Opc == Instruction::Add || - Opc == Instruction::Sub || - Opc == Instruction::Mul) { - 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) { - if (Record[3] & (1 << bitc::SDIV_EXACT)) - Flags |= SDivOperator::IsExact; - } - } - V = ConstantExpr::get(Opc, LHS, RHS, Flags); + V = ConstantExpr::get(Opc, LHS, RHS); } + if (Record.size() >= 4) + SetOptimizationFlags(V, Record[3]); break; } case bitc::CST_CODE_CE_CAST: { // CE_CAST: [opcode, opty, opval] @@ -1074,12 +1075,10 @@ bool BitcodeReader::ParseConstants() { if (!ElTy) return Error("Invalid CE_GEP record"); Elts.push_back(ValueList.getConstantFwdRef(Record[i+1], ElTy)); } + V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], + Elts.size()-1); if (BitCode == bitc::CST_CODE_CE_INBOUNDS_GEP) - V = ConstantExpr::getInBoundsGetElementPtr(Elts[0], &Elts[1], - Elts.size()-1); - else - V = ConstantExpr::getGetElementPtr(Elts[0], &Elts[1], - Elts.size()-1); + cast(V)->setIsInBounds(true); break; } case bitc::CST_CODE_CE_SELECT: // CE_SELECT: [opval#, opval#, opval#] @@ -1611,19 +1610,8 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { int Opc = GetDecodedBinaryOpcode(Record[OpNum++], LHS->getType()); if (Opc == -1) return Error("Invalid BINOP record"); I = BinaryOperator::Create((Instruction::BinaryOps)Opc, LHS, RHS); - if (OpNum < Record.size()) { - if (Opc == Instruction::Add || - Opc == Instruction::Sub || - Opc == Instruction::Mul) { - if (Record[3] & (1 << bitc::OBO_NO_SIGNED_WRAP)) - cast(I)->setHasNoSignedWrap(true); - if (Record[3] & (1 << bitc::OBO_NO_UNSIGNED_WRAP)) - cast(I)->setHasNoUnsignedWrap(true); - } else if (Opc == Instruction::SDiv) { - if (Record[3] & (1 << bitc::SDIV_EXACT)) - cast(I)->setIsExact(true); - } - } + if (OpNum < Record.size()) + SetOptimizationFlags(I, Record[3]); break; } case bitc::FUNC_CODE_INST_CAST: { // CAST: [opval, opty, destty, castopc] @@ -1657,7 +1645,7 @@ bool BitcodeReader::ParseFunctionBody(Function *F) { I = GetElementPtrInst::Create(BasePtr, GEPIdx.begin(), GEPIdx.end()); if (BitCode == bitc::FUNC_CODE_INST_INBOUNDS_GEP) - cast(I)->setIsInBounds(true); + cast(I)->setIsInBounds(true); break; } diff --git a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp index 432b88f911da..ce2f4520c6a5 100644 --- a/llvm/lib/Transforms/Scalar/InstructionCombining.cpp +++ b/llvm/lib/Transforms/Scalar/InstructionCombining.cpp @@ -8086,11 +8086,11 @@ Instruction *InstCombiner::commonPointerCastTransforms(CastInst &CI) { // If we were able to index down into an element, create the GEP // and bitcast the result. This eliminates one bitcast, potentially // two. - Value *NGEP = cast(GEP)->isInBounds() ? - Builder->CreateInBoundsGEP(OrigBase, - NewIndices.begin(), NewIndices.end()) : - Builder->CreateGEP(OrigBase, NewIndices.begin(), NewIndices.end()); + Value *NGEP = Builder->CreateGEP(OrigBase, NewIndices.begin(), + NewIndices.end()); NGEP->takeName(GEP); + if (isa(NGEP) && cast(GEP)->isInBounds()) + cast(NGEP)->setIsInBounds(true); if (isa(CI)) return new BitCastInst(NGEP, CI.getType()); @@ -8805,8 +8805,11 @@ Instruction *InstCombiner::visitBitCast(BitCastInst &CI) { // If we found a path from the src to dest, create the getelementptr now. if (SrcElTy == DstElTy) { SmallVector Idxs(NumZeros+1, ZeroUInt); - return GetElementPtrInst::CreateInBounds(Src, Idxs.begin(), Idxs.end(), "", - ((Instruction*) NULL)); + Instruction *GEP = GetElementPtrInst::Create(Src, + Idxs.begin(), Idxs.end(), "", + ((Instruction*) NULL)); + cast(GEP)->setIsInBounds(true); + return GEP; } } @@ -10478,11 +10481,12 @@ Instruction *InstCombiner::FoldPHIArgGEPIntoPHI(PHINode &PN) { } Value *Base = FixedOperands[0]; - return cast(FirstInst)->isInBounds() ? - GetElementPtrInst::CreateInBounds(Base, FixedOperands.begin()+1, - FixedOperands.end()) : + GetElementPtrInst *GEP = GetElementPtrInst::Create(Base, FixedOperands.begin()+1, FixedOperands.end()); + if (cast(FirstInst)->isInBounds()) + cast(GEP)->setIsInBounds(true); + return GEP; } @@ -10885,13 +10889,14 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Indices.append(GEP.idx_begin()+1, GEP.idx_end()); } - if (!Indices.empty()) - return (cast(&GEP)->isInBounds() && - Src->isInBounds()) ? - GetElementPtrInst::CreateInBounds(Src->getOperand(0), Indices.begin(), - Indices.end(), GEP.getName()) : + if (!Indices.empty()) { + GetElementPtrInst *NewGEP = GetElementPtrInst::Create(Src->getOperand(0), Indices.begin(), Indices.end(), GEP.getName()); + if (cast(&GEP)->isInBounds() && Src->isInBounds()) + cast(NewGEP)->setIsInBounds(true); + return NewGEP; + } } // Handle gep(bitcast x) and gep(gep x, 0, 0, 0). @@ -10921,11 +10926,12 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { if (CATy->getElementType() == XTy->getElementType()) { // -> GEP i8* X, ... SmallVector Indices(GEP.idx_begin()+1, GEP.idx_end()); - return cast(&GEP)->isInBounds() ? - GetElementPtrInst::CreateInBounds(X, Indices.begin(), Indices.end(), - GEP.getName()) : + GetElementPtrInst *NewGEP = GetElementPtrInst::Create(X, Indices.begin(), Indices.end(), GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); + return NewGEP; } if (const ArrayType *XATy = dyn_cast(XTy->getElementType())){ @@ -10953,9 +10959,10 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Value *Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context)); Idx[1] = GEP.getOperand(1); - Value *NewGEP = cast(&GEP)->isInBounds() ? - Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) : + Value *NewGEP = Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); // V and GEP are both pointer types --> BitCast return new BitCastInst(NewGEP, GEP.getType()); } @@ -11012,9 +11019,9 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { Value *Idx[2]; Idx[0] = Constant::getNullValue(Type::getInt32Ty(*Context)); Idx[1] = NewIdx; - Value *NewGEP = cast(&GEP)->isInBounds() ? - Builder->CreateInBoundsGEP(X, Idx, Idx + 2, GEP.getName()) : - Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName()); + Value *NewGEP = Builder->CreateGEP(X, Idx, Idx + 2, GEP.getName()); + if (cast(&GEP)->isInBounds()) + cast(NewGEP)->setIsInBounds(true); // The NewGEP must be pointer typed, so must the old one -> BitCast return new BitCastInst(NewGEP, GEP.getType()); } @@ -11062,11 +11069,10 @@ Instruction *InstCombiner::visitGetElementPtrInst(GetElementPtrInst &GEP) { const Type *InTy = cast(BCI->getOperand(0)->getType())->getElementType(); if (FindElementAtOffset(InTy, Offset, NewIndices, TD, Context)) { - Value *NGEP = cast(&GEP)->isInBounds() ? - Builder->CreateInBoundsGEP(BCI->getOperand(0), NewIndices.begin(), - NewIndices.end()) : - Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(), - NewIndices.end()); + Value *NGEP = Builder->CreateGEP(BCI->getOperand(0), NewIndices.begin(), + NewIndices.end()); + if (cast(&GEP)->isInBounds()) + cast(NGEP)->setIsInBounds(true); if (NGEP->getType() == GEP.getType()) return ReplaceInstUsesWith(GEP, NGEP); @@ -11109,8 +11115,9 @@ Instruction *InstCombiner::visitAllocationInst(AllocationInst &AI) { Value *Idx[2]; Idx[0] = NullIdx; Idx[1] = NullIdx; - Value *V = GetElementPtrInst::CreateInBounds(New, Idx, Idx + 2, - New->getName()+".sub", It); + Value *V = GetElementPtrInst::Create(New, Idx, Idx + 2, + New->getName()+".sub", It); + cast(V)->setIsInBounds(true); // Now make everything use the getelementptr instead of the original // allocation. @@ -11479,9 +11486,11 @@ static Instruction *InstCombineStoreToCast(InstCombiner &IC, StoreInst &SI) { // SIOp0 is a pointer to aggregate and this is a store to the first field, // emit a GEP to index into its first field. - if (!NewGEPIndices.empty()) - CastOp = IC.Builder->CreateInBoundsGEP(CastOp, NewGEPIndices.begin(), - NewGEPIndices.end()); + if (!NewGEPIndices.empty()) { + CastOp = IC.Builder->CreateGEP(CastOp, NewGEPIndices.begin(), + NewGEPIndices.end()); + cast(CastOp)->setIsInBounds(true); + } NewCast = IC.Builder->CreateCast(opcode, SIOp0, CastDstTy, SIOp0->getName()+".c"); @@ -12151,7 +12160,8 @@ Instruction *InstCombiner::visitExtractElementInst(ExtractElementInst &EI) { PointerType::get(EI.getType(), AS), I->getOperand(0)->getName()); Value *GEP = - Builder->CreateInBoundsGEP(Ptr, EI.getOperand(1), I->getName()+".gep"); + Builder->CreateGEP(Ptr, EI.getOperand(1), I->getName()+".gep"); + cast(GEP)->setIsInBounds(true); LoadInst *Load = Builder->CreateLoad(GEP, "tmp"); diff --git a/llvm/lib/VMCore/Constants.cpp b/llvm/lib/VMCore/Constants.cpp index a5b4f289688b..37efafc9b208 100644 --- a/llvm/lib/VMCore/Constants.cpp +++ b/llvm/lib/VMCore/Constants.cpp @@ -632,13 +632,21 @@ Constant* ConstantVector::get(Constant* const* Vals, unsigned NumVals) { } Constant* ConstantExpr::getNSWAdd(Constant* C1, Constant* C2) { - return getTy(C1->getType(), Instruction::Add, C1, C2, - OverflowingBinaryOperator::NoSignedWrap); + Constant *C = getAdd(C1, C2); + // Set nsw attribute, assuming constant folding didn't eliminate the + // Add. + if (AddOperator *Add = dyn_cast(C)) + Add->setHasNoSignedWrap(true); + return C; } Constant* ConstantExpr::getExactSDiv(Constant* C1, Constant* C2) { - return getTy(C1->getType(), Instruction::SDiv, C1, C2, - SDivOperator::IsExact); + Constant *C = getSDiv(C1, C2); + // Set exact attribute, assuming constant folding didn't eliminate the + // SDiv. + if (SDivOperator *SDiv = dyn_cast(C)) + SDiv->setIsExact(true); + return C; } // Utility function for determining if a ConstantExpr is a CastOp or not. This @@ -721,19 +729,15 @@ ConstantExpr::getWithOperandReplaced(unsigned OpNo, Constant *Op) const { for (unsigned i = 1, e = getNumOperands(); i != e; ++i) Ops[i-1] = getOperand(i); if (OpNo == 0) - return cast(this)->isInBounds() ? - ConstantExpr::getInBoundsGetElementPtr(Op, &Ops[0], Ops.size()) : - ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size()); + return ConstantExpr::getGetElementPtr(Op, &Ops[0], Ops.size()); Ops[OpNo-1] = Op; - return cast(this)->isInBounds() ? - ConstantExpr::getInBoundsGetElementPtr(getOperand(0), &Ops[0], Ops.size()) : - ConstantExpr::getGetElementPtr(getOperand(0), &Ops[0], Ops.size()); + return ConstantExpr::getGetElementPtr(getOperand(0), &Ops[0], Ops.size()); } default: assert(getNumOperands() == 2 && "Must be binary operator?"); Op0 = (OpNo == 0) ? Op : getOperand(0); Op1 = (OpNo == 1) ? Op : getOperand(1); - return ConstantExpr::get(getOpcode(), Op0, Op1, SubclassData); + return ConstantExpr::get(getOpcode(), Op0, Op1); } } @@ -775,15 +779,13 @@ getWithOperands(Constant* const *Ops, unsigned NumOps) const { case Instruction::ShuffleVector: return ConstantExpr::getShuffleVector(Ops[0], Ops[1], Ops[2]); case Instruction::GetElementPtr: - return cast(this)->isInBounds() ? - ConstantExpr::getInBoundsGetElementPtr(Ops[0], &Ops[1], NumOps-1) : - ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1); + return ConstantExpr::getGetElementPtr(Ops[0], &Ops[1], NumOps-1); case Instruction::ICmp: case Instruction::FCmp: return ConstantExpr::getCompare(getPredicate(), Ops[0], Ops[1]); default: assert(getNumOperands() == 2 && "Must be binary operator?"); - return ConstantExpr::get(getOpcode(), Ops[0], Ops[1], SubclassData); + return ConstantExpr::get(getOpcode(), Ops[0], Ops[1]); } } @@ -1029,9 +1031,8 @@ static ExprMapKeyType getValType(ConstantExpr *CE) { Operands.reserve(CE->getNumOperands()); for (unsigned i = 0, e = CE->getNumOperands(); i != e; ++i) Operands.push_back(cast(CE->getOperand(i))); - return ExprMapKeyType(CE->getOpcode(), Operands, + return ExprMapKeyType(CE->getOpcode(), Operands, CE->isCompare() ? CE->getPredicate() : 0, - CE->getRawSubclassOptionalData(), CE->hasIndices() ? CE->getIndices() : SmallVector()); } @@ -1279,8 +1280,7 @@ Constant *ConstantExpr::getBitCast(Constant *C, const Type *DstTy) { } Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode, - Constant *C1, Constant *C2, - unsigned Flags) { + Constant *C1, Constant *C2) { // Check the operands for consistency first assert(Opcode >= Instruction::BinaryOpsBegin && Opcode < Instruction::BinaryOpsEnd && @@ -1294,7 +1294,7 @@ Constant *ConstantExpr::getTy(const Type *ReqTy, unsigned Opcode, return FC; // Fold a few common cases... std::vector argVec(1, C1); argVec.push_back(C2); - ExprMapKeyType Key(Opcode, argVec, 0, Flags); + ExprMapKeyType Key(Opcode, argVec); LLVMContextImpl *pImpl = ReqTy->getContext().pImpl; @@ -1322,8 +1322,7 @@ Constant *ConstantExpr::getCompareTy(unsigned short predicate, } } -Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags) { +Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2) { // API compatibility: Adjust integer opcodes to floating-point opcodes. if (C1->getType()->isFPOrFPVector()) { if (Opcode == Instruction::Add) Opcode = Instruction::FAdd; @@ -1388,7 +1387,7 @@ Constant *ConstantExpr::get(unsigned Opcode, Constant *C1, Constant *C2, } #endif - return getTy(C1->getType(), Opcode, C1, C2, Flags); + return getTy(C1->getType(), Opcode, C1, C2); } Constant* ConstantExpr::getSizeOf(const Type* Ty) { @@ -1482,36 +1481,6 @@ Constant *ConstantExpr::getGetElementPtrTy(const Type *ReqTy, Constant *C, return pImpl->ExprConstants.getOrCreate(ReqTy, Key); } -Constant *ConstantExpr::getInBoundsGetElementPtrTy(const Type *ReqTy, - Constant *C, - Value* const *Idxs, - unsigned NumIdx) { - assert(GetElementPtrInst::getIndexedType(C->getType(), Idxs, - Idxs+NumIdx) == - cast(ReqTy)->getElementType() && - "GEP indices invalid!"); - - if (Constant *FC = ConstantFoldGetElementPtr( - ReqTy->getContext(), C, (Constant**)Idxs, NumIdx)) - return FC; // Fold a few common cases... - - assert(isa(C->getType()) && - "Non-pointer type for constant GetElementPtr expression"); - // Look up the constant in the table first to ensure uniqueness - std::vector ArgVec; - ArgVec.reserve(NumIdx+1); - ArgVec.push_back(C); - for (unsigned i = 0; i != NumIdx; ++i) - ArgVec.push_back(cast(Idxs[i])); - const ExprMapKeyType Key(Instruction::GetElementPtr, ArgVec, 0, - GEPOperator::IsInBounds); - - LLVMContextImpl *pImpl = ReqTy->getContext().pImpl; - - // Implicitly locked. - return pImpl->ExprConstants.getOrCreate(ReqTy, Key); -} - Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs, unsigned NumIdx) { // Get the result type of the getelementptr! @@ -1525,12 +1494,12 @@ Constant *ConstantExpr::getGetElementPtr(Constant *C, Value* const *Idxs, Constant *ConstantExpr::getInBoundsGetElementPtr(Constant *C, Value* const *Idxs, unsigned NumIdx) { - // Get the result type of the getelementptr! - const Type *Ty = - GetElementPtrInst::getIndexedType(C->getType(), Idxs, Idxs+NumIdx); - assert(Ty && "GEP indices invalid!"); - unsigned As = cast(C->getType())->getAddressSpace(); - return getInBoundsGetElementPtrTy(PointerType::get(Ty, As), C, Idxs, NumIdx); + Constant *Result = getGetElementPtr(C, Idxs, NumIdx); + // Set in bounds attribute, assuming constant folding didn't eliminate the + // GEP. + if (GEPOperator *GEP = dyn_cast(Result)) + GEP->setIsInBounds(true); + return Result; } Constant *ConstantExpr::getGetElementPtr(Constant *C, Constant* const *Idxs, @@ -2135,7 +2104,7 @@ void ConstantExpr::replaceUsesOfWithOnConstant(Value *From, Value *ToV, Constant *C2 = getOperand(1); if (C1 == From) C1 = To; if (C2 == From) C2 = To; - Replacement = ConstantExpr::get(getOpcode(), C1, C2, SubclassData); + Replacement = ConstantExpr::get(getOpcode(), C1, C2); } else { llvm_unreachable("Unknown ConstantExpr type!"); return; diff --git a/llvm/lib/VMCore/ConstantsContext.h b/llvm/lib/VMCore/ConstantsContext.h index 16975b3611eb..718470aff423 100644 --- a/llvm/lib/VMCore/ConstantsContext.h +++ b/llvm/lib/VMCore/ConstantsContext.h @@ -53,12 +53,10 @@ public: void *operator new(size_t s) { return User::operator new(s, 2); } - BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2, - unsigned Flags) + BinaryConstantExpr(unsigned Opcode, Constant *C1, Constant *C2) : ConstantExpr(C1->getType(), Opcode, &Op<0>(), 2) { Op<0>() = C1; Op<1>() = C2; - SubclassOptionalData = Flags; } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -208,12 +206,9 @@ class GetElementPtrConstantExpr : public ConstantExpr { public: static GetElementPtrConstantExpr *Create(Constant *C, const std::vector&IdxList, - const Type *DestTy, - unsigned Flags) { - GetElementPtrConstantExpr *Result = + const Type *DestTy) { + return new(IdxList.size() + 1) GetElementPtrConstantExpr(C, IdxList, DestTy); - Result->SubclassOptionalData = Flags; - return Result; } /// Transparently provide more efficient getOperand methods. DECLARE_TRANSPARENT_OPERAND_ACCESSORS(Value); @@ -296,32 +291,26 @@ struct ExprMapKeyType { ExprMapKeyType(unsigned opc, const std::vector &ops, - unsigned short flags = 0, - unsigned short optionalflags = 0, + unsigned short pred = 0, const IndexList &inds = IndexList()) - : opcode(opc), subclassoptionaldata(optionalflags), subclassdata(flags), - operands(ops), indices(inds) {} - uint8_t opcode; - uint8_t subclassoptionaldata; - uint16_t subclassdata; + : opcode(opc), predicate(pred), operands(ops), indices(inds) {} + uint16_t opcode; + uint16_t predicate; std::vector operands; IndexList indices; bool operator==(const ExprMapKeyType& that) const { return this->opcode == that.opcode && - this->subclassdata == that.subclassdata && - this->subclassoptionaldata == that.subclassoptionaldata && + this->predicate == that.predicate && this->operands == that.operands && this->indices == that.indices; } bool operator<(const ExprMapKeyType & that) const { - if (this->opcode != that.opcode) return this->opcode < that.opcode; - if (this->operands != that.operands) return this->operands < that.operands; - if (this->subclassdata != that.subclassdata) - return this->subclassdata < that.subclassdata; - if (this->subclassoptionaldata != that.subclassoptionaldata) - return this->subclassoptionaldata < that.subclassoptionaldata; - if (this->indices != that.indices) return this->indices < that.indices; - return false; + return this->opcode < that.opcode || + (this->opcode == that.opcode && this->predicate < that.predicate) || + (this->opcode == that.opcode && this->predicate == that.predicate && + this->operands < that.operands) || + (this->opcode == that.opcode && this->predicate == that.predicate && + this->operands == that.operands && this->indices < that.indices); } bool operator!=(const ExprMapKeyType& that) const { @@ -365,8 +354,7 @@ struct ConstantCreator { return new UnaryConstantExpr(V.opcode, V.operands[0], Ty); if ((V.opcode >= Instruction::BinaryOpsBegin && V.opcode < Instruction::BinaryOpsEnd)) - return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1], - V.subclassoptionaldata); + return new BinaryConstantExpr(V.opcode, V.operands[0], V.operands[1]); if (V.opcode == Instruction::Select) return new SelectConstantExpr(V.operands[0], V.operands[1], V.operands[2]); @@ -385,18 +373,17 @@ struct ConstantCreator { return new ExtractValueConstantExpr(V.operands[0], V.indices, Ty); if (V.opcode == Instruction::GetElementPtr) { std::vector IdxList(V.operands.begin()+1, V.operands.end()); - return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty, - V.subclassoptionaldata); + return GetElementPtrConstantExpr::Create(V.operands[0], IdxList, Ty); } // The compare instructions are weird. We have to encode the predicate // value and it is combined with the instruction opcode by multiplying // the opcode by one hundred. We must decode this to get the predicate. if (V.opcode == Instruction::ICmp) - return new CompareConstantExpr(Ty, Instruction::ICmp, V.subclassdata, + return new CompareConstantExpr(Ty, Instruction::ICmp, V.predicate, V.operands[0], V.operands[1]); if (V.opcode == Instruction::FCmp) - return new CompareConstantExpr(Ty, Instruction::FCmp, V.subclassdata, + return new CompareConstantExpr(Ty, Instruction::FCmp, V.predicate, V.operands[0], V.operands[1]); llvm_unreachable("Invalid ConstantExpr!"); return 0; diff --git a/llvm/lib/VMCore/Instructions.cpp b/llvm/lib/VMCore/Instructions.cpp index 9d8e0477eed9..2d4ab5572176 100644 --- a/llvm/lib/VMCore/Instructions.cpp +++ b/llvm/lib/VMCore/Instructions.cpp @@ -1171,9 +1171,6 @@ bool GetElementPtrInst::hasAllConstantIndices() const { return true; } -void GetElementPtrInst::setIsInBounds(bool B) { - cast(this)->setIsInBounds(B); -} //===----------------------------------------------------------------------===// // ExtractElementInst Implementation @@ -1719,18 +1716,6 @@ bool BinaryOperator::swapOperands() { return false; } -void BinaryOperator::setHasNoUnsignedWrap(bool b) { - cast(this)->setHasNoUnsignedWrap(b); -} - -void BinaryOperator::setHasNoSignedWrap(bool b) { - cast(this)->setHasNoSignedWrap(b); -} - -void BinaryOperator::setIsExact(bool b) { - cast(this)->setIsExact(b); -} - //===----------------------------------------------------------------------===// // CastInst Class //===----------------------------------------------------------------------===// diff --git a/llvm/test/Assembler/flags-plain.ll b/llvm/test/Assembler/flags-plain.ll new file mode 100644 index 000000000000..bf3d5d891f50 --- /dev/null +++ b/llvm/test/Assembler/flags-plain.ll @@ -0,0 +1,28 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_plain_ce() { +; CHECK: ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_plain_ce() { +; CHECK: ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_plain_ce() { +; CHECK: ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sdiv_plain_ce() { +; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64* @gep_plain_ce() { +; CHECK: ret i64* getelementptr (i64* @addr, i64 171) + ret i64* getelementptr (i64* @addr, i64 171) +} diff --git a/llvm/test/Assembler/flags-reversed.ll b/llvm/test/Assembler/flags-reversed.ll new file mode 100644 index 000000000000..25fa6a08dce7 --- /dev/null +++ b/llvm/test/Assembler/flags-reversed.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_both_reversed_ce() { +; CHECK: ret i64 add nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 add nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_both_reversed_ce() { +; CHECK: ret i64 sub nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sub nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_both_reversed_ce() { +; CHECK: ret i64 mul nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 mul nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/llvm/test/Assembler/flags-signed.ll b/llvm/test/Assembler/flags-signed.ll new file mode 100644 index 000000000000..9c408136bc01 --- /dev/null +++ b/llvm/test/Assembler/flags-signed.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +define i64 @add_signed_ce() { +; CHECK: ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @sub_signed_ce() { +; CHECK: ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_signed_ce() { +; CHECK: ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/llvm/test/Assembler/flags-unsigned.ll b/llvm/test/Assembler/flags-unsigned.ll new file mode 100644 index 000000000000..1ddffca4cd31 --- /dev/null +++ b/llvm/test/Assembler/flags-unsigned.ll @@ -0,0 +1,18 @@ +; RUN: llvm-as < %s | llvm-dis | FileCheck %s + +@addr = external global i64 + +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) +} + +define i64 @sub_unsigned_ce() { +; CHECK: ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91) +} + +define i64 @mul_unsigned_ce() { +; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91) + ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91) +} diff --git a/llvm/test/Assembler/flags.ll b/llvm/test/Assembler/flags.ll index 324190905975..981a4e592cef 100644 --- a/llvm/test/Assembler/flags.ll +++ b/llvm/test/Assembler/flags.ll @@ -141,72 +141,4 @@ define i64* @gep_nw_ce() { ret i64* getelementptr inbounds (i64* @addr, i64 171) } -define i64 @add_plain_ce() { -; CHECK: ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 add (i64 ptrtoint (i64* @addr to i64), i64 91) -} -define i64 @sub_plain_ce() { -; CHECK: ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 sub (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @mul_plain_ce() { -; CHECK: ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 mul (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @sdiv_plain_ce() { -; CHECK: ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 sdiv (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64* @gep_plain_ce() { -; CHECK: ret i64* getelementptr (i64* @addr, i64 171) - ret i64* getelementptr (i64* @addr, i64 171) -} - -define i64 @add_both_reversed_ce() { -; CHECK: ret i64 add nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 add nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @sub_both_reversed_ce() { -; CHECK: ret i64 sub nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 sub nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @mul_both_reversed_ce() { -; CHECK: ret i64 mul nuw nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 mul nsw nuw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @add_signed_ce() { -; CHECK: ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 add nsw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @sub_signed_ce() { -; CHECK: ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 sub nsw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @mul_signed_ce() { -; CHECK: ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 mul nsw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -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) -} - -define i64 @sub_unsigned_ce() { -; CHECK: ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 sub nuw (i64 ptrtoint (i64* @addr to i64), i64 91) -} - -define i64 @mul_unsigned_ce() { -; CHECK: ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91) - ret i64 mul nuw (i64 ptrtoint (i64* @addr to i64), i64 91) -}