[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