[llvm] [VectorCombine] Fold reverse order uses of deinterleave (PR #216746)
Kamlesh Kumar via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 21 03:09:14 PDT 2026
https://github.com/kamleshbhalui updated https://github.com/llvm/llvm-project/pull/216746
>From ffbe8e50f96a928d70b9e923d3b3fbec2bc67ded Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Mon, 17 Aug 2026 13:14:48 +0100
Subject: [PATCH 1/2] added the test
---
.../interleave-reordered-deinterleave.ll | 157 ++++++++++++++++++
1 file changed, 157 insertions(+)
create mode 100644 llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
new file mode 100644
index 0000000000000..6754c6d49c155
--- /dev/null
+++ b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
@@ -0,0 +1,157 @@
+; 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 <8 x i16> @reverse_fields_interleave2(<8 x i16> %x) {
+; CHECK-LABEL: define <8 x i16> @reverse_fields_interleave2(
+; CHECK-SAME: <8 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[D]], 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <8 x i16> @llvm.vector.interleave2.v8i16(<4 x i16> [[D1]], <4 x i16> [[D0]])
+; CHECK-NEXT: ret <8 x i16> [[INTERLEAVE]]
+;
+ %d = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %x)
+ %d0 = extractvalue { <4 x i16>, <4 x i16> } %d, 0
+ %d1 = extractvalue { <4 x i16>, <4 x i16> } %d, 1
+ %interleave = call <8 x i16> @llvm.vector.interleave2(<4 x i16> %d1, <4 x i16> %d0)
+ ret <8 x i16> %interleave
+}
+
+define <12 x i16> @reverse_fields_interleave3(<12 x i16> %x) {
+; CHECK-LABEL: define <12 x i16> @reverse_fields_interleave3(
+; CHECK-SAME: <12 x i16> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.vector.deinterleave3.v12i16(<12 x i16> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 2
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <12 x i16> @llvm.vector.interleave3.v12i16(<4 x i16> [[D2]], <4 x i16> [[D1]], <4 x i16> [[D0]])
+; CHECK-NEXT: ret <12 x i16> [[INTERLEAVE]]
+;
+ %d = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.vector.deinterleave3(<12 x i16> %x)
+ %d0 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 0
+ %d1 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 1
+ %d2 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 2
+ %interleave = call <12 x i16> @llvm.vector.interleave3(<4 x i16> %d2, <4 x i16> %d1, <4 x i16> %d0)
+ ret <12 x i16> %interleave
+}
+
+define <16 x i8> @reverse_fields_interleave4(<16 x i8> %x) {
+; CHECK-LABEL: define <16 x i8> @reverse_fields_interleave4(
+; CHECK-SAME: <16 x i8> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } @llvm.vector.deinterleave4.v16i8(<16 x i8> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 2
+; CHECK-NEXT: [[D3:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 3
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i8> @llvm.vector.interleave4.v16i8(<4 x i8> [[D3]], <4 x i8> [[D2]], <4 x i8> [[D1]], <4 x i8> [[D0]])
+; CHECK-NEXT: ret <16 x i8> [[INTERLEAVE]]
+;
+ %d = call { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } @llvm.vector.deinterleave4(<16 x i8> %x)
+ %d0 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 0
+ %d1 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 1
+ %d2 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 2
+ %d3 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 3
+ %interleave = call <16 x i8> @llvm.vector.interleave4(<4 x i8> %d3, <4 x i8> %d2, <4 x i8> %d1, <4 x i8> %d0)
+ ret <16 x i8> %interleave
+}
+
+define <10 x i8> @reverse_fields_interleave5(<10 x i8> %x) {
+; CHECK-LABEL: define <10 x i8> @reverse_fields_interleave5(
+; CHECK-SAME: <10 x i8> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave5.v10i8(<10 x i8> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
+; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
+; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <10 x i8> @llvm.vector.interleave5.v10i8(<2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
+; CHECK-NEXT: ret <10 x i8> [[INTERLEAVE]]
+;
+ %d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave5(<10 x i8> %x)
+ %d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
+ %d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
+ %d2 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 2
+ %d3 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 3
+ %d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
+ %interleave = call <10 x i8> @llvm.vector.interleave5(<2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
+ ret <10 x i8> %interleave
+}
+
+define <12 x i8> @reverse_fields_interleave6(<12 x i8> %x) {
+; CHECK-LABEL: define <12 x i8> @reverse_fields_interleave6(
+; CHECK-SAME: <12 x i8> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave6.v12i8(<12 x i8> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
+; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
+; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
+; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <12 x i8> @llvm.vector.interleave6.v12i8(<2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
+; CHECK-NEXT: ret <12 x i8> [[INTERLEAVE]]
+;
+ %d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave6(<12 x i8> %x)
+ %d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
+ %d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
+ %d2 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 2
+ %d3 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 3
+ %d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
+ %d5 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 5
+ %interleave = call <12 x i8> @llvm.vector.interleave6(<2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
+ ret <12 x i8> %interleave
+}
+
+define <14 x i8> @reverse_fields_interleave7(<14 x i8> %x) {
+; CHECK-LABEL: define <14 x i8> @reverse_fields_interleave7(
+; CHECK-SAME: <14 x i8> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave7.v14i8(<14 x i8> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
+; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
+; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
+; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
+; CHECK-NEXT: [[D6:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 6
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <14 x i8> @llvm.vector.interleave7.v14i8(<2 x i8> [[D6]], <2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
+; CHECK-NEXT: ret <14 x i8> [[INTERLEAVE]]
+;
+ %d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave7(<14 x i8> %x)
+ %d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
+ %d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
+ %d2 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 2
+ %d3 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 3
+ %d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
+ %d5 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 5
+ %d6 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 6
+ %interleave = call <14 x i8> @llvm.vector.interleave7(<2 x i8> %d6, <2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
+ ret <14 x i8> %interleave
+}
+
+define <16 x i8> @reverse_fields_interleave8(<16 x i8> %x) {
+; CHECK-LABEL: define <16 x i8> @reverse_fields_interleave8(
+; CHECK-SAME: <16 x i8> [[X:%.*]]) {
+; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave8.v16i8(<16 x i8> [[X]])
+; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
+; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
+; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
+; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
+; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
+; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
+; CHECK-NEXT: [[D6:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 6
+; CHECK-NEXT: [[D7:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 7
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i8> @llvm.vector.interleave8.v16i8(<2 x i8> [[D7]], <2 x i8> [[D6]], <2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
+; CHECK-NEXT: ret <16 x i8> [[INTERLEAVE]]
+;
+ %d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave8(<16 x i8> %x)
+ %d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
+ %d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
+ %d2 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 2
+ %d3 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 3
+ %d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
+ %d5 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 5
+ %d6 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 6
+ %d7 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 7
+ %interleave = call <16 x i8> @llvm.vector.interleave8(<2 x i8> %d7, <2 x i8> %d6, <2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
+ ret <16 x i8> %interleave
+}
+
>From 0562efeeda3ad97cc1d8dff72582c7cd156ed95a Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Mon, 21 Sep 2026 10:38:01 +0100
Subject: [PATCH 2/2] [VectorCombine] Fold reversed deinterleave/interleave
pairs
Recognize load->deinterleaveN->interleaveN->store patterns where
the deinterleaved fields are reinterleaved in reverse order.
---
.../Transforms/Vectorize/VectorCombine.cpp | 81 ++++++++++
.../interleave-reordered-deinterleave.ll | 149 ++++++++----------
2 files changed, 150 insertions(+), 80 deletions(-)
diff --git a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
index e8c5885f9b1e3..5361e22f4d7d1 100644
--- a/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
+++ b/llvm/lib/Transforms/Vectorize/VectorCombine.cpp
@@ -156,6 +156,7 @@ class VectorCombine {
bool foldEquivalentReductionCmp(Instruction &I);
bool foldReduceAddCmpZero(Instruction &I);
bool foldSelectShuffle(Instruction &I, bool FromReduction = false);
+ bool foldInterleaveOfReorderedDeinterleave(Instruction &I);
bool foldInterleaveIntrinsics(Instruction &I);
bool foldDeinterleaveIntrinsics(Instruction &I);
bool foldBitcastOfVPLoad(Instruction &I);
@@ -6264,11 +6265,91 @@ bool VectorCombine::foldDeinterleaveInterleavePair(Instruction &I) {
return true;
}
+/// Fold a deinterleave whose fields are reinterleaved in reverse order to a
+/// shuffle that reverses the elements within each group.
+/// i.e.
+/// interleaveN(deinterleaveN(X)[N-1], ...,
+/// deinterleaveN(X)[0]) --> group-reverse(X).
+bool VectorCombine::foldInterleaveOfReorderedDeinterleave(Instruction &I) {
+ auto *II = dyn_cast<IntrinsicInst>(&I);
+ if (!II)
+ return false;
+ unsigned Factor = getInterleaveIntrinsicFactor(II->getIntrinsicID());
+ if (!Factor)
+ return false;
+
+ auto *Store = dyn_cast_or_null<StoreInst>(II->getUniqueUndroppableUser());
+ if (!Store)
+ return false;
+
+ IntrinsicInst *Deinterleave = nullptr;
+ for (unsigned I = 0; I != Factor; ++I) {
+ auto *Extract = dyn_cast<ExtractValueInst>(II->getArgOperand(I));
+ if (!Extract || Extract->getNumIndices() != 1 ||
+ *Extract->idx_begin() != Factor - I - 1 || !Extract->hasOneUse())
+ return false;
+
+ auto *CurrentDeinterleave =
+ dyn_cast<IntrinsicInst>(Extract->getAggregateOperand());
+ if (!CurrentDeinterleave ||
+ CurrentDeinterleave->getIntrinsicID() !=
+ Intrinsic::getDeinterleaveIntrinsicID(Factor) ||
+ (Deinterleave && Deinterleave != CurrentDeinterleave))
+ return false;
+ if (!Deinterleave)
+ Deinterleave = CurrentDeinterleave;
+ }
+
+ Value *Input = Deinterleave->getArgOperand(0);
+
+ auto *Load = dyn_cast<LoadInst>(Input);
+ if (!Load)
+ return false;
+
+ auto *InputTy = dyn_cast<FixedVectorType>(Input->getType());
+ if (!InputTy)
+ return false;
+
+ unsigned NumElts = InputTy->getNumElements();
+ SmallVector<int> Mask;
+ for (unsigned I = 0; I != NumElts; I += Factor)
+ llvm::append_range(Mask, llvm::reverse(llvm::seq(I, I + Factor)));
+
+ SmallVector<unsigned, 8> AllIndices(Factor);
+ std::iota(AllIndices.begin(), AllIndices.end(), 0);
+ InstructionCost OldCost = TTI.getInterleavedMemoryOpCost(
+ Instruction::Load, InputTy, Factor, AllIndices, Load->getAlign(),
+ Load->getPointerAddressSpace(), CostKind);
+ OldCost += TTI.getInterleavedMemoryOpCost(
+ Instruction::Store, InputTy, Factor, AllIndices, Store->getAlign(),
+ Store->getPointerAddressSpace(), CostKind);
+
+ InstructionCost NewCost =
+ TTI.getMemoryOpCost(Instruction::Load, InputTy, Load->getAlign(),
+ Load->getPointerAddressSpace(), CostKind) +
+ TTI.getMemoryOpCost(Instruction::Store, InputTy, Store->getAlign(),
+ Store->getPointerAddressSpace(), CostKind);
+ NewCost +=
+ TTI.getShuffleCost(TargetTransformInfo::SK_PermuteSingleSrc, InputTy,
+ InputTy, CostKind, Mask, 0, nullptr, {Input}, &I);
+
+ LLVM_DEBUG(dbgs() << "VC: Folding reordered reinterleave: " << I
+ << "\n OldCost: " << OldCost << " vs NewCost: " << NewCost
+ << "\n");
+ if (!OldCost.isValid() || !NewCost.isValid() || NewCost > OldCost)
+ return false;
+
+ replaceValue(I, *Builder.CreateShuffleVector(Input, Mask));
+ 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
/// before casting it back into `<vscale x 16 x i32>`.
bool VectorCombine::foldInterleaveIntrinsics(Instruction &I) {
+ if (foldInterleaveOfReorderedDeinterleave(I))
+ return true;
const APInt *SplatVal0, *SplatVal1;
if (!match(&I, m_Intrinsic<Intrinsic::vector_interleave2>(
m_APInt(SplatVal0), m_APInt(SplatVal1))))
diff --git a/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
index 6754c6d49c155..9d2987673acc3 100644
--- a/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
+++ b/llvm/test/Transforms/VectorCombine/AArch64/interleave-reordered-deinterleave.ll
@@ -1,72 +1,73 @@
; 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 <8 x i16> @reverse_fields_interleave2(<8 x i16> %x) {
-; CHECK-LABEL: define <8 x i16> @reverse_fields_interleave2(
-; CHECK-SAME: <8 x i16> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2.v8i16(<8 x i16> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i16>, <4 x i16> } [[D]], 1
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <8 x i16> @llvm.vector.interleave2.v8i16(<4 x i16> [[D1]], <4 x i16> [[D0]])
-; CHECK-NEXT: ret <8 x i16> [[INTERLEAVE]]
+define void @reverse_fields_interleave2(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave2(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <8 x i16>, ptr [[SRC]], align 2
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <8 x i16> [[X]], <8 x i16> poison, <8 x i32> <i32 1, i32 0, i32 3, i32 2, i32 5, i32 4, i32 7, i32 6>
+; CHECK-NEXT: store <8 x i16> [[INTERLEAVE]], ptr [[DST]], align 2
+; CHECK-NEXT: ret void
;
+ %x = load <8 x i16>, ptr %src, align 2
%d = call { <4 x i16>, <4 x i16> } @llvm.vector.deinterleave2(<8 x i16> %x)
%d0 = extractvalue { <4 x i16>, <4 x i16> } %d, 0
%d1 = extractvalue { <4 x i16>, <4 x i16> } %d, 1
%interleave = call <8 x i16> @llvm.vector.interleave2(<4 x i16> %d1, <4 x i16> %d0)
- ret <8 x i16> %interleave
+ store <8 x i16> %interleave, ptr %dst, align 2
+ ret void
}
-define <12 x i16> @reverse_fields_interleave3(<12 x i16> %x) {
-; CHECK-LABEL: define <12 x i16> @reverse_fields_interleave3(
-; CHECK-SAME: <12 x i16> [[X:%.*]]) {
+define void @reverse_fields_interleave3(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave3(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <12 x i16>, ptr [[SRC]], align 2
; CHECK-NEXT: [[D:%.*]] = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.vector.deinterleave3.v12i16(<12 x i16> [[X]])
; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 0
; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 1
; CHECK-NEXT: [[D2:%.*]] = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } [[D]], 2
; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <12 x i16> @llvm.vector.interleave3.v12i16(<4 x i16> [[D2]], <4 x i16> [[D1]], <4 x i16> [[D0]])
-; CHECK-NEXT: ret <12 x i16> [[INTERLEAVE]]
+; CHECK-NEXT: store <12 x i16> [[INTERLEAVE]], ptr [[DST]], align 2
+; CHECK-NEXT: ret void
;
+ %x = load <12 x i16>, ptr %src, align 2
%d = call { <4 x i16>, <4 x i16>, <4 x i16> } @llvm.vector.deinterleave3(<12 x i16> %x)
%d0 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 0
%d1 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 1
%d2 = extractvalue { <4 x i16>, <4 x i16>, <4 x i16> } %d, 2
%interleave = call <12 x i16> @llvm.vector.interleave3(<4 x i16> %d2, <4 x i16> %d1, <4 x i16> %d0)
- ret <12 x i16> %interleave
+ store <12 x i16> %interleave, ptr %dst, align 2
+ ret void
}
-define <16 x i8> @reverse_fields_interleave4(<16 x i8> %x) {
-; CHECK-LABEL: define <16 x i8> @reverse_fields_interleave4(
-; CHECK-SAME: <16 x i8> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } @llvm.vector.deinterleave4.v16i8(<16 x i8> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 1
-; CHECK-NEXT: [[D2:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 2
-; CHECK-NEXT: [[D3:%.*]] = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } [[D]], 3
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i8> @llvm.vector.interleave4.v16i8(<4 x i8> [[D3]], <4 x i8> [[D2]], <4 x i8> [[D1]], <4 x i8> [[D0]])
-; CHECK-NEXT: ret <16 x i8> [[INTERLEAVE]]
+define void @reverse_fields_interleave4(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave4(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <16 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <16 x i8> [[X]], <16 x i8> poison, <16 x i32> <i32 3, i32 2, i32 1, i32 0, i32 7, i32 6, i32 5, i32 4, i32 11, i32 10, i32 9, i32 8, i32 15, i32 14, i32 13, i32 12>
+; CHECK-NEXT: store <16 x i8> [[INTERLEAVE]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
;
+ %x = load <16 x i8>, ptr %src, align 1
%d = call { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } @llvm.vector.deinterleave4(<16 x i8> %x)
%d0 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 0
%d1 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 1
%d2 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 2
%d3 = extractvalue { <4 x i8>, <4 x i8>, <4 x i8>, <4 x i8> } %d, 3
%interleave = call <16 x i8> @llvm.vector.interleave4(<4 x i8> %d3, <4 x i8> %d2, <4 x i8> %d1, <4 x i8> %d0)
- ret <16 x i8> %interleave
+ store <16 x i8> %interleave, ptr %dst, align 1
+ ret void
}
-define <10 x i8> @reverse_fields_interleave5(<10 x i8> %x) {
-; CHECK-LABEL: define <10 x i8> @reverse_fields_interleave5(
-; CHECK-SAME: <10 x i8> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave5.v10i8(<10 x i8> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
-; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
-; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
-; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <10 x i8> @llvm.vector.interleave5.v10i8(<2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
-; CHECK-NEXT: ret <10 x i8> [[INTERLEAVE]]
+define void @reverse_fields_interleave5(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave5(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <10 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <10 x i8> [[X]], <10 x i8> poison, <10 x i32> <i32 4, i32 3, i32 2, i32 1, i32 0, i32 9, i32 8, i32 7, i32 6, i32 5>
+; CHECK-NEXT: store <10 x i8> [[INTERLEAVE]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
;
+ %x = load <10 x i8>, ptr %src, align 1
%d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave5(<10 x i8> %x)
%d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
%d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
@@ -74,22 +75,19 @@ define <10 x i8> @reverse_fields_interleave5(<10 x i8> %x) {
%d3 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 3
%d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
%interleave = call <10 x i8> @llvm.vector.interleave5(<2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
- ret <10 x i8> %interleave
+ store <10 x i8> %interleave, ptr %dst, align 1
+ ret void
}
-define <12 x i8> @reverse_fields_interleave6(<12 x i8> %x) {
-; CHECK-LABEL: define <12 x i8> @reverse_fields_interleave6(
-; CHECK-SAME: <12 x i8> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave6.v12i8(<12 x i8> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
-; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
-; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
-; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
-; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <12 x i8> @llvm.vector.interleave6.v12i8(<2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
-; CHECK-NEXT: ret <12 x i8> [[INTERLEAVE]]
+define void @reverse_fields_interleave6(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave6(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <12 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <12 x i8> [[X]], <12 x i8> poison, <12 x i32> <i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 11, i32 10, i32 9, i32 8, i32 7, i32 6>
+; CHECK-NEXT: store <12 x i8> [[INTERLEAVE]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
;
+ %x = load <12 x i8>, ptr %src, align 1
%d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave6(<12 x i8> %x)
%d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
%d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
@@ -98,23 +96,19 @@ define <12 x i8> @reverse_fields_interleave6(<12 x i8> %x) {
%d4 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 4
%d5 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 5
%interleave = call <12 x i8> @llvm.vector.interleave6(<2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
- ret <12 x i8> %interleave
+ store <12 x i8> %interleave, ptr %dst, align 1
+ ret void
}
-define <14 x i8> @reverse_fields_interleave7(<14 x i8> %x) {
-; CHECK-LABEL: define <14 x i8> @reverse_fields_interleave7(
-; CHECK-SAME: <14 x i8> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave7.v14i8(<14 x i8> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
-; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
-; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
-; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
-; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
-; CHECK-NEXT: [[D6:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 6
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <14 x i8> @llvm.vector.interleave7.v14i8(<2 x i8> [[D6]], <2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
-; CHECK-NEXT: ret <14 x i8> [[INTERLEAVE]]
+define void @reverse_fields_interleave7(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave7(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <14 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <14 x i8> [[X]], <14 x i8> poison, <14 x i32> <i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8, i32 7>
+; CHECK-NEXT: store <14 x i8> [[INTERLEAVE]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
;
+ %x = load <14 x i8>, ptr %src, align 1
%d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave7(<14 x i8> %x)
%d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
%d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
@@ -124,24 +118,19 @@ define <14 x i8> @reverse_fields_interleave7(<14 x i8> %x) {
%d5 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 5
%d6 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 6
%interleave = call <14 x i8> @llvm.vector.interleave7(<2 x i8> %d6, <2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
- ret <14 x i8> %interleave
+ store <14 x i8> %interleave, ptr %dst, align 1
+ ret void
}
-define <16 x i8> @reverse_fields_interleave8(<16 x i8> %x) {
-; CHECK-LABEL: define <16 x i8> @reverse_fields_interleave8(
-; CHECK-SAME: <16 x i8> [[X:%.*]]) {
-; CHECK-NEXT: [[D:%.*]] = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave8.v16i8(<16 x i8> [[X]])
-; CHECK-NEXT: [[D0:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 0
-; CHECK-NEXT: [[D1:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 1
-; CHECK-NEXT: [[D2:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 2
-; CHECK-NEXT: [[D3:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 3
-; CHECK-NEXT: [[D4:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 4
-; CHECK-NEXT: [[D5:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 5
-; CHECK-NEXT: [[D6:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 6
-; CHECK-NEXT: [[D7:%.*]] = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } [[D]], 7
-; CHECK-NEXT: [[INTERLEAVE:%.*]] = call <16 x i8> @llvm.vector.interleave8.v16i8(<2 x i8> [[D7]], <2 x i8> [[D6]], <2 x i8> [[D5]], <2 x i8> [[D4]], <2 x i8> [[D3]], <2 x i8> [[D2]], <2 x i8> [[D1]], <2 x i8> [[D0]])
-; CHECK-NEXT: ret <16 x i8> [[INTERLEAVE]]
+define void @reverse_fields_interleave8(ptr %src, ptr %dst) {
+; CHECK-LABEL: define void @reverse_fields_interleave8(
+; CHECK-SAME: ptr [[SRC:%.*]], ptr [[DST:%.*]]) {
+; CHECK-NEXT: [[X:%.*]] = load <16 x i8>, ptr [[SRC]], align 1
+; CHECK-NEXT: [[INTERLEAVE:%.*]] = shufflevector <16 x i8> [[X]], <16 x i8> poison, <16 x i32> <i32 7, i32 6, i32 5, i32 4, i32 3, i32 2, i32 1, i32 0, i32 15, i32 14, i32 13, i32 12, i32 11, i32 10, i32 9, i32 8>
+; CHECK-NEXT: store <16 x i8> [[INTERLEAVE]], ptr [[DST]], align 1
+; CHECK-NEXT: ret void
;
+ %x = load <16 x i8>, ptr %src, align 1
%d = call { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } @llvm.vector.deinterleave8(<16 x i8> %x)
%d0 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 0
%d1 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 1
@@ -152,6 +141,6 @@ define <16 x i8> @reverse_fields_interleave8(<16 x i8> %x) {
%d6 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 6
%d7 = extractvalue { <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8>, <2 x i8> } %d, 7
%interleave = call <16 x i8> @llvm.vector.interleave8(<2 x i8> %d7, <2 x i8> %d6, <2 x i8> %d5, <2 x i8> %d4, <2 x i8> %d3, <2 x i8> %d2, <2 x i8> %d1, <2 x i8> %d0)
- ret <16 x i8> %interleave
+ store <16 x i8> %interleave, ptr %dst, align 1
+ ret void
}
-
More information about the llvm-commits
mailing list