[llvm] [RISCV] Combine chained `V[SZ]EXT_VL` ops (PR #211583)

Sean Clarke via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 28 07:21:44 PDT 2026


https://github.com/xarkenz updated https://github.com/llvm/llvm-project/pull/211583

>From ad805eed9f8a850e271f865ee5d625512ed5bb06 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Wed, 22 Jul 2026 17:01:56 -0500
Subject: [PATCH 1/4] Add combine for nested V[SZ]EXT_VL

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 29 +++++++++++++++++++++
 1 file changed, 29 insertions(+)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 37505a5b187f8..157b67eaef388 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20702,6 +20702,32 @@ static SDValue performVFMADD_VLCombine(SDNode *N,
   return combineOp_VLToVWOp_VL(N, DCI, Subtarget);
 }
 
+static SDValue performVEXT_VLCombine(SDNode *N,
+                                     TargetLowering::DAGCombinerInfo &DCI,
+                                     const RISCVSubtarget &Subtarget) {
+  SDValue Inner = N->getOperand(0);
+  SDValue Mask = N->getOperand(1);
+  SDValue VL = N->getOperand(2);
+
+  // Combine (vext_vl (vext_vl x, m, vl), m, vl) -> (vext_vl x, m, vl)
+  // where vext_vl is either vsext_vl or vzext_vl.
+  using namespace SDPatternMatch;
+  SDValue Src;
+  if (!sd_match(Inner, m_OneUse(m_Node(N->getOpcode(), m_Value(Src),
+                                       m_Specific(Mask), m_Specific(VL)))))
+    return SDValue();
+
+  MVT SrcVT = Src.getSimpleValueType();
+  MVT DstVT = N->getSimpleValueType(0);
+  unsigned Factor = DstVT.getScalarSizeInBits() / SrcVT.getScalarSizeInBits();
+
+  // Only vf2, vf4, vf8 are legal with RVV.
+  if (Factor != 2 && Factor != 4 && Factor != 8)
+    return SDValue();
+
+  return DCI.DAG.getNode(N->getOpcode(), SDLoc(N), DstVT, Src, Mask, VL);
+}
+
 static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,
                                  const RISCVSubtarget &Subtarget) {
   assert(N->getOpcode() == ISD::SRA && "Unexpected opcode");
@@ -23482,6 +23508,9 @@ SDValue RISCVTargetLowering::PerformDAGCombine(SDNode *N,
   case RISCVISD::VFWADD_W_VL:
   case RISCVISD::VFWSUB_W_VL:
     return combineOp_VLToVWOp_VL(N, DCI, Subtarget);
+  case RISCVISD::VSEXT_VL:
+  case RISCVISD::VZEXT_VL:
+    return performVEXT_VLCombine(N, DCI, Subtarget);
   case ISD::LOAD:
   case ISD::STORE: {
     if (DCI.isAfterLegalizeDAG())

>From 107b89de316d616cffb0a3114f4fc34810d5d00d Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Thu, 23 Jul 2026 11:40:42 -0500
Subject: [PATCH 2/4] Add opcode assert

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 10 +++++++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 157b67eaef388..2bee2722c9eb2 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20705,6 +20705,10 @@ static SDValue performVFMADD_VLCombine(SDNode *N,
 static SDValue performVEXT_VLCombine(SDNode *N,
                                      TargetLowering::DAGCombinerInfo &DCI,
                                      const RISCVSubtarget &Subtarget) {
+  unsigned Opcode = N->getOpcode();
+  assert((Opcode == RISCVISD::VSEXT_VL || Opcode == RISCVISD::VZEXT_VL) &&
+         "Unexpected opcode");
+
   SDValue Inner = N->getOperand(0);
   SDValue Mask = N->getOperand(1);
   SDValue VL = N->getOperand(2);
@@ -20713,8 +20717,8 @@ static SDValue performVEXT_VLCombine(SDNode *N,
   // where vext_vl is either vsext_vl or vzext_vl.
   using namespace SDPatternMatch;
   SDValue Src;
-  if (!sd_match(Inner, m_OneUse(m_Node(N->getOpcode(), m_Value(Src),
-                                       m_Specific(Mask), m_Specific(VL)))))
+  if (!sd_match(Inner, m_OneUse(m_Node(Opcode, m_Value(Src), m_Specific(Mask),
+                                       m_Specific(VL)))))
     return SDValue();
 
   MVT SrcVT = Src.getSimpleValueType();
@@ -20725,7 +20729,7 @@ static SDValue performVEXT_VLCombine(SDNode *N,
   if (Factor != 2 && Factor != 4 && Factor != 8)
     return SDValue();
 
-  return DCI.DAG.getNode(N->getOpcode(), SDLoc(N), DstVT, Src, Mask, VL);
+  return DCI.DAG.getNode(Opcode, SDLoc(N), DstVT, Src, Mask, VL);
 }
 
 static SDValue performSRACombine(SDNode *N, SelectionDAG &DAG,

>From 358820d43c31dd1a96129f6865ea57fa70bae8c9 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Mon, 27 Jul 2026 09:43:32 -0500
Subject: [PATCH 3/4] Remove unnecessary factor check

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 7 -------
 1 file changed, 7 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 2bee2722c9eb2..b6d7ff71e8b29 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -20721,14 +20721,7 @@ static SDValue performVEXT_VLCombine(SDNode *N,
                                        m_Specific(VL)))))
     return SDValue();
 
-  MVT SrcVT = Src.getSimpleValueType();
   MVT DstVT = N->getSimpleValueType(0);
-  unsigned Factor = DstVT.getScalarSizeInBits() / SrcVT.getScalarSizeInBits();
-
-  // Only vf2, vf4, vf8 are legal with RVV.
-  if (Factor != 2 && Factor != 4 && Factor != 8)
-    return SDValue();
-
   return DCI.DAG.getNode(Opcode, SDLoc(N), DstVT, Src, Mask, VL);
 }
 

>From 3225811c2e76ae97bcecb432a16f4072dc87a776 Mon Sep 17 00:00:00 2001
From: Sean Clarke <sclarke at tenstorrent.com>
Date: Tue, 28 Jul 2026 09:20:41 -0500
Subject: [PATCH 4/4] Update tests after rebase

---
 .../CodeGen/RISCV/rvv/fixed-vectors-clmul.ll  | 11 ++++------
 .../CodeGen/RISCV/rvv/fixed-vectors-clmulh.ll | 22 +++++++------------
 2 files changed, 12 insertions(+), 21 deletions(-)

diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmul.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmul.ll
index eb0dc89d0bc33..cea53a0bf934f 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmul.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmul.ll
@@ -1949,13 +1949,10 @@ define <4 x i8> @clmulr_v4i8(<4 x i8> %a, <4 x i8> %b) nounwind {
 ;
 ; ZVBC-LABEL: clmulr_v4i8:
 ; ZVBC:       # %bb.0:
-; ZVBC-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
-; ZVBC-NEXT:    vzext.vf2 v10, v9
-; ZVBC-NEXT:    vzext.vf2 v12, v8
-; ZVBC-NEXT:    vsetvli zero, zero, e64, m2, ta, ma
-; ZVBC-NEXT:    vzext.vf4 v8, v10
-; ZVBC-NEXT:    vzext.vf4 v10, v12
-; ZVBC-NEXT:    vclmul.vv v8, v10, v8
+; ZVBC-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; ZVBC-NEXT:    vzext.vf8 v10, v9
+; ZVBC-NEXT:    vzext.vf8 v12, v8
+; ZVBC-NEXT:    vclmul.vv v8, v12, v10
 ; ZVBC-NEXT:    vsetvli zero, zero, e32, m1, ta, ma
 ; ZVBC-NEXT:    vnsrl.wi v10, v8, 0
 ; ZVBC-NEXT:    vsetvli zero, zero, e16, mf2, ta, ma
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmulh.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmulh.ll
index 0516628c5cd0b..027dd1038958c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmulh.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-clmulh.ll
@@ -5395,13 +5395,10 @@ define <4 x i8> @clmulh_v4i8(<4 x i8> %a, <4 x i8> %b) nounwind {
 ;
 ; ZVBC-LABEL: clmulh_v4i8:
 ; ZVBC:       # %bb.0:
-; ZVBC-NEXT:    vsetivli zero, 4, e16, mf2, ta, ma
-; ZVBC-NEXT:    vzext.vf2 v10, v9
-; ZVBC-NEXT:    vzext.vf2 v12, v8
-; ZVBC-NEXT:    vsetvli zero, zero, e64, m2, ta, ma
-; ZVBC-NEXT:    vzext.vf4 v8, v10
-; ZVBC-NEXT:    vzext.vf4 v10, v12
-; ZVBC-NEXT:    vclmul.vv v8, v10, v8
+; ZVBC-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; ZVBC-NEXT:    vzext.vf8 v10, v9
+; ZVBC-NEXT:    vzext.vf8 v12, v8
+; ZVBC-NEXT:    vclmul.vv v8, v12, v10
 ; ZVBC-NEXT:    vsetvli zero, zero, e32, m1, ta, ma
 ; ZVBC-NEXT:    vnsrl.wi v10, v8, 0
 ; ZVBC-NEXT:    vsetvli zero, zero, e16, mf2, ta, ma
@@ -5486,13 +5483,10 @@ define <4 x i16> @clmulh_v4i16(<4 x i16> %a, <4 x i16> %b) nounwind {
 ;
 ; ZVBC-LABEL: clmulh_v4i16:
 ; ZVBC:       # %bb.0:
-; ZVBC-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
-; ZVBC-NEXT:    vzext.vf2 v10, v9
-; ZVBC-NEXT:    vzext.vf2 v12, v8
-; ZVBC-NEXT:    vsetvli zero, zero, e64, m2, ta, ma
-; ZVBC-NEXT:    vzext.vf2 v8, v10
-; ZVBC-NEXT:    vzext.vf2 v10, v12
-; ZVBC-NEXT:    vclmul.vv v8, v10, v8
+; ZVBC-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
+; ZVBC-NEXT:    vzext.vf4 v10, v9
+; ZVBC-NEXT:    vzext.vf4 v12, v8
+; ZVBC-NEXT:    vclmul.vv v8, v12, v10
 ; ZVBC-NEXT:    vsetvli zero, zero, e32, m1, ta, ma
 ; ZVBC-NEXT:    vnsrl.wi v10, v8, 0
 ; ZVBC-NEXT:    vsetvli zero, zero, e16, mf2, ta, ma



More information about the llvm-commits mailing list