#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Twine.h"
#include "llvm/IR/BasicBlock.h"
+#include "llvm/IR/ConstantFolder.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Instructions.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
+#include "llvm/IR/ValueHandle.h"
#include "llvm/Support/CBindingWrapping.h"
-#include "llvm/Support/ConstantFolder.h"
namespace llvm {
- class MDNode;
+class MDNode;
/// \brief This provides the default implementation of the IRBuilder
/// 'InsertHelper' method that is called whenever an instruction is created by
class IRBuilderBase {
DebugLoc CurDbgLocation;
protected:
- /// Save the current debug location here while we are suppressing
- /// line table entries.
- llvm::DebugLoc SavedDbgLocation;
-
BasicBlock *BB;
BasicBlock::iterator InsertPt;
LLVMContext &Context;
+
+ MDNode *DefaultFPMathTag;
+ FastMathFlags FMF;
public:
- IRBuilderBase(LLVMContext &context)
- : Context(context) {
+ IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr)
+ : Context(context), DefaultFPMathTag(FPMathTag), FMF() {
ClearInsertionPoint();
}
/// \brief Clear the insertion point: created instructions will not be
/// inserted into a block.
void ClearInsertionPoint() {
- BB = 0;
- InsertPt = 0;
+ BB = nullptr;
+ InsertPt = nullptr;
}
BasicBlock *GetInsertBlock() const { return BB; }
}
/// \brief Set location information used by debugging information.
- void SetCurrentDebugLocation(const DebugLoc &L) {
- CurDbgLocation = L;
- }
-
- /// \brief Temporarily suppress DebugLocations from being attached
- /// to emitted instructions, until the next call to
- /// SetCurrentDebugLocation() or EnableDebugLocations(). Use this
- /// if you want an instruction to be counted towards the prologue or
- /// if there is no useful source location.
- void DisableDebugLocations() {
- llvm::DebugLoc Empty;
- SavedDbgLocation = getCurrentDebugLocation();
- SetCurrentDebugLocation(Empty);
- }
-
- /// \brief Restore the previously saved DebugLocation.
- void EnableDebugLocations() {
- assert(CurDbgLocation.isUnknown());
- SetCurrentDebugLocation(SavedDbgLocation);
- }
+ void SetCurrentDebugLocation(DebugLoc L) { CurDbgLocation = std::move(L); }
/// \brief Get location information used by debugging information.
- DebugLoc getCurrentDebugLocation() const { return CurDbgLocation; }
+ const DebugLoc &getCurrentDebugLocation() const { return CurDbgLocation; }
/// \brief If this builder has a current debug location, set it on the
/// specified instruction.
public:
/// \brief Creates a new insertion point which doesn't point to anything.
- InsertPoint() : Block(0) {}
+ InsertPoint() : Block(nullptr) {}
/// \brief Creates a new insertion point at the given location.
InsertPoint(BasicBlock *InsertBlock, BasicBlock::iterator InsertPoint)
: Block(InsertBlock), Point(InsertPoint) {}
/// \brief Returns true if this insert point is set.
- bool isSet() const { return (Block != 0); }
+ bool isSet() const { return (Block != nullptr); }
llvm::BasicBlock *getBlock() const { return Block; }
llvm::BasicBlock::iterator getPoint() const { return Point; }
ClearInsertionPoint();
}
+ /// \brief Get the floating point math metadata being used.
+ MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
+
+ /// \brief Get the flags to be applied to created floating point ops
+ FastMathFlags getFastMathFlags() const { return FMF; }
+
+ /// \brief Clear the fast-math flags.
+ void clearFastMathFlags() { FMF.clear(); }
+
+ /// \brief Set the floating point math metadata to be used.
+ void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
+
+ /// \brief Set the fast-math flags to be used with generated fp-math operators
+ void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; }
+
+ //===--------------------------------------------------------------------===//
+ // RAII helpers.
+ //===--------------------------------------------------------------------===//
+
+ // \brief RAII object that stores the current insertion point and restores it
+ // when the object is destroyed. This includes the debug location.
+ class InsertPointGuard {
+ IRBuilderBase &Builder;
+ AssertingVH<BasicBlock> Block;
+ BasicBlock::iterator Point;
+ DebugLoc DbgLoc;
+
+ InsertPointGuard(const InsertPointGuard &) = delete;
+ InsertPointGuard &operator=(const InsertPointGuard &) = delete;
+
+ public:
+ InsertPointGuard(IRBuilderBase &B)
+ : Builder(B), Block(B.GetInsertBlock()), Point(B.GetInsertPoint()),
+ DbgLoc(B.getCurrentDebugLocation()) {}
+
+ ~InsertPointGuard() {
+ Builder.restoreIP(InsertPoint(Block, Point));
+ Builder.SetCurrentDebugLocation(DbgLoc);
+ }
+ };
+
+ // \brief RAII object that stores the current fast math settings and restores
+ // them when the object is destroyed.
+ class FastMathFlagGuard {
+ IRBuilderBase &Builder;
+ FastMathFlags FMF;
+ MDNode *FPMathTag;
+
+ FastMathFlagGuard(const FastMathFlagGuard &) = delete;
+ FastMathFlagGuard &operator=(
+ const FastMathFlagGuard &) = delete;
+
+ public:
+ FastMathFlagGuard(IRBuilderBase &B)
+ : Builder(B), FMF(B.FMF), FPMathTag(B.DefaultFPMathTag) {}
+
+ ~FastMathFlagGuard() {
+ Builder.FMF = FMF;
+ Builder.DefaultFPMathTag = FPMathTag;
+ }
+ };
+
//===--------------------------------------------------------------------===//
// Miscellaneous creation methods.
//===--------------------------------------------------------------------===//
return ConstantInt::get(getInt64Ty(), C);
}
+ /// \brief Get a constant N-bit value, zero extended or truncated from
+ /// a 64-bit value.
+ ConstantInt *getIntN(unsigned N, uint64_t C) {
+ return ConstantInt::get(getIntNTy(N), C);
+ }
+
/// \brief Get a constant integer value.
ConstantInt *getInt(const APInt &AI) {
return ConstantInt::get(Context, AI);
return Type::getInt64Ty(Context);
}
+ /// \brief Fetch the type representing an N-bit integer.
+ IntegerType *getIntNTy(unsigned N) {
+ return Type::getIntNTy(Context, N);
+ }
+
+ /// \brief Fetch the type representing a 16-bit floating point value.
+ Type *getHalfTy() {
+ return Type::getHalfTy(Context);
+ }
+
/// \brief Fetch the type representing a 32-bit floating point value.
Type *getFloatTy() {
return Type::getFloatTy(Context);
}
/// \brief Fetch the type representing a pointer to an integer value.
- IntegerType* getIntPtrTy(DataLayout *DL, unsigned AddrSpace = 0) {
+ IntegerType* getIntPtrTy(const DataLayout *DL, unsigned AddrSpace = 0) {
return DL->getIntPtrType(Context, AddrSpace);
}
/// \brief Create and insert a memset to the specified pointer and the
/// specified value.
///
- /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// If the pointer isn't an i8*, it will be converted. If a TBAA tag is
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemSet(Value *Ptr, Value *Val, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0) {
- return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemSet(Ptr, Val, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemSet(Value *Ptr, Value *Val, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memcpy between the specified pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemCpy(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0,
- MDNode *TBAAStructTag = 0) {
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
return CreateMemCpy(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag,
- TBAAStructTag);
+ TBAAStructTag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemCpy(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0,
- MDNode *TBAAStructTag = 0);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *TBAAStructTag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create and insert a memmove between the specified
/// pointers.
///
/// If the pointers aren't i8*, they will be converted. If a TBAA tag is
- /// specified, it will be added to the instruction.
+ /// specified, it will be added to the instruction. Likewise with alias.scope
+ /// and noalias tags.
CallInst *CreateMemMove(Value *Dst, Value *Src, uint64_t Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0) {
- return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile, TBAATag);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr) {
+ return CreateMemMove(Dst, Src, getInt64(Size), Align, isVolatile,
+ TBAATag, ScopeTag, NoAliasTag);
}
CallInst *CreateMemMove(Value *Dst, Value *Src, Value *Size, unsigned Align,
- bool isVolatile = false, MDNode *TBAATag = 0);
+ bool isVolatile = false, MDNode *TBAATag = nullptr,
+ MDNode *ScopeTag = nullptr,
+ MDNode *NoAliasTag = nullptr);
/// \brief Create a lifetime.start intrinsic.
///
/// If the pointer isn't i8* it will be converted.
- CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = 0);
+ CallInst *CreateLifetimeStart(Value *Ptr, ConstantInt *Size = nullptr);
/// \brief Create a lifetime.end intrinsic.
///
/// If the pointer isn't i8* it will be converted.
- CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = 0);
+ CallInst *CreateLifetimeEnd(Value *Ptr, ConstantInt *Size = nullptr);
+
+ /// \brief Create a call to Masked Load intrinsic
+ CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask,
+ Value *PassThru = 0, const Twine &Name = "");
+
+ /// \brief Create a call to Masked Store intrinsic
+ CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
+ Value *Mask);
+
+ /// \brief Create an assume intrinsic call that allows the optimizer to
+ /// assume that the provided condition will be true.
+ CallInst *CreateAssumption(Value *Cond);
+
+ /// \brief Create a call to the experimental.gc.statepoint intrinsic to
+ /// start a new statepoint sequence.
+ CallInst *CreateGCStatepoint(Value *ActualCallee,
+ ArrayRef<Value *> CallArgs,
+ ArrayRef<Value *> DeoptArgs,
+ ArrayRef<Value *> GCArgs,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.result intrinsic to extract
+ /// the result from a call wrapped in a statepoint.
+ CallInst *CreateGCResult(Instruction *Statepoint,
+ Type *ResultType,
+ const Twine &Name = "");
+
+ /// \brief Create a call to the experimental.gc.relocate intrinsics to
+ /// project the relocated value of one pointer from the statepoint.
+ CallInst *CreateGCRelocate(Instruction *Statepoint,
+ int BaseOffset,
+ int DerivedOffset,
+ Type *ResultType,
+ const Twine &Name = "");
private:
+ /// \brief Create a call to a masked intrinsic with given Id.
+ /// Masked intrinsic has only one overloaded type - data type.
+ CallInst *CreateMaskedIntrinsic(unsigned Id, ArrayRef<Value *> Ops,
+ Type *DataTy, const Twine &Name = "");
+
Value *getCastedInt8PtrValue(Value *Ptr);
};
/// The first template argument handles whether or not to preserve names in the
/// final instruction output. This defaults to on. The second template argument
/// specifies a class to use for creating constants. This defaults to creating
-/// minimally folded constants. The fourth template argument allows clients to
+/// minimally folded constants. The third template argument allows clients to
/// specify custom insertion hooks that are called on every newly created
/// insertion.
template<bool preserveNames = true, typename T = ConstantFolder,
typename Inserter = IRBuilderDefaultInserter<preserveNames> >
class IRBuilder : public IRBuilderBase, public Inserter {
T Folder;
- MDNode *DefaultFPMathTag;
- FastMathFlags FMF;
public:
IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(),
- MDNode *FPMathTag = 0)
- : IRBuilderBase(C), Inserter(I), Folder(F), DefaultFPMathTag(FPMathTag),
- FMF() {
+ MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) {
}
- explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = 0)
- : IRBuilderBase(C), Folder(), DefaultFPMathTag(FPMathTag), FMF() {
+ explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(C, FPMathTag), Folder() {
}
- explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = 0)
- : IRBuilderBase(TheBB->getContext()), Folder(F),
- DefaultFPMathTag(FPMathTag), FMF() {
+ explicit IRBuilder(BasicBlock *TheBB, const T &F, MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) {
SetInsertPoint(TheBB);
}
- explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = 0)
- : IRBuilderBase(TheBB->getContext()), Folder(),
- DefaultFPMathTag(FPMathTag), FMF() {
+ explicit IRBuilder(BasicBlock *TheBB, MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() {
SetInsertPoint(TheBB);
}
- explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = 0)
- : IRBuilderBase(IP->getContext()), Folder(), DefaultFPMathTag(FPMathTag),
- FMF() {
+ explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(IP->getContext(), FPMathTag), Folder() {
SetInsertPoint(IP);
SetCurrentDebugLocation(IP->getDebugLoc());
}
- explicit IRBuilder(Use &U, MDNode *FPMathTag = 0)
- : IRBuilderBase(U->getContext()), Folder(), DefaultFPMathTag(FPMathTag),
- FMF() {
+ explicit IRBuilder(Use &U, MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(U->getContext(), FPMathTag), Folder() {
SetInsertPoint(U);
SetCurrentDebugLocation(cast<Instruction>(U.getUser())->getDebugLoc());
}
IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, const T& F,
- MDNode *FPMathTag = 0)
- : IRBuilderBase(TheBB->getContext()), Folder(F),
- DefaultFPMathTag(FPMathTag), FMF() {
+ MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder(F) {
SetInsertPoint(TheBB, IP);
}
- IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP, MDNode *FPMathTag = 0)
- : IRBuilderBase(TheBB->getContext()), Folder(),
- DefaultFPMathTag(FPMathTag), FMF() {
+ IRBuilder(BasicBlock *TheBB, BasicBlock::iterator IP,
+ MDNode *FPMathTag = nullptr)
+ : IRBuilderBase(TheBB->getContext(), FPMathTag), Folder() {
SetInsertPoint(TheBB, IP);
}
/// \brief Get the constant folder being used.
const T &getFolder() { return Folder; }
- /// \brief Get the floating point math metadata being used.
- MDNode *getDefaultFPMathTag() const { return DefaultFPMathTag; }
-
- /// \brief Get the flags to be applied to created floating point ops
- FastMathFlags getFastMathFlags() const { return FMF; }
-
- /// \brief Clear the fast-math flags.
- void clearFastMathFlags() { FMF.clear(); }
-
- /// \brief SetDefaultFPMathTag - Set the floating point math metadata to be used.
- void SetDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; }
-
- /// \brief Set the fast-math flags to be used with generated fp-math operators
- void SetFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; }
-
/// \brief Return true if this builder is configured to actually add the
/// requested names to IR created through it.
bool isNamePreserving() const { return preserveNames; }
/// \brief Create a conditional 'br Cond, TrueDest, FalseDest'
/// instruction.
BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
- MDNode *BranchWeights = 0) {
+ MDNode *BranchWeights = nullptr) {
return Insert(addBranchWeights(BranchInst::Create(True, False, Cond),
BranchWeights));
}
/// and with a hint for the number of cases that will be added (for efficient
/// allocation).
SwitchInst *CreateSwitch(Value *V, BasicBlock *Dest, unsigned NumCases = 10,
- MDNode *BranchWeights = 0) {
+ MDNode *BranchWeights = nullptr) {
return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases),
BranchWeights));
}
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
BasicBlock *UnwindDest, const Twine &Name = "") {
- return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest,
- ArrayRef<Value *>()),
+ return Insert(InvokeInst::Create(Callee, NormalDest, UnwindDest, None),
Name);
}
InvokeInst *CreateInvoke(Value *Callee, BasicBlock *NormalDest,
return CreateAdd(LHS, RHS, Name, true, false);
}
Value *CreateFAdd(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = 0) {
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFAdd(LC, RC), Name);
bool HasNUW = false, bool HasNSW = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateSub(LC, RC), Name);
+ return Insert(Folder.CreateSub(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Sub, LHS, RHS, Name,
HasNUW, HasNSW);
}
return CreateSub(LHS, RHS, Name, true, false);
}
Value *CreateFSub(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = 0) {
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFSub(LC, RC), Name);
bool HasNUW = false, bool HasNSW = false) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
- return Insert(Folder.CreateMul(LC, RC), Name);
+ return Insert(Folder.CreateMul(LC, RC, HasNUW, HasNSW), Name);
return CreateInsertNUWNSWBinOp(Instruction::Mul, LHS, RHS, Name,
HasNUW, HasNSW);
}
return CreateMul(LHS, RHS, Name, true, false);
}
Value *CreateFMul(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = 0) {
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFMul(LC, RC), Name);
return CreateSDiv(LHS, RHS, Name, true);
}
Value *CreateFDiv(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = 0) {
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFDiv(LC, RC), Name);
return Insert(BinaryOperator::CreateSRem(LHS, RHS), Name);
}
Value *CreateFRem(Value *LHS, Value *RHS, const Twine &Name = "",
- MDNode *FPMathTag = 0) {
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFRem(LC, RC), Name);
}
Value *CreateBinOp(Instruction::BinaryOps Opc,
- Value *LHS, Value *RHS, const Twine &Name = "") {
+ Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateBinOp(Opc, LC, RC), Name);
- return Insert(BinaryOperator::Create(Opc, LHS, RHS), Name);
+ llvm::Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS);
+ if (isa<FPMathOperator>(BinOp))
+ BinOp = AddFPMathAttributes(BinOp, FPMathTag, FMF);
+ return Insert(BinOp, Name);
}
Value *CreateNeg(Value *V, const Twine &Name = "",
Value *CreateNUWNeg(Value *V, const Twine &Name = "") {
return CreateNeg(V, Name, true, false);
}
- Value *CreateFNeg(Value *V, const Twine &Name = "", MDNode *FPMathTag = 0) {
+ Value *CreateFNeg(Value *V, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
if (Constant *VC = dyn_cast<Constant>(V))
return Insert(Folder.CreateFNeg(VC), Name);
return Insert(AddFPMathAttributes(BinaryOperator::CreateFNeg(V),
// Instruction creation methods: Memory Instructions
//===--------------------------------------------------------------------===//
- AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = 0,
+ AllocaInst *CreateAlloca(Type *Ty, Value *ArraySize = nullptr,
const Twine &Name = "") {
return Insert(new AllocaInst(Ty, ArraySize), Name);
}
return Insert(new LoadInst(Ptr), Name);
}
LoadInst *CreateLoad(Value *Ptr, bool isVolatile, const Twine &Name = "") {
- return Insert(new LoadInst(Ptr, 0, isVolatile), Name);
+ return Insert(new LoadInst(Ptr, nullptr, isVolatile), Name);
}
StoreInst *CreateStore(Value *Val, Value *Ptr, bool isVolatile = false) {
return Insert(new StoreInst(Val, Ptr, isVolatile));
return SI;
}
FenceInst *CreateFence(AtomicOrdering Ordering,
- SynchronizationScope SynchScope = CrossThread) {
- return Insert(new FenceInst(Context, Ordering, SynchScope));
- }
- AtomicCmpXchgInst *CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
- AtomicOrdering Ordering,
- SynchronizationScope SynchScope = CrossThread) {
- return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, Ordering, SynchScope));
+ SynchronizationScope SynchScope = CrossThread,
+ const Twine &Name = "") {
+ return Insert(new FenceInst(Context, Ordering, SynchScope), Name);
+ }
+ AtomicCmpXchgInst *
+ CreateAtomicCmpXchg(Value *Ptr, Value *Cmp, Value *New,
+ AtomicOrdering SuccessOrdering,
+ AtomicOrdering FailureOrdering,
+ SynchronizationScope SynchScope = CrossThread) {
+ return Insert(new AtomicCmpXchgInst(Ptr, Cmp, New, SuccessOrdering,
+ FailureOrdering, SynchScope));
}
AtomicRMWInst *CreateAtomicRMW(AtomicRMWInst::BinOp Op, Value *Ptr, Value *Val,
AtomicOrdering Ordering,
const Twine &Name = "") {
return CreateCast(Instruction::BitCast, V, DestTy, Name);
}
+ Value *CreateAddrSpaceCast(Value *V, Type *DestTy,
+ const Twine &Name = "") {
+ return CreateCast(Instruction::AddrSpaceCast, V, DestTy, Name);
+ }
Value *CreateZExtOrBitCast(Value *V, Type *DestTy,
const Twine &Name = "") {
if (V->getType() == DestTy)
return Insert(Folder.CreatePointerCast(VC, DestTy), Name);
return Insert(CastInst::CreatePointerCast(V, DestTy), Name);
}
+
+ Value *CreatePointerBitCastOrAddrSpaceCast(Value *V, Type *DestTy,
+ const Twine &Name = "") {
+ if (V->getType() == DestTy)
+ return V;
+
+ if (Constant *VC = dyn_cast<Constant>(V)) {
+ return Insert(Folder.CreatePointerBitCastOrAddrSpaceCast(VC, DestTy),
+ Name);
+ }
+
+ return Insert(CastInst::CreatePointerBitCastOrAddrSpaceCast(V, DestTy),
+ Name);
+ }
+
Value *CreateIntCast(Value *V, Type *DestTy, bool isSigned,
const Twine &Name = "") {
if (V->getType() == DestTy)
return Insert(Folder.CreateIntCast(VC, DestTy, isSigned), Name);
return Insert(CastInst::CreateIntegerCast(V, DestTy, isSigned), Name);
}
+
+ Value *CreateBitOrPointerCast(Value *V, Type *DestTy,
+ const Twine &Name = "") {
+ if (V->getType() == DestTy)
+ return V;
+ if (V->getType()->isPointerTy() && DestTy->isIntegerTy())
+ return CreatePtrToInt(V, DestTy, Name);
+ if (V->getType()->isIntegerTy() && DestTy->isPointerTy())
+ return CreateIntToPtr(V, DestTy, Name);
+
+ return CreateBitCast(V, DestTy, Name);
+ }
private:
// \brief Provided to resolve 'CreateIntCast(Ptr, Ptr, "...")', giving a
// compile time error, instead of converting the string to bool for the
// isSigned parameter.
- Value *CreateIntCast(Value *, Type *, const char *) LLVM_DELETED_FUNCTION;
+ Value *CreateIntCast(Value *, Type *, const char *) = delete;
public:
Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
if (V->getType() == DestTy)
Value *Zeros = ConstantAggregateZero::get(VectorType::get(I32Ty, NumElts));
return CreateShuffleVector(V, Undef, Zeros, Name + ".splat");
}
+
+ /// \brief 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) {
+ IntegerType *IntTy = cast<IntegerType>(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;
+ }
+
+ /// \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<PointerType>(PtrValue->getType()) &&
+ "trying to create an alignment assumption on a non-pointer?");
+
+ PointerType *PtrTy = cast<PointerType>(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<ConstantInt>(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).