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

via llvm-commits llvm-commits at lists.llvm.org
Sat Oct 3 02:25:49 PDT 2026


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

>From 71eb3b96351604fee4e9944a09488659e5dd6281 Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Sat, 3 Oct 2026 16:34:15 +0800
Subject: [PATCH 1/2] [InstCombine] Add tests for (-X / Y) + Z and its variants

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

diff --git a/llvm/test/Transforms/InstCombine/fadd.ll b/llvm/test/Transforms/InstCombine/fadd.ll
index c3f5cc742dd28..d4c97157a64de 100644
--- a/llvm/test/Transforms/InstCombine/fadd.ll
+++ b/llvm/test/Transforms/InstCombine/fadd.ll
@@ -45,6 +45,18 @@ 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 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 +73,18 @@ 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 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 +135,18 @@ 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 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 +163,18 @@ 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 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 38c6d53d3b62f71f9506616f793ce73478ce9078 Mon Sep 17 00:00:00 2001
From: Wu Haoyu <3540385658 at qq.com>
Date: Sat, 3 Oct 2026 16:52:12 +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.

Fixes #228521
---
 llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp | 4 +++-
 llvm/test/Transforms/InstCombine/fadd.ll              | 8 ++++----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
index 281e3b353f6dd..4622e3f02b87e 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp
@@ -2167,7 +2167,9 @@ 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 *Div = I.getOperand(0);
+    auto *DivInst = cast<BinaryOperator>(Div);
+    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 d4c97157a64de..22985a41b9cdf 100644
--- a/llvm/test/Transforms/InstCombine/fadd.ll
+++ b/llvm/test/Transforms/InstCombine/fadd.ll
@@ -47,7 +47,7 @@ define double @fdiv_fneg1(double %x, double %y, double %pz) {
 
 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:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -75,7 +75,7 @@ define <2 x double> @fdiv_fneg2(<2 x double> %x, <2 x double> %y, <2 x double> %
 
 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:    [[TMP1:%.*]] = fdiv double [[Y:%.*]], [[X:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -137,7 +137,7 @@ define double @fdiv_fneg1_commute(double %x, double %y, double %pz) {
 
 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:    [[TMP1:%.*]] = fdiv double [[X:%.*]], [[Y:%.*]]
 ; CHECK-NEXT:    [[R:%.*]] = fsub ninf double [[Z:%.*]], [[TMP1]]
 ; CHECK-NEXT:    ret double [[R]]
 ;
@@ -165,7 +165,7 @@ define <2 x double> @fdiv_fneg2_commute(<2 x double> %x, <2 x double> %y, <2 x d
 
 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:    [[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