diff options
Diffstat (limited to 'lib/IR/IRBuilder.cpp')
-rw-r--r-- | lib/IR/IRBuilder.cpp | 224 |
1 files changed, 175 insertions, 49 deletions
diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 027c0255bcec..405a56bfb31d 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -1,4 +1,4 @@ -//===---- IRBuilder.cpp - Builder for LLVM Instrs -------------------------===// +//===- IRBuilder.cpp - Builder for LLVM Instrs ----------------------------===// // // The LLVM Compiler Infrastructure // @@ -13,11 +13,27 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/IRBuilder.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/None.h" +#include "llvm/IR/Constant.h" +#include "llvm/IR/Constants.h" +#include "llvm/IR/DerivedTypes.h" #include "llvm/IR/Function.h" +#include "llvm/IR/GlobalValue.h" #include "llvm/IR/GlobalVariable.h" +#include "llvm/IR/IntrinsicInst.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Operator.h" #include "llvm/IR/Statepoint.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" +#include "llvm/Support/Casting.h" +#include "llvm/Support/MathExtras.h" +#include <cassert> +#include <cstdint> +#include <vector> + using namespace llvm; /// CreateGlobalString - Make a new global variable with an initializer that @@ -29,11 +45,10 @@ GlobalVariable *IRBuilderBase::CreateGlobalString(StringRef Str, unsigned AddressSpace) { Constant *StrConstant = ConstantDataArray::getString(Context, Str); Module &M = *BB->getParent()->getParent(); - GlobalVariable *GV = new GlobalVariable(M, StrConstant->getType(), - true, GlobalValue::PrivateLinkage, - StrConstant, Name, nullptr, - GlobalVariable::NotThreadLocal, - AddressSpace); + auto *GV = new GlobalVariable(M, StrConstant->getType(), true, + GlobalValue::PrivateLinkage, StrConstant, Name, + nullptr, GlobalVariable::NotThreadLocal, + AddressSpace); GV->setUnnamedAddr(GlobalValue::UnnamedAddr::Global); return GV; } @@ -44,10 +59,10 @@ Type *IRBuilderBase::getCurrentFunctionReturnType() const { } Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { - PointerType *PT = cast<PointerType>(Ptr->getType()); + auto *PT = cast<PointerType>(Ptr->getType()); if (PT->getElementType()->isIntegerTy(8)) return Ptr; - + // Otherwise, we need to insert a bitcast. PT = getInt8PtrTy(PT->getAddressSpace()); BitCastInst *BCI = new BitCastInst(Ptr, PT, ""); @@ -58,11 +73,14 @@ Value *IRBuilderBase::getCastedInt8PtrValue(Value *Ptr) { static CallInst *createCallHelper(Value *Callee, ArrayRef<Value *> Ops, IRBuilderBase *Builder, - const Twine& Name="") { + const Twine &Name = "", + Instruction *FMFSource = nullptr) { CallInst *CI = CallInst::Create(Callee, Ops, Name); + if (FMFSource) + CI->copyFastMathFlags(FMFSource); Builder->GetInsertBlock()->getInstList().insert(Builder->GetInsertPoint(),CI); Builder->SetInstDebugLocation(CI); - return CI; + return CI; } static InvokeInst *createInvokeHelper(Value *Invokee, BasicBlock *NormalDest, @@ -83,40 +101,81 @@ CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align, bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) { Ptr = getCastedInt8PtrValue(Ptr); - Value *Ops[] = { Ptr, Val, Size, getInt32(Align), getInt1(isVolatile) }; + Value *Ops[] = {Ptr, Val, Size, getInt1(isVolatile)}; Type *Tys[] = { Ptr->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memset, Tys); - + + CallInst *CI = createCallHelper(TheFn, Ops, this); + + if (Align > 0) + cast<MemSetInst>(CI)->setDestAlignment(Align); + + // Set the TBAA info if present. + if (TBAATag) + CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + + return CI; +} + +CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemSet( + Value *Ptr, Value *Val, Value *Size, unsigned Align, uint32_t ElementSize, + MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) { + assert(Align >= ElementSize && + "Pointer alignment must be at least element size."); + + Ptr = getCastedInt8PtrValue(Ptr); + Value *Ops[] = {Ptr, Val, Size, getInt32(ElementSize)}; + Type *Tys[] = {Ptr->getType(), Size->getType()}; + Module *M = BB->getParent()->getParent(); + Value *TheFn = Intrinsic::getDeclaration( + M, Intrinsic::memset_element_unordered_atomic, Tys); + CallInst *CI = createCallHelper(TheFn, Ops, this); - + + cast<AtomicMemSetInst>(CI)->setDestAlignment(Align); + // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); if (ScopeTag) CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); - + if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); - + return CI; } CallInst *IRBuilderBase:: -CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag, MDNode *TBAAStructTag, - MDNode *ScopeTag, MDNode *NoAliasTag) { +CreateMemCpy(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, + Value *Size, bool isVolatile, MDNode *TBAATag, + MDNode *TBAAStructTag, MDNode *ScopeTag, MDNode *NoAliasTag) { + assert((DstAlign == 0 || isPowerOf2_32(DstAlign)) && "Must be 0 or a power of 2"); + assert((SrcAlign == 0 || isPowerOf2_32(SrcAlign)) && "Must be 0 or a power of 2"); Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); - Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) }; + Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memcpy, Tys); - + CallInst *CI = createCallHelper(TheFn, Ops, this); - + + auto* MCI = cast<MemCpyInst>(CI); + if (DstAlign > 0) + MCI->setDestAlignment(DstAlign); + if (SrcAlign > 0) + MCI->setSourceAlignment(SrcAlign); + // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); @@ -124,14 +183,14 @@ CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align, // Set the TBAA Struct info if present. if (TBAAStructTag) CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); - + if (ScopeTag) CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); - + if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); - - return CI; + + return CI; } CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( @@ -154,8 +213,9 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( CallInst *CI = createCallHelper(TheFn, Ops, this); // Set the alignment of the pointer args. - CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign)); - CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign)); + auto *AMCI = cast<AtomicMemCpyInst>(CI); + AMCI->setDestAlignment(DstAlign); + AMCI->setSourceAlignment(SrcAlign); // Set the TBAA info if present. if (TBAATag) @@ -175,30 +235,78 @@ CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemCpy( } CallInst *IRBuilderBase:: -CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align, - bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, +CreateMemMove(Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, + Value *Size, bool isVolatile, MDNode *TBAATag, MDNode *ScopeTag, MDNode *NoAliasTag) { + assert((DstAlign == 0 || isPowerOf2_32(DstAlign)) && "Must be 0 or a power of 2"); + assert((SrcAlign == 0 || isPowerOf2_32(SrcAlign)) && "Must be 0 or a power of 2"); Dst = getCastedInt8PtrValue(Dst); Src = getCastedInt8PtrValue(Src); - - Value *Ops[] = { Dst, Src, Size, getInt32(Align), getInt1(isVolatile) }; + + Value *Ops[] = {Dst, Src, Size, getInt1(isVolatile)}; Type *Tys[] = { Dst->getType(), Src->getType(), Size->getType() }; Module *M = BB->getParent()->getParent(); Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::memmove, Tys); - + CallInst *CI = createCallHelper(TheFn, Ops, this); - + + auto *MMI = cast<MemMoveInst>(CI); + if (DstAlign > 0) + MMI->setDestAlignment(DstAlign); + if (SrcAlign > 0) + MMI->setSourceAlignment(SrcAlign); + // Set the TBAA info if present. if (TBAATag) CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); - + if (ScopeTag) CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); - + if (NoAliasTag) CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); - - return CI; + + return CI; +} + +CallInst *IRBuilderBase::CreateElementUnorderedAtomicMemMove( + Value *Dst, unsigned DstAlign, Value *Src, unsigned SrcAlign, Value *Size, + uint32_t ElementSize, MDNode *TBAATag, MDNode *TBAAStructTag, + MDNode *ScopeTag, MDNode *NoAliasTag) { + assert(DstAlign >= ElementSize && + "Pointer alignment must be at least element size"); + assert(SrcAlign >= ElementSize && + "Pointer alignment must be at least element size"); + Dst = getCastedInt8PtrValue(Dst); + Src = getCastedInt8PtrValue(Src); + + Value *Ops[] = {Dst, Src, Size, getInt32(ElementSize)}; + Type *Tys[] = {Dst->getType(), Src->getType(), Size->getType()}; + Module *M = BB->getParent()->getParent(); + Value *TheFn = Intrinsic::getDeclaration( + M, Intrinsic::memmove_element_unordered_atomic, Tys); + + CallInst *CI = createCallHelper(TheFn, Ops, this); + + // Set the alignment of the pointer args. + CI->addParamAttr(0, Attribute::getWithAlignment(CI->getContext(), DstAlign)); + CI->addParamAttr(1, Attribute::getWithAlignment(CI->getContext(), SrcAlign)); + + // Set the TBAA info if present. + if (TBAATag) + CI->setMetadata(LLVMContext::MD_tbaa, TBAATag); + + // Set the TBAA Struct info if present. + if (TBAAStructTag) + CI->setMetadata(LLVMContext::MD_tbaa_struct, TBAAStructTag); + + if (ScopeTag) + CI->setMetadata(LLVMContext::MD_alias_scope, ScopeTag); + + if (NoAliasTag) + CI->setMetadata(LLVMContext::MD_noalias, NoAliasTag); + + return CI; } static CallInst *getReductionIntrinsic(IRBuilderBase *Builder, Intrinsic::ID ID, @@ -351,7 +459,7 @@ CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { return createCallHelper(FnAssume, Ops, this); } -/// \brief Create a call to a Masked Load intrinsic. +/// Create a call to a Masked Load intrinsic. /// \p Ptr - base pointer for the load /// \p Align - alignment of the source location /// \p Mask - vector of booleans which indicates what vector lanes should @@ -362,7 +470,7 @@ CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask, Value *PassThru, const Twine &Name) { - PointerType *PtrTy = cast<PointerType>(Ptr->getType()); + auto *PtrTy = cast<PointerType>(Ptr->getType()); Type *DataTy = PtrTy->getElementType(); assert(DataTy->isVectorTy() && "Ptr should point to a vector"); assert(Mask && "Mask should not be all-ones (null)"); @@ -374,7 +482,7 @@ CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align, OverloadedTypes, Name); } -/// \brief Create a call to a Masked Store intrinsic. +/// Create a call to a Masked Store intrinsic. /// \p Val - data to be stored, /// \p Ptr - base pointer for the store /// \p Align - alignment of the destination location @@ -382,7 +490,7 @@ CallInst *IRBuilderBase::CreateMaskedLoad(Value *Ptr, unsigned Align, /// be accessed in memory CallInst *IRBuilderBase::CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align, Value *Mask) { - PointerType *PtrTy = cast<PointerType>(Ptr->getType()); + auto *PtrTy = cast<PointerType>(Ptr->getType()); Type *DataTy = PtrTy->getElementType(); assert(DataTy->isVectorTy() && "Ptr should point to a vector"); assert(Mask && "Mask should not be all-ones (null)"); @@ -403,7 +511,7 @@ CallInst *IRBuilderBase::CreateMaskedIntrinsic(Intrinsic::ID Id, return createCallHelper(TheFn, Ops, this, Name); } -/// \brief Create a call to a Masked Gather intrinsic. +/// Create a call to a Masked Gather intrinsic. /// \p Ptrs - vector of pointers for loading /// \p Align - alignment for one element /// \p Mask - vector of booleans which indicates what vector lanes should @@ -435,7 +543,7 @@ CallInst *IRBuilderBase::CreateMaskedGather(Value *Ptrs, unsigned Align, Name); } -/// \brief Create a call to a Masked Scatter intrinsic. +/// Create a call to a Masked Scatter intrinsic. /// \p Data - data to be stored, /// \p Ptrs - the vector of pointers, where the \p Data elements should be /// stored @@ -496,7 +604,7 @@ static CallInst *CreateGCStatepointCallCommon( ArrayRef<T1> TransitionArgs, ArrayRef<T2> DeoptArgs, ArrayRef<T3> GCArgs, const Twine &Name) { // Extract out the type of the callee. - PointerType *FuncPtrType = cast<PointerType>(ActualCallee->getType()); + auto *FuncPtrType = cast<PointerType>(ActualCallee->getType()); assert(isa<FunctionType>(FuncPtrType->getElementType()) && "actual callee must be a callable value"); @@ -507,7 +615,7 @@ static CallInst *CreateGCStatepointCallCommon( Intrinsic::getDeclaration(M, Intrinsic::experimental_gc_statepoint, ArgTypes); - std::vector<llvm::Value *> Args = + std::vector<Value *> Args = getStatepointArgs(*Builder, ID, NumPatchBytes, ActualCallee, Flags, CallArgs, TransitionArgs, DeoptArgs, GCArgs); return createCallHelper(FnStatepoint, Args, Builder, Name); @@ -547,7 +655,7 @@ static InvokeInst *CreateGCStatepointInvokeCommon( uint32_t Flags, ArrayRef<T0> InvokeArgs, ArrayRef<T1> TransitionArgs, ArrayRef<T2> DeoptArgs, ArrayRef<T3> GCArgs, const Twine &Name) { // Extract out the type of the callee. - PointerType *FuncPtrType = cast<PointerType>(ActualInvokee->getType()); + auto *FuncPtrType = cast<PointerType>(ActualInvokee->getType()); assert(isa<FunctionType>(FuncPtrType->getElementType()) && "actual callee must be a callable value"); @@ -556,7 +664,7 @@ static InvokeInst *CreateGCStatepointInvokeCommon( Function *FnStatepoint = Intrinsic::getDeclaration( M, Intrinsic::experimental_gc_statepoint, {FuncPtrType}); - std::vector<llvm::Value *> Args = + std::vector<Value *> Args = getStatepointArgs(*Builder, ID, NumPatchBytes, ActualInvokee, Flags, InvokeArgs, TransitionArgs, DeoptArgs, GCArgs); return createInvokeHelper(FnStatepoint, NormalDest, UnwindDest, Args, Builder, @@ -625,7 +733,25 @@ CallInst *IRBuilderBase::CreateGCRelocate(Instruction *Statepoint, CallInst *IRBuilderBase::CreateBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, const Twine &Name) { - Module *M = BB->getParent()->getParent(); - Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() }); + Module *M = BB->getModule(); + Function *Fn = Intrinsic::getDeclaration(M, ID, { LHS->getType() }); return createCallHelper(Fn, { LHS, RHS }, this, Name); } + +CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID, + Instruction *FMFSource, + const Twine &Name) { + Module *M = BB->getModule(); + Function *Fn = Intrinsic::getDeclaration(M, ID); + return createCallHelper(Fn, {}, this, Name); +} + +CallInst *IRBuilderBase::CreateIntrinsic(Intrinsic::ID ID, + ArrayRef<Value *> Args, + Instruction *FMFSource, + const Twine &Name) { + assert(!Args.empty() && "Expected at least one argument to intrinsic"); + Module *M = BB->getModule(); + Function *Fn = Intrinsic::getDeclaration(M, ID, { Args.front()->getType() }); + return createCallHelper(Fn, Args, this, Name, FMFSource); +} |