[IRBuilder] Fix CreateFDivFMF ignoring source FMF
authorDaniel Woodworth <daniel.woodworth@intel.com>
Tue, 13 Dec 2022 10:35:17 +0000 (11:35 +0100)
committerNikita Popov <npopov@redhat.com>
Tue, 13 Dec 2022 10:35:17 +0000 (11:35 +0100)
This change fixes a small bug in IRBuilderBase::CreateFDivFMF introduced
by accident in rGf34dcf27637f which caused the builder's default fast math
flags to be used for the new fdiv instruction instead of the ones from
the source instruction. It also adds unit testing for the CreateF*FMF
family of functions to more easily catch similar bugs in the future.

Differential Revision: https://reviews.llvm.org/D139583

llvm/include/llvm/IR/IRBuilder.h
llvm/unittests/IR/IRBuilderTest.cpp

index 6da83e9..44baf63 100644 (file)
@@ -1543,6 +1543,7 @@ public:
       return CreateConstrainedFPBinOp(Intrinsic::experimental_constrained_fdiv,
                                       L, R, FMFSource, Name);
 
+    FastMathFlags FMF = FMFSource->getFastMathFlags();
     if (Value *V = Folder.FoldBinOpFMF(Instruction::FDiv, L, R, FMF))
       return V;
     Instruction *I = setFPAttrs(BinaryOperator::CreateFDiv(L, R), nullptr, FMF);
index 32e7b65..ef5f974 100644 (file)
@@ -551,7 +551,7 @@ TEST_F(IRBuilderTest, UnaryOperators) {
 TEST_F(IRBuilderTest, FastMathFlags) {
   IRBuilder<> Builder(BB);
   Value *F, *FC;
-  Instruction *FDiv, *FAdd, *FCmp, *FCall;
+  Instruction *FDiv, *FAdd, *FCmp, *FCall, *FNeg, *FSub, *FMul, *FRem;
 
   F = Builder.CreateLoad(GV->getValueType(), GV);
   F = Builder.CreateFAdd(F, F);
@@ -732,6 +732,36 @@ TEST_F(IRBuilderTest, FastMathFlags) {
   EXPECT_TRUE(FDiv->hasNoNaNs());
   EXPECT_FALSE(FDiv->hasAllowReciprocal());
 
+  // Test that CreateF*FMF functions copy flags from the source instruction
+  // instead of using the builder default.
+  Instruction *const FMFSource = FAdd;
+  EXPECT_FALSE(Builder.getFastMathFlags().noNaNs());
+  EXPECT_TRUE(FMFSource->hasNoNaNs());
+
+  F = Builder.CreateFNegFMF(F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FNeg = cast<Instruction>(F);
+  EXPECT_TRUE(FNeg->hasNoNaNs());
+  F = Builder.CreateFAddFMF(F, F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FAdd = cast<Instruction>(F);
+  EXPECT_TRUE(FAdd->hasNoNaNs());
+  F = Builder.CreateFSubFMF(F, F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FSub = cast<Instruction>(F);
+  EXPECT_TRUE(FSub->hasNoNaNs());
+  F = Builder.CreateFMulFMF(F, F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FMul = cast<Instruction>(F);
+  EXPECT_TRUE(FMul->hasNoNaNs());
+  F = Builder.CreateFDivFMF(F, F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FDiv = cast<Instruction>(F);
+  EXPECT_TRUE(FDiv->hasNoNaNs());
+  F = Builder.CreateFRemFMF(F, F, FMFSource);
+  ASSERT_TRUE(isa<Instruction>(F));
+  FRem = cast<Instruction>(F);
+  EXPECT_TRUE(FRem->hasNoNaNs());
 }
 
 TEST_F(IRBuilderTest, WrapFlags) {