[llvm] [InstCombine] fold the identity interleave (PR #206646)

via llvm-commits llvm-commits at lists.llvm.org
Mon Jun 29 22:06:27 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Kamlesh Kumar (kamleshbhalui)

<details>
<summary>Changes</summary>

If all the extracvalue of deinterleave used in interleave in same order then it is an identity.

---
Full diff: https://github.com/llvm/llvm-project/pull/206646.diff


3 Files Affected:

- (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+39) 
- (modified) llvm/lib/Transforms/InstCombine/InstCombineInternal.h (+2) 
- (added) llvm/test/Transforms/InstCombine/vector-interleave-deinterleave.ll (+211) 


``````````diff
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 0c2d11fab4f43..6cb67aa12fb77 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1914,6 +1914,35 @@ static Instruction *foldNeonShift(IntrinsicInst *II, InstCombinerImpl &IC) {
   return IC.replaceInstUsesWith(*II, Result);
 }
 
+/// interleaveN(extractvalue(deinterleaveN(x), 0), ...,
+///             extractvalue(deinterleaveN(x), N-1)) --> x
+///
+/// When the operands of an interleaveN are exactly the N fields of one
+/// deinterleaveN, in field order, the two cancel out and the interleave just
+/// reproduces the deinterleaved input. The leftover deinterleave/extractvalues
+/// are then trivially dead.
+Instruction *InstCombinerImpl::foldIdentityInterleave(IntrinsicInst &II) {
+  unsigned Factor = getInterleaveIntrinsicFactor(II.getIntrinsicID());
+  assert(Factor && Factor == II.arg_size() && "Unexpected interleave factor");
+
+  Intrinsic::ID DeinterleaveID = Intrinsic::getDeinterleaveIntrinsicID(Factor);
+  IntrinsicInst *DI = nullptr;
+  for (unsigned Idx = 0; Idx != Factor; ++Idx) {
+    auto *EV = dyn_cast<ExtractValueInst>(II.getArgOperand(Idx));
+    if (!EV || EV->getNumIndices() != 1 || *EV->idx_begin() != Idx)
+      return nullptr;
+    auto *CurDI = dyn_cast<IntrinsicInst>(EV->getAggregateOperand());
+    if (!CurDI || CurDI->getIntrinsicID() != DeinterleaveID)
+      return nullptr;
+    if (!DI)
+      DI = CurDI;
+    else if (DI != CurDI)
+      return nullptr;
+  }
+
+  return replaceInstUsesWith(II, DI->getArgOperand(0));
+}
+
 /// CallInst simplification. This mostly only handles folding of intrinsic
 /// instructions. For normal calls, it allows visitCallBase to do the heavy
 /// lifting.
@@ -4076,6 +4105,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
     }
     break;
   }
+  case Intrinsic::vector_interleave2:
+  case Intrinsic::vector_interleave3:
+  case Intrinsic::vector_interleave4:
+  case Intrinsic::vector_interleave5:
+  case Intrinsic::vector_interleave6:
+  case Intrinsic::vector_interleave7:
+  case Intrinsic::vector_interleave8:
+    if (Instruction *I = foldIdentityInterleave(*II))
+      return I;
+    break;
   case Intrinsic::experimental_vp_reverse: {
     Value *X;
     Value *Vec = II->getArgOperand(0);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 8b759e701da60..d2ed8205f7c97 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -825,6 +825,8 @@ class LLVM_LIBRARY_VISIBILITY InstCombinerImpl final
 
   Instruction *foldExtractionOfVectorDeinterleave(ZExtInst &RootZExt);
 
+  Instruction *foldIdentityInterleave(IntrinsicInst &II);
+
   bool replaceInInstruction(Value *V, Value *Old, Value *New,
                             unsigned Depth = 0);
 
diff --git a/llvm/test/Transforms/InstCombine/vector-interleave-deinterleave.ll b/llvm/test/Transforms/InstCombine/vector-interleave-deinterleave.ll
new file mode 100644
index 0000000000000..c9c2d2c0dfe0e
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/vector-interleave-deinterleave.ll
@@ -0,0 +1,211 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+define <vscale x 8 x i32> @interleave_of_deinterleave_f2(<vscale x 8 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_f2(
+; CHECK-NEXT:    ret <vscale x 8 x i32> [[X:%.*]]
+;
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %x)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  %r = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1)
+  ret <vscale x 8 x i32> %r
+}
+
+define <vscale x 16 x i32> @interleave_of_deinterleave_f4(<vscale x 16 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_f4(
+; CHECK-NEXT:    ret <vscale x 16 x i32> [[X:%.*]]
+;
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave4.nxv16i32(<vscale x 16 x i32> %x)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  %e2 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 2
+  %e3 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 3
+  %r = call <vscale x 16 x i32> @llvm.vector.interleave4.nxv16i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1, <vscale x 4 x i32> %e2, <vscale x 4 x i32> %e3)
+  ret <vscale x 16 x i32> %r
+}
+
+define <vscale x 20 x i32> @interleave_of_deinterleave_f5(<vscale x 20 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_f5(
+; CHECK-NEXT:    ret <vscale x 20 x i32> [[X:%.*]]
+;
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave5.nxv20i32(<vscale x 20 x i32> %x)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  %e2 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 2
+  %e3 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 3
+  %e4 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 4
+  %r = call <vscale x 20 x i32> @llvm.vector.interleave5.nxv20i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1, <vscale x 4 x i32> %e2, <vscale x 4 x i32> %e3, <vscale x 4 x i32> %e4)
+  ret <vscale x 20 x i32> %r
+}
+
+define void @interleave_of_deinterleave_load_store(ptr %src, ptr %dst) {
+; CHECK-LABEL: @interleave_of_deinterleave_load_store(
+; CHECK-NEXT:    [[V:%.*]] = load <vscale x 8 x i32>, ptr [[SRC:%.*]], align 32
+; CHECK-NEXT:    store <vscale x 8 x i32> [[V]], ptr [[DST:%.*]], align 32
+; CHECK-NEXT:    ret void
+;
+  %v = load <vscale x 8 x i32>, ptr %src
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %v)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  %r = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1)
+  store <vscale x 8 x i32> %r, ptr %dst
+  ret void
+}
+
+define <vscale x 8 x i32> @interleave_of_deinterleave_extra_uses(<vscale x 8 x i32> %x, ptr %p0, ptr %p1) {
+; CHECK-LABEL: @interleave_of_deinterleave_extra_uses(
+; CHECK-NEXT:    [[D:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[D]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[D]], 1
+; CHECK-NEXT:    store <vscale x 4 x i32> [[E0]], ptr [[P0:%.*]], align 16
+; CHECK-NEXT:    store <vscale x 4 x i32> [[E1]], ptr [[P1:%.*]], align 16
+; CHECK-NEXT:    ret <vscale x 8 x i32> [[X]]
+;
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %x)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  store <vscale x 4 x i32> %e0, ptr %p0
+  store <vscale x 4 x i32> %e1, ptr %p1
+  %r = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1)
+  ret <vscale x 8 x i32> %r
+}
+
+define <vscale x 8 x i32> @interleave_of_deinterleave_swapped(<vscale x 8 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_swapped(
+; CHECK-NEXT:    [[D:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[D]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[D]], 1
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[E1]], <vscale x 4 x i32> [[E0]])
+; CHECK-NEXT:    ret <vscale x 8 x i32> [[R]]
+;
+  %d = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %x)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %d, 1
+  %r = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %e1, <vscale x 4 x i32> %e0)
+  ret <vscale x 8 x i32> %r
+}
+
+define <vscale x 8 x i32> @interleave_of_two_deinterleaves(<vscale x 8 x i32> %x, <vscale x 8 x i32> %y) {
+; CHECK-LABEL: @interleave_of_two_deinterleaves(
+; CHECK-NEXT:    [[DX:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[DY:%.*]] = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> [[Y:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[DX]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } [[DY]], 1
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[E0]], <vscale x 4 x i32> [[E1]])
+; CHECK-NEXT:    ret <vscale x 8 x i32> [[R]]
+;
+  %dx = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %x)
+  %dy = call { <vscale x 4 x i32>, <vscale x 4 x i32> } @llvm.vector.deinterleave2.nxv8i32(<vscale x 8 x i32> %y)
+  %e0 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %dx, 0
+  %e1 = extractvalue { <vscale x 4 x i32>, <vscale x 4 x i32> } %dy, 1
+  %r = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %e0, <vscale x 4 x i32> %e1)
+  ret <vscale x 8 x i32> %r
+}
+
+define <vscale x 8 x i32> @interleave_of_deinterleave_mismatched_factor(<vscale x 8 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_mismatched_factor(
+; CHECK-NEXT:    [[D:%.*]] = call { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } @llvm.vector.deinterleave4.nxv8i32(<vscale x 8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } [[D]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } [[D]], 1
+; CHECK-NEXT:    [[R:%.*]] = call <vscale x 4 x i32> @llvm.vector.interleave2.nxv4i32(<vscale x 2 x i32> [[E0]], <vscale x 2 x i32> [[E1]])
+; CHECK-NEXT:    [[W:%.*]] = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> [[R]], <vscale x 4 x i32> [[R]])
+; CHECK-NEXT:    ret <vscale x 8 x i32> [[W]]
+;
+  %d = call { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } @llvm.vector.deinterleave4.nxv8i32(<vscale x 8 x i32> %x)
+  %e0 = extractvalue { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } %d, 0
+  %e1 = extractvalue { <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32>, <vscale x 2 x i32> } %d, 1
+  %r = call <vscale x 4 x i32> @llvm.vector.interleave2.nxv4i32(<vscale x 2 x i32> %e0, <vscale x 2 x i32> %e1)
+  %w = call <vscale x 8 x i32> @llvm.vector.interleave2.nxv8i32(<vscale x 4 x i32> %r, <vscale x 4 x i32> %r)
+  ret <vscale x 8 x i32> %w
+}
+
+define <8 x i32> @interleave_of_deinterleave_fixed_f2(<8 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_fixed_f2(
+; CHECK-NEXT:    ret <8 x i32> [[X:%.*]]
+;
+  %d = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %x)
+  %e0 = extractvalue { <4 x i32>, <4 x i32> } %d, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32> } %d, 1
+  %r = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> %e0, <4 x i32> %e1)
+  ret <8 x i32> %r
+}
+
+define <16 x i32> @interleave_of_deinterleave_fixed_f4(<16 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_fixed_f4(
+; CHECK-NEXT:    ret <16 x i32> [[X:%.*]]
+;
+  %d = call { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } @llvm.vector.deinterleave4.v16i32(<16 x i32> %x)
+  %e0 = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } %d, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } %d, 1
+  %e2 = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } %d, 2
+  %e3 = extractvalue { <4 x i32>, <4 x i32>, <4 x i32>, <4 x i32> } %d, 3
+  %r = call <16 x i32> @llvm.vector.interleave4.v16i32(<4 x i32> %e0, <4 x i32> %e1, <4 x i32> %e2, <4 x i32> %e3)
+  ret <16 x i32> %r
+}
+
+define void @interleave_of_deinterleave_fixed_load_store(ptr %src, ptr %dst) {
+; CHECK-LABEL: @interleave_of_deinterleave_fixed_load_store(
+; CHECK-NEXT:    [[V:%.*]] = load <8 x i32>, ptr [[SRC:%.*]], align 32
+; CHECK-NEXT:    store <8 x i32> [[V]], ptr [[DST:%.*]], align 32
+; CHECK-NEXT:    ret void
+;
+  %v = load <8 x i32>, ptr %src
+  %d = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %v)
+  %e0 = extractvalue { <4 x i32>, <4 x i32> } %d, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32> } %d, 1
+  %r = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> %e0, <4 x i32> %e1)
+  store <8 x i32> %r, ptr %dst
+  ret void
+}
+
+define <8 x i32> @interleave_of_deinterleave_fixed_extra_uses(<8 x i32> %x, ptr %p0, ptr %p1) {
+; CHECK-LABEL: @interleave_of_deinterleave_fixed_extra_uses(
+; CHECK-NEXT:    [[D:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[D]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[D]], 1
+; CHECK-NEXT:    store <4 x i32> [[E0]], ptr [[P0:%.*]], align 16
+; CHECK-NEXT:    store <4 x i32> [[E1]], ptr [[P1:%.*]], align 16
+; CHECK-NEXT:    ret <8 x i32> [[X]]
+;
+  %d = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %x)
+  %e0 = extractvalue { <4 x i32>, <4 x i32> } %d, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32> } %d, 1
+  store <4 x i32> %e0, ptr %p0
+  store <4 x i32> %e1, ptr %p1
+  %r = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> %e0, <4 x i32> %e1)
+  ret <8 x i32> %r
+}
+
+define <8 x i32> @interleave_of_deinterleave_fixed_swapped(<8 x i32> %x) {
+; CHECK-LABEL: @interleave_of_deinterleave_fixed_swapped(
+; CHECK-NEXT:    [[D:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[D]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[D]], 1
+; CHECK-NEXT:    [[R:%.*]] = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> [[E1]], <4 x i32> [[E0]])
+; CHECK-NEXT:    ret <8 x i32> [[R]]
+;
+  %d = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %x)
+  %e0 = extractvalue { <4 x i32>, <4 x i32> } %d, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32> } %d, 1
+  %r = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> %e1, <4 x i32> %e0)
+  ret <8 x i32> %r
+}
+
+define <8 x i32> @interleave_of_two_deinterleaves_fixed(<8 x i32> %x, <8 x i32> %y) {
+; CHECK-LABEL: @interleave_of_two_deinterleaves_fixed(
+; CHECK-NEXT:    [[DX:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> [[X:%.*]])
+; CHECK-NEXT:    [[DY:%.*]] = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> [[Y:%.*]])
+; CHECK-NEXT:    [[E0:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[DX]], 0
+; CHECK-NEXT:    [[E1:%.*]] = extractvalue { <4 x i32>, <4 x i32> } [[DY]], 1
+; CHECK-NEXT:    [[R:%.*]] = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> [[E0]], <4 x i32> [[E1]])
+; CHECK-NEXT:    ret <8 x i32> [[R]]
+;
+  %dx = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %x)
+  %dy = call { <4 x i32>, <4 x i32> } @llvm.vector.deinterleave2.v8i32(<8 x i32> %y)
+  %e0 = extractvalue { <4 x i32>, <4 x i32> } %dx, 0
+  %e1 = extractvalue { <4 x i32>, <4 x i32> } %dy, 1
+  %r = call <8 x i32> @llvm.vector.interleave2.v8i32(<4 x i32> %e0, <4 x i32> %e1)
+  ret <8 x i32> %r
+}

``````````

</details>


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


More information about the llvm-commits mailing list