[llvm] [ARM] Lower vector interleave operations (PR #225670)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 03:31:05 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-arm
Author: Kamlesh Kumar (kamleshbhalui)
<details>
<summary>Changes</summary>
Adding support for lowering of vector_interleave
and vector_deinterleave operations.
---
Patch is 257.37 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/225670.diff
3 Files Affected:
- (modified) llvm/lib/Target/ARM/ARMISelLowering.cpp (+103)
- (added) llvm/test/CodeGen/ARM/fixed-vector-deinterleave.ll (+3675)
- (added) llvm/test/CodeGen/ARM/fixed-vector-interleave.ll (+2444)
``````````diff
diff --git a/llvm/lib/Target/ARM/ARMISelLowering.cpp b/llvm/lib/Target/ARM/ARMISelLowering.cpp
index 194b597bc77ba2..7f5a8d15477030 100644
--- a/llvm/lib/Target/ARM/ARMISelLowering.cpp
+++ b/llvm/lib/Target/ARM/ARMISelLowering.cpp
@@ -198,6 +198,8 @@ void ARMTargetLowering::addTypeForNEON(MVT VT, MVT PromotedLdStVT) {
}
setOperationAction(ISD::BUILD_VECTOR, VT, Custom);
setOperationAction(ISD::VECTOR_SHUFFLE, VT, Custom);
+ setVectorInterleaveAction({ISD::VECTOR_INTERLEAVE, ISD::VECTOR_DEINTERLEAVE},
+ {2, 3, 4}, VT, Custom);
setOperationAction(ISD::CONCAT_VECTORS, VT, Legal);
setOperationAction(ISD::EXTRACT_SUBVECTOR, VT, Legal);
setOperationAction(ISD::SELECT, VT, Expand);
@@ -9067,6 +9069,103 @@ static SDValue LowerCONCAT_VECTORS_i1(SDValue Op, SelectionDAG &DAG,
return ConcatOps[0];
}
+static SDValue LowerVECTOR_INTERLEAVE(SDValue Op, SelectionDAG &DAG,
+ const ARMSubtarget *ST) {
+ if (!ST->hasNEON())
+ return SDValue();
+ unsigned Factor = Op->getNumOperands();
+ EVT OpVT = Op.getValueType();
+ SDLoc DL(Op);
+
+ if (Factor == 2) {
+ SDValue Zip = DAG.getNode(ARMISD::VZIP, DL, DAG.getVTList(OpVT, OpVT),
+ Op.getOperand(0), Op.getOperand(1));
+ return DAG.getMergeValues({Zip, Zip.getValue(1)}, DL);
+ }
+
+ if (Op->getNumOperands() == 3) {
+ Align Alignment = DAG.getReducedAlign(OpVT, /*UseABI=*/false);
+ SDValue StackPtr =
+ DAG.CreateStackTemporary(OpVT.getStoreSize() * 3, Alignment);
+ MachinePointerInfo StackPtrInfo = MachinePointerInfo::getFixedStack(
+ DAG.getMachineFunction(), cast<FrameIndexSDNode>(StackPtr)->getIndex());
+ SmallVector<SDValue, 6> Ops;
+ Ops.push_back(DAG.getEntryNode());
+ Ops.push_back(
+ DAG.getTargetConstant(Intrinsic::arm_neon_vst3, DL, MVT::i64));
+ Ops.push_back(StackPtr);
+
+ for (SDValue V : Op->ops())
+ Ops.push_back(V);
+ Ops.push_back(DAG.getConstant(Alignment.value(), DL, MVT::i32));
+ EVT TripleOpVT =
+ EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
+ OpVT.getVectorNumElements() * 3);
+ SDValue Chain = DAG.getMemIntrinsicNode(
+ ISD::INTRINSIC_VOID, DL, DAG.getVTList(MVT::Other), Ops, TripleOpVT,
+ StackPtrInfo, Alignment, MachineMemOperand::MOStore);
+
+ SmallVector<SDValue, 3> Results;
+ for (unsigned I = 0; I < 3; ++I) {
+ SDValue Ptr =
+ DAG.getMemBasePlusOffset(StackPtr, OpVT.getStoreSize() * I, DL);
+ Results.push_back(
+ DAG.getLoad(OpVT, DL, Chain, Ptr, MachinePointerInfo()));
+ }
+ return DAG.getMergeValues(Results, DL);
+ }
+
+ return SDValue();
+}
+
+static SDValue LowerVECTOR_DEINTERLEAVE(SDValue Op, SelectionDAG &DAG,
+ const ARMSubtarget *ST) {
+ if (!ST->hasNEON())
+ return SDValue();
+ unsigned Factor = Op->getNumOperands();
+ EVT OpVT = Op.getValueType();
+ SDLoc DL(Op);
+
+ if (Factor == 2) {
+ SDValue Unzip = DAG.getNode(ARMISD::VUZP, DL, DAG.getVTList(OpVT, OpVT),
+ Op.getOperand(0), Op.getOperand(1));
+ return DAG.getMergeValues({Unzip, Unzip.getValue(1)}, DL);
+ }
+
+ if (Op->getNumOperands() == 3) {
+ Align Alignment = DAG.getReducedAlign(OpVT, /*UseABI=*/false);
+ SDValue StackPtr =
+ DAG.CreateStackTemporary(OpVT.getStoreSize() * 3, Alignment);
+
+ SmallVector<SDValue, 3> Chains;
+ for (unsigned I = 0; I < 3; ++I) {
+ SDValue Ptr =
+ DAG.getMemBasePlusOffset(StackPtr, OpVT.getStoreSize() * I, DL);
+ Chains.push_back(DAG.getStore(DAG.getEntryNode(), DL, Op.getOperand(I),
+ Ptr, MachinePointerInfo()));
+ }
+
+ SmallVector<SDValue, 3> Ops;
+ Ops.push_back(DAG.getNode(ISD::TokenFactor, DL, MVT::Other, Chains));
+ Ops.push_back(
+ DAG.getTargetConstant(Intrinsic::arm_neon_vld3, DL, MVT::i64));
+ Ops.push_back(StackPtr);
+
+ EVT TripleOpVT =
+ EVT::getVectorVT(*DAG.getContext(), OpVT.getVectorElementType(),
+ OpVT.getVectorNumElements() * 3);
+ SDVTList VTs = DAG.getVTList(OpVT, OpVT, OpVT, MVT::Other);
+ SDValue LD3 = DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, VTs, Ops,
+ TripleOpVT, MachinePointerInfo(),
+ Alignment, MachineMemOperand::MOLoad);
+
+ return DAG.getMergeValues(
+ {LD3.getValue(0), LD3.getValue(1), LD3.getValue(2)}, DL);
+ }
+
+ return SDValue();
+}
+
static SDValue LowerCONCAT_VECTORS(SDValue Op, SelectionDAG &DAG,
const ARMSubtarget *ST) {
EVT VT = Op->getValueType(0);
@@ -10589,6 +10688,10 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const {
case ISD::INSERT_VECTOR_ELT: return LowerINSERT_VECTOR_ELT(Op, DAG);
case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG, Subtarget);
case ISD::CONCAT_VECTORS: return LowerCONCAT_VECTORS(Op, DAG, Subtarget);
+ case ISD::VECTOR_INTERLEAVE:
+ return LowerVECTOR_INTERLEAVE(Op, DAG, Subtarget);
+ case ISD::VECTOR_DEINTERLEAVE:
+ return LowerVECTOR_DEINTERLEAVE(Op, DAG, Subtarget);
case ISD::TRUNCATE: return LowerTruncate(Op.getNode(), DAG, Subtarget);
case ISD::SIGN_EXTEND:
case ISD::ZERO_EXTEND: return LowerVectorExtend(Op.getNode(), DAG, Subtarget);
diff --git a/llvm/test/CodeGen/ARM/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/ARM/fixed-vector-deinterleave.ll
new file mode 100644
index 00000000000000..ee7da511d1c602
--- /dev/null
+++ b/llvm/test/CodeGen/ARM/fixed-vector-deinterleave.ll
@@ -0,0 +1,3675 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=armv8-none-none-eabi -mattr=+neon %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IAENABLED
+; RUN: llc -mtriple=armv8-none-none-eabi -mattr=+neon -lower-interleaved-accesses=false %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IADISABLED
+
+define void @deinterleave2_v8i8(<16 x i8> %vec) {
+; CHECK-LABEL: deinterleave2_v8i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: vmov d16, r2, r3
+; CHECK-NEXT: vmov d17, r0, r1
+; CHECK-NEXT: vuzp.8 d17, d16
+; CHECK-NEXT: @ fake_use: $d17
+; CHECK-NEXT: @ fake_use: $d16
+; CHECK-NEXT: bx lr
+ %result = call { <8 x i8>, <8 x i8> } @llvm.vector.deinterleave2(<16 x i8> %vec)
+ %result0 = extractvalue { <8 x i8>, <8 x i8> } %result, 0
+ call void (...) @llvm.fake.use(<8 x i8> %result0)
+ %result1 = extractvalue { <8 x i8>, <8 x i8> } %result, 1
+ call void (...) @llvm.fake.use(<8 x i8> %result1)
+ ret void
+}
+
+define void @deinterleave3_v8i8(<24 x i8> %vec) {
+; CHECK-LABEL: deinterleave3_v8i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: .pad #24
+; CHECK-NEXT: sub sp, sp, #24
+; CHECK-NEXT: add r12, sp, #72
+; CHECK-NEXT: vmov.8 d18[0], r0
+; CHECK-NEXT: add r0, sp, #80
+; CHECK-NEXT: vld1.8 {d16[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #40
+; CHECK-NEXT: vld1.8 {d17[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #76
+; CHECK-NEXT: vld1.8 {d16[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #44
+; CHECK-NEXT: vld1.8 {d17[1]}, [r12]
+; CHECK-NEXT: vld1.8 {d16[2]}, [r0]
+; CHECK-NEXT: add r0, sp, #48
+; CHECK-NEXT: vld1.8 {d17[2]}, [r0]
+; CHECK-NEXT: add r0, sp, #84
+; CHECK-NEXT: vld1.8 {d16[3]}, [r0]
+; CHECK-NEXT: add r0, sp, #52
+; CHECK-NEXT: vld1.8 {d17[3]}, [r0]
+; CHECK-NEXT: add r0, sp, #24
+; CHECK-NEXT: vmov.8 d18[1], r1
+; CHECK-NEXT: vmov.8 d18[2], r2
+; CHECK-NEXT: vmov.8 d18[3], r3
+; CHECK-NEXT: vld1.8 {d18[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #88
+; CHECK-NEXT: vld1.8 {d16[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #56
+; CHECK-NEXT: vld1.8 {d17[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #28
+; CHECK-NEXT: vld1.8 {d18[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #92
+; CHECK-NEXT: vld1.8 {d16[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #60
+; CHECK-NEXT: vld1.8 {d17[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #32
+; CHECK-NEXT: vld1.8 {d18[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #96
+; CHECK-NEXT: vld1.8 {d16[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #64
+; CHECK-NEXT: vld1.8 {d17[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #36
+; CHECK-NEXT: vld1.8 {d18[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #100
+; CHECK-NEXT: vld1.8 {d16[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #68
+; CHECK-NEXT: vld1.8 {d17[7]}, [r0]
+; CHECK-NEXT: mov r0, sp
+; CHECK-NEXT: vstr d18, [sp]
+; CHECK-NEXT: vstr d16, [sp, #16]
+; CHECK-NEXT: vstr d17, [sp, #8]
+; CHECK-NEXT: vld3.8 {d16, d17, d18}, [r0:64]
+; CHECK-NEXT: @ fake_use: $d16
+; CHECK-NEXT: @ fake_use: $d17
+; CHECK-NEXT: @ fake_use: $d18 $q8_q9
+; CHECK-NEXT: add sp, sp, #24
+; CHECK-NEXT: bx lr
+ %result = call { <8 x i8>, <8 x i8>, <8 x i8> } @llvm.vector.deinterleave3(<24 x i8> %vec)
+ %result0 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } %result, 0
+ call void (...) @llvm.fake.use(<8 x i8> %result0)
+ %result1 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } %result, 1
+ call void (...) @llvm.fake.use(<8 x i8> %result1)
+ %result2 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8> } %result, 2
+ call void (...) @llvm.fake.use(<8 x i8> %result2)
+ ret void
+}
+
+define void @deinterleave4_v8i8(<32 x i8> %vec) {
+; CHECK-LABEL: deinterleave4_v8i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: mov r12, sp
+; CHECK-NEXT: vld1.64 {d18, d19}, [r12]
+; CHECK-NEXT: vorr d20, d18, d18
+; CHECK-NEXT: vmov d16, r2, r3
+; CHECK-NEXT: vmov d17, r0, r1
+; CHECK-NEXT: vuzp.8 d20, d19
+; CHECK-NEXT: vuzp.8 d17, d16
+; CHECK-NEXT: vuzp.8 d16, d19
+; CHECK-NEXT: @ fake_use: $d16
+; CHECK-NEXT: vuzp.8 d17, d20
+; CHECK-NEXT: @ fake_use: $d17
+; CHECK-NEXT: @ fake_use: $d20
+; CHECK-NEXT: @ fake_use: $d19 $q9
+; CHECK-NEXT: bx lr
+ %result = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.vector.deinterleave4(<32 x i8> %vec)
+ %result0 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 0
+ call void (...) @llvm.fake.use(<8 x i8> %result0)
+ %result1 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 1
+ call void (...) @llvm.fake.use(<8 x i8> %result1)
+ %result2 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 2
+ call void (...) @llvm.fake.use(<8 x i8> %result2)
+ %result3 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 3
+ call void (...) @llvm.fake.use(<8 x i8> %result3)
+ ret void
+}
+
+define void @deinterleave6_v8i8(<48 x i8> %vec) {
+; CHECK-LABEL: deinterleave6_v8i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: .pad #48
+; CHECK-NEXT: sub sp, sp, #48
+; CHECK-NEXT: add r12, sp, #192
+; CHECK-NEXT: vmov.8 d21[0], r0
+; CHECK-NEXT: add r0, sp, #76
+; CHECK-NEXT: vld1.8 {d16[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #160
+; CHECK-NEXT: vld1.8 {d18[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #128
+; CHECK-NEXT: vld1.8 {d20[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #96
+; CHECK-NEXT: vld1.8 {d17[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #64
+; CHECK-NEXT: vld1.8 {d19[0]}, [r12]
+; CHECK-NEXT: add r12, sp, #196
+; CHECK-NEXT: vld1.8 {d16[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #164
+; CHECK-NEXT: vld1.8 {d18[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #132
+; CHECK-NEXT: vld1.8 {d20[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #100
+; CHECK-NEXT: vld1.8 {d17[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #68
+; CHECK-NEXT: vld1.8 {d19[1]}, [r12]
+; CHECK-NEXT: add r12, sp, #200
+; CHECK-NEXT: vld1.8 {d16[2]}, [r12]
+; CHECK-NEXT: add r12, sp, #168
+; CHECK-NEXT: vld1.8 {d18[2]}, [r12]
+; CHECK-NEXT: add r12, sp, #136
+; CHECK-NEXT: vld1.8 {d20[2]}, [r12]
+; CHECK-NEXT: add r12, sp, #104
+; CHECK-NEXT: vld1.8 {d17[2]}, [r12]
+; CHECK-NEXT: add r12, sp, #72
+; CHECK-NEXT: vld1.8 {d19[2]}, [r12]
+; CHECK-NEXT: add r12, sp, #204
+; CHECK-NEXT: vld1.8 {d16[3]}, [r12]
+; CHECK-NEXT: add r12, sp, #172
+; CHECK-NEXT: vld1.8 {d19[3]}, [r0]
+; CHECK-NEXT: add r0, sp, #208
+; CHECK-NEXT: vld1.8 {d18[3]}, [r12]
+; CHECK-NEXT: add r12, sp, #140
+; CHECK-NEXT: vld1.8 {d16[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #176
+; CHECK-NEXT: vld1.8 {d20[3]}, [r12]
+; CHECK-NEXT: add r12, sp, #108
+; CHECK-NEXT: vld1.8 {d18[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #144
+; CHECK-NEXT: vld1.8 {d20[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #48
+; CHECK-NEXT: vld1.8 {d17[3]}, [r12]
+; CHECK-NEXT: vmov.8 d21[1], r1
+; CHECK-NEXT: vmov.8 d21[2], r2
+; CHECK-NEXT: vmov.8 d21[3], r3
+; CHECK-NEXT: vld1.8 {d21[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #112
+; CHECK-NEXT: vld1.8 {d17[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #80
+; CHECK-NEXT: vld1.8 {d19[4]}, [r0]
+; CHECK-NEXT: add r0, sp, #212
+; CHECK-NEXT: vld1.8 {d16[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #180
+; CHECK-NEXT: vld1.8 {d18[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #148
+; CHECK-NEXT: vld1.8 {d20[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #52
+; CHECK-NEXT: vld1.8 {d21[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #116
+; CHECK-NEXT: vld1.8 {d17[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #84
+; CHECK-NEXT: vld1.8 {d19[5]}, [r0]
+; CHECK-NEXT: add r0, sp, #216
+; CHECK-NEXT: vld1.8 {d16[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #184
+; CHECK-NEXT: vld1.8 {d18[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #152
+; CHECK-NEXT: vld1.8 {d20[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #56
+; CHECK-NEXT: vld1.8 {d21[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #120
+; CHECK-NEXT: vld1.8 {d17[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #88
+; CHECK-NEXT: vld1.8 {d19[6]}, [r0]
+; CHECK-NEXT: add r0, sp, #220
+; CHECK-NEXT: vld1.8 {d16[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #188
+; CHECK-NEXT: vld1.8 {d18[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #156
+; CHECK-NEXT: vld1.8 {d20[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #60
+; CHECK-NEXT: vld1.8 {d21[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #124
+; CHECK-NEXT: vld1.8 {d17[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #92
+; CHECK-NEXT: vld1.8 {d19[7]}, [r0]
+; CHECK-NEXT: add r0, sp, #24
+; CHECK-NEXT: vstr d16, [sp, #40]
+; CHECK-NEXT: vstr d18, [sp, #32]
+; CHECK-NEXT: vstr d20, [sp, #24]
+; CHECK-NEXT: vld3.8 {d22, d23, d24}, [r0:64]
+; CHECK-NEXT: mov r0, sp
+; CHECK-NEXT: vorr d20, d22, d22
+; CHECK-NEXT: vorr d26, d23, d23
+; CHECK-NEXT: vstr d21, [sp]
+; CHECK-NEXT: vstr d17, [sp, #16]
+; CHECK-NEXT: vstr d19, [sp, #8]
+; CHECK-NEXT: vld3.8 {d16, d17, d18}, [r0:64]
+; CHECK-NEXT: vorr d21, d16, d16
+; CHECK-NEXT: vorr d27, d17, d17
+; CHECK-NEXT: vuzp.8 d18, d24
+; CHECK-NEXT: @ fake_use: $d18 $q8_q9
+; CHECK-NEXT: vuzp.8 d21, d20
+; CHECK-NEXT: @ fake_use: $d21
+; CHECK-NEXT: vuzp.8 d27, d26
+; CHECK-NEXT: @ fake_use: $d27
+; CHECK-NEXT: @ fake_use: $d20
+; CHECK-NEXT: @ fake_use: $d26
+; CHECK-NEXT: @ fake_use: $d24 $q11_q12
+; CHECK-NEXT: add sp, sp, #48
+; CHECK-NEXT: bx lr
+ %result = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.vector.deinterleave6(<48 x i8> %vec)
+ %result0 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 0
+ call void (...) @llvm.fake.use(<8 x i8> %result0)
+ %result1 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 1
+ call void (...) @llvm.fake.use(<8 x i8> %result1)
+ %result2 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 2
+ call void (...) @llvm.fake.use(<8 x i8> %result2)
+ %result3 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 3
+ call void (...) @llvm.fake.use(<8 x i8> %result3)
+ %result4 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 4
+ call void (...) @llvm.fake.use(<8 x i8> %result4)
+ %result5 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 5
+ call void (...) @llvm.fake.use(<8 x i8> %result5)
+ ret void
+}
+
+define void @deinterleave8_v8i8(<64 x i8> %vec) {
+; CHECK-LABEL: deinterleave8_v8i8:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: add r12, sp, #16
+; CHECK-NEXT: vmov d22, r2, r3
+; CHECK-NEXT: vld1.64 {d16, d17}, [r12]
+; CHECK-NEXT: mov r12, sp
+; CHECK-NEXT: vorr d25, d16, d16
+; CHECK-NEXT: vld1.64 {d18, d19}, [r12]
+; CHECK-NEXT: add r12, sp, #32
+; CHECK-NEXT: vorr d26, d18, d18
+; CHECK-NEXT: vld1.64 {d20, d21}, [r12]
+; CHECK-NEXT: vmov d23, r0, r1
+; CHECK-NEXT: vorr d24, d20, d20
+; CHECK-NEXT: vuzp.8 d25, d17
+; CHECK-NEXT: vuzp.8 d23, d22
+; CHECK-NEXT: vuzp.8 d24, d21
+; CHECK-NEXT: vuzp.8 d26, d19
+; CHECK-NEXT: vuzp.8 d25, d24
+; CHECK-NEXT: vuzp.8 d23, d26
+; CHECK-NEXT: vuzp.8 d17, d21
+; CHECK-NEXT: vuzp.8 d22, d19
+; CHECK-NEXT: vuzp.8 d23, d25
+; CHECK-NEXT: @ fake_use: $d23
+; CHECK-NEXT: vuzp.8 d19, d21
+; CHECK-NEXT: @ fake_use: $d19 $q9
+; CHECK-NEXT: vuzp.8 d22, d17
+; CHECK-NEXT: @ fake_use: $d22
+; CHECK-NEXT: vuzp.8 d26, d24
+; CHECK-NEXT: @ fake_use: $d26
+; CHECK-NEXT: @ fake_use: $d25
+; CHECK-NEXT: @ fake_use: $d17 $q8
+; CHECK-NEXT: @ fake_use: $d24
+; CHECK-NEXT: @ fake_use: $d21 $q10
+; CHECK-NEXT: bx lr
+ %result = call { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } @llvm.vector.deinterleave8(<64 x i8> %vec)
+ %result0 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 0
+ call void (...) @llvm.fake.use(<8 x i8> %result0)
+ %result1 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 1
+ call void (...) @llvm.fake.use(<8 x i8> %result1)
+ %result2 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 2
+ call void (...) @llvm.fake.use(<8 x i8> %result2)
+ %result3 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 3
+ call void (...) @llvm.fake.use(<8 x i8> %result3)
+ %result4 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 4
+ call void (...) @llvm.fake.use(<8 x i8> %result4)
+ %result5 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 5
+ call void (...) @llvm.fake.use(<8 x i8> %result5)
+ %result6 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 6
+ call void (...) @llvm.fake.use(<8 x i8> %result6)
+ %result7 = extractvalue { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> } %result, 7
+ call void (...) @llvm.fake.use(<8 x i8> %result7)
+ ret void
+}
+
+define void @deinterleave2_v4i16(<8 x i16> %vec) {
+; CHECK-LABEL: deinterleave2_v4i16:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: vmov d16, r2, r3
+; CHECK-NEXT: vmov d17, r0, r1
+; CHECK-NEXT: vuzp.16 d17, d16
+; CHECK-NEXT: @ fake_use: $d17
+; CHECK-NEXT: @ fake_use: $d16
+; CHECK-NEXT: bx lr
+ %result = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %vec)
+ %result0 = extractvalue { <4 x i16>, <4 x i16> } %result, 0
+ call void (...) @llvm.fake.use(<4 x i16> %result0)
+ %result1 = extractvalue { <4 x i16>, <4 x i16> } %result, 1
+ call void (...) @llvm.fake.use(<4 x i16> %result1)
+ ret void
+}
+
+define void @deinterleave3_v4i16(<12 x i16> %vec) {
+; CHECK-LABEL: deinterleave3_v4i16:
+; CHECK: @ %bb.0:
+; CHECK-NEXT: .pad #24
+; CHECK-NEXT: sub sp, sp, #24
+; CHECK-NEXT: add r12, sp, #40
+; CHECK-NEXT: vmov.16 d18[0], r0
+; CHECK-NEXT: add r0, sp, #48
+; CHECK-NEXT: vld1.16 {d16[0]}, [r12:16]
+; CHECK-NEXT: add r12, sp, #24
+; CHECK-NEXT: vld1.16 {d17[0]}, [r12:16]
+; CHECK-NEXT: add r12, sp, #44
+; CHECK-NEXT: vld1.16 {d16[1]}, [r12:16]
+; CHECK-NEXT: add r12, sp, #28
+; CHECK-NEXT: vld1.16 {d17[1]}, [r12:16]
+; CHECK-NEXT: vld1.16 {d16[2]}, [r0:16]
+; CHECK-NEXT: add r0, sp, #32
+; CHECK-NEXT: vld1.16 {d17[2]}, [r0:16]
+; CHECK-NEXT: ad...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/225670
More information about the llvm-commits
mailing list