[llvm] 37aca9d - [AArch64] Fold interleave of build_vector (#214403)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 10 21:14:24 PDT 2026
Author: Kamlesh Kumar
Date: 2026-08-11T05:14:19+01:00
New Revision: 37aca9d384347f4f965fa137b0f5463156ba590f
URL: https://github.com/llvm/llvm-project/commit/37aca9d384347f4f965fa137b0f5463156ba590f
DIFF: https://github.com/llvm/llvm-project/commit/37aca9d384347f4f965fa137b0f5463156ba590f.diff
LOG: [AArch64] Fold interleave of build_vector (#214403)
Added:
llvm/test/CodeGen/AArch64/vector-interleave-build-vector.ll
Modified:
llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
Removed:
################################################################################
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index d7db5fb1b9e40..1095464a1ebdd 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -27734,6 +27734,33 @@ SDValue DAGCombiner::visitCONCAT_VECTORS(SDNode *N) {
}
SDValue DAGCombiner::visitVECTOR_INTERLEAVE(SDNode *N) {
+ EVT VT = N->getValueType(0);
+ SDValue Op0 = N->getOperand(0);
+
+ // Fold an interleave of fixed-length BUILD_VECTORs by rearranging their
+ // scalar operands directly.
+ if (Op0.getOpcode() == ISD::BUILD_VECTOR) {
+ EVT EltVT = Op0.getOperand(0).getValueType();
+ if (llvm::all_of(N->op_values(), [&](SDValue Op) {
+ return Op.getOpcode() == ISD::BUILD_VECTOR &&
+ Op.getOperand(0).getValueType() == EltVT;
+ })) {
+ unsigned Factor = N->getNumOperands();
+ unsigned NumElts = VT.getVectorNumElements();
+ SDLoc DL(N);
+ SmallVector<SDValue, 4> Results;
+ SmallVector<SDValue, 16> InterleavedElts;
+ for (unsigned I = 0; I != NumElts; ++I) {
+ for (SDValue op : N->op_values())
+ InterleavedElts.push_back(op.getOperand(I));
+ }
+ for (unsigned I = 0; I < Factor; I++)
+ Results.push_back(DAG.getBuildVector(
+ VT, DL, ArrayRef(InterleavedElts).slice(I * NumElts, NumElts)));
+ return CombineTo(N, &Results);
+ }
+ }
+
// Check to see if all operands are identical.
if (!llvm::all_equal(N->op_values()))
return SDValue();
diff --git a/llvm/test/CodeGen/AArch64/vector-interleave-build-vector.ll b/llvm/test/CodeGen/AArch64/vector-interleave-build-vector.ll
new file mode 100644
index 0000000000000..131df0feae2cc
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/vector-interleave-build-vector.ll
@@ -0,0 +1,214 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu | FileCheck %s
+; RUN: llc < %s -mtriple=aarch64-none-linux-gnu --lower-interleaved-accesses=false | FileCheck %s
+
+define <4 x i8> @interleave2_build_vector(i8 %a, i8 %b) {
+; CHECK-LABEL: interleave2_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.h[1], w1
+; CHECK-NEXT: mov v0.h[2], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.h[3], w8
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %res = call <4 x i8> @llvm.vector.interleave2.v4i8(
+ <2 x i8> %va, <2 x i8> %vb)
+ ret <4 x i8> %res
+}
+
+define <6 x i8> @interleave3_build_vector(i8 %a, i8 %b, i8 %c) {
+; CHECK-LABEL: interleave3_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[4], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[5], w8
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %res = call <6 x i8> @llvm.vector.interleave3.v6i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc)
+ ret <6 x i8> %res
+}
+
+define <8 x i8> @interleave4_build_vector(i8 %a, i8 %b, i8 %c, i8 %d) {
+; CHECK-LABEL: interleave4_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w3
+; CHECK-NEXT: mov v0.b[4], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[5], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[6], w8
+; CHECK-NEXT: mov w8, #23 // =0x17
+; CHECK-NEXT: mov v0.b[7], w8
+; CHECK-NEXT: // kill: def $d0 killed $d0 killed $q0
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %vd = insertelement <2 x i8> <i8 poison, i8 23>, i8 %d, i64 0
+ %res = call <8 x i8> @llvm.vector.interleave4.v8i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc, <2 x i8> %vd)
+ ret <8 x i8> %res
+}
+
+ define <10 x i8> @interleave5_build_vector(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e) {
+; CHECK-LABEL: interleave5_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w3
+; CHECK-NEXT: mov v0.b[4], w4
+; CHECK-NEXT: mov v0.b[5], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[6], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[7], w8
+; CHECK-NEXT: mov w8, #23 // =0x17
+; CHECK-NEXT: mov v0.b[8], w8
+; CHECK-NEXT: mov w8, #24 // =0x18
+; CHECK-NEXT: mov v0.b[9], w8
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %vd = insertelement <2 x i8> <i8 poison, i8 23>, i8 %d, i64 0
+ %ve = insertelement <2 x i8> <i8 poison, i8 24>, i8 %e, i64 0
+ %res = call <10 x i8> @llvm.vector.interleave5.v10i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc, <2 x i8> %vd,
+ <2 x i8> %ve)
+ ret <10 x i8> %res
+ }
+
+define <12 x i8> @interleave6_build_vector(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f) {
+; CHECK-LABEL: interleave6_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w3
+; CHECK-NEXT: mov v0.b[4], w4
+; CHECK-NEXT: mov v0.b[5], w5
+; CHECK-NEXT: mov v0.b[6], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[7], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[8], w8
+; CHECK-NEXT: mov w8, #23 // =0x17
+; CHECK-NEXT: mov v0.b[9], w8
+; CHECK-NEXT: mov w8, #24 // =0x18
+; CHECK-NEXT: mov v0.b[10], w8
+; CHECK-NEXT: mov w8, #25 // =0x19
+; CHECK-NEXT: mov v0.b[11], w8
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %vd = insertelement <2 x i8> <i8 poison, i8 23>, i8 %d, i64 0
+ %ve = insertelement <2 x i8> <i8 poison, i8 24>, i8 %e, i64 0
+ %vf = insertelement <2 x i8> <i8 poison, i8 25>, i8 %f, i64 0
+ %res = call <12 x i8> @llvm.vector.interleave6.v12i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc, <2 x i8> %vd,
+ <2 x i8> %ve, <2 x i8> %vf)
+ ret <12 x i8> %res
+}
+
+ define <14 x i8> @interleave7_build_vector(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g) {
+; CHECK-LABEL: interleave7_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w3
+; CHECK-NEXT: mov v0.b[4], w4
+; CHECK-NEXT: mov v0.b[5], w5
+; CHECK-NEXT: mov v0.b[6], w6
+; CHECK-NEXT: mov v0.b[7], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[8], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[9], w8
+; CHECK-NEXT: mov w8, #23 // =0x17
+; CHECK-NEXT: mov v0.b[10], w8
+; CHECK-NEXT: mov w8, #24 // =0x18
+; CHECK-NEXT: mov v0.b[11], w8
+; CHECK-NEXT: mov w8, #25 // =0x19
+; CHECK-NEXT: mov v0.b[12], w8
+; CHECK-NEXT: mov w8, #26 // =0x1a
+; CHECK-NEXT: mov v0.b[13], w8
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %vd = insertelement <2 x i8> <i8 poison, i8 23>, i8 %d, i64 0
+ %ve = insertelement <2 x i8> <i8 poison, i8 24>, i8 %e, i64 0
+ %vf = insertelement <2 x i8> <i8 poison, i8 25>, i8 %f, i64 0
+ %vg = insertelement <2 x i8> <i8 poison, i8 26>, i8 %g, i64 0
+ %res = call <14 x i8> @llvm.vector.interleave7.v14i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc, <2 x i8> %vd,
+ <2 x i8> %ve, <2 x i8> %vf, <2 x i8> %vg)
+ ret <14 x i8> %res
+ }
+
+define <16 x i8> @interleave8_build_vector(i8 %a, i8 %b, i8 %c, i8 %d, i8 %e, i8 %f, i8 %g, i8 %h) {
+; CHECK-LABEL: interleave8_build_vector:
+; CHECK: // %bb.0:
+; CHECK-NEXT: fmov s0, w0
+; CHECK-NEXT: mov w8, #20 // =0x14
+; CHECK-NEXT: mov v0.b[1], w1
+; CHECK-NEXT: mov v0.b[2], w2
+; CHECK-NEXT: mov v0.b[3], w3
+; CHECK-NEXT: mov v0.b[4], w4
+; CHECK-NEXT: mov v0.b[5], w5
+; CHECK-NEXT: mov v0.b[6], w6
+; CHECK-NEXT: mov v0.b[7], w7
+; CHECK-NEXT: mov v0.b[8], w8
+; CHECK-NEXT: mov w8, #21 // =0x15
+; CHECK-NEXT: mov v0.b[9], w8
+; CHECK-NEXT: mov w8, #22 // =0x16
+; CHECK-NEXT: mov v0.b[10], w8
+; CHECK-NEXT: mov w8, #23 // =0x17
+; CHECK-NEXT: mov v0.b[11], w8
+; CHECK-NEXT: mov w8, #24 // =0x18
+; CHECK-NEXT: mov v0.b[12], w8
+; CHECK-NEXT: mov w8, #25 // =0x19
+; CHECK-NEXT: mov v0.b[13], w8
+; CHECK-NEXT: mov w8, #26 // =0x1a
+; CHECK-NEXT: mov v0.b[14], w8
+; CHECK-NEXT: mov w8, #27 // =0x1b
+; CHECK-NEXT: mov v0.b[15], w8
+; CHECK-NEXT: ret
+ %va = insertelement <2 x i8> <i8 poison, i8 20>, i8 %a, i64 0
+ %vb = insertelement <2 x i8> <i8 poison, i8 21>, i8 %b, i64 0
+ %vc = insertelement <2 x i8> <i8 poison, i8 22>, i8 %c, i64 0
+ %vd = insertelement <2 x i8> <i8 poison, i8 23>, i8 %d, i64 0
+ %ve = insertelement <2 x i8> <i8 poison, i8 24>, i8 %e, i64 0
+ %vf = insertelement <2 x i8> <i8 poison, i8 25>, i8 %f, i64 0
+ %vg = insertelement <2 x i8> <i8 poison, i8 26>, i8 %g, i64 0
+ %vh = insertelement <2 x i8> <i8 poison, i8 27>, i8 %h, i64 0
+ %res = call <16 x i8> @llvm.vector.interleave8.v16i8(
+ <2 x i8> %va, <2 x i8> %vb, <2 x i8> %vc, <2 x i8> %vd,
+ <2 x i8> %ve, <2 x i8> %vf, <2 x i8> %vg, <2 x i8> %vh)
+ ret <16 x i8> %res
+}
+
More information about the llvm-commits
mailing list