Index: include/llvm/IR/IRBuilder.h =================================================================== --- include/llvm/IR/IRBuilder.h +++ include/llvm/IR/IRBuilder.h @@ -550,6 +550,9 @@ /// assume that the provided condition will be true. CallInst *CreateAssumption(Value *Cond); + /// \brief Create an noalias intrinsic. + Instruction *CreateNoAliasPointer(Value *Ptr, MDNode *ScopeTag); + /// \brief Create a call to the experimental.gc.statepoint intrinsic to /// start a new statepoint sequence. CallInst *CreateGCStatepointCall(uint64_t ID, uint32_t NumPatchBytes, Index: lib/IR/IRBuilder.cpp =================================================================== --- lib/IR/IRBuilder.cpp +++ lib/IR/IRBuilder.cpp @@ -17,6 +17,7 @@ #include "llvm/IR/GlobalVariable.h" #include "llvm/IR/Intrinsics.h" #include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Metadata.h" #include "llvm/IR/Statepoint.h" using namespace llvm; @@ -342,6 +343,32 @@ return createCallHelper(FnAssume, Ops, this); } +Instruction *IRBuilderBase::CreateNoAliasPointer(Value *Ptr, MDNode *ScopeTag) { + // FIXME: We can currently mangle just about everything, but not literal + // structs (for those, bitcast to i8*). + Value *CPtr = Ptr; + if (auto *STyp = + dyn_cast(CPtr->getType()->getPointerElementType())) { + if (STyp->isLiteral()) + CPtr = getCastedInt8PtrValue(CPtr); + } + + Type *Types[] = { CPtr->getType() }; + Value *Ops[] = { CPtr, MetadataAsValue::get(Context, ScopeTag) }; + Module *M = BB->getModule(); + Value *FnNoAlias = Intrinsic::getDeclaration(M, Intrinsic::noalias, Types); + Instruction *Ret = createCallHelper(FnNoAlias, Ops, this); + + if (Ret->getType() != Ptr->getType()) { + BitCastInst *BCI = new BitCastInst(Ret, Ptr->getType(), ""); + BB->getInstList().insert(InsertPt, BCI); + SetInstDebugLocation(BCI); + Ret = BCI; + } + + return Ret; +} + /// \brief Create a call to a Masked Load intrinsic. /// \p Ptr - base pointer for the load /// \p Align - alignment of the source location Index: unittests/IR/IRBuilderTest.cpp =================================================================== --- unittests/IR/IRBuilderTest.cpp +++ unittests/IR/IRBuilderTest.cpp @@ -48,6 +48,30 @@ GlobalVariable *GV; }; +TEST_F(IRBuilderTest, NoAlias) { + IRBuilder<> Builder(BB); + AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty()); + + MDBuilder MDB(BB->getContext()); + MDNode *NewDomain = + MDB.createAnonymousAliasScopeDomain("Test Domain"); + MDNode *AScope = + MDB.createAnonymousAliasScope(NewDomain, "Test Scope"); + + CallInst *NAP = cast(Builder.CreateNoAliasPointer(Var1, AScope)); + + EXPECT_EQ(NAP->getArgOperand(0), Var1); + EXPECT_EQ(cast(NAP->getArgOperand(1))->getMetadata(), + AScope); + + IntrinsicInst *II_NAP = dyn_cast(NAP); + ASSERT_TRUE(II_NAP != nullptr); + EXPECT_EQ(II_NAP->getIntrinsicID(), Intrinsic::noalias); + + EXPECT_TRUE(NAP->onlyAccessesArgMemory()); + EXPECT_TRUE(NAP->doesNotThrow()); +} + TEST_F(IRBuilderTest, Lifetime) { IRBuilder<> Builder(BB); AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty());