[llvm] [AArch64][ISel] Fix interleave3 crash (PR #192046)
Matthew Devereau via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 14 08:48:34 PDT 2026
https://github.com/MDevereau updated https://github.com/llvm/llvm-project/pull/192046
>From cc222c023ede447683d5e080508afd58bdb63238 Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Tue, 14 Apr 2026 12:31:31 +0000
Subject: [PATCH 1/3] [AArch64][ISel] Fix interleave3 crash
This fixes a crash where an interleave3 intrinsic is left behind due
to multiple stores, where it has no independent lowering.
---
.../Target/AArch64/AArch64ISelLowering.cpp | 57 +++++++++
.../AArch64/fixed-vector-interleave.ll | 115 ++++++++++++++++++
2 files changed, 172 insertions(+)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ece24767bdbb9..ad5e935c2266a 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -32322,6 +32322,63 @@ SDValue AArch64TargetLowering::LowerVECTOR_INTERLEAVE(SDValue Op,
return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Op->getVTList(), Ops);
}
+ if (Op->getNumOperands() == 3 && (OpVT == MVT::v2f64 || OpVT == MVT::v2i64)) {
+ SDValue A = Op->getOperand(0);
+ SDValue B = Op->getOperand(1);
+ SDValue C = Op->getOperand(2);
+
+ // a0, a1 | b0, b1 | c0, c1
+ // ->
+ // a0, b0 | c0, a1 | b1, c1
+ SDValue Shuffle0 = DAG.getVectorShuffle(OpVT, DL, A, B, {0, 2});
+ SDValue Shuffle1 = DAG.getVectorShuffle(OpVT, DL, A, C, {2, 1});
+ SDValue Shuffle2 = DAG.getVectorShuffle(OpVT, DL, B, C, {1, 3});
+
+ return DAG.getMergeValues({Shuffle0, Shuffle1, Shuffle2}, DL);
+ }
+ if (Op->getNumOperands() == 3 && OpVT.isFixedLengthVector()) {
+ unsigned NElements = OpVT.getVectorNumElements();
+ SDValue A = Op->getOperand(0);
+ SDValue B = Op->getOperand(1);
+ SDValue C = Op->getOperand(2);
+
+ // Build two masks for two shuffles. The first mask shuffles elements from
+ // A and B, and with elements of C represented with -1 so the shuffle
+ // ignores them. The second shuffle then replaces -1 values with the actual
+ // indices from C.
+ SmallVector<int> ABMask;
+ for (unsigned E = 0; E < NElements; E++) {
+ for (unsigned F = 0; F < 3; F++) {
+ if (F == 2)
+ ABMask.push_back(-1);
+ else
+ ABMask.push_back(F * NElements + E);
+ }
+ }
+
+ std::vector<int> ABCMask;
+ for (unsigned F = 0, Idx = 0; F < 3; F++) {
+ for (unsigned E = 0; E < NElements; E++) {
+ if (ABMask[F * NElements + E] == -1)
+ ABCMask.push_back(NElements + Idx++);
+ else
+ ABCMask.push_back(Idx);
+ }
+ }
+
+ SmallVector<SDValue, 3> Shuffles;
+ for (unsigned I = 0; I < 3; I++) {
+ SDValue AB = DAG.getVectorShuffle(
+ OpVT, DL, A, B,
+ ArrayRef<int>(ABMask.data() + NElements * I, NElements));
+ Shuffles.push_back(DAG.getVectorShuffle(
+ OpVT, DL, AB, C,
+ ArrayRef<int>(ABCMask.data() + NElements * I, NElements)));
+ }
+
+ return DAG.getMergeValues(Shuffles, DL);
+ }
+
if (Op->getNumOperands() != 2)
return SDValue();
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
index eb9d576daee4e..054173a5eabbb 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
@@ -453,3 +453,118 @@ define <32 x bfloat> @interleave4_v32bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1
%retval = call <32 x bfloat> @llvm.vector.interleave4.v32bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1, <8 x bfloat> %vec2, <8 x bfloat> %vec3)
ret <32 x bfloat> %retval
}
+
+define void @interleave3_v6f64(ptr %p, ptr %p0, <2 x double> %vec0, <2 x double> %vec1, <2 x double> %vec2) {
+; CHECK-LABEL: interleave3_v6f64:
+; CHECK: // %bb.0:
+; CHECK-NEXT: zip1 v3.2d, v0.2d, v1.2d
+; CHECK-NEXT: mov v0.d[0], v2.d[0]
+; CHECK-NEXT: zip2 v1.2d, v1.2d, v2.2d
+; CHECK-NEXT: stp q3, q0, [x0]
+; CHECK-NEXT: str q1, [x0, #32]
+; CHECK-NEXT: stp q3, q0, [x1]
+; CHECK-NEXT: str q1, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <6 x double> @llvm.vector.interleave3.v6f64(<2 x double> %vec0, <2 x double> %vec1, <2 x double> %vec2)
+ store <6 x double> %retval, ptr %p
+ store <6 x double> %retval, ptr %p0
+ ret void
+}
+
+define void @interleave3_v12f32(ptr %p, ptr %p0, <4 x float> %vec0, <4 x float> %vec1, <4 x float> %vec2) {
+; CHECK-LABEL: interleave3_v12f32:
+; CHECK: // %bb.0:
+; CHECK-NEXT: trn2 v3.4s, v0.4s, v1.4s
+; CHECK-NEXT: trn1 v4.4s, v0.4s, v1.4s
+; CHECK-NEXT: uzp1 v5.4s, v0.4s, v1.4s
+; CHECK-NEXT: ext v3.16b, v3.16b, v0.16b, #4
+; CHECK-NEXT: mov v4.d[1], v0.d[0]
+; CHECK-NEXT: uzp2 v0.4s, v1.4s, v5.4s
+; CHECK-NEXT: zip2 v1.4s, v3.4s, v2.4s
+; CHECK-NEXT: zip1 v5.4s, v4.4s, v2.4s
+; CHECK-NEXT: zip1 v2.4s, v0.4s, v2.4s
+; CHECK-NEXT: dup v0.4s, v0.s[2]
+; CHECK-NEXT: ext v3.16b, v3.16b, v1.16b, #12
+; CHECK-NEXT: zip1 v4.4s, v5.4s, v4.4s
+; CHECK-NEXT: ext v0.16b, v2.16b, v0.16b, #8
+; CHECK-NEXT: zip2 v1.4s, v3.4s, v1.4s
+; CHECK-NEXT: stp q4, q0, [x0]
+; CHECK-NEXT: str q1, [x0, #32]
+; CHECK-NEXT: stp q4, q0, [x1]
+; CHECK-NEXT: str q1, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <12 x float> @llvm.vector.interleave3.v12f32(<4 x float> %vec0, <4 x float> %vec1, <4 x float> %vec2)
+ store <12 x float> %retval, ptr %p
+ store <12 x float> %retval, ptr %p0
+ ret void
+}
+
+define void @interleave3_v24i16(ptr %p, ptr %p0, <8 x i16> %vec0, <8 x i16> %vec1, <8 x i16> %vec2) {
+; CHECK-LABEL: interleave3_v24i16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $q2 killed $q2 killed $q1_q2 def $q1_q2
+; CHECK-NEXT: mov v4.16b, v1.16b
+; CHECK-NEXT: adrp x8, .LCPI32_0
+; CHECK-NEXT: adrp x9, .LCPI32_2
+; CHECK-NEXT: mov v3.16b, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI32_0]
+; CHECK-NEXT: adrp x8, .LCPI32_1
+; CHECK-NEXT: ldr q5, [x9, :lo12:.LCPI32_2]
+; CHECK-NEXT: adrp x9, .LCPI32_4
+; CHECK-NEXT: ldr q6, [x9, :lo12:.LCPI32_4]
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI32_1]
+; CHECK-NEXT: adrp x8, .LCPI32_3
+; CHECK-NEXT: tbl v0.16b, { v1.16b, v2.16b }, v0.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v5.16b
+; CHECK-NEXT: ldr q5, [x8, :lo12:.LCPI32_3]
+; CHECK-NEXT: adrp x8, .LCPI32_5
+; CHECK-NEXT: tbl v5.16b, { v1.16b, v2.16b }, v5.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v6.16b
+; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI32_5]
+; CHECK-NEXT: tbl v1.16b, { v1.16b, v2.16b }, v3.16b
+; CHECK-NEXT: stp q5, q0, [x0, #16]
+; CHECK-NEXT: str q1, [x0]
+; CHECK-NEXT: stp q1, q5, [x1]
+; CHECK-NEXT: str q0, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <24 x i16> @llvm.vector.interleave3.v24i16(<8 x i16> %vec0, <8 x i16> %vec1, <8 x i16> %vec2)
+ store <24 x i16> %retval, ptr %p
+ store <24 x i16> %retval, ptr %p0
+ ret void
+}
+
+define void @interleave3_v48i8(ptr %p, ptr %p0, <16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2) {
+; CHECK-LABEL: interleave3_v48i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $q2 killed $q2 killed $q1_q2 def $q1_q2
+; CHECK-NEXT: mov v4.16b, v1.16b
+; CHECK-NEXT: adrp x8, .LCPI33_0
+; CHECK-NEXT: adrp x9, .LCPI33_2
+; CHECK-NEXT: mov v3.16b, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI33_0]
+; CHECK-NEXT: adrp x8, .LCPI33_1
+; CHECK-NEXT: ldr q5, [x9, :lo12:.LCPI33_2]
+; CHECK-NEXT: adrp x9, .LCPI33_4
+; CHECK-NEXT: ldr q6, [x9, :lo12:.LCPI33_4]
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI33_1]
+; CHECK-NEXT: adrp x8, .LCPI33_3
+; CHECK-NEXT: tbl v0.16b, { v1.16b, v2.16b }, v0.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v5.16b
+; CHECK-NEXT: ldr q5, [x8, :lo12:.LCPI33_3]
+; CHECK-NEXT: adrp x8, .LCPI33_5
+; CHECK-NEXT: tbl v5.16b, { v1.16b, v2.16b }, v5.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v6.16b
+; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI33_5]
+; CHECK-NEXT: tbl v1.16b, { v1.16b, v2.16b }, v3.16b
+; CHECK-NEXT: stp q5, q0, [x0, #16]
+; CHECK-NEXT: str q1, [x0]
+; CHECK-NEXT: stp q1, q5, [x1]
+; CHECK-NEXT: str q0, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <48 x i8> @llvm.vector.interleave3.v48i8(<16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2)
+ store <48 x i8> %retval, ptr %p
+ store <48 x i8> %retval, ptr %p0
+ ret void
+}
>From b336783e01d3aaf1b02bbd9361de8258747f73ec Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Tue, 14 Apr 2026 14:57:41 +0000
Subject: [PATCH 2/3] Add more comments and tests, fix bug
---
.../Target/AArch64/AArch64ISelLowering.cpp | 35 +++++---
.../AArch64/fixed-vector-deinterleave.ll | 4 +
.../AArch64/fixed-vector-interleave.ll | 90 ++++++++++++++++---
3 files changed, 107 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index ad5e935c2266a..62693e08ffe85 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -32322,30 +32322,45 @@ SDValue AArch64TargetLowering::LowerVECTOR_INTERLEAVE(SDValue Op,
return DAG.getNode(ISD::INTRINSIC_WO_CHAIN, DL, Op->getVTList(), Ops);
}
+ // For v2f64 and v2i64, each vector part of the interleaved v6f64 vector can
+ // be made with one shuffle only, as the interleave factor is greater than the
+ // number of elements in the vector. a0, a1 | b0, b1 | c0, c1
+ // ->
+ // a0, b0 | c0, a1 | b1, c1
if (Op->getNumOperands() == 3 && (OpVT == MVT::v2f64 || OpVT == MVT::v2i64)) {
SDValue A = Op->getOperand(0);
SDValue B = Op->getOperand(1);
SDValue C = Op->getOperand(2);
-
- // a0, a1 | b0, b1 | c0, c1
- // ->
- // a0, b0 | c0, a1 | b1, c1
SDValue Shuffle0 = DAG.getVectorShuffle(OpVT, DL, A, B, {0, 2});
SDValue Shuffle1 = DAG.getVectorShuffle(OpVT, DL, A, C, {2, 1});
SDValue Shuffle2 = DAG.getVectorShuffle(OpVT, DL, B, C, {1, 3});
return DAG.getMergeValues({Shuffle0, Shuffle1, Shuffle2}, DL);
}
+
+ // When the interleave factor is less than the number of vector elements we
+ // need two shuffles to mix three vector's elements together:
+ // step1: a0, b0, __, a1, | b1, __, a2, b2 | ...
+ // step2: a0, b0, c0, a1 | b1, c1, a2, b2 | ...
if (Op->getNumOperands() == 3 && OpVT.isFixedLengthVector()) {
unsigned NElements = OpVT.getVectorNumElements();
SDValue A = Op->getOperand(0);
SDValue B = Op->getOperand(1);
SDValue C = Op->getOperand(2);
-
- // Build two masks for two shuffles. The first mask shuffles elements from
- // A and B, and with elements of C represented with -1 so the shuffle
- // ignores them. The second shuffle then replaces -1 values with the actual
- // indices from C.
+ // Build two masks for the two shuffles. The first mask shuffles elements
+ // from A and B, and with elements of C represented with -1 to be ignored.
+ // The second shuffle then replaces -1 values with the actual
+ // indices from C like so:
+
+ // 0 1 2 3 4 5 6 7
+ // a0, a1, a2, a3, b0, b1, b2, b3
+ // t55: v4f32 = vector_shuffle<0,4,u,1> A, B
+ // t55 = a0, b0, -1, a1
+ //
+ // 0 1 2 3 4 5 6 7
+ // a0, b0, -1, a1, c0, c1, c2, c3
+ // t56: v4f32 = vector_shuffle<0,1,4,3> t55, C
+ // t56 = a0, b0, c1, a1
SmallVector<int> ABMask;
for (unsigned E = 0; E < NElements; E++) {
for (unsigned F = 0; F < 3; F++) {
@@ -32362,7 +32377,7 @@ SDValue AArch64TargetLowering::LowerVECTOR_INTERLEAVE(SDValue Op,
if (ABMask[F * NElements + E] == -1)
ABCMask.push_back(NElements + Idx++);
else
- ABCMask.push_back(Idx);
+ ABCMask.push_back(E);
}
}
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index 24670ef2abd24..c1a6122de8f2f 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -392,3 +392,7 @@ define {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} @vector_deinterl
ret {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} %retval
}
+define {<4 x float>, <4 x float>, <4 x float>} @vector_deinterleave3_v4f32_v12f32(<12 x float> %vec) {
+ %retval = call {<4 x float>, <4 x float>, <4 x float>} @llvm.vector.deinterleave3.v12f32(<12 x float> %vec)
+ ret {<4 x float>, <4 x float>, <4 x float>} %retval
+}
\ No newline at end of file
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
index 054173a5eabbb..6ce2a35cb6fba 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
@@ -480,18 +480,14 @@ define void @interleave3_v12f32(ptr %p, ptr %p0, <4 x float> %vec0, <4 x float>
; CHECK-NEXT: ext v3.16b, v3.16b, v0.16b, #4
; CHECK-NEXT: mov v4.d[1], v0.d[0]
; CHECK-NEXT: uzp2 v0.4s, v1.4s, v5.4s
-; CHECK-NEXT: zip2 v1.4s, v3.4s, v2.4s
-; CHECK-NEXT: zip1 v5.4s, v4.4s, v2.4s
-; CHECK-NEXT: zip1 v2.4s, v0.4s, v2.4s
-; CHECK-NEXT: dup v0.4s, v0.s[2]
-; CHECK-NEXT: ext v3.16b, v3.16b, v1.16b, #12
-; CHECK-NEXT: zip1 v4.4s, v5.4s, v4.4s
-; CHECK-NEXT: ext v0.16b, v2.16b, v0.16b, #8
-; CHECK-NEXT: zip2 v1.4s, v3.4s, v1.4s
+; CHECK-NEXT: mov v3.s[0], v2.s[2]
+; CHECK-NEXT: mov v4.s[2], v2.s[0]
+; CHECK-NEXT: mov v0.s[1], v2.s[1]
+; CHECK-NEXT: mov v3.s[3], v2.s[3]
; CHECK-NEXT: stp q4, q0, [x0]
-; CHECK-NEXT: str q1, [x0, #32]
+; CHECK-NEXT: str q3, [x0, #32]
; CHECK-NEXT: stp q4, q0, [x1]
-; CHECK-NEXT: str q1, [x1, #32]
+; CHECK-NEXT: str q3, [x1, #32]
; CHECK-NEXT: ret
%retval = call <12 x float> @llvm.vector.interleave3.v12f32(<4 x float> %vec0, <4 x float> %vec1, <4 x float> %vec2)
store <12 x float> %retval, ptr %p
@@ -534,8 +530,8 @@ define void @interleave3_v24i16(ptr %p, ptr %p0, <8 x i16> %vec0, <8 x i16> %vec
ret void
}
-define void @interleave3_v48i8(ptr %p, ptr %p0, <16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2) {
-; CHECK-LABEL: interleave3_v48i8:
+define void @interleave3_v24f16(ptr %p, ptr %p0, <8 x half> %vec0, <8 x half> %vec1, <8 x half> %vec2) {
+; CHECK-LABEL: interleave3_v24f16:
; CHECK: // %bb.0:
; CHECK-NEXT: // kill: def $q2 killed $q2 killed $q1_q2 def $q1_q2
; CHECK-NEXT: mov v4.16b, v1.16b
@@ -562,6 +558,76 @@ define void @interleave3_v48i8(ptr %p, ptr %p0, <16 x i8> %vec0, <16 x i8> %vec1
; CHECK-NEXT: str q1, [x0]
; CHECK-NEXT: stp q1, q5, [x1]
; CHECK-NEXT: str q0, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <24 x half> @llvm.vector.interleave3.v24f16(<8 x half> %vec0, <8 x half> %vec1, <8 x half> %vec2)
+ store <24 x half> %retval, ptr %p
+ store <24 x half> %retval, ptr %p0
+ ret void
+}
+
+define void @interleave3_v24bf16(ptr %p, ptr %p0, <8 x bfloat> %vec0, <8 x bfloat> %vec1, <8 x bfloat> %vec2) {
+; CHECK-LABEL: interleave3_v24bf16:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $q2 killed $q2 killed $q1_q2 def $q1_q2
+; CHECK-NEXT: mov v4.16b, v1.16b
+; CHECK-NEXT: adrp x8, .LCPI34_0
+; CHECK-NEXT: adrp x9, .LCPI34_2
+; CHECK-NEXT: mov v3.16b, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI34_0]
+; CHECK-NEXT: adrp x8, .LCPI34_1
+; CHECK-NEXT: ldr q5, [x9, :lo12:.LCPI34_2]
+; CHECK-NEXT: adrp x9, .LCPI34_4
+; CHECK-NEXT: ldr q6, [x9, :lo12:.LCPI34_4]
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI34_1]
+; CHECK-NEXT: adrp x8, .LCPI34_3
+; CHECK-NEXT: tbl v0.16b, { v1.16b, v2.16b }, v0.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v5.16b
+; CHECK-NEXT: ldr q5, [x8, :lo12:.LCPI34_3]
+; CHECK-NEXT: adrp x8, .LCPI34_5
+; CHECK-NEXT: tbl v5.16b, { v1.16b, v2.16b }, v5.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v6.16b
+; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI34_5]
+; CHECK-NEXT: tbl v1.16b, { v1.16b, v2.16b }, v3.16b
+; CHECK-NEXT: stp q5, q0, [x0, #16]
+; CHECK-NEXT: str q1, [x0]
+; CHECK-NEXT: stp q1, q5, [x1]
+; CHECK-NEXT: str q0, [x1, #32]
+; CHECK-NEXT: ret
+ %retval = call <24 x bfloat> @llvm.vector.interleave3.v24bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1, <8 x bfloat> %vec2)
+ store <24 x bfloat> %retval, ptr %p
+ store <24 x bfloat> %retval, ptr %p0
+ ret void
+}
+
+define void @interleave3_v48i8(ptr %p, ptr %p0, <16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2) {
+; CHECK-LABEL: interleave3_v48i8:
+; CHECK: // %bb.0:
+; CHECK-NEXT: // kill: def $q2 killed $q2 killed $q1_q2 def $q1_q2
+; CHECK-NEXT: mov v4.16b, v1.16b
+; CHECK-NEXT: adrp x8, .LCPI35_0
+; CHECK-NEXT: adrp x9, .LCPI35_2
+; CHECK-NEXT: mov v3.16b, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI35_0]
+; CHECK-NEXT: adrp x8, .LCPI35_1
+; CHECK-NEXT: ldr q5, [x9, :lo12:.LCPI35_2]
+; CHECK-NEXT: adrp x9, .LCPI35_4
+; CHECK-NEXT: ldr q6, [x9, :lo12:.LCPI35_4]
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v0.16b
+; CHECK-NEXT: ldr q0, [x8, :lo12:.LCPI35_1]
+; CHECK-NEXT: adrp x8, .LCPI35_3
+; CHECK-NEXT: tbl v0.16b, { v1.16b, v2.16b }, v0.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v5.16b
+; CHECK-NEXT: ldr q5, [x8, :lo12:.LCPI35_3]
+; CHECK-NEXT: adrp x8, .LCPI35_5
+; CHECK-NEXT: tbl v5.16b, { v1.16b, v2.16b }, v5.16b
+; CHECK-NEXT: tbl v1.16b, { v3.16b, v4.16b }, v6.16b
+; CHECK-NEXT: ldr q3, [x8, :lo12:.LCPI35_5]
+; CHECK-NEXT: tbl v1.16b, { v1.16b, v2.16b }, v3.16b
+; CHECK-NEXT: stp q5, q0, [x0, #16]
+; CHECK-NEXT: str q1, [x0]
+; CHECK-NEXT: stp q1, q5, [x1]
+; CHECK-NEXT: str q0, [x1, #32]
; CHECK-NEXT: ret
%retval = call <48 x i8> @llvm.vector.interleave3.v48i8(<16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2)
store <48 x i8> %retval, ptr %p
>From 6c891301dcd9b6a416c2fa85e23a49083baa5a8c Mon Sep 17 00:00:00 2001
From: Matthew Devereau <matthew.devereau at arm.com>
Date: Tue, 14 Apr 2026 15:47:19 +0000
Subject: [PATCH 3/3] Remove deinterleave test changes
---
llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll | 4 ----
1 file changed, 4 deletions(-)
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index c1a6122de8f2f..24670ef2abd24 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -392,7 +392,3 @@ define {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} @vector_deinterl
ret {<8 x bfloat>, <8 x bfloat>, <8 x bfloat>, <8 x bfloat>} %retval
}
-define {<4 x float>, <4 x float>, <4 x float>} @vector_deinterleave3_v4f32_v12f32(<12 x float> %vec) {
- %retval = call {<4 x float>, <4 x float>, <4 x float>} @llvm.vector.deinterleave3.v12f32(<12 x float> %vec)
- ret {<4 x float>, <4 x float>, <4 x float>} %retval
-}
\ No newline at end of file
More information about the llvm-commits
mailing list