kpn updated this revision to Diff 176464.
kpn added a comment.
Address review comment: Shrink the diff by eliminating unneeded use of else.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D53157/new/
https://reviews.llvm.org/D53157
Files:
include/llvm/IR/IRBuilder.h
unittests/IR/IRBuilderTest.cpp
Index: unittests/IR/IRBuilderTest.cpp
===================================================================
--- unittests/IR/IRBuilderTest.cpp
+++ unittests/IR/IRBuilderTest.cpp
@@ -123,6 +123,100 @@
EXPECT_FALSE(II->hasNoNaNs());
}
+TEST_F(IRBuilderTest, ConstrainedFP) {
+ IRBuilder<> Builder(BB);
+ Value *V;
+ CallInst *Call;
+ IntrinsicInst *II;
+
+ V = Builder.CreateLoad(GV);
+
+ Call = Builder.CreateConstrainedFAdd(V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
+
+ Call = Builder.CreateConstrainedFSub(V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fsub);
+
+ Call = Builder.CreateConstrainedFMul(V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fmul);
+
+ Call = Builder.CreateConstrainedFDiv(V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fdiv);
+
+ Call = Builder.CreateConstrainedFRem(V, V);
+ II = cast<IntrinsicInst>(Call);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
+
+ // Now see if we get constrained intrinsics instead of non-constrained
+ // instructions.
+ Builder.setIsConstrainedFP(true);
+
+ V = Builder.CreateFAdd(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
+
+ V = Builder.CreateFSub(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fsub);
+
+ V = Builder.CreateFMul(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fmul);
+
+ V = Builder.CreateFDiv(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_fdiv);
+
+ V = Builder.CreateFRem(V, V);
+ ASSERT_TRUE(isa<IntrinsicInst>(V));
+ II = cast<IntrinsicInst>(V);
+ EXPECT_EQ(II->getIntrinsicID(), Intrinsic::experimental_constrained_frem);
+
+ // Verify the codepaths for setting and overriding the default metadata.
+ MDNode *ExceptStr = MDNode::get(Builder.getContext(),
+ MDString::get(Builder.getContext(),
+ "fpexcept.strict"));
+ MDNode *ExceptIgn = MDNode::get(Builder.getContext(),
+ MDString::get(Builder.getContext(),
+ "fpexcept.ignore"));
+ MDNode *RoundDyn = MDNode::get(Builder.getContext(),
+ MDString::get(Builder.getContext(),
+ "round.dynamic"));
+ MDNode *RoundUp = MDNode::get(Builder.getContext(),
+ MDString::get(Builder.getContext(),
+ "round.upward"));
+
+ V = Builder.CreateFAdd(V, V);
+ ASSERT_TRUE(isa<ConstrainedFPIntrinsic>(V));
+ auto *CII = cast<ConstrainedFPIntrinsic>(V);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic);
+
+ Builder.setDefaultConstrainedExcept(ExceptIgn);
+ Builder.setDefaultConstrainedRounding(RoundUp);
+ V = Builder.CreateFAdd(V, V);
+ CII = cast<ConstrainedFPIntrinsic>(V);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebIgnore);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmUpward);
+
+ // Now override the defaults.
+ Call = Builder.CreateConstrainedFAdd(V, V, nullptr, "", RoundDyn, ExceptStr);
+ CII = cast<ConstrainedFPIntrinsic>(Call);
+ ASSERT_TRUE(CII->getExceptionBehavior() == ConstrainedFPIntrinsic::ebStrict);
+ ASSERT_TRUE(CII->getRoundingMode() == ConstrainedFPIntrinsic::rmDynamic);
+
+ Builder.CreateRetVoid();
+ EXPECT_FALSE(verifyModule(*M));
+}
+
TEST_F(IRBuilderTest, Lifetime) {
IRBuilder<> Builder(BB);
AllocaInst *Var1 = Builder.CreateAlloca(Builder.getInt8Ty());
Index: include/llvm/IR/IRBuilder.h
===================================================================
--- include/llvm/IR/IRBuilder.h
+++ include/llvm/IR/IRBuilder.h
@@ -97,13 +97,18 @@
MDNode *DefaultFPMathTag;
FastMathFlags FMF;
+ bool IsFPConstrained;
+ MDNode *DefaultConstrainedExcept;
+ MDNode *DefaultConstrainedRounding;
+
ArrayRef<OperandBundleDef> DefaultOperandBundles;
public:
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
: Context(context), DefaultFPMathTag(FPMathTag),
- DefaultOperandBundles(OpBundles) {
+ IsFPConstrained(false), DefaultConstrainedExcept(nullptr),
+ DefaultConstrainedRounding(nullptr), DefaultOperandBundles(OpBundles) {
ClearInsertionPoint();
}
@@ -219,6 +224,40 @@
/// 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
+ void setIsConstrainedFP(bool IsCon) { IsFPConstrained = IsCon; }
+
+ /// Disable use of constrained floating point math
+ void clearIsConstrainedFP() { setIsConstrainedFP(false); }
+
+ /// Set the exception handling to be used with constrained floating point
+ void setDefaultConstrainedExcept(MDNode *NewExcept) {
+ DefaultConstrainedExcept = NewExcept;
+ }
+
+ /// Set the rounding mode handling to be used with constrained floating point
+ void setDefaultConstrainedRounding(MDNode *NewRounding) {
+ DefaultConstrainedRounding = NewRounding;
+ }
+
+ /// Get the exception handling used with constrained floating point
+ MDNode *getDefaultConstrainedExcept() {
+ if (!DefaultConstrainedExcept) {
+ DefaultConstrainedExcept =
+ MDNode::get(Context, MDString::get(Context, "fpexcept.strict"));
+ }
+ return DefaultConstrainedExcept;
+ }
+
+ /// Get the rounding mode handling used with constrained floating point
+ MDNode *getDefaultConstrainedRounding() {
+ if (!DefaultConstrainedRounding) {
+ DefaultConstrainedRounding =
+ MDNode::get(Context, MDString::get(Context, "round.dynamic"));
+ }
+ return DefaultConstrainedRounding;
+ }
+
//===--------------------------------------------------------------------===//
// RAII helpers.
//===--------------------------------------------------------------------===//
@@ -970,6 +1009,28 @@
return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
}
+ Value *getConstrainedRounding(MDNode *RoundingMD) {
+ MDString *Rounding;
+
+ if (!RoundingMD)
+ RoundingMD = getDefaultConstrainedRounding();
+
+ Rounding = cast<MDString>(RoundingMD->getOperand(0));
+
+ return MetadataAsValue::get(Context, Rounding);
+ }
+
+ Value *getConstrainedExcept(MDNode *ExceptMD) {
+ MDString *Except;
+
+ if (!ExceptMD)
+ ExceptMD = getDefaultConstrainedExcept();
+
+ Except = cast<MDString>(ExceptMD->getOperand(0));
+
+ return MetadataAsValue::get(Context, Except);
+ }
+
public:
Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
@@ -1172,6 +1233,9 @@
Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFAdd(L, R, nullptr, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1181,14 +1245,34 @@
/// default FMF.
Value *CreateFAddFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFAdd(L, R, FMFSource, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), nullptr,
FMFSource->getFastMathFlags());
return Insert(I, Name);
}
+ CallInst *CreateConstrainedFAdd(Value *L, Value *R,
+ Instruction *FMFSource = nullptr, const Twine &Name = "",
+ MDNode *RoundingMD = nullptr,
+ MDNode *ExceptMD = nullptr) {
+
+ Value *Rounding = getConstrainedRounding(RoundingMD);
+ Value *Except = getConstrainedExcept(ExceptMD);
+
+ return CreateIntrinsic(Intrinsic::experimental_constrained_fadd,
+ { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFSub(L, R, nullptr, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1198,14 +1282,35 @@
/// default FMF.
Value *CreateFSubFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFSub(L, R, FMFSource, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), nullptr,
FMFSource->getFastMathFlags());
return Insert(I, Name);
}
+ CallInst *CreateConstrainedFSub(Value *L, Value *R,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "",
+ MDNode *RoundingMD = nullptr,
+ MDNode *ExceptMD = nullptr) {
+
+ Value *Rounding = getConstrainedRounding(RoundingMD);
+ Value *Except = getConstrainedExcept(ExceptMD);
+
+ return CreateIntrinsic(Intrinsic::experimental_constrained_fsub,
+ { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFMul(L, R, nullptr, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1215,14 +1320,35 @@
/// default FMF.
Value *CreateFMulFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFMul(L, R, FMFSource, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), nullptr,
FMFSource->getFastMathFlags());
return Insert(I, Name);
}
+ CallInst *CreateConstrainedFMul(Value *L, Value *R,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "",
+ MDNode *RoundingMD = nullptr,
+ MDNode *ExceptMD = nullptr) {
+
+ Value *Rounding = getConstrainedRounding(RoundingMD);
+ Value *Except = getConstrainedExcept(ExceptMD);
+
+ return CreateIntrinsic(Intrinsic::experimental_constrained_fmul,
+ { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFDiv(L, R, nullptr, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1232,14 +1358,35 @@
/// default FMF.
Value *CreateFDivFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFDiv(L, R, FMFSource, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr,
FMFSource->getFastMathFlags());
return Insert(I, Name);
}
+ CallInst *CreateConstrainedFDiv(Value *L, Value *R,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "",
+ MDNode *RoundingMD = nullptr,
+ MDNode *ExceptMD = nullptr) {
+
+ Value *Rounding = getConstrainedRounding(RoundingMD);
+ Value *Except = getConstrainedExcept(ExceptMD);
+
+ return CreateIntrinsic(Intrinsic::experimental_constrained_fdiv,
+ { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFRem(L, R, nullptr, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1249,12 +1396,30 @@
/// default FMF.
Value *CreateFRemFMF(Value *L, Value *R, Instruction *FMFSource,
const Twine &Name = "") {
+ if (IsFPConstrained)
+ return CreateConstrainedFRem(L, R, FMFSource, Name, nullptr, nullptr);
+
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), nullptr,
FMFSource->getFastMathFlags());
return Insert(I, Name);
}
+ CallInst *CreateConstrainedFRem(Value *L, Value *R,
+ Instruction *FMFSource = nullptr,
+ const Twine &Name = "",
+ MDNode *RoundingMD = nullptr,
+ MDNode *ExceptMD = nullptr) {
+
+ Value *Rounding = getConstrainedRounding(RoundingMD);
+ Value *Except = getConstrainedExcept(ExceptMD);
+
+ return CreateIntrinsic(Intrinsic::experimental_constrained_frem,
+ { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateBinOp(Instruction::BinaryOps Opc,
Value *LHS, Value *RHS, const Twine &Name = "",
MDNode *FPMathTag = nullptr) {
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits