Changeset View
Changeset View
Standalone View
Standalone View
llvm/trunk/include/llvm/IR/IRBuilder.h
Show All 25 Lines | |||||
#include "llvm/IR/DataLayout.h" | #include "llvm/IR/DataLayout.h" | ||||
#include "llvm/IR/DebugLoc.h" | #include "llvm/IR/DebugLoc.h" | ||||
#include "llvm/IR/DerivedTypes.h" | #include "llvm/IR/DerivedTypes.h" | ||||
#include "llvm/IR/Function.h" | #include "llvm/IR/Function.h" | ||||
#include "llvm/IR/GlobalVariable.h" | #include "llvm/IR/GlobalVariable.h" | ||||
#include "llvm/IR/InstrTypes.h" | #include "llvm/IR/InstrTypes.h" | ||||
#include "llvm/IR/Instruction.h" | #include "llvm/IR/Instruction.h" | ||||
#include "llvm/IR/Instructions.h" | #include "llvm/IR/Instructions.h" | ||||
#include "llvm/IR/Intrinsics.h" | #include "llvm/IR/IntrinsicInst.h" | ||||
#include "llvm/IR/LLVMContext.h" | #include "llvm/IR/LLVMContext.h" | ||||
#include "llvm/IR/Module.h" | #include "llvm/IR/Module.h" | ||||
#include "llvm/IR/Operator.h" | #include "llvm/IR/Operator.h" | ||||
#include "llvm/IR/Type.h" | #include "llvm/IR/Type.h" | ||||
#include "llvm/IR/Value.h" | #include "llvm/IR/Value.h" | ||||
#include "llvm/IR/ValueHandle.h" | #include "llvm/IR/ValueHandle.h" | ||||
#include "llvm/Support/AtomicOrdering.h" | #include "llvm/Support/AtomicOrdering.h" | ||||
#include "llvm/Support/CBindingWrapping.h" | #include "llvm/Support/CBindingWrapping.h" | ||||
▲ Show 20 Lines • Show All 48 Lines • ▼ Show 20 Lines | |||||
protected: | protected: | ||||
BasicBlock *BB; | BasicBlock *BB; | ||||
BasicBlock::iterator InsertPt; | BasicBlock::iterator InsertPt; | ||||
LLVMContext &Context; | LLVMContext &Context; | ||||
MDNode *DefaultFPMathTag; | MDNode *DefaultFPMathTag; | ||||
FastMathFlags FMF; | FastMathFlags FMF; | ||||
bool IsFPConstrained; | |||||
ConstrainedFPIntrinsic::ExceptionBehavior DefaultConstrainedExcept; | |||||
ConstrainedFPIntrinsic::RoundingMode DefaultConstrainedRounding; | |||||
ArrayRef<OperandBundleDef> DefaultOperandBundles; | ArrayRef<OperandBundleDef> DefaultOperandBundles; | ||||
public: | public: | ||||
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr, | IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr, | ||||
ArrayRef<OperandBundleDef> OpBundles = None) | ArrayRef<OperandBundleDef> OpBundles = None) | ||||
: Context(context), DefaultFPMathTag(FPMathTag), | : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false), | ||||
DefaultConstrainedExcept(ConstrainedFPIntrinsic::ebStrict), | |||||
DefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDynamic), | |||||
DefaultOperandBundles(OpBundles) { | DefaultOperandBundles(OpBundles) { | ||||
ClearInsertionPoint(); | ClearInsertionPoint(); | ||||
} | } | ||||
//===--------------------------------------------------------------------===// | //===--------------------------------------------------------------------===// | ||||
// Builder configuration methods | // Builder configuration methods | ||||
//===--------------------------------------------------------------------===// | //===--------------------------------------------------------------------===// | ||||
▲ Show 20 Lines • Show All 100 Lines • ▼ Show 20 Lines | public: | ||||
void clearFastMathFlags() { FMF.clear(); } | void clearFastMathFlags() { FMF.clear(); } | ||||
/// Set the floating point math metadata to be used. | /// Set the floating point math metadata to be used. | ||||
void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } | void setDefaultFPMathTag(MDNode *FPMathTag) { DefaultFPMathTag = FPMathTag; } | ||||
/// Set the fast-math flags to be used with generated fp-math operators | /// Set the fast-math flags to be used with generated fp-math operators | ||||
void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } | void setFastMathFlags(FastMathFlags NewFMF) { FMF = NewFMF; } | ||||
/// Enable/Disable use of constrained floating point math. When | |||||
/// enabled the CreateF<op>() calls instead create constrained | |||||
/// floating point intrinsic calls. Fast math flags are unaffected | |||||
/// by this setting. | |||||
void setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; } | |||||
/// Query for the use of constrained floating point math | |||||
bool getIsFPConstrained() { return IsFPConstrained; } | |||||
/// Set the exception handling to be used with constrained floating point | |||||
void setDefaultConstrainedExcept( | |||||
ConstrainedFPIntrinsic::ExceptionBehavior NewExcept) { | |||||
DefaultConstrainedExcept = NewExcept; | |||||
} | |||||
/// Set the rounding mode handling to be used with constrained floating point | |||||
void setDefaultConstrainedRounding( | |||||
ConstrainedFPIntrinsic::RoundingMode NewRounding) { | |||||
DefaultConstrainedRounding = NewRounding; | |||||
} | |||||
/// Get the exception handling used with constrained floating point | |||||
ConstrainedFPIntrinsic::ExceptionBehavior getDefaultConstrainedExcept() { | |||||
return DefaultConstrainedExcept; | |||||
} | |||||
/// Get the rounding mode handling used with constrained floating point | |||||
ConstrainedFPIntrinsic::RoundingMode getDefaultConstrainedRounding() { | |||||
return DefaultConstrainedRounding; | |||||
} | |||||
//===--------------------------------------------------------------------===// | //===--------------------------------------------------------------------===// | ||||
// RAII helpers. | // RAII helpers. | ||||
//===--------------------------------------------------------------------===// | //===--------------------------------------------------------------------===// | ||||
// RAII object that stores the current insertion point and restores it | // RAII object that stores the current insertion point and restores it | ||||
// when the object is destroyed. This includes the debug location. | // when the object is destroyed. This includes the debug location. | ||||
class InsertPointGuard { | class InsertPointGuard { | ||||
IRBuilderBase &Builder; | IRBuilderBase &Builder; | ||||
▲ Show 20 Lines • Show All 811 Lines • ▼ Show 20 Lines | private: | ||||
Value *foldConstant(Instruction::BinaryOps Opc, Value *L, | Value *foldConstant(Instruction::BinaryOps Opc, Value *L, | ||||
Value *R, const Twine &Name) const { | Value *R, const Twine &Name) const { | ||||
auto *LC = dyn_cast<Constant>(L); | auto *LC = dyn_cast<Constant>(L); | ||||
auto *RC = dyn_cast<Constant>(R); | auto *RC = dyn_cast<Constant>(R); | ||||
return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; | return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr; | ||||
} | } | ||||
Value *getConstrainedFPRounding( | |||||
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding) { | |||||
ConstrainedFPIntrinsic::RoundingMode UseRounding = | |||||
DefaultConstrainedRounding; | |||||
if (Rounding.hasValue()) | |||||
UseRounding = Rounding.getValue(); | |||||
Optional<StringRef> RoundingStr = | |||||
ConstrainedFPIntrinsic::RoundingModeToStr(UseRounding); | |||||
assert(RoundingStr.hasValue() && "Garbage strict rounding mode!"); | |||||
auto *RoundingMDS = MDString::get(Context, RoundingStr.getValue()); | |||||
return MetadataAsValue::get(Context, RoundingMDS); | |||||
} | |||||
Value *getConstrainedFPExcept( | |||||
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except) { | |||||
ConstrainedFPIntrinsic::ExceptionBehavior UseExcept = | |||||
DefaultConstrainedExcept; | |||||
if (Except.hasValue()) | |||||
UseExcept = Except.getValue(); | |||||
Optional<StringRef> ExceptStr = | |||||
ConstrainedFPIntrinsic::ExceptionBehaviorToStr(UseExcept); | |||||
assert(ExceptStr.hasValue() && "Garbage strict exception behavior!"); | |||||
auto *ExceptMDS = MDString::get(Context, ExceptStr.getValue()); | |||||
return MetadataAsValue::get(Context, ExceptMDS); | |||||
} | |||||
public: | public: | ||||
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", | Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "", | ||||
bool HasNUW = false, bool HasNSW = false) { | bool HasNUW = false, bool HasNSW = false) { | ||||
if (auto *LC = dyn_cast<Constant>(LHS)) | if (auto *LC = dyn_cast<Constant>(LHS)) | ||||
if (auto *RC = dyn_cast<Constant>(RHS)) | if (auto *RC = dyn_cast<Constant>(RHS)) | ||||
return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); | return Insert(Folder.CreateAdd(LC, RC, HasNUW, HasNSW), Name); | ||||
return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, | return CreateInsertNUWNSWBinOp(Instruction::Add, LHS, RHS, Name, | ||||
HasNUW, HasNSW); | HasNUW, HasNSW); | ||||
▲ Show 20 Lines • Show All 202 Lines • ▼ Show 20 Lines | public: | ||||
} | } | ||||
Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { | Value *CreateXor(Value *LHS, uint64_t RHS, const Twine &Name = "") { | ||||
return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); | return CreateXor(LHS, ConstantInt::get(LHS->getType(), RHS), Name); | ||||
} | } | ||||
Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "", | Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "", | ||||
MDNode *FPMD = nullptr) { | MDNode *FPMD = nullptr) { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, | |||||
L, R, nullptr, Name, FPMD); | |||||
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF); | Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
/// Copy fast-math-flags from an instruction rather than using the builder's | /// Copy fast-math-flags from an instruction rather than using the builder's | ||||
/// default FMF. | /// default FMF. | ||||
Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, | Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource, | ||||
const Twine &Name = "") { | const Twine &Name = "") { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd, | |||||
L, R, FMFSource, Name); | |||||
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, | Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr, | ||||
FMFSource->getFastMathFlags()); | FMFSource->getFastMathFlags()); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", | Value *CreateFSub(Value *L, Value *R, const Twine &Name = "", | ||||
MDNode *FPMD = nullptr) { | MDNode *FPMD = nullptr) { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, | |||||
L, R, nullptr, Name, FPMD); | |||||
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF); | Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
/// Copy fast-math-flags from an instruction rather than using the builder's | /// Copy fast-math-flags from an instruction rather than using the builder's | ||||
/// default FMF. | /// default FMF. | ||||
Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, | Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource, | ||||
const Twine &Name = "") { | const Twine &Name = "") { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub, | |||||
L, R, FMFSource, Name); | |||||
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, | Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr, | ||||
FMFSource->getFastMathFlags()); | FMFSource->getFastMathFlags()); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", | Value *CreateFMul(Value *L, Value *R, const Twine &Name = "", | ||||
MDNode *FPMD = nullptr) { | MDNode *FPMD = nullptr) { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, | |||||
L, R, nullptr, Name, FPMD); | |||||
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF); | Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
/// Copy fast-math-flags from an instruction rather than using the builder's | /// Copy fast-math-flags from an instruction rather than using the builder's | ||||
/// default FMF. | /// default FMF. | ||||
Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource, | Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource, | ||||
const Twine &Name = "") { | const Twine &Name = "") { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul, | |||||
L, R, FMFSource, Name); | |||||
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, | Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr, | ||||
FMFSource->getFastMathFlags()); | FMFSource->getFastMathFlags()); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", | Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "", | ||||
MDNode *FPMD = nullptr) { | MDNode *FPMD = nullptr) { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, | |||||
L, R, nullptr, Name, FPMD); | |||||
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF); | Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
/// Copy fast-math-flags from an instruction rather than using the builder's | /// Copy fast-math-flags from an instruction rather than using the builder's | ||||
/// default FMF. | /// default FMF. | ||||
Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource, | Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource, | ||||
const Twine &Name = "") { | const Twine &Name = "") { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv, | |||||
L, R, FMFSource, Name); | |||||
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, | Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, | ||||
FMFSource->getFastMathFlags()); | FMFSource->getFastMathFlags()); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", | Value *CreateFRem(Value *L, Value *R, const Twine &Name = "", | ||||
MDNode *FPMD = nullptr) { | MDNode *FPMD = nullptr) { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, | |||||
L, R, nullptr, Name, FPMD); | |||||
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF); | Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
/// Copy fast-math-flags from an instruction rather than using the builder's | /// Copy fast-math-flags from an instruction rather than using the builder's | ||||
/// default FMF. | /// default FMF. | ||||
Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource, | Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource, | ||||
const Twine &Name = "") { | const Twine &Name = "") { | ||||
if (IsFPConstrained) | |||||
return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem, | |||||
L, R, FMFSource, Name); | |||||
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; | if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V; | ||||
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, | Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr, | ||||
FMFSource->getFastMathFlags()); | FMFSource->getFastMathFlags()); | ||||
return Insert(I, Name); | return Insert(I, Name); | ||||
} | } | ||||
Value *CreateBinOp(Instruction::BinaryOps Opc, | Value *CreateBinOp(Instruction::BinaryOps Opc, | ||||
Value *LHS, Value *RHS, const Twine &Name = "", | Value *LHS, Value *RHS, const Twine &Name = "", | ||||
MDNode *FPMathTag = nullptr) { | MDNode *FPMathTag = nullptr) { | ||||
if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V; | if (Value *V = foldConstant(Opc, LHS, RHS, Name)) return V; | ||||
Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); | Instruction *BinOp = BinaryOperator::Create(Opc, LHS, RHS); | ||||
if (isa<FPMathOperator>(BinOp)) | if (isa<FPMathOperator>(BinOp)) | ||||
BinOp = setFPAttrs(BinOp, FPMathTag, FMF); | BinOp = setFPAttrs(BinOp, FPMathTag, FMF); | ||||
return Insert(BinOp, Name); | return Insert(BinOp, Name); | ||||
} | } | ||||
CallInst *CreateConstrainedFPBinOp( | |||||
Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr, | |||||
const Twine &Name = "", MDNode *FPMathTag = nullptr, | |||||
Optional<ConstrainedFPIntrinsic::RoundingMode> Rounding = None, | |||||
Optional<ConstrainedFPIntrinsic::ExceptionBehavior> Except = None) { | |||||
Value *RoundingV = getConstrainedFPRounding(Rounding); | |||||
Value *ExceptV = getConstrainedFPExcept(Except); | |||||
FastMathFlags UseFMF = FMF; | |||||
if (FMFSource) | |||||
UseFMF = FMFSource->getFastMathFlags(); | |||||
CallInst *C = CreateIntrinsic(ID, {L->getType()}, | |||||
{L, R, RoundingV, ExceptV}, nullptr, Name); | |||||
return cast<CallInst>(setFPAttrs(C, FPMathTag, UseFMF)); | |||||
} | |||||
Value *CreateNeg(Value *V, const Twine &Name = "", | Value *CreateNeg(Value *V, const Twine &Name = "", | ||||
bool HasNUW = false, bool HasNSW = false) { | bool HasNUW = false, bool HasNSW = false) { | ||||
if (auto *VC = dyn_cast<Constant>(V)) | if (auto *VC = dyn_cast<Constant>(V)) | ||||
return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); | return Insert(Folder.CreateNeg(VC, HasNUW, HasNSW), Name); | ||||
BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); | BinaryOperator *BO = Insert(BinaryOperator::CreateNeg(V), Name); | ||||
if (HasNUW) BO->setHasNoUnsignedWrap(); | if (HasNUW) BO->setHasNoUnsignedWrap(); | ||||
if (HasNSW) BO->setHasNoSignedWrap(); | if (HasNSW) BO->setHasNoSignedWrap(); | ||||
return BO; | return BO; | ||||
▲ Show 20 Lines • Show All 1,059 Lines • Show Last 20 Lines |