[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 6da83e99130af4c5f67cfb7bd4f725283bd914ca..44baf639bbb2478aa87bd25e38f0c5579ac2fe5b 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 32e7b65d3ff6ad4764a19b37f3f5683c0e05b6fe..ef5f974419029d440f1f0657743407842a56c916 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) {