[llvm] [InstCombine] Drop wrong ninf for `(-X / Y) + Z` (PR #228684)

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 12:07:53 PDT 2026


https://github.com/suogesi updated https://github.com/llvm/llvm-project/pull/228684

>From a5a6afc21a6cec19b13865d069e68daf8bbaad3f Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Sun, 4 Oct 2026 02:51:20 +0800
Subject: [PATCH 1/2] [InstCombine] Add tests for `(-X / Y) + Z` and its
 variants

---
 llvm/test/Transforms/InstCombine/fadd.ll | 100 +++++++++++++++++++++++
 1 file changed, 100 insertions(+)

diff --git a/llvm/test/Transforms/InstCombine/fadd.ll b/llvm/test/Transforms/InstCombine/fadd.ll
index 2311685db410d..a791c884ec05e 100644
--- a/llvm/test/Transforms/InstCombine/fadd.ll
+++ b/llvm/test/Transforms/InstCombine/fadd.ll
@@ -45,6 +45,31 @@ define double @fdiv_fneg1(double %x, double %y, double %pz) {
   ret double %r
 }
 
+define double @fdiv_fneg1_ninf(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg1_ninf(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv ninf double %nx, %y
+  %r  = fadd ninf double %z, %d
+  ret double %r
+}
+
+; Negative case: ninf of fadd shouldn't propagate to fdiv.
+define double @fdiv_fneg1_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg1_ninf_does_not_propagate_to_div(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv double %nx, %y
+  %r  = fadd ninf double %z, %d
+  ret double %r
+}
+
 ; Z + (Y / -X) --> Z - (Y / X)
 
 define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
@@ -61,6 +86,31 @@ define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %
   ret <2 x double> %r
 }
 
+define double @fdiv_fneg2_ninf(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg2_ninf(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv ninf double %y, %nx
+  %r  = fadd ninf double %z, %d
+  ret double %r
+}
+
+; Negative case: ninf of fadd shouldn't propagate to fdiv.
+define double @fdiv_fneg2_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg2_ninf_does_not_propagate_to_div(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv double %y, %nx
+  %r  = fadd ninf double %z, %d
+  ret double %r
+}
+
 ; Z + (-X * Y) --> Z - (X * Y)
 
 define double @fmul_fneg1(double %x, double %y, double %pz) {
@@ -111,6 +161,31 @@ define double @fdiv_fneg1_commute(double %x, double %y, double %pz) {
   ret double %r
 }
 
+define double @fdiv_fneg1_commute_ninf(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg1_commute_ninf(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv ninf double %nx, %y
+  %r  = fadd ninf double %d, %z
+  ret double %r
+}
+
+; Negative case: ninf of fadd shouldn't propagate to fdiv.
+define double @fdiv_fneg1_commute_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg1_commute_ninf_does_not_propagate_to_div(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv double %nx, %y
+  %r  = fadd ninf double %d, %z
+  ret double %r
+}
+
 ; (Y / -X) + Z --> Z - (Y / X)
 
 define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x double> %pz) {
@@ -127,6 +202,31 @@ define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x d
   ret <2 x double> %r
 }
 
+define double @fdiv_fneg2_commute_ninf(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg2_commute_ninf(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv ninf double %y, %nx
+  %r  = fadd ninf double %d, %z
+  ret double %r
+}
+
+; Negative case: ninf of fadd shouldn't propagate to fdiv.
+define double @fdiv_fneg2_commute_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
+; CHECK-LABEL: @fdiv_fneg2_commute_ninf_does_not_propagate_to_div(
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
+; CHECK-NEXT:    ret double [[R]]
+;
+  %nx = fneg double %x
+  %d  = fdiv double %y, %nx
+  %r  = fadd ninf double %d, %z
+  ret double %r
+}
+
 ; (-X * Y) + Z --> Z - (X * Y)
 
 define double @fmul_fneg1_commute(double %x, double %y, double %pz) {

>From 9fab7dae96280a18208b43439bb9064660a08667 Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Sun, 4 Oct 2026 02:56:49 +0800
Subject: [PATCH 2/2] [InstCombine] Drop wrong `ninf` for `(-X / Y) + Z`

When folding `(-X / Y) + Z` into `Z - X / Y`, it is treated as a
`BinaryOperator` so final `ninf` is same as the add instruction. This is
wrong when add instruction has `ninf` but div instruction doesn't have
`ninf`.

Take first operand as `FMFSource` so the optimized div instruction have
correct `ninf` now.
---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 10 +++++++++-
 llvm/test/Transforms/InstCombine/fadd.ll              |  8 ++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 27d884f66a9ce..a288fcf2483d4 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2166,7 +2166,15 @@ Instruction *InstCombinerImpl::visitFAdd(BinaryOperator &I) {
                          m_Value(Z))) ||
       match(&I, m_c_FAdd(m_OneUse(m_FDiv(m_Value(X), m_FNeg(m_Value(Y)))),
                          m_Value(Z)))) {
-    Value *XY = Builder.CreateFDivFMF(X, Y, &I);
+    Value *LHS = I.getOperand(0);
+    Value *RHS = I.getOperand(1);
+    BinaryOperator *DivInst;
+    if (auto *Inst = dyn_cast<BinaryOperator>(LHS)) {
+        DivInst = Inst;
+    } else {
+        DivInst = cast<BinaryOperator>(RHS);
+    }
+    Value *XY = Builder.CreateFDivFMF(X, Y, DivInst);
     return BinaryOperator::CreateFSubFMF(Z, XY, &I);
   }
 
diff --git a/llvm/test/Transforms/InstCombine/fadd.ll b/llvm/test/Transforms/InstCombine/fadd.ll
index a791c884ec05e..0ff51902d2c0a 100644
--- a/llvm/test/Transforms/InstCombine/fadd.ll
+++ b/llvm/test/Transforms/InstCombine/fadd.ll
@@ -60,7 +60,7 @@ define double @fdiv_fneg1_ninf(double %x, double %y, double %z) {
 ; Negative case: ninf of fadd shouldn't propagate to fdiv.
 define double @fdiv_fneg1_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fdiv_fneg1_ninf_does_not_propagate_to_div(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -101,7 +101,7 @@ define double @fdiv_fneg2_ninf(double %x, double %y, double %z) {
 ; Negative case: ninf of fadd shouldn't propagate to fdiv.
 define double @fdiv_fneg2_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fdiv_fneg2_ninf_does_not_propagate_to_div(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -176,7 +176,7 @@ define double @fdiv_fneg1_commute_ninf(double %x, double %y, double %z) {
 ; Negative case: ninf of fadd shouldn't propagate to fdiv.
 define double @fdiv_fneg1_commute_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fdiv_fneg1_commute_ninf_does_not_propagate_to_div(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -217,7 +217,7 @@ define double @fdiv_fneg2_commute_ninf(double %x, double %y, double %z) {
 ; Negative case: ninf of fadd shouldn't propagate to fdiv.
 define double @fdiv_fneg2_commute_ninf_does_not_propagate_to_div(double %x, double %y, double %z) {
 ; CHECK-LABEL: @fdiv_fneg2_commute_ninf_does_not_propagate_to_div(
-; CHECK-NEXT:    [[TMP1:%.*]] = fdiv ninf double [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT:    [[TMP1:%.*]] = fdiv double [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;



More information about the llvm-commits mailing list