kpn updated this revision to Diff 202436.
kpn marked 4 inline comments as done.
kpn added a comment.
Address review comments.
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
@@ -122,6 +122,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
@@ -96,13 +96,17 @@
MDNode *DefaultFPMathTag;
FastMathFlags FMF;
+ bool IsFPConstrained;
+ MDNode *DefaultConstrainedExcept = nullptr;
+ MDNode *DefaultConstrainedRounding = nullptr;
+
ArrayRef<OperandBundleDef> DefaultOperandBundles;
public:
IRBuilderBase(LLVMContext &context, MDNode *FPMathTag = nullptr,
ArrayRef<OperandBundleDef> OpBundles = None)
: Context(context), DefaultFPMathTag(FPMathTag),
- DefaultOperandBundles(OpBundles) {
+ IsFPConstrained(false), DefaultConstrainedExcept(nullptr) {
ClearInsertionPoint();
}
@@ -218,6 +222,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 setIsFPConstrained(bool IsCon) { IsFPConstrained = IsCon; }
+
+ /// Disable use of constrained floating point math
+ void clearIsConstrainedFP() { setIsFPConstrained(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.
//===--------------------------------------------------------------------===//
@@ -1045,6 +1083,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) {
@@ -1247,6 +1307,10 @@
Value *CreateFAdd(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fadd,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FAdd, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFAdd(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1256,6 +1320,10 @@
/// 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());
@@ -1264,6 +1332,10 @@
Value *CreateFSub(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fsub,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FSub, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFSub(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1273,6 +1345,10 @@
/// 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());
@@ -1281,6 +1357,10 @@
Value *CreateFMul(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fmul,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FMul, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFMul(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1290,6 +1370,10 @@
/// 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());
@@ -1298,6 +1382,10 @@
Value *CreateFDiv(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FDiv, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1307,6 +1395,10 @@
/// 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());
@@ -1315,6 +1407,10 @@
Value *CreateFRem(Value *L, Value *R, const Twine &Name = "",
MDNode *FPMD = nullptr) {
+ if (IsFPConstrained)
+ return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_frem,
+ L, R, nullptr, Name);
+
if (Value *V = foldConstant(Instruction::FRem, L, R, Name)) return V;
Instruction *I = setFPAttrs(BinaryOperator::CreateFRem(L, R), FPMD, FMF);
return Insert(I, Name);
@@ -1324,6 +1420,10 @@
/// 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());
@@ -1340,6 +1440,20 @@
return Insert(BinOp, Name);
}
+ CallInst *CreateConstrainedFPBinOp(Intrinsic::ID ID, 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(ID, { L->getType() },
+ { L, R, Rounding, Except },
+ FMFSource, Name);
+ }
+
Value *CreateNeg(Value *V, const Twine &Name = "",
bool HasNUW = false, bool HasNSW = false) {
if (auto *VC = dyn_cast<Constant>(V))
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits