#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/IR/Instructions.h"
+#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/LLVMContext.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/ValueHandle.h"
/// \brief Common base class shared among various IRBuilders.
class IRBuilderBase {
DebugLoc CurDbgLocation;
+
protected:
BasicBlock *BB;
BasicBlock::iterator InsertPt;
MDNode *DefaultFPMathTag;
FastMathFlags FMF;
-public:
+public:
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr)
: Context(context), DefaultFPMathTag(FPMathTag), FMF() {
ClearInsertionPoint();
void SetInsertPoint(BasicBlock *TheBB, BasicBlock::iterator IP) {
BB = TheBB;
InsertPt = IP;
- }
-
- /// \brief Find the nearest point that dominates this use, and specify that
- /// created instructions should be inserted at this point.
- void SetInsertPoint(Use &U) {
- Instruction *UseInst = cast<Instruction>(U.getUser());
- if (PHINode *Phi = dyn_cast<PHINode>(UseInst)) {
- BasicBlock *PredBB = Phi->getIncomingBlock(U);
- assert(U != PredBB->getTerminator() && "critical edge not split");
- SetInsertPoint(PredBB, PredBB->getTerminator());
- return;
- }
- SetInsertPoint(UseInst);
+ if (IP != TheBB->end())
+ SetCurrentDebugLocation(IP->getDebugLoc());
}
/// \brief Set location information used by debugging information.
}
/// \brief Fetch the type representing a 128-bit integer.
- IntegerType *getInt128Ty() {
- return Type::getInt128Ty(Context);
- }
-
+ IntegerType *getInt128Ty() { return Type::getInt128Ty(Context); }
+
/// \brief Fetch the type representing an N-bit integer.
IntegerType *getIntNTy(unsigned N) {
return Type::getIntNTy(Context, N);
/// \brief Create a call to Masked Load intrinsic
CallInst *CreateMaskedLoad(Value *Ptr, unsigned Align, Value *Mask,
- Value *PassThru = 0, const Twine &Name = "");
+ Value *PassThru = nullptr, const Twine &Name = "");
/// \brief Create a call to Masked Store intrinsic
CallInst *CreateMaskedStore(Value *Val, Value *Ptr, unsigned Align,
typename Inserter = IRBuilderDefaultInserter<preserveNames> >
class IRBuilder : public IRBuilderBase, public Inserter {
T Folder;
+
public:
- IRBuilder(LLVMContext &C, const T &F, const Inserter &I = Inserter(),
+ IRBuilder(LLVMContext &C, const T &F, Inserter I = Inserter(),
MDNode *FPMathTag = nullptr)
- : IRBuilderBase(C, FPMathTag), Inserter(I), Folder(F) {
- }
+ : IRBuilderBase(C, FPMathTag), Inserter(std::move(I)), Folder(F) {}
explicit IRBuilder(LLVMContext &C, MDNode *FPMathTag = nullptr)
: IRBuilderBase(C, FPMathTag), Folder() {
explicit IRBuilder(Instruction *IP, MDNode *FPMathTag = nullptr)
: IRBuilderBase(IP->getContext(), FPMathTag), Folder() {
SetInsertPoint(IP);
- SetCurrentDebugLocation(IP->getDebugLoc());
- }
-
- 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,
//===--------------------------------------------------------------------===//
private:
- /// \brief Helper to add branch weight metadata onto an instruction.
+ /// \brief Helper to add branch weight and unpredictable metadata onto an
+ /// instruction.
/// \returns The annotated instruction.
template <typename InstTy>
- InstTy *addBranchWeights(InstTy *I, MDNode *Weights) {
+ InstTy *addBranchMetadata(InstTy *I, MDNode *Weights, MDNode *Unpredictable) {
if (Weights)
I->setMetadata(LLVMContext::MD_prof, Weights);
+ if (Unpredictable)
+ I->setMetadata(LLVMContext::MD_unpredictable, Unpredictable);
return I;
}
/// \brief Create a conditional 'br Cond, TrueDest, FalseDest'
/// instruction.
BranchInst *CreateCondBr(Value *Cond, BasicBlock *True, BasicBlock *False,
- MDNode *BranchWeights = nullptr) {
- return Insert(addBranchWeights(BranchInst::Create(True, False, Cond),
- BranchWeights));
+ MDNode *BranchWeights = nullptr,
+ MDNode *Unpredictable = nullptr) {
+ return Insert(addBranchMetadata(BranchInst::Create(True, False, Cond),
+ BranchWeights, Unpredictable));
}
/// \brief Create a switch instruction with the specified value, default dest,
/// 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 = nullptr) {
- return Insert(addBranchWeights(SwitchInst::Create(V, Dest, NumCases),
- BranchWeights));
+ MDNode *BranchWeights = nullptr,
+ MDNode *Unpredictable = nullptr) {
+ return Insert(addBranchMetadata(SwitchInst::Create(V, Dest, NumCases),
+ BranchWeights, Unpredictable));
}
/// \brief Create an indirect branch instruction with the specified address
return Insert(ResumeInst::Create(Exn));
}
+ CleanupReturnInst *CreateCleanupRet(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB = nullptr) {
+ return Insert(CleanupReturnInst::Create(CleanupPad, UnwindBB));
+ }
+
+ CleanupEndPadInst *CreateCleanupEndPad(CleanupPadInst *CleanupPad,
+ BasicBlock *UnwindBB = nullptr) {
+ return Insert(CleanupEndPadInst::Create(CleanupPad, UnwindBB));
+ }
+
+ CatchPadInst *CreateCatchPad(BasicBlock *NormalDest, BasicBlock *UnwindDest,
+ ArrayRef<Value *> Args, const Twine &Name = "") {
+ return Insert(CatchPadInst::Create(NormalDest, UnwindDest, Args), Name);
+ }
+
+ CatchEndPadInst *CreateCatchEndPad(BasicBlock *UnwindBB = nullptr) {
+ return Insert(CatchEndPadInst::Create(Context, UnwindBB));
+ }
+
+ TerminatePadInst *CreateTerminatePad(BasicBlock *UnwindBB = nullptr,
+ ArrayRef<Value *> Args = {},
+ const Twine &Name = "") {
+ return Insert(TerminatePadInst::Create(Context, UnwindBB, Args), Name);
+ }
+
+ CleanupPadInst *CreateCleanupPad(ArrayRef<Value *> Args,
+ const Twine &Name = "") {
+ return Insert(CleanupPadInst::Create(Context, Args), Name);
+ }
+
+ CatchReturnInst *CreateCatchRet(CatchPadInst *CatchPad, BasicBlock *BB) {
+ return Insert(CatchReturnInst::Create(CatchPad, BB));
+ }
+
UnreachableInst *CreateUnreachable() {
return Insert(new UnreachableInst(Context));
}
I->setFastMathFlags(FMF);
return I;
}
+
public:
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
const Twine &Name = "") {
if (V->getType() == DestTy)
return V;
- if (V->getType()->isPointerTy() && DestTy->isIntegerTy())
+ if (V->getType()->getScalarType()->isPointerTy() &&
+ DestTy->getScalarType()->isIntegerTy())
return CreatePtrToInt(V, DestTy, Name);
- if (V->getType()->isIntegerTy() && DestTy->isPointerTy())
+ if (V->getType()->getScalarType()->isIntegerTy() &&
+ DestTy->getScalarType()->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 *) = delete;
+
public:
Value *CreateFPCast(Value *V, Type *DestTy, const Twine &Name = "") {
if (V->getType() == DestTy)
return CreateICmp(ICmpInst::ICMP_SLE, LHS, RHS, Name);
}
- Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name);
+ Value *CreateFCmpOEQ(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_OEQ, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name);
+ Value *CreateFCmpOGT(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_OGT, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name);
+ Value *CreateFCmpOGE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_OGE, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name);
+ Value *CreateFCmpOLT(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_OLT, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name);
+ Value *CreateFCmpOLE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_OLE, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name);
+ Value *CreateFCmpONE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_ONE, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name);
+ Value *CreateFCmpORD(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_ORD, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name);
+ Value *CreateFCmpUNO(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_UNO, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name);
+ Value *CreateFCmpUEQ(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_UEQ, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name);
+ Value *CreateFCmpUGT(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_UGT, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name);
+ Value *CreateFCmpUGE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_UGE, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name);
+ Value *CreateFCmpULT(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_ULT, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name);
+ Value *CreateFCmpULE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_ULE, LHS, RHS, Name, FPMathTag);
}
- Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "") {
- return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name);
+ Value *CreateFCmpUNE(Value *LHS, Value *RHS, const Twine &Name = "",
+ MDNode *FPMathTag = nullptr) {
+ return CreateFCmp(FCmpInst::FCMP_UNE, LHS, RHS, Name, FPMathTag);
}
Value *CreateICmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
return Insert(new ICmpInst(P, LHS, RHS), Name);
}
Value *CreateFCmp(CmpInst::Predicate P, Value *LHS, Value *RHS,
- const Twine &Name = "") {
+ const Twine &Name = "", MDNode *FPMathTag = nullptr) {
if (Constant *LC = dyn_cast<Constant>(LHS))
if (Constant *RC = dyn_cast<Constant>(RHS))
return Insert(Folder.CreateFCmp(P, LC, RC), Name);
- return Insert(new FCmpInst(P, LHS, RHS), Name);
+ return Insert(AddFPMathAttributes(new FCmpInst(P, LHS, RHS),
+ FPMathTag, FMF), Name);
}
//===--------------------------------------------------------------------===//
return Insert(PHINode::Create(Ty, NumReservedValues), Name);
}
- CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args,
+ CallInst *CreateCall(Value *Callee, ArrayRef<Value *> Args = None,
const Twine &Name = "") {
return Insert(CallInst::Create(Callee, Args), Name);
}
Name);
}
+ /// \brief Create an invariant.group.barrier intrinsic call, that stops
+ /// optimizer to propagate equality using invariant.group metadata.
+ /// If Ptr type is different from i8*, it's casted to i8* before call
+ /// and casted back to Ptr type after call.
+ Value *CreateInvariantGroupBarrier(Value *Ptr) {
+ Module *M = BB->getParent()->getParent();
+ Function *FnInvariantGroupBarrier = Intrinsic::getDeclaration(M,
+ Intrinsic::invariant_group_barrier);
+
+ Type *ArgumentAndReturnType = FnInvariantGroupBarrier->getReturnType();
+ assert(ArgumentAndReturnType ==
+ FnInvariantGroupBarrier->getFunctionType()->getParamType(0) &&
+ "InvariantGroupBarrier should take and return the same type");
+ Type *PtrType = Ptr->getType();
+
+ bool PtrTypeConversionNeeded = PtrType != ArgumentAndReturnType;
+ if (PtrTypeConversionNeeded)
+ Ptr = CreateBitCast(Ptr, ArgumentAndReturnType);
+
+ CallInst *Fn = CreateCall(FnInvariantGroupBarrier, {Ptr});
+
+ if (PtrTypeConversionNeeded)
+ return CreateBitCast(Fn, PtrType);
+ return Fn;
+ }
+
/// \brief Return a vector value that contains \arg V broadcasted to \p
/// NumElts elements.
Value *CreateVectorSplat(unsigned NumElts, Value *V, const Twine &Name = "") {
// Create wrappers for C Binding types (see CBindingWrapping.h).
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(IRBuilder<>, LLVMBuilderRef)
-}
+} // end namespace llvm
-#endif
+#endif // LLVM_IR_IRBUILDER_H