[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