From 76ce614af7d36fa1134a3db6a0c46c47f1eb1a24 Mon Sep 17 00:00:00 2001 From: Hal Finkel Date: Wed, 15 Oct 2014 23:44:22 +0000 Subject: [PATCH] Add CreateAlignmentAssumption to IRBuilder Clang CodeGen had a utility function for creating pointer alignment assumptions using the @llvm.assume intrinsic. This functionality will also be needed by the inliner (to preserve function-argument alignment attributes when inlining), so this moves the utility function into IRBuilder where it can be used both by Clang CodeGen and also other LLVM-level code. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@219875 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/IRBuilder.h | 42 +++++++++++++++++++++++++++++++++++++ lib/IR/IRBuilder.cpp | 11 ++++++++++ 2 files changed, 53 insertions(+) diff --git a/include/llvm/IR/IRBuilder.h b/include/llvm/IR/IRBuilder.h index c074be8ad4a..d803bf407e6 100644 --- a/include/llvm/IR/IRBuilder.h +++ b/include/llvm/IR/IRBuilder.h @@ -429,6 +429,10 @@ public: /// If the pointer isn't i8* it will be converted. CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr); + /// \brief Create an assume intrinsic call that allows the optimizer to + /// assume that the provided condition will be true. + CallInst *CreateAssumption(Value *Cond); + private: Value *getCastedInt8PtrValue(Value *Ptr); }; @@ -1524,6 +1528,44 @@ public: } return V; } + + /// \brief Create an assume intrinsic call that represents an alignment + /// assumption on the provided pointer. + /// + /// An optional offset can be provided, and if it is provided, the offset + /// must be subtracted from the provided pointer to get the pointer with the + /// specified alignment. + CallInst *CreateAlignmentAssumption(const DataLayout &DL, Value *PtrValue, + unsigned Alignment, + Value *OffsetValue = nullptr) { + assert(isa(PtrValue->getType()) && + "trying to create an alignment assumption on a non-pointer?"); + + PointerType *PtrTy = cast(PtrValue->getType()); + Type *IntPtrTy = getIntPtrTy(&DL, PtrTy->getAddressSpace()); + Value *PtrIntValue = CreatePtrToInt(PtrValue, IntPtrTy, "ptrint"); + + Value *Mask = ConstantInt::get(IntPtrTy, + Alignment > 0 ? Alignment - 1 : 0); + if (OffsetValue) { + bool IsOffsetZero = false; + if (ConstantInt *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"); + + return CreateAssumption(InvCond); + } }; // Create wrappers for C Binding types (see CBindingWrapping.h). diff --git a/lib/IR/IRBuilder.cpp b/lib/IR/IRBuilder.cpp index 7448e50bd82..a4c5d9766a2 100644 --- a/lib/IR/IRBuilder.cpp +++ b/lib/IR/IRBuilder.cpp @@ -172,3 +172,14 @@ CallInst *IRBuilderBase::CreateLifetimeEnd(Value *Ptr, ConstantInt *Size) { Value *TheFn = Intrinsic::getDeclaration(M, Intrinsic::lifetime_end); return createCallHelper(TheFn, Ops, this); } + +CallInst *IRBuilderBase::CreateAssumption(Value *Cond) { + assert(Cond->getType() == getInt1Ty() && + "an assumption condition must be of type i1"); + + Value *Ops[] = { Cond }; + Module *M = BB->getParent()->getParent(); + Value *FnAssume = Intrinsic::getDeclaration(M, Intrinsic::assume); + return createCallHelper(FnAssume, Ops, this); +} + -- 2.40.0