[llvm] [InstCombine] fold the identity interleave (PR #206646)
Kamlesh Kumar via llvm-commits
llvm-commits at lists.llvm.org
Mon Jun 29 22:05:51 PDT 2026
https://github.com/kamleshbhalui created https://github.com/llvm/llvm-project/pull/206646
If all the extracvalue of deinterleave used in interleave in same order then it is an identity.
>From 961a375e9ce727f63a0ea00016bd978d389e388a Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Tue, 30 Jun 2026 05:40:35 +0100
Subject: [PATCH] [InstCombine] fold the identity interleave
If all the extracvalue of deinterleave used in interleave
in same order then it is an identity.
---
.../InstCombine/InstCombineCalls.cpp | 39 ++++
.../InstCombine/InstCombineInternal.h | 2 +
.../vector-interleave-deinterleave.ll | 211 ++++++++++++++++++
3 files changed, 252 insertions(+)
create mode 100644 llvm/test/Transforms/InstCombine/vector-interleave-deinterleave.ll
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
+}
More information about the llvm-commits
mailing list