[llvm] [RISCV] Avoid early split for fixed-length VECTOR_DEINTERLEAVE (PR #226453)

via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 04:55:41 PDT 2026


https://github.com/compilersutra updated https://github.com/llvm/llvm-project/pull/226453

>From 127eaba7694a115ff0d2c105e91fbe1c564d600e Mon Sep 17 00:00:00 2001
From: compilersutra <osc at compilersutra.com>
Date: Fri, 25 Sep 2026 17:00:01 +0530
Subject: [PATCH 1/2] [RISCV] Avoid early split for fixed-length
 VECTOR_DEINTERLEAVE

When the LMUL=8 limit forces a stack+vlseg path, keep the operands
intact and issue legal-sized vlseg chunks instead of splitting first.

Fixes #222938
---
 llvm/lib/Target/RISCV/RISCVISelLowering.cpp   | 139 ++++++++++++++
 .../RISCV/rvv/vector-deinterleave-fixed.ll    | 176 +++++++-----------
 2 files changed, 206 insertions(+), 109 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7a5905fc4b3ea5..7180fc565422e2 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -14719,6 +14719,145 @@ SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
   // If concatenating would exceed LMUL=8, we need to split.
   if ((ContainerVecVT.getSizeInBits().getKnownMinValue() * Factor) >
       (8 * RISCV::RVVBitsPerBlock)) {
+    // Fixed-length store+vlseg path: keep operands intact, spill them
+    // contiguously, then issue legal-sized vlseg at consecutive offsets.
+    // Avoids extract/concat tax from splitting operands first (#222938).
+    // Scalable keeps the shared recursive split below.
+    if (IsFixedVector) {
+      const unsigned NumElts = VecVT.getVectorNumElements();
+      MVT ElemVT = VecVT.getVectorElementType();
+
+      // Largest per-field element count with EMUL * NFIELDS <= 8.
+      // Only consider power-of-two lengths: useRVVForFixedLengthVectorVT
+      // rejects non-pow2 types, and MVT::getVectorVT may be invalid for
+      // arbitrary lengths.
+      unsigned ChunkElts = 0;
+      for (unsigned K = 1u << Log2_32(NumElts); K >= 1; K /= 2) {
+        MVT ChunkVT = MVT::getVectorVT(ElemVT, K);
+        if (!ChunkVT.isValid() || !ChunkVT.isFixedLengthVector() ||
+            !useRVVForFixedLengthVectorVT(ChunkVT))
+          continue;
+        MVT ChunkContainer = getContainerForFixedLengthVector(ChunkVT);
+        if (ChunkContainer.getSizeInBits().getKnownMinValue() * Factor <=
+            (8 * RISCV::RVVBitsPerBlock)) {
+          ChunkElts = K;
+          break;
+        }
+      }
+      assert(ChunkElts != 0 && "expected a legal fixed-length vlseg chunk");
+
+      MVT XLenVT = Subtarget.getXLenVT();
+      auto &MF = DAG.getMachineFunction();
+      SDValue Chain = DAG.getEntryNode();
+      Align Alignment = DAG.getReducedAlign(VecVT, /*UseABI=*/false);
+
+      ElementCount ActualConcatEC = VecVT.getVectorElementCount() * Factor;
+      EVT ConcatEVT =
+          EVT::getVectorVT(*DAG.getContext(), ElemVT, ActualConcatEC);
+      SDValue StackPtr =
+          DAG.CreateStackTemporary(ConcatEVT.getStoreSize(), Alignment);
+      auto FrameIndex = cast<FrameIndexSDNode>(StackPtr.getNode())->getIndex();
+      MachinePointerInfo PtrInfo =
+          MachinePointerInfo::getFixedStack(MF, FrameIndex);
+
+      TypeSize VecSize = VecVT.getStoreSize();
+      SDValue BasePtr = StackPtr;
+      MachinePointerInfo PI = PtrInfo;
+      SmallVector<SDValue, 8> Tokens(Factor);
+      for (auto [Idx, FieldOp] : enumerate(Op->op_values())) {
+        if (Idx) {
+          BasePtr = DAG.getObjectPtrOffset(DL, BasePtr, VecSize);
+          PI = PI.getWithOffset(VecSize);
+        }
+        Tokens[Idx] = DAG.getStore(Chain, DL, FieldOp, BasePtr, PI, Alignment);
+      }
+      Chain = DAG.getTokenFactor(DL, Tokens);
+
+      const unsigned ElemBytes = VecVT.getScalarStoreSize();
+
+      static const Intrinsic::ID VlsegIntrinsicsIds[] = {
+          Intrinsic::riscv_vlseg2_mask, Intrinsic::riscv_vlseg3_mask,
+          Intrinsic::riscv_vlseg4_mask, Intrinsic::riscv_vlseg5_mask,
+          Intrinsic::riscv_vlseg6_mask, Intrinsic::riscv_vlseg7_mask,
+          Intrinsic::riscv_vlseg8_mask};
+
+      SmallVector<SmallVector<SDValue, 4>, 8> Parts(Factor);
+      MVT ChunkVT = MVT::getVectorVT(ElemVT, ChunkElts);
+      MVT ChunkContainer = getContainerForFixedLengthVector(ChunkVT);
+      MVT WideVT =
+          MVT::getVectorVT(ElemVT, ChunkElts * PowerOf2Ceil(Factor));
+      assert(WideVT.isValid() && WideVT.isFixedLengthVector() &&
+             "expected legal wide passthru VT for chunked vlseg");
+      MVT WideContainer = getContainerForFixedLengthVector(WideVT);
+
+      for (unsigned Offset = 0; Offset < NumElts; Offset += ChunkElts) {
+        unsigned ThisChunkElts = std::min(ChunkElts, NumElts - Offset);
+
+        SDValue ChunkPtr = DAG.getObjectPtrOffset(
+            DL, StackPtr,
+            TypeSize::getFixed(static_cast<uint64_t>(Offset) * Factor *
+                               ElemBytes));
+        MachinePointerInfo ChunkPI = PtrInfo.getWithOffset(
+            static_cast<uint64_t>(Offset) * Factor * ElemBytes);
+
+        SDValue Mask, VL;
+        std::tie(Mask, VL) =
+            getDefaultVLOps(ChunkVT, ChunkContainer, DL, DAG, Subtarget);
+        // Partial final chunk: keep the legal (pow2) container, shrink VL.
+        if (ThisChunkElts != ChunkElts)
+          VL = DAG.getConstant(ThisChunkElts, DL, XLenVT);
+
+        SDValue Passthru = DAG.getUNDEF(WideContainer);
+
+        SDValue LoadOps[] = {
+            Chain,
+            DAG.getTargetConstant(VlsegIntrinsicsIds[Factor - 2], DL, XLenVT),
+            Passthru,
+            ChunkPtr,
+            Mask,
+            VL,
+            DAG.getTargetConstant(
+                RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC, DL,
+                XLenVT),
+            DAG.getTargetConstant(Log2_64(VecVT.getScalarSizeInBits()), DL,
+                                  XLenVT)};
+
+        unsigned Sz = Factor * ChunkContainer.getVectorMinNumElements() *
+                      ChunkContainer.getScalarSizeInBits();
+        EVT VecTupTy = MVT::getRISCVVectorTupleVT(Sz, Factor);
+
+        SDValue Load = DAG.getMemIntrinsicNode(
+            ISD::INTRINSIC_W_CHAIN, DL, DAG.getVTList({VecTupTy, MVT::Other}),
+            LoadOps, ElemVT, ChunkPI, Alignment, MachineMemOperand::MOLoad,
+            LocationSize::beforeOrAfterPointer());
+        Chain = Load.getValue(1);
+
+        for (unsigned i = 0; i != Factor; ++i) {
+          SDValue FieldRes =
+              DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL, ChunkContainer, Load,
+                          DAG.getTargetConstant(i, DL, MVT::i32));
+          SDValue Fixed = convertFromScalableVector(ChunkVT, FieldRes, DAG,
+                                                    Subtarget);
+          if (ThisChunkElts != ChunkElts) {
+            EVT NarrowVT =
+                EVT::getVectorVT(*DAG.getContext(), ElemVT, ThisChunkElts);
+            Fixed = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, NarrowVT, Fixed,
+                                DAG.getVectorIdxConstant(0, DL));
+          }
+          Parts[i].push_back(Fixed);
+        }
+      }
+
+      SmallVector<SDValue, 8> Res(Factor);
+      for (unsigned i = 0; i != Factor; ++i) {
+        if (Parts[i].size() == 1)
+          Res[i] = Parts[i][0];
+        else
+          Res[i] = DAG.getNode(ISD::CONCAT_VECTORS, DL, VecVT, Parts[i]);
+      }
+      return DAG.getMergeValues(Res, DL);
+    }
+
     SmallVector<SDValue, 8> Ops(Factor * 2);
     for (unsigned i = 0; i != Factor; ++i) {
       auto [OpLo, OpHi] = DAG.SplitVectorOperand(Op.getNode(), i);
diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
index bce071e988f0ef..1ea3769b7f621b 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
@@ -231,38 +231,38 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; RV32-NEXT:    sw s0, 632(sp) # 4-byte Folded Spill
 ; RV32-NEXT:    addi s0, sp, 640
 ; RV32-NEXT:    andi sp, sp, -128
-; RV32-NEXT:    addi a1, sp, 252
+; RV32-NEXT:    addi a1, sp, 60
 ; RV32-NEXT:    vsetivli zero, 1, e32, mf2, ta, ma
 ; RV32-NEXT:    vse32.v v23, (a1)
-; RV32-NEXT:    addi a1, sp, 248
+; RV32-NEXT:    addi a1, sp, 56
 ; RV32-NEXT:    vse32.v v22, (a1)
-; RV32-NEXT:    addi a1, sp, 244
+; RV32-NEXT:    addi a1, sp, 52
 ; RV32-NEXT:    vse32.v v21, (a1)
-; RV32-NEXT:    addi a1, sp, 240
+; RV32-NEXT:    addi a1, sp, 48
 ; RV32-NEXT:    vse32.v v20, (a1)
-; RV32-NEXT:    addi a1, sp, 236
+; RV32-NEXT:    addi a1, sp, 44
 ; RV32-NEXT:    vse32.v v19, (a1)
-; RV32-NEXT:    addi a1, sp, 232
+; RV32-NEXT:    addi a1, sp, 40
 ; RV32-NEXT:    vse32.v v18, (a1)
-; RV32-NEXT:    addi a1, sp, 228
+; RV32-NEXT:    addi a1, sp, 36
 ; RV32-NEXT:    vse32.v v17, (a1)
-; RV32-NEXT:    addi a1, sp, 224
+; RV32-NEXT:    addi a1, sp, 32
 ; RV32-NEXT:    vse32.v v16, (a1)
-; RV32-NEXT:    addi a1, sp, 220
+; RV32-NEXT:    addi a1, sp, 28
 ; RV32-NEXT:    vse32.v v15, (a1)
-; RV32-NEXT:    addi a1, sp, 216
+; RV32-NEXT:    addi a1, sp, 24
 ; RV32-NEXT:    vse32.v v14, (a1)
-; RV32-NEXT:    addi a1, sp, 212
+; RV32-NEXT:    addi a1, sp, 20
 ; RV32-NEXT:    vse32.v v13, (a1)
-; RV32-NEXT:    addi a1, sp, 208
+; RV32-NEXT:    addi a1, sp, 16
 ; RV32-NEXT:    vse32.v v12, (a1)
-; RV32-NEXT:    addi a1, sp, 204
+; RV32-NEXT:    addi a1, sp, 12
 ; RV32-NEXT:    vse32.v v11, (a1)
-; RV32-NEXT:    addi a1, sp, 200
+; RV32-NEXT:    addi a1, sp, 8
 ; RV32-NEXT:    vse32.v v10, (a1)
-; RV32-NEXT:    addi a1, sp, 196
+; RV32-NEXT:    addi a1, sp, 4
 ; RV32-NEXT:    vse32.v v9, (a1)
-; RV32-NEXT:    addi a1, sp, 192
+; RV32-NEXT:    mv a1, sp
 ; RV32-NEXT:    vse32.v v8, (a1)
 ; RV32-NEXT:    addi a2, a0, 64
 ; RV32-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
@@ -276,33 +276,19 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; RV32-NEXT:    vse32.v v8, (a3)
 ; RV32-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; RV32-NEXT:    vle32.v v8, (a0)
-; RV32-NEXT:    addi a3, sp, 64
-; RV32-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; RV32-NEXT:    vse32.v v8, (a3)
-; RV32-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
-; RV32-NEXT:    vle32.v v12, (a1)
-; RV32-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; RV32-NEXT:    vslidedown.vi v16, v12, 8
-; RV32-NEXT:    mv a1, sp
-; RV32-NEXT:    vslidedown.vi v8, v8, 8
-; RV32-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; RV32-NEXT:    vse32.v v12, (a1)
-; RV32-NEXT:    addi a3, sp, 32
-; RV32-NEXT:    vse32.v v16, (a3)
-; RV32-NEXT:    addi a3, sp, 96
+; RV32-NEXT:    addi a3, sp, 128
 ; RV32-NEXT:    vse32.v v8, (a3)
+; RV32-NEXT:    vle32.v v8, (a1)
+; RV32-NEXT:    addi a1, sp, 64
+; RV32-NEXT:    vse32.v v8, (a1)
 ; RV32-NEXT:    lw a0, 112(a0)
 ; RV32-NEXT:    sw a0, 432(sp)
-; RV32-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; RV32-NEXT:    vle32.v v8, (a2)
-; RV32-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; RV32-NEXT:    vslidedown.vi v12, v8, 8
-; RV32-NEXT:    addi a0, sp, 128
-; RV32-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; RV32-NEXT:    addi a0, sp, 192
 ; RV32-NEXT:    vse32.v v8, (a0)
 ; RV32-NEXT:    addi a0, sp, 160
-; RV32-NEXT:    vse32.v v12, (a0)
-; RV32-NEXT:    vlseg3e32.v v20, (a3)
+; RV32-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
+; RV32-NEXT:    vlseg3e32.v v20, (a0)
 ; RV32-NEXT:    vlseg3e32.v v12, (a1)
 ; RV32-NEXT:    vmv4r.v v28, v20
 ; RV32-NEXT:    vmv2r.v v30, v8
@@ -329,37 +315,37 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; RV64-NEXT:    addi a1, a0, 112
 ; RV64-NEXT:    vsetivli zero, 1, e32, mf2, ta, ma
 ; RV64-NEXT:    vle32.v v24, (a1)
-; RV64-NEXT:    addi a1, sp, 252
+; RV64-NEXT:    addi a1, sp, 60
 ; RV64-NEXT:    vse32.v v23, (a1)
-; RV64-NEXT:    addi a1, sp, 248
+; RV64-NEXT:    addi a1, sp, 56
 ; RV64-NEXT:    vse32.v v22, (a1)
-; RV64-NEXT:    addi a1, sp, 244
+; RV64-NEXT:    addi a1, sp, 52
 ; RV64-NEXT:    vse32.v v21, (a1)
-; RV64-NEXT:    addi a1, sp, 240
+; RV64-NEXT:    addi a1, sp, 48
 ; RV64-NEXT:    vse32.v v20, (a1)
-; RV64-NEXT:    addi a1, sp, 236
+; RV64-NEXT:    addi a1, sp, 44
 ; RV64-NEXT:    vse32.v v19, (a1)
-; RV64-NEXT:    addi a1, sp, 232
+; RV64-NEXT:    addi a1, sp, 40
 ; RV64-NEXT:    vse32.v v18, (a1)
-; RV64-NEXT:    addi a1, sp, 228
+; RV64-NEXT:    addi a1, sp, 36
 ; RV64-NEXT:    vse32.v v17, (a1)
-; RV64-NEXT:    addi a1, sp, 224
+; RV64-NEXT:    addi a1, sp, 32
 ; RV64-NEXT:    vse32.v v16, (a1)
-; RV64-NEXT:    addi a1, sp, 220
+; RV64-NEXT:    addi a1, sp, 28
 ; RV64-NEXT:    vse32.v v15, (a1)
-; RV64-NEXT:    addi a1, sp, 216
+; RV64-NEXT:    addi a1, sp, 24
 ; RV64-NEXT:    vse32.v v14, (a1)
-; RV64-NEXT:    addi a1, sp, 212
+; RV64-NEXT:    addi a1, sp, 20
 ; RV64-NEXT:    vse32.v v13, (a1)
-; RV64-NEXT:    addi a1, sp, 208
+; RV64-NEXT:    addi a1, sp, 16
 ; RV64-NEXT:    vse32.v v12, (a1)
-; RV64-NEXT:    addi a1, sp, 204
+; RV64-NEXT:    addi a1, sp, 12
 ; RV64-NEXT:    vse32.v v11, (a1)
-; RV64-NEXT:    addi a1, sp, 200
+; RV64-NEXT:    addi a1, sp, 8
 ; RV64-NEXT:    vse32.v v10, (a1)
-; RV64-NEXT:    addi a1, sp, 196
+; RV64-NEXT:    addi a1, sp, 4
 ; RV64-NEXT:    vse32.v v9, (a1)
-; RV64-NEXT:    addi a1, sp, 192
+; RV64-NEXT:    mv a1, sp
 ; RV64-NEXT:    vse32.v v8, (a1)
 ; RV64-NEXT:    addi a2, a0, 64
 ; RV64-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
@@ -376,30 +362,16 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; RV64-NEXT:    vse32.v v24, (a3)
 ; RV64-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; RV64-NEXT:    vle32.v v8, (a0)
+; RV64-NEXT:    addi a0, sp, 128
+; RV64-NEXT:    vse32.v v8, (a0)
+; RV64-NEXT:    vle32.v v8, (a1)
 ; RV64-NEXT:    addi a0, sp, 64
-; RV64-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
 ; RV64-NEXT:    vse32.v v8, (a0)
-; RV64-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
-; RV64-NEXT:    vle32.v v12, (a1)
-; RV64-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; RV64-NEXT:    vslidedown.vi v16, v12, 8
-; RV64-NEXT:    mv a0, sp
-; RV64-NEXT:    vslidedown.vi v8, v8, 8
-; RV64-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; RV64-NEXT:    vse32.v v12, (a0)
-; RV64-NEXT:    addi a1, sp, 32
-; RV64-NEXT:    vse32.v v16, (a1)
-; RV64-NEXT:    addi a1, sp, 96
-; RV64-NEXT:    vse32.v v8, (a1)
-; RV64-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; RV64-NEXT:    vle32.v v8, (a2)
-; RV64-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; RV64-NEXT:    vslidedown.vi v12, v8, 8
-; RV64-NEXT:    addi a2, sp, 128
+; RV64-NEXT:    addi a1, sp, 192
+; RV64-NEXT:    vse32.v v8, (a1)
+; RV64-NEXT:    addi a1, sp, 160
 ; RV64-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; RV64-NEXT:    vse32.v v8, (a2)
-; RV64-NEXT:    addi a2, sp, 160
-; RV64-NEXT:    vse32.v v12, (a2)
 ; RV64-NEXT:    vlseg3e32.v v20, (a1)
 ; RV64-NEXT:    vlseg3e32.v v12, (a0)
 ; RV64-NEXT:    vmv4r.v v28, v20
@@ -427,37 +399,37 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; ZVZIP-NEXT:    addi a1, a0, 112
 ; ZVZIP-NEXT:    vsetivli zero, 1, e32, mf2, ta, ma
 ; ZVZIP-NEXT:    vle32.v v24, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 252
+; ZVZIP-NEXT:    addi a1, sp, 60
 ; ZVZIP-NEXT:    vse32.v v23, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 248
+; ZVZIP-NEXT:    addi a1, sp, 56
 ; ZVZIP-NEXT:    vse32.v v22, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 244
+; ZVZIP-NEXT:    addi a1, sp, 52
 ; ZVZIP-NEXT:    vse32.v v21, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 240
+; ZVZIP-NEXT:    addi a1, sp, 48
 ; ZVZIP-NEXT:    vse32.v v20, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 236
+; ZVZIP-NEXT:    addi a1, sp, 44
 ; ZVZIP-NEXT:    vse32.v v19, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 232
+; ZVZIP-NEXT:    addi a1, sp, 40
 ; ZVZIP-NEXT:    vse32.v v18, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 228
+; ZVZIP-NEXT:    addi a1, sp, 36
 ; ZVZIP-NEXT:    vse32.v v17, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 224
+; ZVZIP-NEXT:    addi a1, sp, 32
 ; ZVZIP-NEXT:    vse32.v v16, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 220
+; ZVZIP-NEXT:    addi a1, sp, 28
 ; ZVZIP-NEXT:    vse32.v v15, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 216
+; ZVZIP-NEXT:    addi a1, sp, 24
 ; ZVZIP-NEXT:    vse32.v v14, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 212
+; ZVZIP-NEXT:    addi a1, sp, 20
 ; ZVZIP-NEXT:    vse32.v v13, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 208
+; ZVZIP-NEXT:    addi a1, sp, 16
 ; ZVZIP-NEXT:    vse32.v v12, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 204
+; ZVZIP-NEXT:    addi a1, sp, 12
 ; ZVZIP-NEXT:    vse32.v v11, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 200
+; ZVZIP-NEXT:    addi a1, sp, 8
 ; ZVZIP-NEXT:    vse32.v v10, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 196
+; ZVZIP-NEXT:    addi a1, sp, 4
 ; ZVZIP-NEXT:    vse32.v v9, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 192
+; ZVZIP-NEXT:    mv a1, sp
 ; ZVZIP-NEXT:    vse32.v v8, (a1)
 ; ZVZIP-NEXT:    addi a2, a0, 64
 ; ZVZIP-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
@@ -474,30 +446,16 @@ define {<15 x i32>, <15 x i32>, <15 x i32>} @vector_deinterleave3_v15i32_v45i32(
 ; ZVZIP-NEXT:    vse32.v v24, (a3)
 ; ZVZIP-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; ZVZIP-NEXT:    vle32.v v8, (a0)
+; ZVZIP-NEXT:    addi a0, sp, 128
+; ZVZIP-NEXT:    vse32.v v8, (a0)
+; ZVZIP-NEXT:    vle32.v v8, (a1)
 ; ZVZIP-NEXT:    addi a0, sp, 64
-; ZVZIP-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
 ; ZVZIP-NEXT:    vse32.v v8, (a0)
-; ZVZIP-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
-; ZVZIP-NEXT:    vle32.v v12, (a1)
-; ZVZIP-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; ZVZIP-NEXT:    vslidedown.vi v16, v12, 8
-; ZVZIP-NEXT:    mv a0, sp
-; ZVZIP-NEXT:    vslidedown.vi v8, v8, 8
-; ZVZIP-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; ZVZIP-NEXT:    vse32.v v12, (a0)
-; ZVZIP-NEXT:    addi a1, sp, 32
-; ZVZIP-NEXT:    vse32.v v16, (a1)
-; ZVZIP-NEXT:    addi a1, sp, 96
-; ZVZIP-NEXT:    vse32.v v8, (a1)
-; ZVZIP-NEXT:    vsetivli zero, 16, e32, m4, ta, ma
 ; ZVZIP-NEXT:    vle32.v v8, (a2)
-; ZVZIP-NEXT:    vsetivli zero, 8, e32, m4, ta, ma
-; ZVZIP-NEXT:    vslidedown.vi v12, v8, 8
-; ZVZIP-NEXT:    addi a2, sp, 128
+; ZVZIP-NEXT:    addi a1, sp, 192
+; ZVZIP-NEXT:    vse32.v v8, (a1)
+; ZVZIP-NEXT:    addi a1, sp, 160
 ; ZVZIP-NEXT:    vsetivli zero, 8, e32, m2, ta, ma
-; ZVZIP-NEXT:    vse32.v v8, (a2)
-; ZVZIP-NEXT:    addi a2, sp, 160
-; ZVZIP-NEXT:    vse32.v v12, (a2)
 ; ZVZIP-NEXT:    vlseg3e32.v v20, (a1)
 ; ZVZIP-NEXT:    vlseg3e32.v v12, (a0)
 ; ZVZIP-NEXT:    vmv4r.v v28, v20

>From 9a4154295d8b26a022f9fe2119b66d2c3dbf65a0 Mon Sep 17 00:00:00 2001
From: compilersutra <osc at compilersutra.com>
Date: Fri, 25 Sep 2026 17:18:42 +0530
Subject: [PATCH 2/2] [RISCV] clang-format fixed-length VECTOR_DEINTERLEAVE
 path

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

diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
index 7180fc565422e2..887288426f5ea1 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.cpp
@@ -14784,8 +14784,7 @@ SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
       SmallVector<SmallVector<SDValue, 4>, 8> Parts(Factor);
       MVT ChunkVT = MVT::getVectorVT(ElemVT, ChunkElts);
       MVT ChunkContainer = getContainerForFixedLengthVector(ChunkVT);
-      MVT WideVT =
-          MVT::getVectorVT(ElemVT, ChunkElts * PowerOf2Ceil(Factor));
+      MVT WideVT = MVT::getVectorVT(ElemVT, ChunkElts * PowerOf2Ceil(Factor));
       assert(WideVT.isValid() && WideVT.isFixedLengthVector() &&
              "expected legal wide passthru VT for chunked vlseg");
       MVT WideContainer = getContainerForFixedLengthVector(WideVT);
@@ -14816,9 +14815,9 @@ SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
             ChunkPtr,
             Mask,
             VL,
-            DAG.getTargetConstant(
-                RISCVVType::TAIL_AGNOSTIC | RISCVVType::MASK_AGNOSTIC, DL,
-                XLenVT),
+            DAG.getTargetConstant(RISCVVType::TAIL_AGNOSTIC |
+                                      RISCVVType::MASK_AGNOSTIC,
+                                  DL, XLenVT),
             DAG.getTargetConstant(Log2_64(VecVT.getScalarSizeInBits()), DL,
                                   XLenVT)};
 
@@ -14836,8 +14835,8 @@ SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
           SDValue FieldRes =
               DAG.getNode(RISCVISD::TUPLE_EXTRACT, DL, ChunkContainer, Load,
                           DAG.getTargetConstant(i, DL, MVT::i32));
-          SDValue Fixed = convertFromScalableVector(ChunkVT, FieldRes, DAG,
-                                                    Subtarget);
+          SDValue Fixed =
+              convertFromScalableVector(ChunkVT, FieldRes, DAG, Subtarget);
           if (ThisChunkElts != ChunkElts) {
             EVT NarrowVT =
                 EVT::getVectorVT(*DAG.getContext(), ElemVT, ThisChunkElts);



More information about the llvm-commits mailing list