diff --git a/llvm/include/llvm/IR/IRBuilder.h b/llvm/include/llvm/IR/IRBuilder.h --- a/llvm/include/llvm/IR/IRBuilder.h +++ b/llvm/include/llvm/IR/IRBuilder.h @@ -1585,20 +1585,7 @@ Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr, const Twine &Name = "", MDNode *FPMathTag = nullptr, Optional Rounding = None, - Optional Except = None) { - Value *RoundingV = getConstrainedFPRounding(Rounding); - Value *ExceptV = getConstrainedFPExcept(Except); - - FastMathFlags UseFMF = FMF; - if (FMFSource) - UseFMF = FMFSource->getFastMathFlags(); - - CallInst *C = CreateIntrinsic(ID, {L->getType()}, - {L, R, RoundingV, ExceptV}, nullptr, Name); - setConstrainedFPCallAttr(C); - setFPAttrs(C, FPMathTag, UseFMF); - return C; - } + Optional Except = None); Value *CreateNeg(Value *V, const Twine &Name = "", bool HasNUW = false, bool HasNSW = false) { @@ -1657,20 +1644,7 @@ /// Create either a UnaryOperator or BinaryOperator depending on \p Opc. /// Correct number of operands must be passed accordingly. Value *CreateNAryOp(unsigned Opc, ArrayRef Ops, - const Twine &Name = "", - MDNode *FPMathTag = nullptr) { - if (Instruction::isBinaryOp(Opc)) { - assert(Ops.size() == 2 && "Invalid number of operands!"); - return CreateBinOp(static_cast(Opc), - Ops[0], Ops[1], Name, FPMathTag); - } - if (Instruction::isUnaryOp(Opc)) { - assert(Ops.size() == 1 && "Invalid number of operands!"); - return CreateUnOp(static_cast(Opc), - Ops[0], Name, FPMathTag); - } - llvm_unreachable("Unexpected opcode!"); - } + const Twine &Name = "", MDNode *FPMathTag = nullptr); //===--------------------------------------------------------------------===// // Instruction creation methods: Memory Instructions @@ -2234,38 +2208,7 @@ Instruction *FMFSource = nullptr, const Twine &Name = "", MDNode *FPMathTag = nullptr, Optional Rounding = None, - Optional Except = None) { - Value *ExceptV = getConstrainedFPExcept(Except); - - FastMathFlags UseFMF = FMF; - if (FMFSource) - UseFMF = FMFSource->getFastMathFlags(); - - CallInst *C; - bool HasRoundingMD = false; - switch (ID) { - default: - break; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - HasRoundingMD = ROUND_MODE; \ - break; -#include "llvm/IR/ConstrainedOps.def" - } - if (HasRoundingMD) { - Value *RoundingV = getConstrainedFPRounding(Rounding); - C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV}, - nullptr, Name); - } else - C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr, - Name); - - setConstrainedFPCallAttr(C); - - if (isa(C)) - setFPAttrs(C, FPMathTag, UseFMF); - return C; - } + Optional Except = None); // Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a // compile time error, instead of converting the string to bool for the @@ -2414,32 +2357,12 @@ // Helper routine to create either a signaling or a quiet FP comparison. Value *CreateFCmpHelper(CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name, MDNode *FPMathTag, - bool IsSignaling) { - if (IsFPConstrained) { - auto ID = IsSignaling ? Intrinsic::experimental_constrained_fcmps - : Intrinsic::experimental_constrained_fcmp; - return CreateConstrainedFPCmp(ID, P, LHS, RHS, Name); - } - - if (auto *LC = dyn_cast(LHS)) - if (auto *RC = dyn_cast(RHS)) - return Insert(Folder.CreateFCmp(P, LC, RC), Name); - return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name); - } + bool IsSignaling); public: CallInst *CreateConstrainedFPCmp( Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R, - const Twine &Name = "", - Optional Except = None) { - Value *PredicateV = getConstrainedFPPredicate(P); - Value *ExceptV = getConstrainedFPExcept(Except); - - CallInst *C = CreateIntrinsic(ID, {L->getType()}, - {L, R, PredicateV, ExceptV}, nullptr, Name); - setConstrainedFPCallAttr(C); - return C; - } + const Twine &Name = "", Optional Except = None); //===--------------------------------------------------------------------===// // Instruction creation methods: Other Instructions @@ -2508,47 +2431,10 @@ CallInst *CreateConstrainedFPCall( Function *Callee, ArrayRef Args, const Twine &Name = "", Optional Rounding = None, - Optional Except = None) { - llvm::SmallVector UseArgs; - - for (auto *OneArg : Args) - UseArgs.push_back(OneArg); - bool HasRoundingMD = false; - switch (Callee->getIntrinsicID()) { - default: - break; -#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ - case Intrinsic::INTRINSIC: \ - HasRoundingMD = ROUND_MODE; \ - break; -#include "llvm/IR/ConstrainedOps.def" - } - if (HasRoundingMD) - UseArgs.push_back(getConstrainedFPRounding(Rounding)); - UseArgs.push_back(getConstrainedFPExcept(Except)); - - CallInst *C = CreateCall(Callee, UseArgs, Name); - setConstrainedFPCallAttr(C); - return C; - } + Optional Except = None); Value *CreateSelect(Value *C, Value *True, Value *False, - const Twine &Name = "", Instruction *MDFrom = nullptr) { - if (auto *CC = dyn_cast(C)) - if (auto *TC = dyn_cast(True)) - if (auto *FC = dyn_cast(False)) - return Insert(Folder.CreateSelect(CC, TC, FC), Name); - - SelectInst *Sel = SelectInst::Create(C, True, False); - if (MDFrom) { - MDNode *Prof = MDFrom->getMetadata(LLVMContext::MD_prof); - MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable); - Sel = addBranchMetadata(Sel, Prof, Unpred); - } - if (isa(Sel)) - setFPAttrs(Sel, nullptr /* MDNode* */, FMF); - return Insert(Sel, Name); - } + const Twine &Name = "", Instruction *MDFrom = nullptr); VAArgInst *CreateVAArg(Value *List, Type *Ty, const Twine &Name = "") { return Insert(new VAArgInst(List, Ty), Name); @@ -2652,186 +2538,37 @@ /// This is intended to implement C-style pointer subtraction. As such, the /// pointers must be appropriately aligned for their element types and /// pointing into the same object. - Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = "") { - assert(LHS->getType() == RHS->getType() && - "Pointer subtraction operand types must match!"); - auto *ArgType = cast(LHS->getType()); - Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); - Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); - Value *Difference = CreateSub(LHS_int, RHS_int); - return CreateExactSDiv(Difference, - ConstantExpr::getSizeOf(ArgType->getElementType()), - Name); - } + Value *CreatePtrDiff(Value *LHS, Value *RHS, const Twine &Name = ""); /// Create a launder.invariant.group intrinsic call. If Ptr type is /// different from pointer to i8, it's casted to pointer to i8 in the same /// address space before call and casted back to Ptr type after call. - Value *CreateLaunderInvariantGroup(Value *Ptr) { - assert(isa(Ptr->getType()) && - "launder.invariant.group only applies to pointers."); - // FIXME: we could potentially avoid casts to/from i8*. - auto *PtrType = Ptr->getType(); - auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); - if (PtrType != Int8PtrTy) - Ptr = CreateBitCast(Ptr, Int8PtrTy); - Module *M = BB->getParent()->getParent(); - Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration( - M, Intrinsic::launder_invariant_group, {Int8PtrTy}); - - assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy && - FnLaunderInvariantGroup->getFunctionType()->getParamType(0) == - Int8PtrTy && - "LaunderInvariantGroup should take and return the same type"); - - CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr}); - - if (PtrType != Int8PtrTy) - return CreateBitCast(Fn, PtrType); - return Fn; - } + Value *CreateLaunderInvariantGroup(Value *Ptr); /// \brief Create a strip.invariant.group intrinsic call. If Ptr type is /// different from pointer to i8, it's casted to pointer to i8 in the same /// address space before call and casted back to Ptr type after call. - Value *CreateStripInvariantGroup(Value *Ptr) { - assert(isa(Ptr->getType()) && - "strip.invariant.group only applies to pointers."); - - // FIXME: we could potentially avoid casts to/from i8*. - auto *PtrType = Ptr->getType(); - auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); - if (PtrType != Int8PtrTy) - Ptr = CreateBitCast(Ptr, Int8PtrTy); - Module *M = BB->getParent()->getParent(); - Function *FnStripInvariantGroup = Intrinsic::getDeclaration( - M, Intrinsic::strip_invariant_group, {Int8PtrTy}); - - assert(FnStripInvariantGroup->getReturnType() == Int8PtrTy && - FnStripInvariantGroup->getFunctionType()->getParamType(0) == - Int8PtrTy && - "StripInvariantGroup should take and return the same type"); - - CallInst *Fn = CreateCall(FnStripInvariantGroup, {Ptr}); - - if (PtrType != Int8PtrTy) - return CreateBitCast(Fn, PtrType); - return Fn; - } + Value *CreateStripInvariantGroup(Value *Ptr); /// Return a vector value that contains \arg V broadcasted to \p /// NumElts elements. - Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") { - assert(NumElts > 0 && "Cannot splat to an empty vector!"); - - // First insert it into an undef vector so we can shuffle it. - Type *I32Ty = getInt32Ty(); - Value *Undef = UndefValue::get(VectorType::get(V->getType(), NumElts)); - V = CreateInsertElement(Undef, V, ConstantInt::get(I32Ty, 0), - Name + ".splatinsert"); - - // Shuffle the value across the desired number of elements. - Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); - return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); - } + Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = ""); /// Return a value that has been extracted from a larger integer type. Value *CreateExtractInteger(const DataLayout &DL, Value *From, IntegerType *ExtractedTy, uint64_t Offset, - const Twine &Name) { - auto *IntTy = cast(From->getType()); - assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= - DL.getTypeStoreSize(IntTy) && - "Element extends past full value"); - uint64_t ShAmt = 8 * Offset; - Value *V = From; - if (DL.isBigEndian()) - ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - - DL.getTypeStoreSize(ExtractedTy) - Offset); - if (ShAmt) { - V = CreateLShr(V, ShAmt, Name + ".shift"); - } - assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && - "Cannot extract to a larger integer!"); - if (ExtractedTy != IntTy) { - V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); - } - return V; - } + const Twine &Name); Value *CreatePreserveArrayAccessIndex(Type *ElTy, Value *Base, unsigned Dimension, unsigned LastIndex, - MDNode *DbgInfo) { - assert(isa(Base->getType()) && - "Invalid Base ptr type for preserve.array.access.index."); - auto *BaseType = Base->getType(); - - Value *LastIndexV = getInt32(LastIndex); - Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - SmallVector IdxList; - for (unsigned I = 0; I < Dimension; ++I) - IdxList.push_back(Zero); - IdxList.push_back(LastIndexV); - - Type *ResultType = - GetElementPtrInst::getGEPReturnType(ElTy, Base, IdxList); - - Module *M = BB->getParent()->getParent(); - Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( - M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); - - Value *DimV = getInt32(Dimension); - CallInst *Fn = - CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); - if (DbgInfo) - Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); - - return Fn; - } + MDNode *DbgInfo); Value *CreatePreserveUnionAccessIndex(Value *Base, unsigned FieldIndex, - MDNode *DbgInfo) { - assert(isa(Base->getType()) && - "Invalid Base ptr type for preserve.union.access.index."); - auto *BaseType = Base->getType(); - - Module *M = BB->getParent()->getParent(); - Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration( - M, Intrinsic::preserve_union_access_index, {BaseType, BaseType}); - - Value *DIIndex = getInt32(FieldIndex); - CallInst *Fn = - CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); - if (DbgInfo) - Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); - - return Fn; - } + MDNode *DbgInfo); Value *CreatePreserveStructAccessIndex(Type *ElTy, Value *Base, unsigned Index, unsigned FieldIndex, - MDNode *DbgInfo) { - assert(isa(Base->getType()) && - "Invalid Base ptr type for preserve.struct.access.index."); - auto *BaseType = Base->getType(); - - Value *GEPIndex = getInt32(Index); - Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); - Type *ResultType = - GetElementPtrInst::getGEPReturnType(ElTy, Base, {Zero, GEPIndex}); - - Module *M = BB->getParent()->getParent(); - Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration( - M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType}); - - Value *DIIndex = getInt32(FieldIndex); - CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, - {Base, GEPIndex, DIIndex}); - if (DbgInfo) - Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); - - return Fn; - } + MDNode *DbgInfo); private: /// Helper function that creates an assume intrinsic call that @@ -2841,30 +2578,7 @@ CallInst *CreateAlignmentAssumptionHelper(const DataLayout &DL, Value *PtrValue, Value *Mask, Type *IntPtrTy, Value *OffsetValue, - Value **TheCheck) { - Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); - - if (OffsetValue) { - bool IsOffsetZero = false; - if (const auto *CI = dyn_cast(OffsetValue)) - IsOffsetZero = CI->isZero(); - - if (!IsOffsetZero) { - if (OffsetValue->getType() != IntPtrTy) - OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, - "offsetcast"); - PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); - } - } - - Value *Zero = ConstantInt::get(IntPtrTy, 0); - Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); - Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); - if (TheCheck) - *TheCheck = InvCond; - - return CreateAssumption(InvCond); - } + Value **TheCheck); public: /// Create an assume intrinsic call that represents an alignment @@ -2879,17 +2593,7 @@ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, unsigned Alignment, Value *OffsetValue = nullptr, - Value **TheCheck = nullptr) { - assert(isa(PtrValue->getType()) && - "trying to create an alignment assumption on a non-pointer?"); - assert(Alignment != 0 && "Invalid Alignment"); - auto *PtrTy = cast(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - - Value *Mask = ConstantInt::get(IntPtrTy, Alignment - 1); - return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, - OffsetValue, TheCheck); - } + Value **TheCheck = nullptr); /// Create an assume intrinsic call that represents an alignment /// assumption on the provided pointer. @@ -2906,21 +2610,7 @@ CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, Value *Alignment, Value *OffsetValue = nullptr, - Value **TheCheck = nullptr) { - assert(isa(PtrValue->getType()) && - "trying to create an alignment assumption on a non-pointer?"); - auto *PtrTy = cast(PtrValue->getType()); - Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); - - if (Alignment->getType() != IntPtrTy) - Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ false, - "alignmentcast"); - - Value *Mask = CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "mask"); - - return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, - OffsetValue, TheCheck); - } + Value **TheCheck = nullptr); }; /// This provides a uniform API for creating instructions and inserting diff --git a/llvm/lib/IR/IRBuilder.cpp b/llvm/lib/IR/IRBuilder.cpp --- a/llvm/lib/IR/IRBuilder.cpp +++ b/llvm/lib/IR/IRBuilder.cpp @@ -767,6 +767,382 @@ return createCallHelper(Fn, Args, this, Name, FMFSource); } +CallInst *IRBuilderBase::CreateConstrainedFPBinOp( + Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource, + const Twine &Name, MDNode *FPMathTag, + Optional Rounding, + Optional Except) { + Value *RoundingV = getConstrainedFPRounding(Rounding); + Value *ExceptV = getConstrainedFPExcept(Except); + + FastMathFlags UseFMF = FMF; + if (FMFSource) + UseFMF = FMFSource->getFastMathFlags(); + + CallInst *C = CreateIntrinsic(ID, {L->getType()}, + {L, R, RoundingV, ExceptV}, nullptr, Name); + setConstrainedFPCallAttr(C); + setFPAttrs(C, FPMathTag, UseFMF); + return C; +} + +Value *IRBuilderBase::CreateNAryOp(unsigned Opc, ArrayRef Ops, + const Twine &Name, MDNode *FPMathTag) { + if (Instruction::isBinaryOp(Opc)) { + assert(Ops.size() == 2 && "Invalid number of operands!"); + return CreateBinOp(static_cast(Opc), + Ops[0], Ops[1], Name, FPMathTag); + } + if (Instruction::isUnaryOp(Opc)) { + assert(Ops.size() == 1 && "Invalid number of operands!"); + return CreateUnOp(static_cast(Opc), + Ops[0], Name, FPMathTag); + } + llvm_unreachable("Unexpected opcode!"); +} + +CallInst *IRBuilderBase::CreateConstrainedFPCast( + Intrinsic::ID ID, Value *V, Type *DestTy, + Instruction *FMFSource, const Twine &Name, MDNode *FPMathTag, + Optional Rounding, + Optional Except) { + Value *ExceptV = getConstrainedFPExcept(Except); + + FastMathFlags UseFMF = FMF; + if (FMFSource) + UseFMF = FMFSource->getFastMathFlags(); + + CallInst *C; + bool HasRoundingMD = false; + switch (ID) { + default: + break; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ + case Intrinsic::INTRINSIC: \ + HasRoundingMD = ROUND_MODE; \ + break; +#include "llvm/IR/ConstrainedOps.def" + } + if (HasRoundingMD) { + Value *RoundingV = getConstrainedFPRounding(Rounding); + C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, RoundingV, ExceptV}, + nullptr, Name); + } else + C = CreateIntrinsic(ID, {DestTy, V->getType()}, {V, ExceptV}, nullptr, + Name); + + setConstrainedFPCallAttr(C); + + if (isa(C)) + setFPAttrs(C, FPMathTag, UseFMF); + return C; +} + +Value *IRBuilderBase::CreateFCmpHelper( + CmpInst::Predicate P, Value *LHS, Value *RHS, const Twine &Name, + MDNode *FPMathTag, bool IsSignaling) { + if (IsFPConstrained) { + auto ID = IsSignaling ? Intrinsic::experimental_constrained_fcmps + : Intrinsic::experimental_constrained_fcmp; + return CreateConstrainedFPCmp(ID, P, LHS, RHS, Name); + } + + if (auto *LC = dyn_cast(LHS)) + if (auto *RC = dyn_cast(RHS)) + return Insert(Folder.CreateFCmp(P, LC, RC), Name); + return Insert(setFPAttrs(new FCmpInst(P, LHS, RHS), FPMathTag, FMF), Name); +} + +CallInst *IRBuilderBase::CreateConstrainedFPCmp( + Intrinsic::ID ID, CmpInst::Predicate P, Value *L, Value *R, + const Twine &Name, Optional Except) { + Value *PredicateV = getConstrainedFPPredicate(P); + Value *ExceptV = getConstrainedFPExcept(Except); + + CallInst *C = CreateIntrinsic(ID, {L->getType()}, + {L, R, PredicateV, ExceptV}, nullptr, Name); + setConstrainedFPCallAttr(C); + return C; +} + +CallInst *IRBuilderBase::CreateConstrainedFPCall( + Function *Callee, ArrayRef Args, const Twine &Name, + Optional Rounding, + Optional Except) { + llvm::SmallVector UseArgs; + + for (auto *OneArg : Args) + UseArgs.push_back(OneArg); + bool HasRoundingMD = false; + switch (Callee->getIntrinsicID()) { + default: + break; +#define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ + case Intrinsic::INTRINSIC: \ + HasRoundingMD = ROUND_MODE; \ + break; +#include "llvm/IR/ConstrainedOps.def" + } + if (HasRoundingMD) + UseArgs.push_back(getConstrainedFPRounding(Rounding)); + UseArgs.push_back(getConstrainedFPExcept(Except)); + + CallInst *C = CreateCall(Callee, UseArgs, Name); + setConstrainedFPCallAttr(C); + return C; +} + +Value *IRBuilderBase::CreateSelect(Value *C, Value *True, Value *False, + const Twine &Name, Instruction *MDFrom) { + if (auto *CC = dyn_cast(C)) + if (auto *TC = dyn_cast(True)) + if (auto *FC = dyn_cast(False)) + return Insert(Folder.CreateSelect(CC, TC, FC), Name); + + SelectInst *Sel = SelectInst::Create(C, True, False); + if (MDFrom) { + MDNode *Prof = MDFrom->getMetadata(LLVMContext::MD_prof); + MDNode *Unpred = MDFrom->getMetadata(LLVMContext::MD_unpredictable); + Sel = addBranchMetadata(Sel, Prof, Unpred); + } + if (isa(Sel)) + setFPAttrs(Sel, nullptr /* MDNode* */, FMF); + return Insert(Sel, Name); +} + +Value *IRBuilderBase::CreatePtrDiff(Value *LHS, Value *RHS, + const Twine &Name) { + assert(LHS->getType() == RHS->getType() && + "Pointer subtraction operand types must match!"); + auto *ArgType = cast(LHS->getType()); + Value *LHS_int = CreatePtrToInt(LHS, Type::getInt64Ty(Context)); + Value *RHS_int = CreatePtrToInt(RHS, Type::getInt64Ty(Context)); + Value *Difference = CreateSub(LHS_int, RHS_int); + return CreateExactSDiv(Difference, + ConstantExpr::getSizeOf(ArgType->getElementType()), + Name); +} + +Value *IRBuilderBase::CreateLaunderInvariantGroup(Value *Ptr) { + assert(isa(Ptr->getType()) && + "launder.invariant.group only applies to pointers."); + // FIXME: we could potentially avoid casts to/from i8*. + auto *PtrType = Ptr->getType(); + auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); + if (PtrType != Int8PtrTy) + Ptr = CreateBitCast(Ptr, Int8PtrTy); + Module *M = BB->getParent()->getParent(); + Function *FnLaunderInvariantGroup = Intrinsic::getDeclaration( + M, Intrinsic::launder_invariant_group, {Int8PtrTy}); + + assert(FnLaunderInvariantGroup->getReturnType() == Int8PtrTy && + FnLaunderInvariantGroup->getFunctionType()->getParamType(0) == + Int8PtrTy && + "LaunderInvariantGroup should take and return the same type"); + + CallInst *Fn = CreateCall(FnLaunderInvariantGroup, {Ptr}); + + if (PtrType != Int8PtrTy) + return CreateBitCast(Fn, PtrType); + return Fn; +} + +Value *IRBuilderBase::CreateStripInvariantGroup(Value *Ptr) { + assert(isa(Ptr->getType()) && + "strip.invariant.group only applies to pointers."); + + // FIXME: we could potentially avoid casts to/from i8*. + auto *PtrType = Ptr->getType(); + auto *Int8PtrTy = getInt8PtrTy(PtrType->getPointerAddressSpace()); + if (PtrType != Int8PtrTy) + Ptr = CreateBitCast(Ptr, Int8PtrTy); + Module *M = BB->getParent()->getParent(); + Function *FnStripInvariantGroup = Intrinsic::getDeclaration( + M, Intrinsic::strip_invariant_group, {Int8PtrTy}); + + assert(FnStripInvariantGroup->getReturnType() == Int8PtrTy && + FnStripInvariantGroup->getFunctionType()->getParamType(0) == + Int8PtrTy && + "StripInvariantGroup should take and return the same type"); + + CallInst *Fn = CreateCall(FnStripInvariantGroup, {Ptr}); + + if (PtrType != Int8PtrTy) + return CreateBitCast(Fn, PtrType); + return Fn; +} + +Value *IRBuilderBase::CreateVectorSplat(unsigned NumElts, Value *V, + const Twine &Name) { + assert(NumElts > 0 && "Cannot splat to an empty vector!"); + + // First insert it into an undef vector so we can shuffle it. + Type *I32Ty = getInt32Ty(); + Value *Undef = UndefValue::get(VectorType::get(V->getType(), NumElts)); + V = CreateInsertElement(Undef, V, ConstantInt::get(I32Ty, 0), + Name + ".splatinsert"); + + // Shuffle the value across the desired number of elements. + Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts)); + return CreateShuffleVector(V, Undef, Zeros, Name + ".splat"); +} + +Value *IRBuilderBase::CreateExtractInteger( + const DataLayout &DL, Value *From, IntegerType *ExtractedTy, + uint64_t Offset, const Twine &Name) { + auto *IntTy = cast(From->getType()); + assert(DL.getTypeStoreSize(ExtractedTy) + Offset <= + DL.getTypeStoreSize(IntTy) && + "Element extends past full value"); + uint64_t ShAmt = 8 * Offset; + Value *V = From; + if (DL.isBigEndian()) + ShAmt = 8 * (DL.getTypeStoreSize(IntTy) - + DL.getTypeStoreSize(ExtractedTy) - Offset); + if (ShAmt) { + V = CreateLShr(V, ShAmt, Name + ".shift"); + } + assert(ExtractedTy->getBitWidth() <= IntTy->getBitWidth() && + "Cannot extract to a larger integer!"); + if (ExtractedTy != IntTy) { + V = CreateTrunc(V, ExtractedTy, Name + ".trunc"); + } + return V; +} + +Value *IRBuilderBase::CreatePreserveArrayAccessIndex( + Type *ElTy, Value *Base, unsigned Dimension, unsigned LastIndex, + MDNode *DbgInfo) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.array.access.index."); + auto *BaseType = Base->getType(); + + Value *LastIndexV = getInt32(LastIndex); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + SmallVector IdxList; + for (unsigned I = 0; I < Dimension; ++I) + IdxList.push_back(Zero); + IdxList.push_back(LastIndexV); + + Type *ResultType = + GetElementPtrInst::getGEPReturnType(ElTy, Base, IdxList); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveArrayAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_array_access_index, {ResultType, BaseType}); + + Value *DimV = getInt32(Dimension); + CallInst *Fn = + CreateCall(FnPreserveArrayAccessIndex, {Base, DimV, LastIndexV}); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; +} + +Value *IRBuilderBase::CreatePreserveUnionAccessIndex( + Value *Base, unsigned FieldIndex, MDNode *DbgInfo) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.union.access.index."); + auto *BaseType = Base->getType(); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveUnionAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_union_access_index, {BaseType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = + CreateCall(FnPreserveUnionAccessIndex, {Base, DIIndex}); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; +} + +Value *IRBuilderBase::CreatePreserveStructAccessIndex( + Type *ElTy, Value *Base, unsigned Index, unsigned FieldIndex, + MDNode *DbgInfo) { + assert(isa(Base->getType()) && + "Invalid Base ptr type for preserve.struct.access.index."); + auto *BaseType = Base->getType(); + + Value *GEPIndex = getInt32(Index); + Constant *Zero = ConstantInt::get(Type::getInt32Ty(Context), 0); + Type *ResultType = + GetElementPtrInst::getGEPReturnType(ElTy, Base, {Zero, GEPIndex}); + + Module *M = BB->getParent()->getParent(); + Function *FnPreserveStructAccessIndex = Intrinsic::getDeclaration( + M, Intrinsic::preserve_struct_access_index, {ResultType, BaseType}); + + Value *DIIndex = getInt32(FieldIndex); + CallInst *Fn = CreateCall(FnPreserveStructAccessIndex, + {Base, GEPIndex, DIIndex}); + if (DbgInfo) + Fn->setMetadata(LLVMContext::MD_preserve_access_index, DbgInfo); + + return Fn; +} + +CallInst *IRBuilderBase::CreateAlignmentAssumptionHelper( + const DataLayout &DL, Value *PtrValue, Value *Mask, Type *IntPtrTy, + Value *OffsetValue, Value **TheCheck) { + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + if (OffsetValue) { + bool IsOffsetZero = false; + if (const auto *CI = dyn_cast(OffsetValue)) + IsOffsetZero = CI->isZero(); + + if (!IsOffsetZero) { + if (OffsetValue->getType() != IntPtrTy) + OffsetValue = CreateIntCast(OffsetValue, IntPtrTy, /*isSigned*/ true, + "offsetcast"); + PtrIntValue = CreateSub(PtrIntValue, OffsetValue, "offsetptr"); + } + } + + Value *Zero = ConstantInt::get(IntPtrTy, 0); + Value *MaskedPtr = CreateAnd(PtrIntValue, Mask, "maskedptr"); + Value *InvCond = CreateICmpEQ(MaskedPtr, Zero, "maskcond"); + if (TheCheck) + *TheCheck = InvCond; + + return CreateAssumption(InvCond); +} + +CallInst *IRBuilderBase::CreateAlignmentAssumption( + const DataLayout &DL, Value *PtrValue, unsigned Alignment, + Value *OffsetValue, Value **TheCheck) { + assert(isa(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + assert(Alignment != 0 && "Invalid Alignment"); + auto *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); + + Value *Mask = ConstantInt::get(IntPtrTy, Alignment - 1); + return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, + OffsetValue, TheCheck); +} + +CallInst *IRBuilderBase::CreateAlignmentAssumption( + const DataLayout &DL, Value *PtrValue, Value *Alignment, + Value *OffsetValue, Value **TheCheck) { + assert(isa(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + auto *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(DL, PtrTy->getAddressSpace()); + + if (Alignment->getType() != IntPtrTy) + Alignment = CreateIntCast(Alignment, IntPtrTy, /*isSigned*/ false, + "alignmentcast"); + + Value *Mask = CreateSub(Alignment, ConstantInt::get(IntPtrTy, 1), "mask"); + + return CreateAlignmentAssumptionHelper(DL, PtrValue, Mask, IntPtrTy, + OffsetValue, TheCheck); +} + IRBuilderDefaultInserter::~IRBuilderDefaultInserter() {} IRBuilderCallbackInserter::~IRBuilderCallbackInserter() {} IRBuilderFolder::~IRBuilderFolder() {}