[llvm] [RISCV] Fix incorrect fixed vector lowering for VECTOR_DEINTERLEAVE (PR #207254)

Craig Topper via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 2 13:46:29 PDT 2026


================
@@ -13163,6 +13148,83 @@ SDValue RISCVTargetLowering::lowerVECTOR_DEINTERLEAVE(SDValue Op,
     return DAG.getMergeValues(Res, DL);
   }
 
+  // Convert to scalable vectors.
+  if (VecVT.isFixedLengthVector()) {
+    ElementCount OrigEC = VecVT.getVectorElementCount();
+    // Note that we cannot just convert individual operands to scalable vectors
+    // and call it a day: as scalable vector container is always equal or
+    // larger than the fixed vector subject, in the case where it is larger
+    // than fixed vector, this approach will create "padded" lanes in the
+    // conceptually concated vector created by VECTOR_DEINTERLEAVE per its
+    // semantics.
+
+    // First, concat operands into a larger (fixed) vector.
+    // There are two ways to do this: insert each operands into a larger
+    // (legal) vector one by one, or concat_vectors with additional
+    // operands to pad to legal type. The first way seems to lead to
+    // worse codegen primarily because we don't run DAGCombiner to
+    // simplify stuffs before some of the insert_subvector got
+    // lower into vslideup/down prematurely.
+    EVT ConcatVecEVT = EVT(VecVT).changeVectorElementCount(
+        *DAG.getContext(), OrigEC.multiplyCoefficientBy(Factor));
+    SmallVector<SDValue, 8> ConcatOps(Op->op_begin(), Op->op_end());
+    MVT ConcatVecVT;
+    if (!isTypeLegal(ConcatVecEVT)) {
+      // SplitVector should already be handled above.
+      assert(getTypeAction(*DAG.getContext(), ConcatVecEVT) ==
+             TargetLowering::TypeWidenVector);
+      ConcatVecVT =
+          getTypeToTransformTo(*DAG.getContext(), ConcatVecEVT).getSimpleVT();
+      ElementCount WidenedConcatEC = ConcatVecVT.getVectorElementCount();
+      // Both OrigEC and WidenedConcatEC are both derived from legal fixed
+      // vector types. A legal fixed vector's element count is always power of
+      // two, so WidenedConcatEC will always be a multiple of OrigEC.
+      assert(WidenedConcatEC.hasKnownScalarFactor(OrigEC));
+      unsigned NumTotalConcatOps = WidenedConcatEC.getKnownScalarFactor(OrigEC);
+      assert(NumTotalConcatOps > Factor);
+      ConcatOps.append(NumTotalConcatOps - Factor, DAG.getUNDEF(VecVT));
+    } else {
+      ConcatVecVT = ConcatVecEVT.getSimpleVT();
+    }
+
+    SDValue ConcatVec =
+        DAG.getNode(ISD::CONCAT_VECTORS, DL, ConcatVecVT, ConcatOps);
+    MVT ConcatContainerVT = getContainerForFixedLengthVector(ConcatVecVT);
+    ElementCount ConcatContainerEC = ConcatContainerVT.getVectorElementCount();
+    ConcatVec =
+        convertToScalableVector(ConcatContainerVT, ConcatVec, DAG, Subtarget);
+
+    MVT ContainerVT = getContainerForFixedLengthVector(VecVT);
+    ElementCount ContainerEC = ContainerVT.getVectorElementCount();
+
+    SmallVector<SDValue, 8> Ops(Factor);
+    // Then, we extract the new scalable sub-vectors.
+    for (unsigned i = 0U; i < Factor; ++i) {
+      ElementCount Idx = ContainerEC.multiplyCoefficientBy(i);
+      // Index might be out-of-bound. This usually happens on large
+      // VLEN where a single or a few VR registers is enough to caputre
----------------
topperc wrote:

```suggestion
      // VLEN where a single or a few VR registers is enough to capture
```

https://github.com/llvm/llvm-project/pull/207254


More information about the llvm-commits mailing list