[llvm] [DAGCombine] Do not gate a pre-legalization FADD fold on FMUL legality (PR #218748)
Dennis Duda via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 07:14:17 PDT 2026
https://github.com/seritools updated https://github.com/llvm/llvm-project/pull/218748
>From c94f07dce76f705541a0ce57b55c5769507476bf Mon Sep 17 00:00:00 2001
From: Dennis Duda <git at seri.tools>
Date: Tue, 25 Aug 2026 19:56:57 +0200
Subject: [PATCH 1/2] [DAGCombine] Pre-commit test for the FADD-chain-to-FMUL
fold
---
.../CodeGen/RISCV/fadd-fmul-dagcombine.ll | 61 +++++++++++++++++++
1 file changed, 61 insertions(+)
create mode 100644 llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
diff --git a/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll b/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
new file mode 100644
index 0000000000000..4ff7dd48f9a64
--- /dev/null
+++ b/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
@@ -0,0 +1,61 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc -mtriple=riscv32 < %s | FileCheck -check-prefix=RV32I %s
+; RUN: llc -mtriple=riscv32 -mattr=+f < %s | FileCheck -check-prefix=RV32IF %s
+
+; Chains of FADDs of the same value can fold into a multiplication. RV32I
+; expands FMUL to a libcall, so the fold's gating on FMUL legality is
+; observable here; RV32IF has a legal FMUL for comparison.
+
+define float @fadd_chain_to_fmul(float %a) nounwind {
+; RV32I-LABEL: fadd_chain_to_fmul:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: mv s0, a0
+; RV32I-NEXT: mv a1, a0
+; RV32I-NEXT: call __addsf3
+; RV32I-NEXT: mv a1, s0
+; RV32I-NEXT: call __addsf3
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV32IF-LABEL: fadd_chain_to_fmul:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: lui a0, 263168
+; RV32IF-NEXT: fmv.w.x fa5, a0
+; RV32IF-NEXT: fmul.s fa0, fa0, fa5
+; RV32IF-NEXT: ret
+ %1 = fadd fast float %a, %a
+ %2 = fadd fast float %1, %a
+ ret float %2
+}
+
+define float @fmul_fadd_to_fmul(float %a) nounwind {
+; RV32I-LABEL: fmul_fadd_to_fmul:
+; RV32I: # %bb.0:
+; RV32I-NEXT: addi sp, sp, -16
+; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
+; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
+; RV32I-NEXT: mv s0, a0
+; RV32I-NEXT: lui a1, 263168
+; RV32I-NEXT: call __mulsf3
+; RV32I-NEXT: mv a1, s0
+; RV32I-NEXT: call __addsf3
+; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
+; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
+; RV32I-NEXT: addi sp, sp, 16
+; RV32I-NEXT: ret
+;
+; RV32IF-LABEL: fmul_fadd_to_fmul:
+; RV32IF: # %bb.0:
+; RV32IF-NEXT: lui a0, 264192
+; RV32IF-NEXT: fmv.w.x fa5, a0
+; RV32IF-NEXT: fmul.s fa0, fa0, fa5
+; RV32IF-NEXT: ret
+ %1 = fmul fast float %a, 3.0
+ %2 = fadd fast float %1, %a
+ ret float %2
+}
>From a6ae1f34a0475626a97530a00ec3c35112eb0644 Mon Sep 17 00:00:00 2001
From: Dennis Duda <git at seri.tools>
Date: Tue, 25 Aug 2026 20:08:42 +0200
Subject: [PATCH 2/2] [DAGCombine] Do not gate a pre-legalization FADD fold on
FMUL legality
---
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 3 ++-
llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll | 16 +++-------------
2 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 5567fcaf7fcb3..ca292fc81afa6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -19400,7 +19400,8 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
// We can fold chains of FADD's of the same value into multiplications.
// This transform is not safe in general because we are reducing the number
// of rounding steps.
- if (TLI.isOperationLegalOrCustom(ISD::FMUL, VT) && !N0CFP && !N1CFP) {
+ if ((!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FMUL, VT)) &&
+ !N0CFP && !N1CFP) {
if (N0.getOpcode() == ISD::FMUL) {
bool CFP00 = DAG.isConstantFPBuildVectorOrConstantFP(N0.getOperand(0));
bool CFP01 = DAG.isConstantFPBuildVectorOrConstantFP(N0.getOperand(1));
diff --git a/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll b/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
index 4ff7dd48f9a64..9afcd1f1f0d11 100644
--- a/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
+++ b/llvm/test/CodeGen/RISCV/fadd-fmul-dagcombine.ll
@@ -11,14 +11,9 @@ define float @fadd_chain_to_fmul(float %a) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
-; RV32I-NEXT: mv s0, a0
-; RV32I-NEXT: mv a1, a0
-; RV32I-NEXT: call __addsf3
-; RV32I-NEXT: mv a1, s0
-; RV32I-NEXT: call __addsf3
+; RV32I-NEXT: lui a1, 263168
+; RV32I-NEXT: call __mulsf3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
-; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
@@ -38,14 +33,9 @@ define float @fmul_fadd_to_fmul(float %a) nounwind {
; RV32I: # %bb.0:
; RV32I-NEXT: addi sp, sp, -16
; RV32I-NEXT: sw ra, 12(sp) # 4-byte Folded Spill
-; RV32I-NEXT: sw s0, 8(sp) # 4-byte Folded Spill
-; RV32I-NEXT: mv s0, a0
-; RV32I-NEXT: lui a1, 263168
+; RV32I-NEXT: lui a1, 264192
; RV32I-NEXT: call __mulsf3
-; RV32I-NEXT: mv a1, s0
-; RV32I-NEXT: call __addsf3
; RV32I-NEXT: lw ra, 12(sp) # 4-byte Folded Reload
-; RV32I-NEXT: lw s0, 8(sp) # 4-byte Folded Reload
; RV32I-NEXT: addi sp, sp, 16
; RV32I-NEXT: ret
;
More information about the llvm-commits
mailing list