[llvm] [VectorCombine][AArch64] Fix reverse uses of deinterleave (PR #216308)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Aug 14 05:14:54 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-vectorizers
@llvm/pr-subscribers-llvm-transforms
Author: Kamlesh Kumar (kamleshbhalui)
<details>
<summary>Changes</summary>
Fold a reversed deinterleave with reversed field order to a vector reverse.
i.e. interleaveN(reverse(deinterleaveN(X)[N-1]), ...,reverse(deinterleaveN(X)[0])) --> reverse(X).
This is always profitable if interleave store cancels interleave load.
---
Patch is 22.66 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/216308.diff
2 Files Affected:
- (modified) llvm/lib/Transforms/Vectorize/VectorCombine.cpp (+62)
- (added) llvm/test/Transforms/VectorCombine/AArch64/interleave-reverse-deinterleave.ll (+280)
``````````diff
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index 9eeeef16c7bd3..3aa4a1ca104d2 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -155,6 +155,7 @@ class VectorCombine {
bool foldEquivalentReductionCmp(Instruction &I);
bool foldReduceAddCmpZero(Instruction &I);
bool foldSelectShuffle(Instruction &I, bool FromReduction = false);
+ bool foldInterleaveOfReversedDeinterleave(Instruction &I);
bool foldInterleaveIntrinsics(Instruction &I);
bool foldDeinterleaveIntrinsics(Instruction &I);
bool foldBitcastOfVPLoad(Instruction &I);
@@ -5905,6 +5906,65 @@ bool VectorCombine::foldInsExtVectorToShuffle(Instruction &I) {
return true;
}
+/// Fold a reversed deinterleave with reversed field order to a vector reverse.
+/// i.e.
+/// interleaveN(reverse(deinterleaveN(X)[N-1]), ...,
+/// reverse(deinterleaveN(X)[0])) --> reverse(X).
+bool VectorCombine::foldInterleaveOfReversedDeinterleave(Instruction &I) {
+ auto *II = dyn_cast<IntrinsicInst>(&I);
+ if (!II)
+ return false;
+ unsigned Factor = getInterleaveIntrinsicFactor(II->getIntrinsicID());
+ if (!Factor)
+ return false;
+
+ IntrinsicInst *Deinterleave = nullptr;
+ for (unsigned Idx = 0; Idx != Factor; ++Idx) {
+ Value *Op = II->getArgOperand(Idx);
+ // Every reverse must feed only this interleave, otherwise
+ // it's not profitable to fold.
+ if (!Op->hasOneUse())
+ return false;
+
+ Value *Reversed = nullptr;
+ if (auto *Shuffle = dyn_cast<ShuffleVectorInst>(Op)) {
+ ArrayRef<int> Mask = Shuffle->getShuffleMask();
+ if (!Shuffle->isReverse() ||
+ !llvm::all_of(Mask, [NumElts = static_cast<int>(Mask.size())](
+ int MaskElt) { return MaskElt < NumElts; }))
+ return false;
+ Reversed = Shuffle->getOperand(0);
+ } else if (!match(Op, m_Intrinsic<Intrinsic::vector_reverse>(
+ m_Value(Reversed)))) {
+ return false;
+ }
+
+ auto *Extract = dyn_cast<ExtractValueInst>(Reversed);
+ if (!Extract || !Extract->hasOneUse() || Extract->getNumIndices() != 1 ||
+ *Extract->idx_begin() != (Factor - Idx - 1))
+ return false;
+ auto *CurrentDeinterleave =
+ dyn_cast<IntrinsicInst>(Extract->getAggregateOperand());
+ if (!CurrentDeinterleave)
+ return false;
+ if (CurrentDeinterleave->getIntrinsicID() !=
+ Intrinsic::getDeinterleaveIntrinsicID(Factor) ||
+ (Deinterleave && Deinterleave != CurrentDeinterleave))
+ return false;
+
+ Deinterleave = CurrentDeinterleave;
+ }
+
+ if (!Deinterleave->hasNUses(Factor))
+ return false;
+
+ Value *Input = Deinterleave->getArgOperand(0);
+ Value *Reverse = Builder.CreateIntrinsic(Intrinsic::vector_reverse,
+ {Input->getType()}, {Input});
+ replaceValue(I, *Reverse);
+ return true;
+}
+
/// If we're interleaving 2 constant splats, for instance `<vscale x 8 x i32>
/// <splat of 666>` and `<vscale x 8 x i32> <splat of 777>`, we can create a
/// larger splat `<vscale x 8 x i64> <splat of ((777 << 32) | 666)>` first
@@ -6551,6 +6611,8 @@ bool VectorCombine::run() {
return true;
if (scalarizeVPIntrinsic(I))
return true;
+ if (foldInterleaveOfReversedDeinterleave(I))
+ return true;
if (foldInterleaveIntrinsics(I))
return true;
if (foldBitcastOfVPLoad(I))
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/interleave-reverse-deinterleave.ll b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reverse-deinterleave.ll
new file mode 100644
index 0000000000000..106b1cf5e0c16
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reverse-deinterleave.ll
@@ -0,0 +1,280 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mtriple=aarch64-linux-gnu -passes=vector-combine -S %s | FileCheck %s
+
+define <24 x i16> @reverse_interleave3(<24 x i16> %x) {
+; CHECK-LABEL: define <24 x i16> @reverse_interleave3(
+; CHECK-SAME: <24 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <24 x i16> @llvm.vector.reverse.v24i16(<24 x i16> [[X]])
+; CHECK-NEXT: ret <24 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.vector.deinterleave3(<24 x i16> %x)
+ %e0 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 2
+ %r0 = shufflevector <8 x i16> %e0, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r1 = shufflevector <8 x i16> %e1, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r2 = shufflevector <8 x i16> %e2, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <24 x i16> @llvm.vector.interleave3(<8 x i16> %r2, <8 x i16> %r1, <8 x i16> %r0)
+ ret <24 x i16> %interleave
+}
+
+define <24 x i16> @reverse_intrinsic_interleave3(<24 x i16> %x) {
+; CHECK-LABEL: define <24 x i16> @reverse_intrinsic_interleave3(
+; CHECK-SAME: <24 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <24 x i16> @llvm.vector.reverse.v24i16(<24 x i16> [[X]])
+; CHECK-NEXT: ret <24 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.vector.deinterleave3(<24 x i16> %x)
+ %e0 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 2
+ %r0 = call <8 x i16> @llvm.vector.reverse(<8 x i16> %e0)
+ %r1 = call <8 x i16> @llvm.vector.reverse(<8 x i16> %e1)
+ %r2 = call <8 x i16> @llvm.vector.reverse(<8 x i16> %e2)
+ %interleave = call <24 x i16> @llvm.vector.interleave3(<8 x i16> %r2, <8 x i16> %r1, <8 x i16> %r0)
+ ret <24 x i16> %interleave
+}
+
+define <vscale x 24 x i16> @reverse_intrinsic_interleave3_scalable(<vscale x 24 x i16> %x) {
+; CHECK-LABEL: define <vscale x 24 x i16> @reverse_intrinsic_interleave3_scalable(
+; CHECK-SAME: <vscale x 24 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <vscale x 24 x i16> @llvm.vector.reverse.nxv24i16(<vscale x 24 x i16> [[X]])
+; CHECK-NEXT: ret <vscale x 24 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16> } @llvm.vector.deinterleave3(<vscale x 24 x i16> %x)
+ %e0 = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <vscale x 8 x i16>, <vscale x 8 x i16>, <vscale x 8 x i16> } %deinterleave, 2
+ %r0 = call <vscale x 8 x i16> @llvm.vector.reverse(<vscale x 8 x i16> %e0)
+ %r1 = call <vscale x 8 x i16> @llvm.vector.reverse(<vscale x 8 x i16> %e1)
+ %r2 = call <vscale x 8 x i16> @llvm.vector.reverse(<vscale x 8 x i16> %e2)
+ %interleave = call <vscale x 24 x i16> @llvm.vector.interleave3(<vscale x 8 x i16> %r2, <vscale x 8 x i16> %r1, <vscale x 8 x i16> %r0)
+ ret <vscale x 24 x i16> %interleave
+}
+
+define <24 x i16> @group_reverse_interleave3(<24 x i16> %x) {
+; CHECK-LABEL: define <24 x i16> @group_reverse_interleave3(
+; CHECK-SAME: <24 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.vector.deinterleave3.v24i16(<24 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[E2:%.*]] = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } [[DEINTERLEAVE]], 2
+; CHECK-NEXT: [[R0:%.*]] = shufflevector <8 x i16> [[E0]], <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R1:%.*]] = shufflevector <8 x i16> [[E1]], <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R2:%.*]] = shufflevector <8 x i16> [[E2]], <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <24 x i16> @llvm.vector.interleave3.v24i16(<8 x i16> [[R0]], <8 x i16> [[R1]], <8 x i16> [[R2]])
+; CHECK-NEXT: ret <24 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.vector.deinterleave3(<24 x i16> %x)
+ %e0 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 2
+ %r0 = shufflevector <8 x i16> %e0, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r1 = shufflevector <8 x i16> %e1, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r2 = shufflevector <8 x i16> %e2, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <24 x i16> @llvm.vector.interleave3(<8 x i16> %r0, <8 x i16> %r1, <8 x i16> %r2)
+ ret <24 x i16> %interleave
+}
+
+define <6 x i16> @reverse_second_operand_interleave2(<6 x i16> %x) {
+; CHECK-LABEL: define <6 x i16> @reverse_second_operand_interleave2(
+; CHECK-SAME: <6 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <3 x i16>, <3 x i16> } @llvm.vector.deinterleave2.v6i16(<6 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <3 x i16>, <3 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <3 x i16>, <3 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[R0:%.*]] = shufflevector <3 x i16> [[E0]], <3 x i16> zeroinitializer, <3 x i32> <i32 5, i32 4, i32 3>
+; CHECK-NEXT: [[R1:%.*]] = shufflevector <3 x i16> [[E1]], <3 x i16> zeroinitializer, <3 x i32> <i32 5, i32 4, i32 3>
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <6 x i16> @llvm.vector.interleave2.v6i16(<3 x i16> [[R1]], <3 x i16> [[R0]])
+; CHECK-NEXT: ret <6 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <3 x i16>, <3 x i16> } @llvm.vector.deinterleave2(<6 x i16> %x)
+ %e0 = extractvalue { <3 x i16>, <3 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <3 x i16>, <3 x i16> } %deinterleave, 1
+ %r0 = shufflevector <3 x i16> %e0, <3 x i16> zeroinitializer, <3 x i32> <i32 5, i32 4, i32 3>
+ %r1 = shufflevector <3 x i16> %e1, <3 x i16> zeroinitializer, <3 x i32> <i32 5, i32 4, i32 3>
+ %interleave = call <6 x i16> @llvm.vector.interleave2(<3 x i16> %r1, <3 x i16> %r0)
+ ret <6 x i16> %interleave
+}
+
+define <6 x i16> @reverse_poison_mask_interleave2(<6 x i16> %x) {
+; CHECK-LABEL: define <6 x i16> @reverse_poison_mask_interleave2(
+; CHECK-SAME: <6 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <6 x i16> @llvm.vector.reverse.v6i16(<6 x i16> [[X]])
+; CHECK-NEXT: ret <6 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <3 x i16>, <3 x i16> } @llvm.vector.deinterleave2(<6 x i16> %x)
+ %e0 = extractvalue { <3 x i16>, <3 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <3 x i16>, <3 x i16> } %deinterleave, 1
+ %r0 = shufflevector <3 x i16> %e0, <3 x i16> poison, <3 x i32> <i32 2, i32 poison, i32 0>
+ %r1 = shufflevector <3 x i16> %e1, <3 x i16> poison, <3 x i32> <i32 2, i32 1, i32 poison>
+ %interleave = call <6 x i16> @llvm.vector.interleave2(<3 x i16> %r1, <3 x i16> %r0)
+ ret <6 x i16> %interleave
+}
+
+define <16 x i16> @reverse_interleave4(<16 x i16> %x) {
+; CHECK-LABEL: define <16 x i16> @reverse_interleave4(
+; CHECK-SAME: <16 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i16> @llvm.vector.reverse.v16i16(<16 x i16> [[X]])
+; CHECK-NEXT: ret <16 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } @llvm.vector.deinterleave4(<16 x i16> %x)
+ %e0 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %deinterleave, 2
+ %e3 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16>, <4 x i16> } %deinterleave, 3
+ %r0 = shufflevector <4 x i16> %e0, <4 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %r1 = shufflevector <4 x i16> %e1, <4 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %r2 = shufflevector <4 x i16> %e2, <4 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %r3 = shufflevector <4 x i16> %e3, <4 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <16 x i16> @llvm.vector.interleave4(<4 x i16> %r3, <4 x i16> %r2, <4 x i16> %r1, <4 x i16> %r0)
+ ret <16 x i16> %interleave
+}
+
+define <24 x i16> @mixed_reverse_interleave3(<24 x i16> %x) {
+; CHECK-LABEL: define <24 x i16> @mixed_reverse_interleave3(
+; CHECK-SAME: <24 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <24 x i16> @llvm.vector.reverse.v24i16(<24 x i16> [[X]])
+; CHECK-NEXT: ret <24 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <8 x i16>, <8 x i16>, <8 x i16> } @llvm.vector.deinterleave3(<24 x i16> %x)
+ %e0 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 1
+ %e2 = extractvalue { <8 x i16>, <8 x i16>, <8 x i16> } %deinterleave, 2
+ %r0 = shufflevector <8 x i16> %e0, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r1 = call <8 x i16> @llvm.vector.reverse(<8 x i16> %e1)
+ %r2 = shufflevector <8 x i16> %e2, <8 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <24 x i16> @llvm.vector.interleave3(<8 x i16> %r2, <8 x i16> %r1, <8 x i16> %r0)
+ ret <24 x i16> %interleave
+}
+
+define <8 x i16> @narrowing_shuffle_interleave2(<16 x i16> %x) {
+; CHECK-LABEL: define <8 x i16> @narrowing_shuffle_interleave2(
+; CHECK-SAME: <16 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <8 x i16>, <8 x i16> } @llvm.vector.deinterleave2.v16i16(<16 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <8 x i16>, <8 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <8 x i16>, <8 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[R0:%.*]] = shufflevector <8 x i16> [[E0]], <8 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R1:%.*]] = shufflevector <8 x i16> [[E1]], <8 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <8 x i16> @llvm.vector.interleave2.v8i16(<4 x i16> [[R1]], <4 x i16> [[R0]])
+; CHECK-NEXT: ret <8 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <8 x i16>, <8 x i16> } @llvm.vector.deinterleave2(<16 x i16> %x)
+ %e0 = extractvalue { <8 x i16>, <8 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <8 x i16>, <8 x i16> } %deinterleave, 1
+ %r0 = shufflevector <8 x i16> %e0, <8 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %r1 = shufflevector <8 x i16> %e1, <8 x i16> poison, <4 x i32> <i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <8 x i16> @llvm.vector.interleave2(<4 x i16> %r1, <4 x i16> %r0)
+ ret <8 x i16> %interleave
+}
+
+define <16 x i16> @widening_shuffle_interleave2(<8 x i16> %x) {
+; CHECK-LABEL: define <16 x i16> @widening_shuffle_interleave2(
+; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[R0:%.*]] = shufflevector <4 x i16> [[E0]], <4 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[R1:%.*]] = shufflevector <4 x i16> [[E1]], <4 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i16> @llvm.vector.interleave2.v16i16(<8 x i16> [[R1]], <8 x i16> [[R0]])
+; CHECK-NEXT: ret <16 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %x)
+ %e0 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 1
+ %r0 = shufflevector <4 x i16> %e0, <4 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %r1 = shufflevector <4 x i16> %e1, <4 x i16> poison, <8 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0>
+ %interleave = call <16 x i16> @llvm.vector.interleave2(<8 x i16> %r1, <8 x i16> %r0)
+ ret <16 x i16> %interleave
+}
+
+define <8 x i16> @multi_use_reverse_interleave2(<8 x i16> %x) {
+; CHECK-LABEL: define <8 x i16> @multi_use_reverse_interleave2(
+; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[R0:%.*]] = call <4 x i16> @llvm.vector.reverse.v4i16(<4 x i16> [[E0]])
+; CHECK-NEXT: [[R1:%.*]] = call <4 x i16> @llvm.vector.reverse.v4i16(<4 x i16> [[E1]])
+; CHECK-NEXT: call void (...) @llvm.fake.use(<4 x i16> [[R0]])
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <8 x i16> @llvm.vector.interleave2.v8i16(<4 x i16> [[R1]], <4 x i16> [[R0]])
+; CHECK-NEXT: ret <8 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %x)
+ %e0 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 1
+ %r0 = call <4 x i16> @llvm.vector.reverse(<4 x i16> %e0)
+ %r1 = call <4 x i16> @llvm.vector.reverse(<4 x i16> %e1)
+ call void (...) @llvm.fake.use(<4 x i16> %r0)
+ %interleave = call <8 x i16> @llvm.vector.interleave2(<4 x i16> %r1, <4 x i16> %r0)
+ ret <8 x i16> %interleave
+}
+
+define <8 x i16> @extra_extract_use_interleave2(<8 x i16> %x) {
+; CHECK-LABEL: define <8 x i16> @extra_extract_use_interleave2(
+; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[DEINTERLEAVE:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
+; CHECK-NEXT: [[E0:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: [[E1:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 1
+; CHECK-NEXT: [[EXTRA:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[DEINTERLEAVE]], 0
+; CHECK-NEXT: call void (...) @llvm.fake.use(<4 x i16> [[EXTRA]])
+; CHECK-NEXT: [[R0:%.*]] = call <4 x i16> @llvm.vector.reverse.v4i16(<4 x i16> [[E0]])
+; CHECK-NEXT: [[R1:%.*]] = call <4 x i16> @llvm.vector.reverse.v4i16(<4 x i16> [[E1]])
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <8 x i16> @llvm.vector.interleave2.v8i16(<4 x i16> [[R1]], <4 x i16> [[R0]])
+; CHECK-NEXT: ret <8 x i16> [[INTERLEAVE]]
+;
+ %deinterleave = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %x)
+ %e0 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 0
+ %e1 = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 1
+ %extra = extractvalue { <4 x i16>, <4 x i16> } %deinterleave, 0
+ call void (...) @llvm.fake.use(<4 x i16> %extra)
+ %r0 = call <4 x i16> @llvm.vector.reverse(<4 x i16> %e0)
+ %r1 = call <4 x i16> @llvm.vector.reverse(<4 x i16> %e1)
+ %interleave = call <8 x i16> @llvm.vector.interleave2(<4 x i16> %r1, <4 x i16> %r0)
+ ret <8 x i16> %interleave
+}
+
+define <8 x i16> @two_deinterleaves_interleave2(<8 x i16> %x, <8 x i16> %y) {
+; CHECK-LABEL: define <8 x i16> @two_deinterleaves_interleave2(
+; CHECK-SAME: <8 x i16> [[X:%.*]], <8 x i16> [[Y:%.*]]) {
+; CHECK-NEXT: [[D0:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
+; CHECK-NEXT: [[D1:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[Y]])...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/216308
More information about the llvm-commits
mailing list