[llvm] [CodeGen] Expand unsupported (de)interleave intrinsics (PR #207439)
Kamlesh Kumar via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 6 02:11:57 PDT 2026
https://github.com/kamleshbhalui updated https://github.com/llvm/llvm-project/pull/207439
>From 64d28c518d2e2aa75d6f58d495452780324ffb07 Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Fri, 3 Jul 2026 17:42:09 +0000
Subject: [PATCH] [CodeGen] Expand unsupported (de)interleave intrinsics
Not all targets support lowering of (de)interleave natively.
Add a generic fallback that lowers them to shuffle, allowing
targets to reuse existing lowering paths.
---
llvm/include/llvm/CodeGen/TargetLowering.h | 6 +
.../SelectionDAG/SelectionDAGBuilder.cpp | 54 +++--
llvm/lib/Target/AArch64/AArch64ISelLowering.h | 5 +
llvm/lib/Target/RISCV/RISCVISelLowering.h | 4 +
.../AArch64/fixed-vector-deinterleave.ll | 111 +++++++++-
.../AArch64/fixed-vector-interleave.ll | 62 ++++++
.../rvv/fixed-vectors-deinterleave-load.ll | 20 +-
.../RISCV/rvv/vector-deinterleave-fixed.ll | 197 ++++++------------
8 files changed, 285 insertions(+), 174 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/TargetLowering.h b/llvm/include/llvm/CodeGen/TargetLowering.h
index 7a10a693934fd..839d8e323d749 100644
--- a/llvm/include/llvm/CodeGen/TargetLowering.h
+++ b/llvm/include/llvm/CodeGen/TargetLowering.h
@@ -3300,6 +3300,12 @@ class LLVM_ABI TargetLoweringBase {
/// Default to be the minimum interleave factor: 2.
virtual unsigned getMaxSupportedInterleaveFactor() const { return 2; }
+ /// Return true if target supports interleave intrinsics.
+ virtual bool isInterleaveIntrinsicSupported(unsigned /*Factor*/,
+ EVT VT) const {
+ return VT.isScalableVector();
+ }
+
/// Lower an interleaved load to target specific intrinsics. Return
/// true on success.
///
diff --git a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
index 8aa184423c60c..bdd2acc6d103d 100644
--- a/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
@@ -12976,34 +12976,44 @@ void SelectionDAGBuilder::visitVectorReverse(const CallInst &I) {
void SelectionDAGBuilder::visitVectorDeinterleave(const CallInst &I,
unsigned Factor) {
auto DL = getCurSDLoc();
+ const TargetLowering &TLI = DAG.getTargetLoweringInfo();
SDValue InVec = getValue(I.getOperand(0));
+ EVT InVT = InVec.getValueType();
SmallVector<EVT, 4> ValueVTs;
- ComputeValueVTs(DAG.getTargetLoweringInfo(), DAG.getDataLayout(), I.getType(),
- ValueVTs);
+ ComputeValueVTs(TLI, DAG.getDataLayout(), I.getType(), ValueVTs);
EVT OutVT = ValueVTs[0];
unsigned OutNumElts = OutVT.getVectorMinNumElements();
- SmallVector<SDValue, 4> SubVecs(Factor);
- for (unsigned i = 0; i != Factor; ++i) {
- assert(ValueVTs[i] == OutVT && "Expected VTs to be the same");
- SubVecs[i] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, OutVT, InVec,
- DAG.getVectorIdxConstant(OutNumElts * i, DL));
- }
-
- // Use VECTOR_SHUFFLE for fixed-length vectors with factor of 2 to benefit
- // from existing legalisation and combines.
- if (OutVT.isFixedLengthVector() && Factor == 2) {
- SDValue Even = DAG.getVectorShuffle(OutVT, DL, SubVecs[0], SubVecs[1],
- createStrideMask(0, 2, OutNumElts));
- SDValue Odd = DAG.getVectorShuffle(OutVT, DL, SubVecs[0], SubVecs[1],
- createStrideMask(1, 2, OutNumElts));
- SDValue Res = DAG.getMergeValues({Even, Odd}, getCurSDLoc());
- setValue(&I, Res);
+ // Use VECTOR_SHUFFLE for fixed-length vectors that the target does not lower
+ // natively.
+ if (!TLI.isInterleaveIntrinsicSupported(Factor, InVT)) {
+ unsigned WideNumElts = InVT.getVectorNumElements();
+
+ SmallVector<SDValue, 8> Results;
+ Results.reserve(Factor);
+ for (unsigned I = 0; I != Factor; ++I) {
+ SmallVector<int, 16> Mask(WideNumElts, -1);
+ for (unsigned J = 0; J != OutNumElts; ++J)
+ Mask[J] = I + J * Factor;
+ SDValue Shuffle =
+ DAG.getVectorShuffle(InVT, DL, InVec, DAG.getUNDEF(InVT), Mask);
+ Results.push_back(DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, OutVT, Shuffle,
+ DAG.getVectorIdxConstant(0, DL)));
+ }
+
+ setValue(&I, DAG.getMergeValues(Results, DL));
return;
}
+ SmallVector<SDValue, 4> SubVecs(Factor);
+ for (unsigned I = 0; I != Factor; ++I) {
+ assert(ValueVTs[I] == OutVT && "Expected VTs to be the same");
+ SubVecs[I] = DAG.getNode(ISD::EXTRACT_SUBVECTOR, DL, OutVT, InVec,
+ DAG.getVectorIdxConstant(OutNumElts * I, DL));
+ }
+
SDValue Res = DAG.getNode(ISD::VECTOR_DEINTERLEAVE, DL,
DAG.getVTList(ValueVTs), SubVecs);
setValue(&I, Res);
@@ -13023,13 +13033,13 @@ void SelectionDAGBuilder::visitVectorInterleave(const CallInst &I,
"Expected VTs to be the same");
}
- // Use VECTOR_SHUFFLE for fixed-length vectors with factor of 2 to benefit
- // from existing legalisation and combines.
- if (OutVT.isFixedLengthVector() && Factor == 2) {
+ // Use VECTOR_SHUFFLE for fixed-length vectors that the target does not lower
+ // natively.
+ if (!TLI.isInterleaveIntrinsicSupported(Factor, OutVT)) {
unsigned NumElts = InVT.getVectorMinNumElements();
SDValue V = DAG.getNode(ISD::CONCAT_VECTORS, DL, OutVT, InVecs);
setValue(&I, DAG.getVectorShuffle(OutVT, DL, V, DAG.getUNDEF(OutVT),
- createInterleaveMask(NumElts, 2)));
+ createInterleaveMask(NumElts, Factor)));
return;
}
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
index ad67705377661..809001795f8d9 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h
@@ -232,6 +232,11 @@ class AArch64TargetLowering : public TargetLowering {
unsigned getMaxSupportedInterleaveFactor() const override { return 4; }
+ bool isInterleaveIntrinsicSupported(unsigned Factor, EVT VT) const override {
+ return VT.isScalableVector() || Factor == 3 ||
+ (Factor > 2 && Factor % 2 == 0);
+ }
+
bool lowerInterleavedLoad(Instruction *Load, Value *Mask,
ArrayRef<ShuffleVectorInst *> Shuffles,
ArrayRef<unsigned> Indices, unsigned Factor,
diff --git a/llvm/lib/Target/RISCV/RISCVISelLowering.h b/llvm/lib/Target/RISCV/RISCVISelLowering.h
index 4e7912ed815dd..792b8a03b755f 100644
--- a/llvm/lib/Target/RISCV/RISCVISelLowering.h
+++ b/llvm/lib/Target/RISCV/RISCVISelLowering.h
@@ -432,6 +432,10 @@ class RISCVTargetLowering : public TargetLowering {
unsigned getMaxSupportedInterleaveFactor() const override { return 8; }
+ bool isInterleaveIntrinsicSupported(unsigned Factor, EVT VT) const override {
+ return VT.isScalableVector() || Factor > 2;
+ }
+
bool fallBackToDAGISel(const Instruction &Inst) const override;
bool lowerInterleavedLoad(Instruction *Load, Value *Mask,
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index 8c48cc609c75a..719e5dc67336e 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -5,10 +5,8 @@
define {<2 x half>, <2 x half>} @vector_deinterleave_v2f16_v4f16(<4 x half> %vec) {
; CHECK-SD-LABEL: vector_deinterleave_v2f16_v4f16:
; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: // kill: def $d0 killed $d0 def $q0
-; CHECK-SD-NEXT: dup v1.2s, v0.s[1]
-; CHECK-SD-NEXT: zip1 v2.4h, v0.4h, v1.4h
-; CHECK-SD-NEXT: trn2 v1.4h, v0.4h, v1.4h
+; CHECK-SD-NEXT: uzp1 v2.4h, v0.4h, v0.4h
+; CHECK-SD-NEXT: uzp2 v1.4h, v0.4h, v0.4h
; CHECK-SD-NEXT: fmov d0, d2
; CHECK-SD-NEXT: ret
;
@@ -48,9 +46,9 @@ define {<8 x half>, <8 x half>} @vector_deinterleave_v8f16_v16f16(<16 x half> %v
define {<2 x float>, <2 x float>} @vector_deinterleave_v2f32_v4f32(<4 x float> %vec) {
; CHECK-SD-LABEL: vector_deinterleave_v2f32_v4f32:
; CHECK-SD: // %bb.0:
-; CHECK-SD-NEXT: mov d1, v0.d[1]
-; CHECK-SD-NEXT: zip1 v2.2s, v0.2s, v1.2s
-; CHECK-SD-NEXT: zip2 v1.2s, v0.2s, v1.2s
+; CHECK-SD-NEXT: uzp1 v2.4s, v0.4s, v0.4s
+; CHECK-SD-NEXT: uzp2 v1.4s, v0.4s, v0.4s
+; CHECK-SD-NEXT: // kill: def $d1 killed $d1 killed $q1
; CHECK-SD-NEXT: fmov d0, d2
; CHECK-SD-NEXT: ret
;
@@ -846,3 +844,102 @@ define {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8
%retval = call {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} @llvm.vector.deinterleave8.v64bf16(<64 x bfloat> %ins7)
ret {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} %retval
}
+
+define {<4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>} @vector_deinterleave5_v20i16(<4 x i16> %a, <4 x i16> %b, <4 x i16> %c, <4 x i16> %d, <4 x i16> %e) {
+; CHECK-LABEL: vector_deinterleave5_v20i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov d6, d2
+; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3
+; CHECK-NEXT: adrp x8, .LCPI42_1
+; CHECK-NEXT: adrp x9, .LCPI42_2
+; CHECK-NEXT: fmov d5, d0
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI42_1]
+; CHECK-NEXT: adrp x8, .LCPI42_4
+; CHECK-NEXT: ldr q7, [x8, :lo12:.LCPI42_4]
+; CHECK-NEXT: adrp x10, .LCPI42_3
+; CHECK-NEXT: ldr q2, [x9, :lo12:.LCPI42_2]
+; CHECK-NEXT: // kill: def $d4 killed $d4 def $q4
+; CHECK-NEXT: adrp x8, .LCPI42_0
+; CHECK-NEXT: mov v5.d[1], v1.d[0]
+; CHECK-NEXT: mov v6.d[1], v3.d[0]
+; CHECK-NEXT: ldr q3, [x10, :lo12:.LCPI42_3]
+; CHECK-NEXT: tbl v7.16b, { v5.16b, v6.16b }, v7.16b
+; CHECK-NEXT: tbl v1.16b, { v5.16b, v6.16b }, v0.16b
+; CHECK-NEXT: tbl v2.16b, { v5.16b, v6.16b }, v2.16b
+; CHECK-NEXT: tbl v3.16b, { v5.16b, v6.16b }, v3.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI42_0]
+; CHECK-NEXT: tbl v0.16b, { v5.16b, v6.16b }, v0.16b
+; CHECK-NEXT: mov v7.h[3], v4.h[3]
+; CHECK-NEXT: mov v1.h[3], v4.h[0]
+; CHECK-NEXT: mov v2.h[3], v4.h[1]
+; CHECK-NEXT: mov v3.h[3], v4.h[2]
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT: // kill: def $d2 killed $d2 killed $q2
+; CHECK-NEXT: // kill: def $d3 killed $d3 killed $q3
+; CHECK-NEXT: fmov d4, d7
+; CHECK-NEXT: ret
+ %ins0 = call <20 x i16> @llvm.vector.insert.v20i16.v4i16(<20 x i16> poison, <4 x i16> %a, i64 0)
+ %ins1 = call <20 x i16> @llvm.vector.insert.v20i16.v4i16(<20 x i16> %ins0, <4 x i16> %b, i64 4)
+ %ins2 = call <20 x i16> @llvm.vector.insert.v20i16.v4i16(<20 x i16> %ins1, <4 x i16> %c, i64 8)
+ %ins3 = call <20 x i16> @llvm.vector.insert.v20i16.v4i16(<20 x i16> %ins2, <4 x i16> %d, i64 12)
+ %ins4 = call <20 x i16> @llvm.vector.insert.v20i16.v4i16(<20 x i16> %ins3, <4 x i16> %e, i64 16)
+ %retval = call {<4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>} @llvm.vector.deinterleave5.v20i16(<20 x i16> %ins4)
+ ret {<4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16>} %retval
+}
+
+define {<4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>} @vector_deinterleave7_v28i8(<4 x i8> %a, <4 x i8> %b, <4 x i8> %c, <4 x i8> %d, <4 x i8> %e, <4 x i8> %f, <4 x i8> %g) {
+; CHECK-LABEL: vector_deinterleave7_v28i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: uzp1 v19.8b, v0.8b, v1.8b
+; CHECK-NEXT: uzp1 v18.8b, v2.8b, v3.8b
+; CHECK-NEXT: // kill: def $d6 killed $d6 def $q6
+; CHECK-NEXT: uzp1 v4.8b, v4.8b, v5.8b
+; CHECK-NEXT: xtn v5.8b, v6.8h
+; CHECK-NEXT: mov b7, v19.b[4]
+; CHECK-NEXT: mov b16, v19.b[5]
+; CHECK-NEXT: mov b17, v19.b[6]
+; CHECK-NEXT: mov b0, v19.b[0]
+; CHECK-NEXT: mov b1, v19.b[1]
+; CHECK-NEXT: mov b2, v19.b[2]
+; CHECK-NEXT: mov b3, v19.b[3]
+; CHECK-NEXT: mov v7.b[2], v18.b[3]
+; CHECK-NEXT: mov v16.b[2], v18.b[4]
+; CHECK-NEXT: mov v17.b[2], v18.b[5]
+; CHECK-NEXT: mov v0.b[2], v19.b[7]
+; CHECK-NEXT: mov v1.b[2], v18.b[0]
+; CHECK-NEXT: mov v2.b[2], v18.b[1]
+; CHECK-NEXT: mov v3.b[2], v18.b[2]
+; CHECK-NEXT: mov v7.b[4], v4.b[2]
+; CHECK-NEXT: mov v16.b[4], v4.b[3]
+; CHECK-NEXT: mov v17.b[4], v4.b[4]
+; CHECK-NEXT: mov v0.b[4], v18.b[6]
+; CHECK-NEXT: mov v1.b[4], v18.b[7]
+; CHECK-NEXT: mov v2.b[4], v4.b[0]
+; CHECK-NEXT: mov v3.b[4], v4.b[1]
+; CHECK-NEXT: mov v7.b[6], v5.b[1]
+; CHECK-NEXT: mov v16.b[6], v5.b[2]
+; CHECK-NEXT: mov v17.b[6], v5.b[3]
+; CHECK-NEXT: mov v0.b[6], v4.b[5]
+; CHECK-NEXT: mov v1.b[6], v4.b[6]
+; CHECK-NEXT: mov v2.b[6], v4.b[7]
+; CHECK-NEXT: mov v3.b[6], v5.b[0]
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: // kill: def $d1 killed $d1 killed $q1
+; CHECK-NEXT: // kill: def $d2 killed $d2 killed $q2
+; CHECK-NEXT: // kill: def $d3 killed $d3 killed $q3
+; CHECK-NEXT: fmov d4, d7
+; CHECK-NEXT: fmov d5, d16
+; CHECK-NEXT: fmov d6, d17
+; CHECK-NEXT: ret
+ %ins0 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> poison, <4 x i8> %a, i64 0)
+ %ins1 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins0, <4 x i8> %b, i64 4)
+ %ins2 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins1, <4 x i8> %c, i64 8)
+ %ins3 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins2, <4 x i8> %d, i64 12)
+ %ins4 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins3, <4 x i8> %e, i64 16)
+ %ins5 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins4, <4 x i8> %f, i64 20)
+ %ins6 = call <28 x i8> @llvm.vector.insert.v28i8.v4i8(<28 x i8> %ins5, <4 x i8> %g, i64 24)
+ %retval = call {<4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>} @llvm.vector.deinterleave7.v28i8(<28 x i8> %ins6)
+ ret {<4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8>} %retval
+}
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
index 2d368c0ec456f..2e4f3757c9089 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
@@ -813,3 +813,65 @@ define <32 x i16> @interleave8_v32i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16
%retval = call <32 x i16> @llvm.vector.interleave8.v32i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16> %vec2, <4 x i16> %vec3, <4 x i16> %vec4, <4 x i16> %vec5, <4 x i16> %vec6, <4 x i16> %vec7)
ret <32 x i16> %retval
}
+
+define <20 x i16> @interleave5_v20i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16> %vec2, <4 x i16> %vec3, <4 x i16> %vec4) {
+; CHECK-LABEL: interleave5_v20i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $d4 killed $d4 killed $q3_q4 def $q3_q4
+; CHECK-NEXT: fmov d5, d3
+; CHECK-NEXT: fmov d7, d2
+; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT: adrp x9, .LCPI45_0
+; CHECK-NEXT: fmov d6, d0
+; CHECK-NEXT: adrp x10, .LCPI45_2
+; CHECK-NEXT: ldr q0, [x9, :lo12:.LCPI45_0]
+; CHECK-NEXT: adrp x9, .LCPI45_3
+; CHECK-NEXT: ldr q2, [x9, :lo12:.LCPI45_3]
+; CHECK-NEXT: adrp x9, .LCPI45_1
+; CHECK-NEXT: mov v7.d[1], v5.d[0]
+; CHECK-NEXT: mov v6.d[1], v1.d[0]
+; CHECK-NEXT: ldr q1, [x10, :lo12:.LCPI45_2]
+; CHECK-NEXT: tbl v3.16b, { v6.16b, v7.16b }, v0.16b
+; CHECK-NEXT: tbl v0.16b, { v6.16b, v7.16b }, v1.16b
+; CHECK-NEXT: tbl v1.16b, { v6.16b, v7.16b }, v2.16b
+; CHECK-NEXT: ldr q2, [x9, :lo12:.LCPI45_1]
+; CHECK-NEXT: mov v0.h[3], v4.h[3]
+; CHECK-NEXT: mov v1.h[4], v4.h[0]
+; CHECK-NEXT: tbl v2.16b, { v3.16b, v4.16b }, v2.16b
+; CHECK-NEXT: str d0, [x8, #32]
+; CHECK-NEXT: stp q1, q2, [x8]
+; CHECK-NEXT: ret
+ %retval = call <20 x i16> @llvm.vector.interleave5.v20i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16> %vec2, <4 x i16> %vec3, <4 x i16> %vec4)
+ ret <20 x i16> %retval
+}
+
+define <28 x i8> @interleave7_v28i8(<4 x i8> %vec0, <4 x i8> %vec1, <4 x i8> %vec2, <4 x i8> %vec3, <4 x i8> %vec4, <4 x i8> %vec5, <4 x i8> %vec6) {
+; CHECK-LABEL: interleave7_v28i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $d2 killed $d2 def $q2
+; CHECK-NEXT: // kill: def $d0 killed $d0 def $q0
+; CHECK-NEXT: // kill: def $d6 killed $d6 killed $q4_q5_q6 def $q4_q5_q6
+; CHECK-NEXT: // kill: def $d3 killed $d3 def $q3
+; CHECK-NEXT: // kill: def $d1 killed $d1 def $q1
+; CHECK-NEXT: adrp x9, .LCPI46_0
+; CHECK-NEXT: mov v2.d[1], v3.d[0]
+; CHECK-NEXT: mov v0.d[1], v1.d[0]
+; CHECK-NEXT: // kill: def $d5 killed $d5 killed $q4_q5_q6 def $q4_q5_q6
+; CHECK-NEXT: ldr q1, [x9, :lo12:.LCPI46_0]
+; CHECK-NEXT: // kill: def $d4 killed $d4 killed $q4_q5_q6 def $q4_q5_q6
+; CHECK-NEXT: adrp x9, .LCPI46_1
+; CHECK-NEXT: tbl v4.16b, { v4.16b, v5.16b, v6.16b }, v1.16b
+; CHECK-NEXT: uzp1 v3.16b, v0.16b, v2.16b
+; CHECK-NEXT: ldr q0, [x9, :lo12:.LCPI46_1]
+; CHECK-NEXT: adrp x9, .LCPI46_2
+; CHECK-NEXT: ldr q1, [x9, :lo12:.LCPI46_2]
+; CHECK-NEXT: tbl v0.16b, { v3.16b, v4.16b }, v0.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v1.16b
+; CHECK-NEXT: mov s2, v0.s[2]
+; CHECK-NEXT: str q1, [x8]
+; CHECK-NEXT: str d0, [x8, #16]
+; CHECK-NEXT: str s2, [x8, #24]
+; CHECK-NEXT: ret
+ %retval = call <28 x i8> @llvm.vector.interleave7.v28i8(<4 x i8> %vec0, <4 x i8> %vec1, <4 x i8> %vec2, <4 x i8> %vec3, <4 x i8> %vec4, <4 x i8> %vec5, <4 x i8> %vec6)
+ ret <28 x i8> %retval
+}
diff --git a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-deinterleave-load.ll b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-deinterleave-load.ll
index ffc9067a78604..d81ad8206ba6c 100644
--- a/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-deinterleave-load.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/fixed-vectors-deinterleave-load.ll
@@ -12,24 +12,16 @@ define {<16 x i1>, <16 x i1>} @vector_deinterleave_load_v16i1_v32i1(ptr %p) {
; CHECK-NEXT: li a1, 32
; CHECK-NEXT: vsetvli zero, a1, e8, m2, ta, ma
; CHECK-NEXT: vlm.v v0, (a0)
-; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vmv.v.i v8, 0
-; CHECK-NEXT: vmerge.vim v9, v8, 1, v0
-; CHECK-NEXT: vsetivli zero, 2, e8, mf4, ta, ma
-; CHECK-NEXT: vslidedown.vi v0, v0, 2
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vnsrl.wi v10, v9, 0
-; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vmerge.vim v8, v8, 1, v0
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vnsrl.wi v9, v9, 8
-; CHECK-NEXT: vnsrl.wi v11, v8, 0
-; CHECK-NEXT: vnsrl.wi v8, v8, 8
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
-; CHECK-NEXT: vslideup.vi v10, v11, 8
-; CHECK-NEXT: vslideup.vi v9, v8, 8
+; CHECK-NEXT: vnsrl.wi v10, v8, 0
+; CHECK-NEXT: vsetvli zero, a1, e8, m2, ta, ma
; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vmsne.vi v8, v9, 0
+; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
+; CHECK-NEXT: vnsrl.wi v10, v8, 8
+; CHECK-NEXT: vsetvli zero, a1, e8, m2, ta, ma
+; CHECK-NEXT: vmsne.vi v8, v10, 0
; CHECK-NEXT: ret
%vec = load <32 x i1>, ptr %p
%deinterleaved.results = call {<16 x i1>, <16 x i1>} @llvm.vector.deinterleave2.v32i1(<32 x i1> %vec)
diff --git a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
index 07fb8675d85e8..13b5f54b17ba3 100644
--- a/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
+++ b/llvm/test/CodeGen/RISCV/rvv/vector-deinterleave-fixed.ll
@@ -8,24 +8,18 @@
define {<16 x i1>, <16 x i1>} @vector_deinterleave_v16i1_v32i1(<32 x i1> %vec) {
; CHECK-LABEL: vector_deinterleave_v16i1_v32i1:
; CHECK: # %bb.0:
-; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
+; CHECK-NEXT: li a0, 32
+; CHECK-NEXT: vsetvli zero, a0, e8, m2, ta, ma
; CHECK-NEXT: vmv.v.i v8, 0
-; CHECK-NEXT: vmerge.vim v9, v8, 1, v0
-; CHECK-NEXT: vsetivli zero, 2, e8, mf4, ta, ma
-; CHECK-NEXT: vslidedown.vi v0, v0, 2
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vnsrl.wi v10, v9, 0
-; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
; CHECK-NEXT: vmerge.vim v8, v8, 1, v0
-; CHECK-NEXT: vsetivli zero, 8, e8, mf2, ta, ma
-; CHECK-NEXT: vnsrl.wi v9, v9, 8
-; CHECK-NEXT: vnsrl.wi v11, v8, 0
-; CHECK-NEXT: vnsrl.wi v8, v8, 8
; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
-; CHECK-NEXT: vslideup.vi v10, v11, 8
-; CHECK-NEXT: vslideup.vi v9, v8, 8
+; CHECK-NEXT: vnsrl.wi v10, v8, 0
+; CHECK-NEXT: vsetvli zero, a0, e8, m2, ta, ma
; CHECK-NEXT: vmsne.vi v0, v10, 0
-; CHECK-NEXT: vmsne.vi v8, v9, 0
+; CHECK-NEXT: vsetivli zero, 16, e8, m1, ta, ma
+; CHECK-NEXT: vnsrl.wi v10, v8, 8
+; CHECK-NEXT: vsetvli zero, a0, e8, m2, ta, ma
+; CHECK-NEXT: vmsne.vi v8, v10, 0
; CHECK-NEXT: ret
%retval = call {<16 x i1>, <16 x i1>} @llvm.vector.deinterleave2.v32i1(<32 x i1> %vec)
ret {<16 x i1>, <16 x i1>} %retval
@@ -74,22 +68,22 @@ ret {<4 x i32>, <4 x i32>} %retval
define {<2 x i64>, <2 x i64>} @vector_deinterleave_v2i64_v4i64(<4 x i64> %vec) {
; V-LABEL: vector_deinterleave_v2i64_v4i64:
; 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: vsetivli zero, 1, e8, mf8, ta, ma
+; V-NEXT: vmv.v.i v0, 2
+; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
+; V-NEXT: vslidedown.vi v10, v8, 1
+; V-NEXT: vslidedown.vi v10, v8, 2, v0.t
+; V-NEXT: vslidedown.vi v8, v8, 1, v0.t
; 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:
; ZVZIP: # %bb.0:
-; ZVZIP-NEXT: vsetivli zero, 2, e64, m1, ta, ma
-; ZVZIP-NEXT: vunzipe.v v10, v8
-; ZVZIP-NEXT: vunzipo.v v11, v8
-; ZVZIP-NEXT: vmv.v.v v8, v10
-; ZVZIP-NEXT: vmv.v.v v9, v11
+; ZVZIP-NEXT: vsetivli zero, 4, e64, m2, ta, ma
+; ZVZIP-NEXT: vunzipe.v v12, v8
+; ZVZIP-NEXT: vunzipo.v v14, v8
+; ZVZIP-NEXT: vmv1r.v v8, v12
+; ZVZIP-NEXT: vmv1r.v v9, v14
; ZVZIP-NEXT: ret
%retval = call {<2 x i64>, <2 x i64>} @llvm.vector.deinterleave2.v4i64(<4 x i64> %vec)
ret {<2 x i64>, <2 x i64>} %retval
@@ -98,44 +92,24 @@ ret {<2 x i64>, <2 x i64>} %retval
define {<4 x i64>, <4 x i64>} @vector_deinterleave_v4i64_v8i64(<8 x i64> %vec) {
; V-LABEL: vector_deinterleave_v4i64_v8i64:
; V: # %bb.0:
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v0, 8
-; V-NEXT: vsetivli zero, 4, e64, m4, ta, ma
-; V-NEXT: vslidedown.vi v16, v8, 4
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, ma
-; V-NEXT: vslideup.vi v12, v16, 2
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v10, 2
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslideup.vi v12, v16, 1, v0.t
-; V-NEXT: vmv2r.v v14, v8
-; V-NEXT: vmv1r.v v0, v10
-; V-NEXT: vslidedown.vi v14, v8, 1, v0.t
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v11, 12
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslidedown.vi v18, v8, 1
-; V-NEXT: vmv1r.v v0, v11
-; V-NEXT: vmerge.vvm v12, v14, v12, v0
-; V-NEXT: vmv1r.v v0, v10
-; V-NEXT: vslidedown.vi v18, v8, 2, v0.t
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v0, 4
-; V-NEXT: vmv2r.v v8, v16
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslideup.vi v8, v16, 1, v0.t
-; V-NEXT: vmv1r.v v0, v11
-; V-NEXT: vmerge.vvm v10, v18, v8, v0
+; V-NEXT: li a0, 85
+; V-NEXT: vsetivli zero, 8, e64, m4, ta, ma
+; V-NEXT: vmv.s.x v16, a0
+; V-NEXT: vcompress.vm v12, v8, v16
+; V-NEXT: li a0, 170
+; V-NEXT: vmv.s.x v14, a0
+; V-NEXT: vcompress.vm v16, v8, v14
; V-NEXT: vmv2r.v v8, v12
+; V-NEXT: vmv2r.v v10, v16
; V-NEXT: ret
;
; ZVZIP-LABEL: vector_deinterleave_v4i64_v8i64:
; ZVZIP: # %bb.0:
-; ZVZIP-NEXT: vsetivli zero, 4, e64, m2, ta, ma
-; ZVZIP-NEXT: vunzipe.v v12, v8
-; ZVZIP-NEXT: vunzipo.v v14, v8
-; ZVZIP-NEXT: vmv.v.v v8, v12
-; ZVZIP-NEXT: vmv.v.v v10, v14
+; ZVZIP-NEXT: vsetivli zero, 8, e64, m4, ta, ma
+; ZVZIP-NEXT: vunzipe.v v16, v8
+; ZVZIP-NEXT: vunzipo.v v20, v8
+; ZVZIP-NEXT: vmv2r.v v8, v16
+; ZVZIP-NEXT: vmv2r.v v10, v20
; ZVZIP-NEXT: ret
%retval = call {<4 x i64>, <4 x i64>} @llvm.vector.deinterleave2.v8i64(<8 x i64> %vec)
ret {<4 x i64>, <4 x i64>} %retval
@@ -144,37 +118,18 @@ define {<4 x i64>, <4 x i64>} @vector_deinterleave_v4i64_v8i64(<8 x i64> %vec) {
define {<8 x i64>, <8 x i64>} @vector_deinterleave_v8i64_v16i64(<16 x i64> %vec) {
; V-LABEL: vector_deinterleave_v8i64_v16i64:
; V: # %bb.0:
-; V-NEXT: li a0, 85
-; V-NEXT: vsetivli zero, 8, e64, m4, ta, ma
+; V-NEXT: lui a0, 5
+; V-NEXT: addi a0, a0, 1365
+; V-NEXT: vsetivli zero, 16, e64, m8, ta, ma
+; V-NEXT: vmv.s.x v24, a0
+; V-NEXT: vcompress.vm v16, v8, v24
+; V-NEXT: lui a0, 11
+; V-NEXT: addi a0, a0, -1366
; V-NEXT: vmv.s.x v20, a0
-; V-NEXT: vcompress.vm v16, v8, v20
-; V-NEXT: vsetivli zero, 8, e64, m8, ta, ma
-; V-NEXT: vslidedown.vi v24, v8, 8
-; V-NEXT: vsetivli zero, 8, e16, m1, ta, ma
-; V-NEXT: vid.v v12
-; V-NEXT: vadd.vv v20, v12, v12
-; V-NEXT: vmv.v.i v0, -16
-; V-NEXT: vadd.vi v12, v20, -8
-; V-NEXT: vsetvli zero, zero, e64, m4, ta, mu
-; V-NEXT: vrgatherei16.vv v16, v24, v12, v0.t
-; V-NEXT: li a0, 170
-; V-NEXT: vmv.s.x v21, a0
-; V-NEXT: vcompress.vm v12, v8, v21
-; V-NEXT: vsetvli zero, zero, e16, m1, ta, ma
-; V-NEXT: vadd.vi v8, v20, -7
-; V-NEXT: vsetvli zero, zero, e64, m4, ta, mu
-; V-NEXT: vrgatherei16.vv v12, v24, v8, v0.t
-; V-NEXT: vmv.v.v v8, v16
+; V-NEXT: vcompress.vm v24, v8, v20
+; V-NEXT: vmv4r.v v8, v16
+; V-NEXT: vmv4r.v v12, v24
; V-NEXT: ret
-;
-; ZVZIP-LABEL: vector_deinterleave_v8i64_v16i64:
-; ZVZIP: # %bb.0:
-; ZVZIP-NEXT: vsetivli zero, 8, e64, m4, ta, ma
-; ZVZIP-NEXT: vunzipe.v v16, v8
-; ZVZIP-NEXT: vunzipo.v v20, v8
-; ZVZIP-NEXT: vmv.v.v v8, v16
-; ZVZIP-NEXT: vmv.v.v v12, v20
-; ZVZIP-NEXT: ret
%retval = call {<8 x i64>, <8 x i64>} @llvm.vector.deinterleave2.v16i64(<16 x i64> %vec)
ret {<8 x i64>, <8 x i64>} %retval
}
@@ -525,22 +480,22 @@ ret {<4 x float>, <4 x float>} %retval
define {<2 x double>, <2 x double>} @vector_deinterleave_v2f64_v4f64(<4 x double> %vec) {
; V-LABEL: vector_deinterleave_v2f64_v4f64:
; 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: vsetivli zero, 1, e8, mf8, ta, ma
+; V-NEXT: vmv.v.i v0, 2
+; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
+; V-NEXT: vslidedown.vi v10, v8, 1
+; V-NEXT: vslidedown.vi v10, v8, 2, v0.t
+; V-NEXT: vslidedown.vi v8, v8, 1, v0.t
; 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:
; ZVZIP: # %bb.0:
-; ZVZIP-NEXT: vsetivli zero, 2, e64, m1, ta, ma
-; ZVZIP-NEXT: vunzipe.v v10, v8
-; ZVZIP-NEXT: vunzipo.v v11, v8
-; ZVZIP-NEXT: vmv.v.v v8, v10
-; ZVZIP-NEXT: vmv.v.v v9, v11
+; ZVZIP-NEXT: vsetivli zero, 4, e64, m2, ta, ma
+; ZVZIP-NEXT: vunzipe.v v12, v8
+; ZVZIP-NEXT: vunzipo.v v14, v8
+; ZVZIP-NEXT: vmv1r.v v8, v12
+; ZVZIP-NEXT: vmv1r.v v9, v14
; ZVZIP-NEXT: ret
%retval = call {<2 x double>, <2 x double>} @llvm.vector.deinterleave2.v4f64(<4 x double> %vec)
ret {<2 x double>, <2 x double>} %retval
@@ -549,44 +504,24 @@ ret {<2 x double>, <2 x double>} %retval
define {<4 x double>, <4 x double>} @vector_deinterleave_v4f64_v8f64(<8 x double> %vec) {
; V-LABEL: vector_deinterleave_v4f64_v8f64:
; V: # %bb.0:
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v0, 8
-; V-NEXT: vsetivli zero, 4, e64, m4, ta, ma
-; V-NEXT: vslidedown.vi v16, v8, 4
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, ma
-; V-NEXT: vslideup.vi v12, v16, 2
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v10, 2
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslideup.vi v12, v16, 1, v0.t
-; V-NEXT: vmv2r.v v14, v8
-; V-NEXT: vmv1r.v v0, v10
-; V-NEXT: vslidedown.vi v14, v8, 1, v0.t
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v11, 12
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslidedown.vi v18, v8, 1
-; V-NEXT: vmv1r.v v0, v11
-; V-NEXT: vmerge.vvm v12, v14, v12, v0
-; V-NEXT: vmv1r.v v0, v10
-; V-NEXT: vslidedown.vi v18, v8, 2, v0.t
-; V-NEXT: vsetivli zero, 1, e8, mf8, ta, ma
-; V-NEXT: vmv.v.i v0, 4
-; V-NEXT: vmv2r.v v8, v16
-; V-NEXT: vsetivli zero, 4, e64, m2, ta, mu
-; V-NEXT: vslideup.vi v8, v16, 1, v0.t
-; V-NEXT: vmv1r.v v0, v11
-; V-NEXT: vmerge.vvm v10, v18, v8, v0
+; V-NEXT: li a0, 85
+; V-NEXT: vsetivli zero, 8, e64, m4, ta, ma
+; V-NEXT: vmv.s.x v16, a0
+; V-NEXT: vcompress.vm v12, v8, v16
+; V-NEXT: li a0, 170
+; V-NEXT: vmv.s.x v14, a0
+; V-NEXT: vcompress.vm v16, v8, v14
; V-NEXT: vmv2r.v v8, v12
+; V-NEXT: vmv2r.v v10, v16
; V-NEXT: ret
;
; ZVZIP-LABEL: vector_deinterleave_v4f64_v8f64:
; ZVZIP: # %bb.0:
-; ZVZIP-NEXT: vsetivli zero, 4, e64, m2, ta, ma
-; ZVZIP-NEXT: vunzipe.v v12, v8
-; ZVZIP-NEXT: vunzipo.v v14, v8
-; ZVZIP-NEXT: vmv.v.v v8, v12
-; ZVZIP-NEXT: vmv.v.v v10, v14
+; ZVZIP-NEXT: vsetivli zero, 8, e64, m4, ta, ma
+; ZVZIP-NEXT: vunzipe.v v16, v8
+; ZVZIP-NEXT: vunzipo.v v20, v8
+; ZVZIP-NEXT: vmv2r.v v8, v16
+; ZVZIP-NEXT: vmv2r.v v10, v20
; ZVZIP-NEXT: ret
%retval = call {<4 x double>, <4 x double>} @llvm.vector.deinterleave2.v8f64(<8 x double> %vec)
ret {<4 x double>, <4 x double>} %retval
More information about the llvm-commits
mailing list