kpn updated this revision to Diff 202987.
kpn added a comment.

Address the rest of the review comments, hopefully.

I've lifted from mibintc's D62730 <https://reviews.llvm.org/D62730> the enums 
for the exception behavior and rounding modes. The rest of that set of changes 
is better left to a separate ticket after all.

Since I now have those requested enums I've changed the relevant public 
functions to take them instead of an MDNode*.

There is no standalone or comprehensive IRBuilder documentation that I could 
find. I hope the references in comments back to the LangRef are good enough. I 
used the exact language from it to make it easier to reference said doc.


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,70 @@
   EXPECT_FALSE(II->hasNoNaNs());
 }
 
+TEST_F(IRBuilderTest, ConstrainedFP) {
+  IRBuilder<> Builder(BB);
+  Value *V;
+  CallInst *Call;
+  IntrinsicInst *II;
+
+  V = Builder.CreateLoad(GV);
+
+  // See if we get constrained intrinsics instead of non-constrained
+  // instructions.
+  Builder.setIsFPConstrained(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.
+  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(IRBuilderBase::CE_Ignore);
+  Builder.setDefaultConstrainedRounding(IRBuilderBase::CR_Upward);
+  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.CreateConstrainedFPBinOp(
+        Intrinsic::experimental_constrained_fadd, V, V, nullptr, "",
+        IRBuilderBase::CR_Dynamic, IRBuilderBase::CE_Strict);
+  CII = cast<ConstrainedFPIntrinsic>(Call);
+  EXPECT_EQ(CII->getIntrinsicID(), Intrinsic::experimental_constrained_fadd);
+  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
@@ -88,6 +88,30 @@
 class IRBuilderBase {
   DebugLoc CurDbgLocation;
 
+public:
+  /// Specifies the required exception behavior. This is only used when
+  /// when constrained floating point is enabled. See the LLVM Language
+  /// Reference Manual for details.
+  enum ConstrainedExceptKind {
+    CE_Unspecified, ///< Use as a placeholder to not affect exception
+                    ///< behavior.
+    CE_Strict,      ///< This corresponds to "fpexcept.strict".
+    CE_Ignore,      ///< This corresponds to "fpexcept.ignore".
+    CE_MayTrap      ///< This corresponds to "fpexcept.maytrap".
+  };
+  /// Specifies the rounding mode to be assumed. This is only used when
+  /// when constrained floating point is enabled. See the LLVM Language
+  /// Reference Manual for details.
+  enum ConstrainedRoundingKind {
+    CR_Unspecified, ///< Use as a placeholder to not affect rounding
+                    ///< behavior.
+    CR_Dynamic,     ///< This corresponds to "fpround.dynamic".
+    CR_ToNearest,   ///< This corresponds to "fpround.tonearest".
+    CR_Downward,    ///< This corresponds to "fpround.downward".
+    CR_Upward,      ///< This corresponds to "fpround.upward".
+    CR_ToZero       ///< This corresponds to "fpround.tozero".
+  };
+
 protected:
   BasicBlock *BB;
   BasicBlock::iterator InsertPt;
@@ -96,12 +120,18 @@
   MDNode *DefaultFPMathTag;
   FastMathFlags FMF;
 
+  bool IsFPConstrained;
+  ConstrainedExceptKind DefaultConstrainedExcept;
+  ConstrainedRoundingKind 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(CE_Unspecified),
+        DefaultConstrainedRounding(CR_Unspecified),
         DefaultOperandBundles(OpBundles) {
     ClearInsertionPoint();
   }
@@ -218,6 +248,35 @@
   /// 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 clearIsFPConstrained() { setIsFPConstrained(false); }
+
+  /// 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(ConstrainedExceptKind NewExcept) {
+    DefaultConstrainedExcept = NewExcept;
+  }
+
+  /// Set the rounding mode handling to be used with constrained floating point
+  void setDefaultConstrainedRounding(ConstrainedRoundingKind NewRounding) {
+    DefaultConstrainedRounding = NewRounding;
+  }
+
+  /// Get the exception handling used with constrained floating point
+  ConstrainedExceptKind getDefaultConstrainedExcept() {
+    return DefaultConstrainedExcept;
+  }
+
+  /// Get the rounding mode handling used with constrained floating point
+  ConstrainedRoundingKind getDefaultConstrainedRounding() {
+    return DefaultConstrainedRounding;
+  }
+
   //===--------------------------------------------------------------------===//
   // RAII helpers.
   //===--------------------------------------------------------------------===//
@@ -1045,6 +1104,68 @@
     return (LC && RC) ? Insert(Folder.CreateBinOp(Opc, LC, RC), Name) : nullptr;
   }
 
+  Value *getConstrainedRounding(ConstrainedRoundingKind Rounding) {
+    ConstrainedRoundingKind UseRounding = DefaultConstrainedRounding;
+
+    if (Rounding != CR_Unspecified)
+      UseRounding = Rounding;
+
+    MDNode *RoundingMD;
+    switch (UseRounding) {
+    case CR_Unspecified:
+    case CR_Dynamic:
+      RoundingMD =
+          MDNode::get(Context, MDString::get(Context, "round.dynamic"));
+      break;
+    case CR_ToNearest:
+      RoundingMD =
+          MDNode::get(Context, MDString::get(Context, "round.tonearest"));
+      break;
+    case CR_Downward:
+      RoundingMD =
+          MDNode::get(Context, MDString::get(Context, "round.downward"));
+      break;
+    case CR_Upward:
+      RoundingMD = MDNode::get(Context, MDString::get(Context, "round.upward"));
+      break;
+    case CR_ToZero:
+      RoundingMD = MDNode::get(Context, MDString::get(Context, "round.tozero"));
+      break;
+    }
+
+    MDString *RoundingMDS = cast<MDString>(RoundingMD->getOperand(0));
+
+    return MetadataAsValue::get(Context, RoundingMDS);
+  }
+
+  Value *getConstrainedExcept(ConstrainedExceptKind Except) {
+    ConstrainedExceptKind UseExcept = DefaultConstrainedExcept;
+
+    if (Except != CE_Unspecified)
+      UseExcept = Except;
+
+    MDNode *ExceptMD;
+    switch (UseExcept) {
+    case CE_Unspecified:
+    case CE_Strict:
+      ExceptMD =
+          MDNode::get(Context, MDString::get(Context, "fpexcept.strict"));
+      break;
+    case CE_Ignore:
+      ExceptMD =
+          MDNode::get(Context, MDString::get(Context, "fpexcept.ignore"));
+      break;
+    case CE_MayTrap:
+      ExceptMD =
+          MDNode::get(Context, MDString::get(Context, "fpexcept.maytrap"));
+      break;
+    }
+
+    MDString *ExceptMDS = cast<MDString>(ExceptMD->getOperand(0));
+
+    return MetadataAsValue::get(Context, ExceptMDS);
+  }
+
 public:
   Value *CreateAdd(Value *LHS, Value *RHS, const Twine &Name = "",
                    bool HasNUW = false, bool HasNSW = false) {
@@ -1247,6 +1368,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 +1381,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 +1393,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 +1406,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 +1418,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 +1431,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 +1443,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 +1456,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 +1468,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 +1481,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 +1501,18 @@
     return Insert(BinOp, Name);
   }
 
+  CallInst *CreateConstrainedFPBinOp(
+      Intrinsic::ID ID, Value *L, Value *R, Instruction *FMFSource = nullptr,
+      const Twine &Name = "", ConstrainedRoundingKind Rounding = CR_Unspecified,
+      ConstrainedExceptKind Except = CE_Unspecified) {
+
+    Value *RoundingV = getConstrainedRounding(Rounding);
+    Value *ExceptV = getConstrainedExcept(Except);
+
+    return CreateIntrinsic(ID, {L->getType()}, {L, R, RoundingV, ExceptV},
+                           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
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to