[llvm] [DAGCombine]Fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B)) (PR #173967)

Liao Chunyu via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 7 18:50:34 PST 2026


https://github.com/ChunyuLiao updated https://github.com/llvm/llvm-project/pull/173967

>From fc39d23acac3d0458545af8530b6678b41e4d775 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Tue, 30 Dec 2025 06:20:40 +0000
Subject: [PATCH 01/11] init testcase

---
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index 6f997082a3d35..532d165791fa0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -79,3 +79,15 @@ define <vscale x 8 x float> @vfnmadd(<vscale x 8 x float> %va, <vscale x 8 x flo
   %vd = call <vscale x 8 x float> @llvm.fma.v8f32(<vscale x 8 x float> %va, <vscale x 8 x float> splat (float -2.000000e+00), <vscale x 8 x float> %neg)
   ret <vscale x 8 x float> %vd
 }
+
+define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
+; CHECK-LABEL: vfsub_vf_nxv8f32:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    fneg.s fa5, fa5
+; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    ret
+  %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  ret <vscale x 8 x float> %vd
+}

>From 5162f9fef26705d2a111f9b1465b7787b17e6653 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Tue, 30 Dec 2025 06:21:48 +0000
Subject: [PATCH 02/11] [DAGCombine]Fold (fadd A, Splat(fneg(B))) -> (fsub A,
 Splat(B))

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 13 +++++++++++++
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll    |  3 +--
 2 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ee28260a74127..93044e17438ee 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18038,6 +18038,19 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
             N0, DAG, LegalOperations, ForCodeSize))
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
+  // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
+  if (VT.isVector() &&
+      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
+    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
+      SDValue SplatN0 = N1->getOperand(0);
+      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
+        SDValue Splat =
+            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
+        return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
+      }
+    }
+  }
+
   auto isFMulNegTwo = [](SDValue FMul) {
     if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL)
       return false;
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index 532d165791fa0..e7eac891674e8 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,9 +84,8 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    vfsub.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
   %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd

>From 596bdccc0ba30601584f8a678cade8d2c63b7bae Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 31 Dec 2025 08:53:20 +0000
Subject: [PATCH 03/11] Revert "[DAGCombine]Fold (fadd A, Splat(fneg(B))) ->
 (fsub A, Splat(B))"

This reverts commit 53feacfeb2b638ce1a60bde313a52b8cadc4a283.
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 13 -------------
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll    |  3 ++-
 2 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 93044e17438ee..ee28260a74127 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18038,19 +18038,6 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
             N0, DAG, LegalOperations, ForCodeSize))
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
-  // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
-  if (VT.isVector() &&
-      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
-    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
-      SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
-        SDValue Splat =
-            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
-        return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
-      }
-    }
-  }
-
   auto isFMulNegTwo = [](SDValue FMul) {
     if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL)
       return false;
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index e7eac891674e8..532d165791fa0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,8 +84,9 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfsub.vf v8, v8, fa5
+; CHECK-NEXT:    vfadd.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
   %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd

>From 53613566151aca5b0d422e16389260075739b872 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 31 Dec 2025 09:49:57 +0000
Subject: [PATCH 04/11] [DAG]Add splat_vector to
 TargetLowering::getNegatedExpression splat_vector(fneg(x)) to
 splat_vector(x), then DAGCombine performs some optimizations using these
 results.

---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 13 +++++++++++++
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll       | 14 ++++++++++++--
 2 files changed, 25 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 94464e792c645..8e2aa3180fba5 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -7554,6 +7554,19 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
     Cost = NegatibleCost::Neutral;
     return CFP;
   }
+  case ISD::SPLAT_VECTOR: {
+    SDValue X = Op.getOperand(0);
+    if (!isOperationLegal(ISD::SPLAT_VECTOR, VT))
+      break;
+
+    NegatibleCost CostX = NegatibleCost::Expensive;
+    SDValue NegX =
+        getNegatedExpression(X, DAG, LegalOps, OptForSize, CostX, Depth);
+    if (!NegX || CostX >= NegatibleCost::Neutral)
+      break;
+    Cost = CostX;
+    return DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, NegX);
+  }
   case ISD::BUILD_VECTOR: {
     // Only permit BUILD_VECTOR of constants.
     if (llvm::any_of(Op->op_values(), [&](SDValue N) {
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index 532d165791fa0..bc91d620d0814 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,10 +84,20 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    vfsub.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
   %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd
 }
+
+define <vscale x 8 x float> @vfsub_vf(<vscale x 8 x float> %va) {
+; CHECK-LABEL: vfsub_vf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    ret
+  %vd = fsub <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  ret <vscale x 8 x float> %vd
+}

>From ce7cbf9a54960727f8072cff5fa20cbe653389a9 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Sun, 4 Jan 2026 09:07:42 +0000
Subject: [PATCH 05/11] Revert "[DAG]Add splat_vector to
 TargetLowering::getNegatedExpression"

This reverts commit 30f4c8f230eee7b3d76b43af781bfdf1b3d2454c.
---
 llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp | 13 -------------
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll       | 14 ++------------
 2 files changed, 2 insertions(+), 25 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 8e2aa3180fba5..94464e792c645 100644
--- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -7554,19 +7554,6 @@ SDValue TargetLowering::getNegatedExpression(SDValue Op, SelectionDAG &DAG,
     Cost = NegatibleCost::Neutral;
     return CFP;
   }
-  case ISD::SPLAT_VECTOR: {
-    SDValue X = Op.getOperand(0);
-    if (!isOperationLegal(ISD::SPLAT_VECTOR, VT))
-      break;
-
-    NegatibleCost CostX = NegatibleCost::Expensive;
-    SDValue NegX =
-        getNegatedExpression(X, DAG, LegalOps, OptForSize, CostX, Depth);
-    if (!NegX || CostX >= NegatibleCost::Neutral)
-      break;
-    Cost = CostX;
-    return DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, NegX);
-  }
   case ISD::BUILD_VECTOR: {
     // Only permit BUILD_VECTOR of constants.
     if (llvm::any_of(Op->op_values(), [&](SDValue N) {
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index bc91d620d0814..532d165791fa0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,20 +84,10 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfsub.vf v8, v8, fa5
-; CHECK-NEXT:    ret
-  %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
-  ret <vscale x 8 x float> %vd
-}
-
-define <vscale x 8 x float> @vfsub_vf(<vscale x 8 x float> %va) {
-; CHECK-LABEL: vfsub_vf:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
 ; CHECK-NEXT:    vfadd.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
-  %vd = fsub <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd
 }

>From eeef94802d4ff411e8f6af2828876df9bf6cebe0 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Mon, 5 Jan 2026 02:58:13 +0000
Subject: [PATCH 06/11] [DAGCombine]Fold (fadd A, Splat(fneg(B))) -> (fsub A,
 Splat(B)) At the same time,fold (fsub A, Splat(fneg(B))) -> (fadd A,
 Splat(B))

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 25 +++++++++++++++++++
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll    | 15 +++++++++--
 2 files changed, 38 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ee28260a74127..4fc0e85af7b25 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18038,6 +18038,19 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
             N0, DAG, LegalOperations, ForCodeSize))
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
+  // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
+  if (VT.isVector() &&
+      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
+    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
+      SDValue SplatN0 = N1->getOperand(0);
+      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
+        SDValue Splat =
+            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
+        return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
+      }
+    }
+  }
+
   auto isFMulNegTwo = [](SDValue FMul) {
     if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL)
       return false;
@@ -18278,6 +18291,18 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
           TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize))
     return DAG.getNode(ISD::FADD, DL, VT, N0, NegN1);
 
+  // fold (fsub A, Splat(fneg(B))) -> (fadd A, Splat(B))
+  if (VT.isVector() &&
+      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FADD, VT))) {
+    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
+      SDValue SplatN0 = N1->getOperand(0);
+      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
+        SDValue Splat =
+            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
+        return DAG.getNode(ISD::FADD, DL, VT, N0, Splat);
+      }
+    }
+  }
   // FSUB -> FMA combines:
   if (SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(N)) {
     AddToWorklist(Fused.getNode());
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index 532d165791fa0..b9f7e725405be 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,10 +84,21 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    vfsub.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
   %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd
 }
+
+
+define <vscale x 8 x float> @vfsub_vf(<vscale x 8 x float> %va) {
+; CHECK-LABEL: vfsub_vf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    ret
+  %vd = fsub <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  ret <vscale x 8 x float> %vd
+}

>From 3511e98ac18fae2fcfcfaa906d8b9bc35ad94278 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Mon, 5 Jan 2026 03:11:51 +0000
Subject: [PATCH 07/11] Add TLI.isFNegFree(VT)

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4fc0e85af7b25..38728427cb837 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18043,7 +18043,8 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
       (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
     if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
       SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
+      if (SplatN0.getOpcode() == ISD::FNEG &&
+          (TLI.isFNegFree(VT) || SplatN0.hasOneUse())) {
         SDValue Splat =
             DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
         return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
@@ -18296,7 +18297,8 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
       (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FADD, VT))) {
     if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
       SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
+      if (SplatN0.getOpcode() == ISD::FNEG &&
+          (TLI.isFNegFree(VT) || SplatN0.hasOneUse())) {
         SDValue Splat =
             DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
         return DAG.getNode(ISD::FADD, DL, VT, N0, Splat);

>From 8d5703d0439e3728bc3c39d7b9771380f683d20c Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 7 Jan 2026 01:33:05 +0000
Subject: [PATCH 08/11] Revert "Add TLI.isFNegFree(VT)"

This reverts commit 5649f0ae622474142b9ed13f0df09b374b4a5a81.
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 38728427cb837..4fc0e85af7b25 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18043,8 +18043,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
       (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
     if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
       SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG &&
-          (TLI.isFNegFree(VT) || SplatN0.hasOneUse())) {
+      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
         SDValue Splat =
             DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
         return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
@@ -18297,8 +18296,7 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
       (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FADD, VT))) {
     if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
       SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG &&
-          (TLI.isFNegFree(VT) || SplatN0.hasOneUse())) {
+      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
         SDValue Splat =
             DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
         return DAG.getNode(ISD::FADD, DL, VT, N0, Splat);

>From ec0fe7645de266fe7b877489d8e6dbfc95249bcf Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 7 Jan 2026 01:33:16 +0000
Subject: [PATCH 09/11] Revert "[DAGCombine]Fold (fadd A, Splat(fneg(B))) ->
 (fsub A, Splat(B))"

This reverts commit 4937d222e08a7a7a604920b7a443300be47a461f.
---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 25 -------------------
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll    | 15 ++---------
 2 files changed, 2 insertions(+), 38 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 4fc0e85af7b25..ee28260a74127 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18038,19 +18038,6 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
             N0, DAG, LegalOperations, ForCodeSize))
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
-  // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
-  if (VT.isVector() &&
-      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FSUB, VT))) {
-    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
-      SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
-        SDValue Splat =
-            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
-        return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
-      }
-    }
-  }
-
   auto isFMulNegTwo = [](SDValue FMul) {
     if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL)
       return false;
@@ -18291,18 +18278,6 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
           TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize))
     return DAG.getNode(ISD::FADD, DL, VT, N0, NegN1);
 
-  // fold (fsub A, Splat(fneg(B))) -> (fadd A, Splat(B))
-  if (VT.isVector() &&
-      (!LegalOperations || TLI.isOperationLegalOrCustom(ISD::FADD, VT))) {
-    if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
-      SDValue SplatN0 = N1->getOperand(0);
-      if (SplatN0.getOpcode() == ISD::FNEG && SplatN0.hasOneUse()) {
-        SDValue Splat =
-            DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
-        return DAG.getNode(ISD::FADD, DL, VT, N0, Splat);
-      }
-    }
-  }
   // FSUB -> FMA combines:
   if (SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(N)) {
     AddToWorklist(Fused.getNode());
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index b9f7e725405be..532d165791fa0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,21 +84,10 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfsub.vf v8, v8, fa5
-; CHECK-NEXT:    ret
-  %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
-  ret <vscale x 8 x float> %vd
-}
-
-
-define <vscale x 8 x float> @vfsub_vf(<vscale x 8 x float> %va) {
-; CHECK-LABEL: vfsub_vf:
-; CHECK:       # %bb.0:
-; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
 ; CHECK-NEXT:    vfadd.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
-  %vd = fsub <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd
 }

>From 4fbb519cc2bcc8c2ee8077692f742120d90a2a55 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Wed, 7 Jan 2026 02:05:13 +0000
Subject: [PATCH 10/11] [DAGCombine]Fold (fadd A, Splat(fneg(B))) -> (fsub A,
 Splat(B)) Fold (fsub A, Splat(fneg(B))) -> (fadd A, Splat(B))

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 22 +++++++++++++++++++
 llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll    | 15 +++++++++++--
 2 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index ee28260a74127..69a340e3d9daa 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18038,6 +18038,17 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
             N0, DAG, LegalOperations, ForCodeSize))
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
+  // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
+  if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
+    SDValue SplatN0 = N1->getOperand(0);
+    if (SDValue NegN0 = TLI.getCheaperNegatedExpression(
+            SplatN0, DAG, LegalOperations, ForCodeSize)) {
+      SDValue Splat =
+          DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
+      return DAG.getNode(ISD::FSUB, DL, VT, N0, Splat);
+    }
+  }
+
   auto isFMulNegTwo = [](SDValue FMul) {
     if (!FMul.hasOneUse() || FMul.getOpcode() != ISD::FMUL)
       return false;
@@ -18278,6 +18289,17 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
           TLI.getNegatedExpression(N1, DAG, LegalOperations, ForCodeSize))
     return DAG.getNode(ISD::FADD, DL, VT, N0, NegN1);
 
+  // fold (fsub A, Splat(fneg(B))) -> (fadd A, Splat(B))
+  if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
+    SDValue SplatN0 = N1->getOperand(0);
+    if (SDValue NegN0 = TLI.getCheaperNegatedExpression(
+            SplatN0, DAG, LegalOperations, ForCodeSize)) {
+      SDValue Splat =
+          DAG.getNode(ISD::SPLAT_VECTOR, DL, VT, SplatN0->getOperand(0));
+      return DAG.getNode(ISD::FADD, DL, VT, N0, Splat);
+    }
+  }
+
   // FSUB -> FMA combines:
   if (SDValue Fused = visitFSUBForFMACombine<EmptyMatchContext>(N)) {
     AddToWorklist(Fused.getNode());
diff --git a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
index 532d165791fa0..b9f7e725405be 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vsplats-zfa.ll
@@ -84,10 +84,21 @@ define <vscale x 8 x float> @vfsub_vf_nxv8f32(<vscale x 8 x float> %va) {
 ; CHECK-LABEL: vfsub_vf_nxv8f32:
 ; CHECK:       # %bb.0:
 ; CHECK-NEXT:    fli.s fa5, 2.0
-; CHECK-NEXT:    fneg.s fa5, fa5
 ; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
-; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    vfsub.vf v8, v8, fa5
 ; CHECK-NEXT:    ret
   %vd = fadd <vscale x 8 x float> %va, splat (float -2.000000e+00)
   ret <vscale x 8 x float> %vd
 }
+
+
+define <vscale x 8 x float> @vfsub_vf(<vscale x 8 x float> %va) {
+; CHECK-LABEL: vfsub_vf:
+; CHECK:       # %bb.0:
+; CHECK-NEXT:    fli.s fa5, 2.0
+; CHECK-NEXT:    vsetvli a0, zero, e32, m4, ta, ma
+; CHECK-NEXT:    vfadd.vf v8, v8, fa5
+; CHECK-NEXT:    ret
+  %vd = fsub <vscale x 8 x float> %va, splat (float -2.000000e+00)
+  ret <vscale x 8 x float> %vd
+}

>From 9b4a5c25c4407d8e00cc9cba39073921eca53ead Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Thu, 8 Jan 2026 02:18:42 +0000
Subject: [PATCH 11/11] Add todo for ISD::SPLAT_VECTOR

---
 llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 69a340e3d9daa..a8bd8914665aa 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -18039,6 +18039,7 @@ SDValue DAGCombiner::visitFADD(SDNode *N) {
       return DAG.getNode(ISD::FSUB, DL, VT, N1, NegN0);
 
   // fold (fadd A, Splat(fneg(B))) -> (fsub A, Splat(B))
+  // TODO: move ISD::SPLAT_VECTOR handling inside getCheaperNegatedExpression
   if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
     SDValue SplatN0 = N1->getOperand(0);
     if (SDValue NegN0 = TLI.getCheaperNegatedExpression(
@@ -18290,6 +18291,7 @@ SDValue DAGCombiner::visitFSUB(SDNode *N) {
     return DAG.getNode(ISD::FADD, DL, VT, N0, NegN1);
 
   // fold (fsub A, Splat(fneg(B))) -> (fadd A, Splat(B))
+  // TODO: move ISD::SPLAT_VECTOR handling inside getCheaperNegatedExpression
   if (N1.getOpcode() == ISD::SPLAT_VECTOR) {
     SDValue SplatN0 = N1->getOperand(0);
     if (SDValue NegN0 = TLI.getCheaperNegatedExpression(



More information about the llvm-commits mailing list