[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