[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