[llvm] [InstCombine] Ensure Safe Handling of Flags in foldFNegIntoConstant (PR #94148)

Matt Arsenault via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 30 06:33:36 PDT 2024


https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/94148

>From 9a1e5b063f71b85c30648a8d8e1b6ed339c2140c Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 31 May 2024 22:42:04 +0530
Subject: [PATCH 1/5] [InstCombine] Ensure Safe Handling of Flags in
 foldFNegIntoConstant

---
 .../InstCombine/InstCombineAddSub.cpp         |  9 +++-
 llvm/test/Transforms/InstCombine/fneg.ll      | 41 +++++++++++++++++++
 2 files changed, 49 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index e5c3a20e1a6487..d06f00fbf55c4a 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2757,8 +2757,15 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   // Fold negation into constant operand.
   // -(X * C) --> X * (-C)
   if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
-    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
+    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
+      if (match(C, m_AnyZeroFP()) && I.getFastMathFlags().noInfs()) {
+        return BinaryOperator::CreateFMulFMF(
+            X, NegC,
+            I.getFastMathFlags() &
+                cast<FPMathOperator>(I.getOperand(0))->getFastMathFlags());
+      }
       return BinaryOperator::CreateFMulFMF(X, NegC, &I);
+    }
   // -(X / C) --> X / (-C)
   if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C))))
     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 3c4088832feaaa..eb93b5a1b03650 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -1109,4 +1109,45 @@ define float @test_fneg_select_maxnum(float %x) {
   ret float %neg
 }
 
+define float @test_fneg_ninf_mul_with_anyzero(float %a) {
+; CHECK-LABEL: @test_fneg_ninf_mul_with_anyzero(
+; CHECK-NEXT:    [[F:%.*]] = fmul float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    ret float [[F]]
+;
+  %mul = fmul float %a, 0.0
+  %f = fneg ninf float %mul
+  ret float %f
+}
+
+define float @test_fsub_ninf_mul_with_anyzero(float %a) {
+; CHECK-LABEL: @test_fsub_ninf_mul_with_anyzero(
+; CHECK-NEXT:    [[F2:%.*]] = fmul float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    ret float [[F2]]
+;
+  %f1 = fmul float %a, 0.000000
+  %f2 = fsub ninf float -0.000000, %f1
+  ret float %f2
+}
+
+define float @test_fneg_nnan_mul_with_anyzero(float %a) {
+; CHECK-LABEL: @test_fneg_nnan_mul_with_anyzero(
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[A:%.*]]
+; CHECK-NEXT:    [[F2:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
+; CHECK-NEXT:    ret float [[F2]]
+;
+  %f1 = fmul float %a, 0.000000
+  %f2 = fneg nnan float %f1
+  ret float %f2
+}
+
+define float @test_fneg_nsz_mul_with_anyzero(float %a) {
+; CHECK-LABEL: @test_fneg_nsz_mul_with_anyzero(
+; CHECK-NEXT:    [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    ret float [[F2]]
+;
+  %f1 = fmul float %a, 0.000000
+  %f2 = fneg nsz float %f1
+  ret float %f2
+}
+
 !0 = !{}

>From 0bf11f0b6e8649d068831be8e9e05817612c13ca Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 7 Jun 2024 16:16:44 +0530
Subject: [PATCH 2/5] Fixes logic and update tests

---
 .../InstCombine/InstCombineAddSub.cpp         | 24 +++++++++--
 llvm/test/Transforms/InstCombine/fneg.ll      | 42 +++++++++++++++++++
 2 files changed, 62 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index d06f00fbf55c4a..ac6184a4a4ca75 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2741,6 +2741,22 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   return TryToNarrowDeduceFlags();
 }
 
+static FastMathFlags getCorrectFMFForFNeg(FastMathFlags F1, FastMathFlags F2) {
+
+  FastMathFlags NF1 = F1 & F2;
+  FastMathFlags NF2 = F1 | F2;
+  if (NF2.noNaNs())
+    return F2;
+
+  if (NF1.any() || (F1.none() && F2.none()))
+    return NF1;
+
+  if (F1.all() || F2.all())
+    return F2;
+
+  return NF1;
+}
+
 /// This eliminates floating-point negation in either 'fneg(X)' or
 /// 'fsub(-0.0, X)' form by combining into a constant operand.
 static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
@@ -2758,11 +2774,11 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   // -(X * C) --> X * (-C)
   if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
-      if (match(C, m_AnyZeroFP()) && I.getFastMathFlags().noInfs()) {
-        return BinaryOperator::CreateFMulFMF(
+      FastMathFlags FMF = cast<FPMathOperator>(I.getOperand(0))->getFastMathFlags();
+      if (I.getFastMathFlags().noInfs()) {
+          return BinaryOperator::CreateFMulFMF(
             X, NegC,
-            I.getFastMathFlags() &
-                cast<FPMathOperator>(I.getOperand(0))->getFastMathFlags());
+            getCorrectFMFForFNeg(I.getFastMathFlags(), FMF));
       }
       return BinaryOperator::CreateFMulFMF(X, NegC, &I);
     }
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index eb93b5a1b03650..2bf9d8eef52dca 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -1150,4 +1150,46 @@ define float @test_fneg_nsz_mul_with_anyzero(float %a) {
   ret float %f2
 }
 
+define float @test_fneg_ninf_mul_nnan_with_const(float %a) {
+; CHECK-LABEL: @test_fneg_ninf_mul_nnan_with_const(
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg float [[A:%.*]]
+; CHECK-NEXT:    [[F2:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
+; CHECK-NEXT:    ret float [[F2]]
+;
+  %f1 = fmul nnan float %a, 0.000000
+  %f2 = fneg ninf float %f1
+  ret float %f2
+}
+
+define float @test_fneg_ninf_mul_nsz_with_const(float %a) {
+; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_const(
+; CHECK-NEXT:    [[F2:%.*]] = fmul float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    ret float [[F2]]
+;
+  %f1 = fmul nsz float %a, 0.000000
+  %f2 = fneg ninf float %f1
+  ret float %f2
+}
+
+define <2 x float> @test_fneg_ninf_mul_nnan_with_vec_const(<2 x float> %a) {
+; CHECK-LABEL: @test_fneg_ninf_mul_nnan_with_vec_const(
+; CHECK-NEXT:    [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[F2]]
+;
+  %f1 = fmul nnan <2 x float> %a, <float 0.000000, float -0.000000>
+  %f2 = fneg ninf <2 x float> %f1
+  ret <2 x float> %f2
+}
+
+define <2 x float> @test_fneg_ninf_mul_nsz_with_vec_const(<2 x float> %a) {
+; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_vec_const(
+; CHECK-NEXT:    [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[F2]]
+;
+  %f1 = fmul nsz <2 x float> %a, <float 0.000000, float -0.000000>
+  %f2 = fneg ninf <2 x float> %f1
+  ret <2 x float> %f2
+}
+
+
 !0 = !{}

>From 4656f8858d4f2a7cb9197c20edc76cc4dda8ddaa Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Tue, 9 Jul 2024 11:17:01 +0530
Subject: [PATCH 3/5] Propagate the `FNegOp` FMF flag instead of `I`.

---
 .../InstCombine/InstCombineAddSub.cpp         | 27 ++---------------
 llvm/test/Transforms/InstCombine/fneg.ll      | 30 ++++++++++++-------
 llvm/test/Transforms/InstCombine/fsub.ll      |  2 +-
 3 files changed, 22 insertions(+), 37 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index ac6184a4a4ca75..9237fa836d2479 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2741,22 +2741,6 @@ Instruction *InstCombinerImpl::visitSub(BinaryOperator &I) {
   return TryToNarrowDeduceFlags();
 }
 
-static FastMathFlags getCorrectFMFForFNeg(FastMathFlags F1, FastMathFlags F2) {
-
-  FastMathFlags NF1 = F1 & F2;
-  FastMathFlags NF2 = F1 | F2;
-  if (NF2.noNaNs())
-    return F2;
-
-  if (NF1.any() || (F1.none() && F2.none()))
-    return NF1;
-
-  if (F1.all() || F2.all())
-    return F2;
-
-  return NF1;
-}
-
 /// This eliminates floating-point negation in either 'fneg(X)' or
 /// 'fsub(-0.0, X)' form by combining into a constant operand.
 static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
@@ -2773,15 +2757,8 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   // Fold negation into constant operand.
   // -(X * C) --> X * (-C)
   if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
-    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
-      FastMathFlags FMF = cast<FPMathOperator>(I.getOperand(0))->getFastMathFlags();
-      if (I.getFastMathFlags().noInfs()) {
-          return BinaryOperator::CreateFMulFMF(
-            X, NegC,
-            getCorrectFMFForFNeg(I.getFastMathFlags(), FMF));
-      }
-      return BinaryOperator::CreateFMulFMF(X, NegC, &I);
-    }
+    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
+      return BinaryOperator::CreateFMulFMF(X, NegC, FNegOp);
   // -(X / C) --> X / (-C)
   if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C))))
     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 2bf9d8eef52dca..9315467ece3a1c 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -41,7 +41,7 @@ define float @fmul_fneg(float %x) {
 
 define float @fmul_fsub_fmf(float %x) {
 ; CHECK-LABEL: @fmul_fsub_fmf(
-; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
+; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+01
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %m = fmul float %x, 42.0
@@ -51,7 +51,7 @@ define float @fmul_fsub_fmf(float %x) {
 
 define float @fmul_fneg_fmf(float %x) {
 ; CHECK-LABEL: @fmul_fneg_fmf(
-; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
+; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+01
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %m = fmul float %x, 42.0
@@ -1121,31 +1121,30 @@ define float @test_fneg_ninf_mul_with_anyzero(float %a) {
 
 define float @test_fsub_ninf_mul_with_anyzero(float %a) {
 ; CHECK-LABEL: @test_fsub_ninf_mul_with_anyzero(
-; CHECK-NEXT:    [[F2:%.*]] = fmul float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[F2]]
 ;
-  %f1 = fmul float %a, 0.000000
+  %f1 = fmul nsz float %a, 0.000000
   %f2 = fsub ninf float -0.000000, %f1
   ret float %f2
 }
 
 define float @test_fneg_nnan_mul_with_anyzero(float %a) {
 ; CHECK-LABEL: @test_fneg_nnan_mul_with_anyzero(
-; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[A:%.*]]
-; CHECK-NEXT:    [[F2:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
+; CHECK-NEXT:    [[F2:%.*]] = fmul ninf float [[A:%.*]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[F2]]
 ;
-  %f1 = fmul float %a, 0.000000
+  %f1 = fmul ninf float %a, 0.000000
   %f2 = fneg nnan float %f1
   ret float %f2
 }
 
 define float @test_fneg_nsz_mul_with_anyzero(float %a) {
 ; CHECK-LABEL: @test_fneg_nsz_mul_with_anyzero(
-; CHECK-NEXT:    [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    [[F2:%.*]] = fmul ninf float [[A:%.*]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[F2]]
 ;
-  %f1 = fmul float %a, 0.000000
+  %f1 = fmul ninf float %a, 0.000000
   %f2 = fneg nsz float %f1
   ret float %f2
 }
@@ -1163,7 +1162,7 @@ define float @test_fneg_ninf_mul_nnan_with_const(float %a) {
 
 define float @test_fneg_ninf_mul_nsz_with_const(float %a) {
 ; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_const(
-; CHECK-NEXT:    [[F2:%.*]] = fmul float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[F2]]
 ;
   %f1 = fmul nsz float %a, 0.000000
@@ -1183,7 +1182,7 @@ define <2 x float> @test_fneg_ninf_mul_nnan_with_vec_const(<2 x float> %a) {
 
 define <2 x float> @test_fneg_ninf_mul_nsz_with_vec_const(<2 x float> %a) {
 ; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_vec_const(
-; CHECK-NEXT:    [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    [[F2:%.*]] = fmul nsz <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
 ; CHECK-NEXT:    ret <2 x float> [[F2]]
 ;
   %f1 = fmul nsz <2 x float> %a, <float 0.000000, float -0.000000>
@@ -1191,5 +1190,14 @@ define <2 x float> @test_fneg_ninf_mul_nsz_with_vec_const(<2 x float> %a) {
   ret <2 x float> %f2
 }
 
+define <2 x float> @test_fneg_nnan_ninf_mul_with_vec_const(<2 x float> %a) {
+; CHECK-LABEL: @test_fneg_nnan_ninf_mul_with_vec_const(
+; CHECK-NEXT:    [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[F2]]
+;
+  %f1 = fmul <2 x float> %a, <float 0.000000, float -0.000000>
+  %f2 = fneg nnan ninf <2 x float> %f1
+  ret <2 x float> %f2
+}
 
 !0 = !{}
diff --git a/llvm/test/Transforms/InstCombine/fsub.ll b/llvm/test/Transforms/InstCombine/fsub.ll
index cffc63405ddcbc..b43ea2a13b99d2 100644
--- a/llvm/test/Transforms/InstCombine/fsub.ll
+++ b/llvm/test/Transforms/InstCombine/fsub.ll
@@ -98,7 +98,7 @@ define float @sub_sub_nsz(float %x, float %y, float %z) {
 
 define float @sub_add_neg_x(float %x, float %y) {
 ; CHECK-LABEL: @sub_add_neg_x(
-; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -5.000000e+00
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %mul = fmul float %x, 5.000000e+00

>From 0d761fb325203419254b4e43d300a87884747b9c Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 23 Aug 2024 13:41:59 +0530
Subject: [PATCH 4/5] Update Flag Propagation Logic

---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp |  8 ++++++--
 llvm/test/Transforms/InstCombine/fneg.ll              | 11 ++++++-----
 llvm/test/Transforms/InstCombine/fsub.ll              |  2 +-
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 9237fa836d2479..c1267c6bb06094 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2757,8 +2757,12 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   // Fold negation into constant operand.
   // -(X * C) --> X * (-C)
   if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
-    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
-      return BinaryOperator::CreateFMulFMF(X, NegC, FNegOp);
+    if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
+      FastMathFlags Flag = I.getFastMathFlags() | FNegOp->getFastMathFlags();
+      Flag.setNoInfs(I.getFastMathFlags().noInfs() &&
+                     FNegOp->getFastMathFlags().noInfs());
+      return BinaryOperator::CreateFMulFMF(X, NegC, Flag);
+    }
   // -(X / C) --> X / (-C)
   if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C))))
     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 9315467ece3a1c..60bda8eeea3286 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -41,7 +41,7 @@ define float @fmul_fneg(float %x) {
 
 define float @fmul_fsub_fmf(float %x) {
 ; CHECK-LABEL: @fmul_fsub_fmf(
-; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+01
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %m = fmul float %x, 42.0
@@ -51,7 +51,7 @@ define float @fmul_fsub_fmf(float %x) {
 
 define float @fmul_fneg_fmf(float %x) {
 ; CHECK-LABEL: @fmul_fneg_fmf(
-; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -4.200000e+01
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %m = fmul float %x, 42.0
@@ -1131,7 +1131,8 @@ define float @test_fsub_ninf_mul_with_anyzero(float %a) {
 
 define float @test_fneg_nnan_mul_with_anyzero(float %a) {
 ; CHECK-LABEL: @test_fneg_nnan_mul_with_anyzero(
-; CHECK-NEXT:    [[F2:%.*]] = fmul ninf float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    [[TMP1:%.*]] = fneg nnan float [[A:%.*]]
+; CHECK-NEXT:    [[F2:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
 ; CHECK-NEXT:    ret float [[F2]]
 ;
   %f1 = fmul ninf float %a, 0.000000
@@ -1141,7 +1142,7 @@ define float @test_fneg_nnan_mul_with_anyzero(float %a) {
 
 define float @test_fneg_nsz_mul_with_anyzero(float %a) {
 ; CHECK-LABEL: @test_fneg_nsz_mul_with_anyzero(
-; CHECK-NEXT:    [[F2:%.*]] = fmul ninf float [[A:%.*]], -0.000000e+00
+; CHECK-NEXT:    [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
 ; CHECK-NEXT:    ret float [[F2]]
 ;
   %f1 = fmul ninf float %a, 0.000000
@@ -1192,7 +1193,7 @@ define <2 x float> @test_fneg_ninf_mul_nsz_with_vec_const(<2 x float> %a) {
 
 define <2 x float> @test_fneg_nnan_ninf_mul_with_vec_const(<2 x float> %a) {
 ; CHECK-LABEL: @test_fneg_nnan_ninf_mul_with_vec_const(
-; CHECK-NEXT:    [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
 ; CHECK-NEXT:    ret <2 x float> [[F2]]
 ;
   %f1 = fmul <2 x float> %a, <float 0.000000, float -0.000000>
diff --git a/llvm/test/Transforms/InstCombine/fsub.ll b/llvm/test/Transforms/InstCombine/fsub.ll
index b43ea2a13b99d2..cffc63405ddcbc 100644
--- a/llvm/test/Transforms/InstCombine/fsub.ll
+++ b/llvm/test/Transforms/InstCombine/fsub.ll
@@ -98,7 +98,7 @@ define float @sub_sub_nsz(float %x, float %y, float %z) {
 
 define float @sub_add_neg_x(float %x, float %y) {
 ; CHECK-LABEL: @sub_add_neg_x(
-; CHECK-NEXT:    [[R:%.*]] = fmul float [[X:%.*]], -5.000000e+00
+; CHECK-NEXT:    [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
 ; CHECK-NEXT:    ret float [[R]]
 ;
   %mul = fmul float %x, 5.000000e+00

>From 8a40c659a51a7f68307290b20a92d5d9f641502c Mon Sep 17 00:00:00 2001
From: SahilPatidar <patidarsahil2001 at gmail.com>
Date: Fri, 27 Sep 2024 17:01:51 +0530
Subject: [PATCH 5/5] Refactor logic and add additional tests

---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp |  7 ++++---
 llvm/test/Transforms/InstCombine/fneg.ll              | 10 ++++++++++
 2 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index c1267c6bb06094..9e9c3fc7b25fba 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2758,9 +2758,10 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
   // -(X * C) --> X * (-C)
   if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
     if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
-      FastMathFlags Flag = I.getFastMathFlags() | FNegOp->getFastMathFlags();
-      Flag.setNoInfs(I.getFastMathFlags().noInfs() &&
-                     FNegOp->getFastMathFlags().noInfs());
+      FastMathFlags FMF = I.getFastMathFlags();
+      FastMathFlags OpFMF = FNegOp->getFastMathFlags();
+      FastMathFlags Flag = FMF | OpFMF;
+      Flag.setNoInfs(FMF.noInfs() && OpFMF.noInfs());
       return BinaryOperator::CreateFMulFMF(X, NegC, Flag);
     }
   // -(X / C) --> X / (-C)
diff --git a/llvm/test/Transforms/InstCombine/fneg.ll b/llvm/test/Transforms/InstCombine/fneg.ll
index 60bda8eeea3286..4d68faf178d9cf 100644
--- a/llvm/test/Transforms/InstCombine/fneg.ll
+++ b/llvm/test/Transforms/InstCombine/fneg.ll
@@ -1201,4 +1201,14 @@ define <2 x float> @test_fneg_nnan_ninf_mul_with_vec_const(<2 x float> %a) {
   ret <2 x float> %f2
 }
 
+define <2 x float> @test_fneg_nnan_ninf_mul_ninf_with_vec_const(<2 x float> %a) {
+; CHECK-LABEL: @test_fneg_nnan_ninf_mul_ninf_with_vec_const(
+; CHECK-NEXT:    [[F2:%.*]] = fmul nnan ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
+; CHECK-NEXT:    ret <2 x float> [[F2]]
+;
+  %f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>
+  %f2 = fneg nnan ninf <2 x float> %f1
+  ret <2 x float> %f2
+}
+
 !0 = !{}



More information about the llvm-commits mailing list