|
@@ -31,7 +31,7 @@
|
|
|
#include "llvm/IR/InstrTypes.h"
|
|
|
#include "llvm/IR/Instruction.h"
|
|
|
#include "llvm/IR/Instructions.h"
|
|
|
-#include "llvm/IR/Intrinsics.h"
|
|
|
+#include "llvm/IR/IntrinsicInst.h"
|
|
|
#include "llvm/IR/LLVMContext.h"
|
|
|
#include "llvm/IR/Module.h"
|
|
|
#include "llvm/IR/Operator.h"
|
|
@@ -96,12 +96,18 @@ protected:
|
|
|
MDNode *DefaultFPMathTag;
|
|
|
FastMathFlags FMF;
|
|
|
|
|
|
+ bool IsFPConstrained;
|
|
|
+ ConstrainedFPIntrinsic::ExceptionBehavior DefaultConstrainedExcept;
|
|
|
+ ConstrainedFPIntrinsic::RoundingMode DefaultConstrainedRounding;
|
|
|
+
|
|
|
ArrayRef<OperandBundleDef> DefaultOperandBundles;
|
|
|
|
|
|
public:
|
|
|
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
|
|
|
ArrayRef<OperandBundleDef> OpBundles = None)
|
|
|
- : Context(context), DefaultFPMathTag(FPMathTag),
|
|
|
+ : Context(context), DefaultFPMathTag(FPMathTag), IsFPConstrained(false),
|
|
|
+ DefaultConstrainedExcept(ConstrainedFPIntrinsic::ebStrict),
|
|
|
+ DefaultConstrainedRounding(ConstrainedFPIntrinsic::rmDynamic),
|
|
|
DefaultOperandBundles(OpBundles) {
|
|
|
ClearInsertionPoint();
|
|
|
}
|
|
@@ -218,6 +224,37 @@ public:
|
|
|
/// Set the fast-math flags to be used with generated fp-math operators
|
|
|
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.
|
|
|
//===--------------------------------------------------------------------===//
|
|
@@ -1045,6 +1082,38 @@ private:
|
|
|
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:
|
|
|
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
|
|
|
bool HasNUW = false, bool HasNSW = false) {
|
|
@@ -1263,6 +1332,10 @@ public:
|
|
|
|
|
|
Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
|
|
|
return Insert(I, Name);
|
|
@@ -1272,6 +1345,10 @@ public:
|
|
|
/// default FMF.
|
|
|
Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr,
|
|
|
FMFSource->getFastMathFlags());
|
|
@@ -1280,6 +1357,10 @@ public:
|
|
|
|
|
|
Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
|
|
|
return Insert(I, Name);
|
|
@@ -1289,6 +1370,10 @@ public:
|
|
|
/// default FMF.
|
|
|
Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr,
|
|
|
FMFSource->getFastMathFlags());
|
|
@@ -1297,6 +1382,10 @@ public:
|
|
|
|
|
|
Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
|
|
|
return Insert(I, Name);
|
|
@@ -1306,6 +1395,10 @@ public:
|
|
|
/// default FMF.
|
|
|
Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr,
|
|
|
FMFSource->getFastMathFlags());
|
|
@@ -1314,6 +1407,10 @@ public:
|
|
|
|
|
|
Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
|
|
|
return Insert(I, Name);
|
|
@@ -1323,6 +1420,10 @@ public:
|
|
|
/// default FMF.
|
|
|
Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr,
|
|
|
FMFSource->getFastMathFlags());
|
|
@@ -1331,6 +1432,10 @@ public:
|
|
|
|
|
|
Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
|
|
|
return Insert(I, Name);
|
|
@@ -1340,6 +1445,10 @@ public:
|
|
|
/// default FMF.
|
|
|
Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
|
|
|
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;
|
|
|
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr,
|
|
|
FMFSource->getFastMathFlags());
|
|
@@ -1356,6 +1465,23 @@ public:
|
|
|
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 = "",
|
|
|
bool HasNUW = false, bool HasNSW = false) {
|
|
|
if (auto *VC = dyn_cast<Constant>(V))
|