[llvm] [RISCV] Lower prefix slidedown shuffles using VL + tail-undisturbed (PR #210927)

Liao Chunyu via llvm-commits llvm-commits at lists.llvm.org
Tue Aug 4 01:18:49 PDT 2026


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

>From e7cd0f7a3228ca9cceef1bd2fa6b5b6fe2ce15eb Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Mon, 13 Jul 2026 06:34:03 +0000
Subject: [PATCH 1/5] [RISCV] Lower prefix slide-pair shuffle as vslidedown

 Example: vector_shuffle v8:v8i8, v9:v8i8 <9, 10, 2, 3, 4, 5, 6, 7>
 We get:  vmv.v.i v0, 3 + vslidedown.vi  .... v0.t
 VL is the number of 1s in MaskVals (the mask),
 when the high bits are consecutive 1s.
 This eliminates the mask-generating instruction.

 Reuse SrcInfo and MaskVals from the generic slide-pair
 path to derive the offset and VL
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   | 65 ++++++++++++++++
 .../rvv/fixed-vectors-shuffle-deinterleave.ll |  7 +-
 .../fixed-vectors-shuffle-deinterleave2.ll    | 77 +++++++++++--------
 .../rvv/fixed-vectors-shuffle-exact-vlen.ll   | 10 +--
 .../rvv/fixed-vectors-shuffle-transpose.ll    | 24 +++---
 5 files changed, 127 insertions(+), 56 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 5530ab1d79b7d..b42a63ba13f90 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5596,6 +5596,66 @@ static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT,
       DL, VT, convertFromScalableVector(SrcVT, Slidedown, DAG, Subtarget), 0);
 }
 
+// vector_shuffle v8:v8i8, v9:v8i8 <9, 10, 2, 3, 4, 5, 6, 7>
+// ->
+// vsetvli zero, 2, e8, mf2, tu, ma
+// vslideup.v1 v8, v9, 1
+static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
+    const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef<SDValue> MaskVals,
+    const std::array<std::pair<int, int>, 2> &SrcInfo, MVT ContainerVT,
+    const RISCVSubtarget &Subtarget, SelectionDAG &DAG) {
+  if (V1.isUndef() || V2.isUndef() || MaskVals.empty())
+    return SDValue();
+
+  const unsigned NumElts = VT.getVectorNumElements();
+  MVT XLenVT = Subtarget.getXLenVT();
+
+  int SlideAmt = SrcInfo[1].second;
+  // The first is not slide, the second is slidedown.
+  if (SrcInfo[0].second != 0 || SlideAmt >= 0)
+    return SDValue();
+
+  if (static_cast<unsigned>(-SlideAmt) >= NumElts)
+    return SDValue();
+
+  // Count the number of 1s in MaskVals,
+  // and ensure all 1s are at the beginning.
+  unsigned NumOnes = 0;
+  for (SDValue V : MaskVals) {
+    if (V.isUndef())
+      continue;
+    auto *C = dyn_cast<ConstantSDNode>(V);
+    if (!C)
+      return SDValue();
+    if (!C->isZero())
+      ++NumOnes;
+  }
+
+  if (NumOnes == 0 || NumOnes == NumElts || NumOnes > NumElts + SlideAmt)
+    return SDValue();
+
+  for (unsigned I = 0; I != NumOnes; ++I) {
+    auto *C = dyn_cast<ConstantSDNode>(MaskVals[I]);
+    if (!C || C->isZero())
+      return SDValue();
+  }
+
+  SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
+  SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
+
+  if (!Src1.hasOneUse())
+    return SDValue();
+
+  unsigned Policy =
+      RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED | RISCVVType::MASK_AGNOSTIC;
+  auto TrueMask = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).first;
+  SDValue VL = DAG.getConstant(NumOnes, DL, XLenVT);
+  SDValue Slidedown = getVSlidedown(DAG, Subtarget, DL, ContainerVT, Src1, Src2,
+                                    DAG.getConstant(-SlideAmt, DL, XLenVT),
+                                    TrueMask, VL, Policy);
+  return convertFromScalableVector(VT, Slidedown, DAG, Subtarget);
+}
+
 // Because vslideup leaves the destination elements at the start intact, we can
 // use it to perform shuffles that insert subvectors:
 //
@@ -6949,6 +7009,11 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
       MaskVals.push_back(DAG.getConstant(C, DL, XLenVT));
     }
     assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
+
+    if (SDValue V = lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
+            DL, VT, V1, V2, MaskVals, SrcInfo, ContainerVT, Subtarget, DAG))
+      return V;
+
     MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
     SDValue SelectMask = convertToScalableVector(
         ContainerVT.changeVectorElementType(MVT::i1),
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll
index 03fc1c30d8aac..d2d35c51ea3e0 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave.ll
@@ -431,11 +431,12 @@ entry:
 define void @deinterleave8_8_i8_two_source(ptr %in0, ptr %in1, ptr %out) {
 ; CHECK-LABEL: deinterleave8_8_i8_two_source:
 ; CHECK:       # %bb.0: # %entry
-; CHECK-NEXT:    vsetivli zero, 8, e8, mf2, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
+; CHECK-NEXT:    vsetivli zero, 8, e8, mf2, ta, ma
 ; CHECK-NEXT:    vle8.v v8, (a0)
 ; CHECK-NEXT:    vle8.v v9, (a1)
-; CHECK-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; CHECK-NEXT:    vsetivli zero, 1, e8, mf2, tu, ma
+; CHECK-NEXT:    vslidedown.vi v9, v8, 1
+; CHECK-NEXT:    vsetivli zero, 8, e8, mf2, ta, ma
 ; CHECK-NEXT:    vse8.v v9, (a2)
 ; CHECK-NEXT:    ret
 entry:
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave2.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave2.ll
index 94429ac18dd3d..37bf0f8d4899c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave2.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-deinterleave2.ll
@@ -294,11 +294,12 @@ define void @vnsrl_32_i32(ptr %in, ptr %out) {
 ; ZVE32F-LABEL: vnsrl_32_i32:
 ; ZVE32F:       # %bb.0: # %entry
 ; ZVE32F-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
-; ZVE32F-NEXT:    vmv.v.i v0, 1
 ; ZVE32F-NEXT:    vle32.v v8, (a0)
-; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, mu
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vslidedown.vi v9, v8, 2
-; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; ZVE32F-NEXT:    vsetivli zero, 1, e32, m1, tu, ma
+; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vse32.v v9, (a1)
 ; ZVE32F-NEXT:    ret
 ;
@@ -367,11 +368,12 @@ define void @vnsrl_32_float(ptr %in, ptr %out) {
 ; ZVE32F-LABEL: vnsrl_32_float:
 ; ZVE32F:       # %bb.0: # %entry
 ; ZVE32F-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
-; ZVE32F-NEXT:    vmv.v.i v0, 1
 ; ZVE32F-NEXT:    vle32.v v8, (a0)
-; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, mu
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vslidedown.vi v9, v8, 2
-; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; ZVE32F-NEXT:    vsetivli zero, 1, e32, m1, tu, ma
+; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vse32.v v9, (a1)
 ; ZVE32F-NEXT:    ret
 ;
@@ -429,11 +431,12 @@ define void @vnsrl_64_i64(ptr %in, ptr %out) {
 ; V-LABEL: vnsrl_64_i64:
 ; V:       # %bb.0: # %entry
 ; V-NEXT:    vsetivli zero, 4, e64, m1, ta, ma
-; V-NEXT:    vmv.v.i v0, 1
 ; V-NEXT:    vle64.v v8, (a0)
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vslidedown.vi v9, v8, 2
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vse64.v v9, (a1)
 ; V-NEXT:    ret
 ;
@@ -498,11 +501,12 @@ define void @vnsrl_64_double(ptr %in, ptr %out) {
 ; V-LABEL: vnsrl_64_double:
 ; V:       # %bb.0: # %entry
 ; V-NEXT:    vsetivli zero, 4, e64, m1, ta, ma
-; V-NEXT:    vmv.v.i v0, 1
 ; V-NEXT:    vle64.v v8, (a0)
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vslidedown.vi v9, v8, 2
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vse64.v v9, (a1)
 ; V-NEXT:    ret
 ;
@@ -1217,21 +1221,23 @@ entry:
 define void @vnsrl_32_i32_two_source(ptr %in0, ptr %in1, ptr %out) {
 ; V-LABEL: vnsrl_32_i32_two_source:
 ; V:       # %bb.0: # %entry
-; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
 ; V-NEXT:    vle32.v v8, (a0)
 ; V-NEXT:    vle32.v v9, (a1)
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e32, mf2, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
 ; V-NEXT:    vse32.v v9, (a2)
 ; V-NEXT:    ret
 ;
 ; ZVE32F-LABEL: vnsrl_32_i32_two_source:
 ; ZVE32F:       # %bb.0: # %entry
-; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, mu
-; ZVE32F-NEXT:    vmv.v.i v0, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vle32.v v8, (a0)
 ; ZVE32F-NEXT:    vle32.v v9, (a1)
-; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; ZVE32F-NEXT:    vsetivli zero, 1, e32, m1, tu, ma
+; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vse32.v v9, (a2)
 ; ZVE32F-NEXT:    ret
 ;
@@ -1289,21 +1295,23 @@ entry:
 define void @vnsrl_32_float_two_source(ptr %in0, ptr %in1, ptr %out) {
 ; V-LABEL: vnsrl_32_float_two_source:
 ; V:       # %bb.0: # %entry
-; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
 ; V-NEXT:    vle32.v v8, (a0)
 ; V-NEXT:    vle32.v v9, (a1)
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e32, mf2, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e32, mf2, ta, ma
 ; V-NEXT:    vse32.v v9, (a2)
 ; V-NEXT:    ret
 ;
 ; ZVE32F-LABEL: vnsrl_32_float_two_source:
 ; ZVE32F:       # %bb.0: # %entry
-; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, mu
-; ZVE32F-NEXT:    vmv.v.i v0, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vle32.v v8, (a0)
 ; ZVE32F-NEXT:    vle32.v v9, (a1)
-; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; ZVE32F-NEXT:    vsetivli zero, 1, e32, m1, tu, ma
+; ZVE32F-NEXT:    vslidedown.vi v9, v8, 1
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vse32.v v9, (a2)
 ; ZVE32F-NEXT:    ret
 ;
@@ -1361,21 +1369,23 @@ entry:
 define void @vnsrl_64_i64_two_source(ptr %in0, ptr %in1, ptr %out) {
 ; V-LABEL: vnsrl_64_i64_two_source:
 ; V:       # %bb.0: # %entry
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vle64.v v8, (a0)
 ; V-NEXT:    vle64.v v9, (a1)
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vse64.v v9, (a2)
 ; V-NEXT:    ret
 ;
 ; ZVE32F-LABEL: vnsrl_64_i64_two_source:
 ; ZVE32F:       # %bb.0: # %entry
-; ZVE32F-NEXT:    vsetivli zero, 4, e32, m1, ta, mu
-; ZVE32F-NEXT:    vmv.v.i v0, 3
+; ZVE32F-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vle32.v v8, (a0)
 ; ZVE32F-NEXT:    vle32.v v9, (a1)
-; ZVE32F-NEXT:    vslidedown.vi v9, v8, 2, v0.t
+; ZVE32F-NEXT:    vsetivli zero, 2, e32, m1, tu, ma
+; ZVE32F-NEXT:    vslidedown.vi v9, v8, 2
+; ZVE32F-NEXT:    vsetivli zero, 4, e32, m1, ta, ma
 ; ZVE32F-NEXT:    vse32.v v9, (a2)
 ; ZVE32F-NEXT:    ret
 ;
@@ -1432,11 +1442,12 @@ entry:
 define void @vnsrl_64_double_two_source(ptr %in0, ptr %in1, ptr %out) {
 ; V-LABEL: vnsrl_64_double_two_source:
 ; V:       # %bb.0: # %entry
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vle64.v v8, (a0)
 ; V-NEXT:    vle64.v v9, (a1)
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v9, v8, 1
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; V-NEXT:    vse64.v v9, (a2)
 ; V-NEXT:    ret
 ;
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
index 534eb5ca75fc4..ecb04f8c31235 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
@@ -229,9 +229,8 @@ define i64 @extract_any_extend_vector_inreg_v16i64(<16 x i64> %a0, i32 %a1) vsca
 ; RV32:       # %bb.0:
 ; RV32-NEXT:    vsetivli zero, 16, e64, m8, ta, ma
 ; RV32-NEXT:    vmv.v.i v16, 0
-; RV32-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; RV32-NEXT:    vmv.v.i v0, 1
-; RV32-NEXT:    vslidedown.vi v18, v15, 1, v0.t
+; RV32-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; RV32-NEXT:    vslidedown.vi v18, v15, 1
 ; RV32-NEXT:    vsetivli zero, 1, e64, m8, ta, ma
 ; RV32-NEXT:    vslidedown.vx v8, v16, a0
 ; RV32-NEXT:    li a0, 32
@@ -255,9 +254,8 @@ define i64 @extract_any_extend_vector_inreg_v16i64(<16 x i64> %a0, i32 %a1) vsca
 ; RV64-NEXT:    andi sp, sp, -128
 ; RV64-NEXT:    vsetivli zero, 16, e64, m8, ta, ma
 ; RV64-NEXT:    vmv.v.i v16, 0
-; RV64-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; RV64-NEXT:    vmv.v.i v0, 1
-; RV64-NEXT:    vslidedown.vi v18, v15, 1, v0.t
+; RV64-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; RV64-NEXT:    vslidedown.vi v18, v15, 1
 ; RV64-NEXT:    mv s1, sp
 ; RV64-NEXT:    vs8r.v v16, (s1)
 ; RV64-NEXT:    andi a0, a0, 15
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-transpose.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-transpose.ll
index ad7cf7eee5023..058fe1def6e58 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-transpose.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-transpose.ll
@@ -119,9 +119,8 @@ define <2 x i32> @trn1.v2i32(<2 x i32> %v0, <2 x i32> %v1) {
 define <2 x i32> @trn2.v2i32(<2 x i32> %v0, <2 x i32> %v1) {
 ; CHECK-LABEL: trn2.v2i32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 2, e32, mf2, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
-; CHECK-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; CHECK-NEXT:    vsetivli zero, 1, e32, mf2, tu, ma
+; CHECK-NEXT:    vslidedown.vi v9, v8, 1
 ; CHECK-NEXT:    vmv1r.v v8, v9
 ; CHECK-NEXT:    ret
   %tmp0 = shufflevector <2 x i32> %v0, <2 x i32> %v1, <2 x i32> <i32 1, i32 3>
@@ -164,10 +163,9 @@ define <2 x i64> @trn1.v2i64(<2 x i64> %v0, <2 x i64> %v1) {
 define <2 x i64> @trn2.v2i64(<2 x i64> %v0, <2 x i64> %v1) {
 ; CHECK-LABEL: trn2.v2i64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
-; CHECK-NEXT:    vslidedown.vi v9, v8, 1, v0.t
-; CHECK-NEXT:    vmv.v.v v8, v9
+; CHECK-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; CHECK-NEXT:    vslidedown.vi v9, v8, 1
+; CHECK-NEXT:    vmv1r.v v8, v9
 ; CHECK-NEXT:    ret
   %tmp0 = shufflevector <2 x i64> %v0, <2 x i64> %v1, <2 x i32> <i32 1, i32 3>
   ret <2 x i64> %tmp0
@@ -186,9 +184,8 @@ define <2 x float> @trn1.v2f32(<2 x float> %v0, <2 x float> %v1) {
 define <2 x float> @trn2.v2f32(<2 x float> %v0, <2 x float> %v1) {
 ; CHECK-LABEL: trn2.v2f32:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 2, e32, mf2, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
-; CHECK-NEXT:    vslidedown.vi v9, v8, 1, v0.t
+; CHECK-NEXT:    vsetivli zero, 1, e32, mf2, tu, ma
+; CHECK-NEXT:    vslidedown.vi v9, v8, 1
 ; CHECK-NEXT:    vmv1r.v v8, v9
 ; CHECK-NEXT:    ret
   %tmp0 = shufflevector <2 x float> %v0, <2 x float> %v1, <2 x i32> <i32 1, i32 3>
@@ -231,10 +228,9 @@ define <2 x double> @trn1.v2f64(<2 x double> %v0, <2 x double> %v1) {
 define <2 x double> @trn2.v2f64(<2 x double> %v0, <2 x double> %v1) {
 ; CHECK-LABEL: trn2.v2f64:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
-; CHECK-NEXT:    vslidedown.vi v9, v8, 1, v0.t
-; CHECK-NEXT:    vmv.v.v v8, v9
+; CHECK-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; CHECK-NEXT:    vslidedown.vi v9, v8, 1
+; CHECK-NEXT:    vmv1r.v v8, v9
 ; CHECK-NEXT:    ret
   %tmp0 = shufflevector <2 x double> %v0, <2 x double> %v1, <2 x i32> <i32 1, i32 3>
   ret <2 x double> %tmp0

>From 970ea75274d698b4892880b53136e27c45849e4a Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Thu, 23 Jul 2026 08:25:06 +0000
Subject: [PATCH 2/5] address comment from lukel97, use mask

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   | 64 ++++++++++---------
 .../rvv/fixed-vectors-shuffle-exact-vlen.ll   |  7 +-
 .../RISCV/rvv/vector-deinterleave-fixed.ll    | 20 +++---
 3 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index b42a63ba13f90..8d75e9337cb36 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5599,12 +5599,12 @@ static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT,
 // vector_shuffle v8:v8i8, v9:v8i8 <9, 10, 2, 3, 4, 5, 6, 7>
 // ->
 // vsetvli zero, 2, e8, mf2, tu, ma
-// vslideup.v1 v8, v9, 1
+// vslidedown.vi v8, v9, 1
 static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
-    const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef<SDValue> MaskVals,
+    const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef<int> Mask,
     const std::array<std::pair<int, int>, 2> &SrcInfo, MVT ContainerVT,
     const RISCVSubtarget &Subtarget, SelectionDAG &DAG) {
-  if (V1.isUndef() || V2.isUndef() || MaskVals.empty())
+  if (V1.isUndef() || V2.isUndef())
     return SDValue();
 
   const unsigned NumElts = VT.getVectorNumElements();
@@ -5615,44 +5615,46 @@ static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
   if (SrcInfo[0].second != 0 || SlideAmt >= 0)
     return SDValue();
 
-  if (static_cast<unsigned>(-SlideAmt) >= NumElts)
+  unsigned SlideDownAmt = -SlideAmt;
+  if (SlideDownAmt >= NumElts)
     return SDValue();
 
-  // Count the number of 1s in MaskVals,
-  // and ensure all 1s are at the beginning.
-  unsigned NumOnes = 0;
-  for (SDValue V : MaskVals) {
-    if (V.isUndef())
-      continue;
-    auto *C = dyn_cast<ConstantSDNode>(V);
-    if (!C)
-      return SDValue();
-    if (!C->isZero())
-      ++NumOnes;
+  // Check whether the leading lanes are consecutive lanes
+  // from the second slide.
+  auto IsSecondSlideLane = [&](unsigned I) {
+    int M = Mask[I];
+    if (M < 0)
+      return false;
+
+    int Src = M >= (int)NumElts;
+    int Diff = (int)I - (M % NumElts);
+    return Src == SrcInfo[1].first && Diff == SrcInfo[1].second;
+  };
+
+  unsigned VL = 0;
+  for (unsigned I = 0; I != NumElts; ++I) {
+    if (!IsSecondSlideLane(I))
+      break;
+    ++VL;
   }
 
-  if (NumOnes == 0 || NumOnes == NumElts || NumOnes > NumElts + SlideAmt)
+  if (VL == 0 || VL == NumElts || VL > NumElts - SlideDownAmt)
     return SDValue();
 
-  for (unsigned I = 0; I != NumOnes; ++I) {
-    auto *C = dyn_cast<ConstantSDNode>(MaskVals[I]);
-    if (!C || C->isZero())
+  for (unsigned I = VL; I != NumElts; ++I)
+    if (IsSecondSlideLane(I))
       return SDValue();
-  }
 
   SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
   SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
 
-  if (!Src1.hasOneUse())
-    return SDValue();
-
   unsigned Policy =
       RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED | RISCVVType::MASK_AGNOSTIC;
   auto TrueMask = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).first;
-  SDValue VL = DAG.getConstant(NumOnes, DL, XLenVT);
+  SDValue VLOp = DAG.getConstant(VL, DL, XLenVT);
   SDValue Slidedown = getVSlidedown(DAG, Subtarget, DL, ContainerVT, Src1, Src2,
-                                    DAG.getConstant(-SlideAmt, DL, XLenVT),
-                                    TrueMask, VL, Policy);
+                                    DAG.getConstant(SlideDownAmt, DL, XLenVT),
+                                    TrueMask, VLOp, Policy);
   return convertFromScalableVector(VT, Slidedown, DAG, Subtarget);
 }
 
@@ -5667,7 +5669,7 @@ static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
 // vector_shuffle v8:v8i8, v9:v8i8 <0, 1, 8, 9, 10, 5, 6, 7>
 // ->
 // vsetvli zero, 5, e8, mf2, tu, ma
-// vslideup.v1 v8, v9, 2
+// vslideup.vi v8, v9, 2
 static SDValue lowerVECTOR_SHUFFLEAsVSlideup(const SDLoc &DL, MVT VT,
                                              SDValue V1, SDValue V2,
                                              ArrayRef<int> Mask,
@@ -6990,6 +6992,10 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
           return V;
     }
 
+    if (SDValue V = lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
+            DL, VT, V1, V2, Mask, SrcInfo, ContainerVT, Subtarget, DAG))
+      return V;
+
     // Build the mask.  Note that vslideup unconditionally preserves elements
     // below the slide amount in the destination, and thus those elements are
     // undefined in the mask.  If the mask ends up all true (or undef), it
@@ -7010,10 +7016,6 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
     }
     assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
 
-    if (SDValue V = lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
-            DL, VT, V1, V2, MaskVals, SrcInfo, ContainerVT, Subtarget, DAG))
-      return V;
-
     MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
     SDValue SelectMask = convertToScalableVector(
         ContainerVT.changeVectorElementType(MVT::i1),
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
index ecb04f8c31235..6a296910ae382 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-shuffle-exact-vlen.ll
@@ -283,12 +283,13 @@ define i64 @extract_any_extend_vector_inreg_v16i64(<16 x i64> %a0, i32 %a1) vsca
 define <4 x double> @shuffles_add(<4 x double> %0, <4 x double> %1) vscale_range(2,2) {
 ; CHECK-LABEL: shuffles_add:
 ; CHECK:       # %bb.0:
-; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; CHECK-NEXT:    vmv.v.i v0, 1
+; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; CHECK-NEXT:    vmv1r.v v13, v10
 ; CHECK-NEXT:    vslideup.vi v13, v11, 1
-; CHECK-NEXT:    vslidedown.vi v11, v10, 1, v0.t
+; CHECK-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; CHECK-NEXT:    vslidedown.vi v11, v10, 1
 ; CHECK-NEXT:    vmv1r.v v10, v9
+; CHECK-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
 ; CHECK-NEXT:    vrgather.vi v12, v9, 0
 ; CHECK-NEXT:    vsetivli zero, 4, e64, m2, ta, ma
 ; CHECK-NEXT:    vfadd.vv v8, v12, v10
diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
index bce071e988f0e..0c61b3212307b 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
@@ -76,11 +76,13 @@ define {<2 x i64>, <2 x i64>} @vector_deinterleave_v2i64_v4i64(<4 x i64> %vec) {
 ; V:       # %bb.0:
 ; V-NEXT:    vsetivli zero, 2, e64, m2, ta, ma
 ; V-NEXT:    vslidedown.vi v10, v8, 2
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vmv1r.v v9, v8
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; V-NEXT:    vslideup.vi v9, v10, 1
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v10, v8, 1
+; V-NEXT:    vmv1r.v v8, v9
 ; V-NEXT:    vmv1r.v v9, v10
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
-; V-NEXT:    vslideup.vi v8, v10, 1
 ; V-NEXT:    ret
 ;
 ; ZVZIP-LABEL: vector_deinterleave_v2i64_v4i64:
@@ -802,11 +804,13 @@ define {<2 x double>, <2 x double>} @vector_deinterleave_v2f64_v4f64(<4 x double
 ; V:       # %bb.0:
 ; V-NEXT:    vsetivli zero, 2, e64, m2, ta, ma
 ; V-NEXT:    vslidedown.vi v10, v8, 2
-; V-NEXT:    vsetivli zero, 2, e64, m1, ta, mu
-; V-NEXT:    vmv.v.i v0, 1
+; V-NEXT:    vmv1r.v v9, v8
+; V-NEXT:    vsetivli zero, 2, e64, m1, ta, ma
+; V-NEXT:    vslideup.vi v9, v10, 1
+; V-NEXT:    vsetivli zero, 1, e64, m1, tu, ma
+; V-NEXT:    vslidedown.vi v10, v8, 1
+; V-NEXT:    vmv1r.v v8, v9
 ; V-NEXT:    vmv1r.v v9, v10
-; V-NEXT:    vslidedown.vi v9, v8, 1, v0.t
-; V-NEXT:    vslideup.vi v8, v10, 1
 ; V-NEXT:    ret
 ;
 ; ZVZIP-LABEL: vector_deinterleave_v2f64_v4f64:

>From bf509d323c7b8970b6ebd71af858b5027f6a472e Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Thu, 23 Jul 2026 08:32:01 +0000
Subject: [PATCH 3/5] address from mshockwave

---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 8d75e9337cb36..af2eb5219129f 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5602,7 +5602,7 @@ static SDValue lowerVECTOR_SHUFFLEAsVSlidedown(const SDLoc &DL, MVT VT,
 // vslidedown.vi v8, v9, 1
 static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
     const SDLoc &DL, MVT VT, SDValue V1, SDValue V2, ArrayRef<int> Mask,
-    const std::array<std::pair<int, int>, 2> &SrcInfo, MVT ContainerVT,
+    ArrayRef<std::pair<int, int>> SrcInfo, MVT ContainerVT,
     const RISCVSubtarget &Subtarget, SelectionDAG &DAG) {
   if (V1.isUndef() || V2.isUndef())
     return SDValue();

>From 21d0363d48161adaa239c914799d1d40b6edbf32 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Thu, 23 Jul 2026 08:53:32 +0000
Subject: [PATCH 4/5] delete empty line

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

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index af2eb5219129f..baf0d67a84be5 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -7015,7 +7015,6 @@ SDValue RISCVTargetLowering::lowerVECTOR_SHUFFLE(SDValue Op,
       MaskVals.push_back(DAG.getConstant(C, DL, XLenVT));
     }
     assert(MaskVals.size() == NumElts && "Unexpected select-like shuffle");
-
     MVT MaskVT = MVT::getVectorVT(MVT::i1, NumElts);
     SDValue SelectMask = convertToScalableVector(
         ContainerVT.changeVectorElementType(MVT::i1),

>From 4dea9165a209946aebbf5264ae49154a6ca5f7d2 Mon Sep 17 00:00:00 2001
From: Liao Chunyu <chunyu at iscas.ac.cn>
Date: Tue, 4 Aug 2026 07:14:11 +0000
Subject: [PATCH 5/5] merge to loops and other comments

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

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index baf0d67a84be5..62c344bd2fe46 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -5615,10 +5615,6 @@ static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
   if (SrcInfo[0].second != 0 || SlideAmt >= 0)
     return SDValue();
 
-  unsigned SlideDownAmt = -SlideAmt;
-  if (SlideDownAmt >= NumElts)
-    return SDValue();
-
   // Check whether the leading lanes are consecutive lanes
   // from the second slide.
   auto IsSecondSlideLane = [&](unsigned I) {
@@ -5632,19 +5628,22 @@ static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
   };
 
   unsigned VL = 0;
+  bool IsFirst = false;
   for (unsigned I = 0; I != NumElts; ++I) {
-    if (!IsSecondSlideLane(I))
-      break;
+    if (!IsSecondSlideLane(I)) {
+      IsFirst = true;
+      continue;
+    }
+
+    if (IsFirst)
+      return SDValue();
     ++VL;
   }
 
+  unsigned SlideDownAmt = -SlideAmt;
   if (VL == 0 || VL == NumElts || VL > NumElts - SlideDownAmt)
     return SDValue();
 
-  for (unsigned I = VL; I != NumElts; ++I)
-    if (IsSecondSlideLane(I))
-      return SDValue();
-
   SDValue Src1 = SrcInfo[0].first == 0 ? V1 : V2;
   SDValue Src2 = SrcInfo[1].first == 0 ? V1 : V2;
 
@@ -5652,6 +5651,8 @@ static SDValue lowerVECTOR_SHUFFLEAsPrefixVSlidedown(
       RISCVVType::TAIL_UNDISTURBED_MASK_UNDISTURBED | RISCVVType::MASK_AGNOSTIC;
   auto TrueMask = getDefaultVLOps(VT, ContainerVT, DL, DAG, Subtarget).first;
   SDValue VLOp = DAG.getConstant(VL, DL, XLenVT);
+  Src1 = convertToScalableVector(ContainerVT, Src1, DAG, Subtarget);
+  Src2 = convertToScalableVector(ContainerVT, Src2, DAG, Subtarget);
   SDValue Slidedown = getVSlidedown(DAG, Subtarget, DL, ContainerVT, Src1, Src2,
                                     DAG.getConstant(SlideDownAmt, DL, XLenVT),
                                     TrueMask, VLOp, Policy);



More information about the llvm-commits mailing list