[llvm] [AArch64] Add combine for interleave deinterleave (PR #208414)

Kamlesh Kumar via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 19 23:34:30 PDT 2026


https://github.com/kamleshbhalui updated https://github.com/llvm/llvm-project/pull/208414

>From b3b45d4241e1e78eddaae53044ac60d3917dc931 Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Thu, 9 Jul 2026 10:11:35 +0000
Subject: [PATCH 1/4] [AArch64] Pre-commit tests for interleave/deinterleave
 DAG combine

---
 .../AArch64/vector-deinterleave-load.ll       | 186 ++++++++++++++++++
 .../AArch64/vector-interleave-store.ll        | 104 ++++++++++
 2 files changed, 290 insertions(+)
 create mode 100644 llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
 create mode 100644 llvm/test/CodeGen/AArch64/vector-interleave-store.ll

diff --git a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
new file mode 100644
index 0000000000000..c79dc0624b5c3
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
@@ -0,0 +1,186 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,IA-ENABLE
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
+
+define void @aarch64_vector_deinterleave_idx_ld2(ptr %ptr, i64 %idx) {
+; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld2:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsl x8, x1, #2
+; IA-ENABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    add x8, x8, #16
+; IA-ENABLE-NEXT:    add x10, x0, x9
+; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    ld2 { v0.4s, v1.4s }, [x10]
+; IA-ENABLE-NEXT:    str q0, [x0, x9]
+; IA-ENABLE-NEXT:    str q1, [x0, x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld2:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    lsl x8, x1, #2
+; IA-DISABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    add x8, x8, #16
+; IA-DISABLE-NEXT:    add x9, x0, x9
+; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    ldp q1, q0, [x9]
+; IA-DISABLE-NEXT:    uzp1 v2.4s, v1.4s, v0.4s
+; IA-DISABLE-NEXT:    uzp2 v0.4s, v1.4s, v0.4s
+; IA-DISABLE-NEXT:    str q2, [x9]
+; IA-DISABLE-NEXT:    str q0, [x0, x8]
+; IA-DISABLE-NEXT:    ret
+entry:
+  %idx1 = lshr i64 %idx, 2
+  %a1 = add i64 %idx, 4
+  %idx2 = lshr i64 %a1, 2
+
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx2
+
+  %load = load <8 x float>, ptr %gep1, align 16
+  %deinterleave = call { <4 x float>, <4 x float> } @llvm.vector.deinterleave2.v8f32(<8 x float> %load)
+  %m0_3 = extractvalue { <4 x float>, <4 x float> } %deinterleave, 0
+  %m4_7 = extractvalue { <4 x float>, <4 x float> } %deinterleave, 1
+
+  store <4 x float> %m0_3, ptr %gep1, align 16
+  store <4 x float> %m4_7, ptr %gep2, align 16
+  ret void
+}
+
+define void @aarch64_vector_deinterleave_idx_ld3(ptr %ptr, i64 %idx) {
+; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld3:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsl x8, x1, #2
+; IA-ENABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    add x10, x0, x9
+; IA-ENABLE-NEXT:    ld3 { v0.4s, v1.4s, v2.4s }, [x10]
+; IA-ENABLE-NEXT:    add x10, x8, #16
+; IA-ENABLE-NEXT:    add x8, x8, #32
+; IA-ENABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    str q0, [x0, x9]
+; IA-ENABLE-NEXT:    str q1, [x0, x10]
+; IA-ENABLE-NEXT:    str q2, [x0, x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld3:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    sub sp, sp, #48
+; IA-DISABLE-NEXT:    .cfi_def_cfa_offset 48
+; IA-DISABLE-NEXT:    lsl x9, x1, #2
+; IA-DISABLE-NEXT:    mov x8, sp
+; IA-DISABLE-NEXT:    and x10, x9, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    add x10, x0, x10
+; IA-DISABLE-NEXT:    ldp q1, q0, [x10, #16]
+; IA-DISABLE-NEXT:    ldr q2, [x10]
+; IA-DISABLE-NEXT:    str q2, [sp]
+; IA-DISABLE-NEXT:    stp q1, q0, [sp, #16]
+; IA-DISABLE-NEXT:    ld3 { v0.4s, v1.4s, v2.4s }, [x8]
+; IA-DISABLE-NEXT:    add x8, x9, #16
+; IA-DISABLE-NEXT:    add x9, x9, #32
+; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    str q0, [x10]
+; IA-DISABLE-NEXT:    str q1, [x0, x8]
+; IA-DISABLE-NEXT:    str q2, [x0, x9]
+; IA-DISABLE-NEXT:    add sp, sp, #48
+; IA-DISABLE-NEXT:    ret
+entry:
+  %idx1 = lshr i64 %idx, 2
+  %a1 = add i64 %idx, 4
+  %idx2 = lshr i64 %a1, 2
+  %a2 = add i64 %idx, 8
+  %idx3 = lshr i64 %a2, 2
+
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx2
+  %gep3 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx3
+
+  %load = load <12 x float>, ptr %gep1, align 16
+  %deinterleave = call { <4 x float>, <4 x float>, <4 x float> } @llvm.vector.deinterleave3.v12f32(<12 x float> %load)
+  %m0_3 = extractvalue { <4 x float>, <4 x float>, <4 x float> } %deinterleave, 0
+  %m4_7 = extractvalue { <4 x float>, <4 x float>, <4 x float> } %deinterleave, 1
+  %m8_11 = extractvalue { <4 x float>, <4 x float>, <4 x float> } %deinterleave, 2
+
+  store <4 x float> %m0_3, ptr %gep1, align 16
+  store <4 x float> %m4_7, ptr %gep2, align 16
+  store <4 x float> %m8_11, ptr %gep3, align 16
+  ret void
+}
+
+define void @aarch64_vector_deinterleave_idx_ld4(ptr %ptr, i64 %idx) {
+; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld4:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsl x8, x1, #2
+; IA-ENABLE-NEXT:    add x9, x8, #64
+; IA-ENABLE-NEXT:    add x11, x8, #96
+; IA-ENABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    add x10, x0, x9
+; IA-ENABLE-NEXT:    ld4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x10]
+; IA-ENABLE-NEXT:    add x10, x8, #80
+; IA-ENABLE-NEXT:    add x8, x8, #112
+; IA-ENABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    str q0, [x0, x9]
+; IA-ENABLE-NEXT:    and x9, x11, #0xfffffffffffffff0
+; IA-ENABLE-NEXT:    str q1, [x0, x10]
+; IA-ENABLE-NEXT:    str q2, [x0, x9]
+; IA-ENABLE-NEXT:    str q3, [x0, x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld4:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    lsl x8, x1, #2
+; IA-DISABLE-NEXT:    add x9, x8, #64
+; IA-DISABLE-NEXT:    add x10, x8, #80
+; IA-DISABLE-NEXT:    add x11, x8, #96
+; IA-DISABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    add x8, x8, #112
+; IA-DISABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    add x9, x0, x9
+; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    ldp q1, q0, [x9]
+; IA-DISABLE-NEXT:    ldp q3, q2, [x9, #32]
+; IA-DISABLE-NEXT:    uzp1 v5.4s, v1.4s, v0.4s
+; IA-DISABLE-NEXT:    uzp2 v0.4s, v1.4s, v0.4s
+; IA-DISABLE-NEXT:    uzp1 v4.4s, v3.4s, v2.4s
+; IA-DISABLE-NEXT:    uzp2 v2.4s, v3.4s, v2.4s
+; IA-DISABLE-NEXT:    uzp1 v1.4s, v5.4s, v4.4s
+; IA-DISABLE-NEXT:    uzp1 v3.4s, v0.4s, v2.4s
+; IA-DISABLE-NEXT:    uzp2 v4.4s, v5.4s, v4.4s
+; IA-DISABLE-NEXT:    uzp2 v0.4s, v0.4s, v2.4s
+; IA-DISABLE-NEXT:    str q1, [x9]
+; IA-DISABLE-NEXT:    and x9, x11, #0xfffffffffffffff0
+; IA-DISABLE-NEXT:    str q3, [x0, x10]
+; IA-DISABLE-NEXT:    str q4, [x0, x9]
+; IA-DISABLE-NEXT:    str q0, [x0, x8]
+; IA-DISABLE-NEXT:    ret
+entry:
+  %a1 = add i64 %idx, 16
+  %idx1 = lshr i64 %a1, 2
+  %a2 = add i64 %idx, 20
+  %idx2 = lshr i64 %a2, 2
+  %a3 = add i64 %idx, 24
+  %idx3 = lshr i64 %a3, 2
+  %a4 = add i64 %idx, 28
+  %idx4 = lshr i64 %a4, 2
+
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+  %gep2 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx2
+  %gep3 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx3
+  %gep4 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx4
+
+  %load = load <16 x float>, ptr %gep1, align 16
+  %deinterleave = call { <4 x float>, <4 x float>, <4 x float>, <4 x float> } @llvm.vector.deinterleave4.v16f32(<16 x float> %load)
+  %m0_3 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %deinterleave, 0
+  %m4_7 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %deinterleave, 1
+  %m8_11 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %deinterleave, 2
+  %m12_15 = extractvalue { <4 x float>, <4 x float>, <4 x float>, <4 x float> } %deinterleave, 3
+
+  store <4 x float> %m0_3, ptr %gep1, align 16
+  store <4 x float> %m4_7, ptr %gep2, align 16
+  store <4 x float> %m8_11, ptr %gep3, align 16
+  store <4 x float> %m12_15, ptr %gep4, align 16
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
new file mode 100644
index 0000000000000..c5edb6cf82984
--- /dev/null
+++ b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
@@ -0,0 +1,104 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,IA-ENABLE
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
+define void @aarch64_vector_interleave_idx_st2(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1) {
+; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st2:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsr x8, x1, #2
+; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
+; IA-ENABLE-NEXT:    st2 { v0.4s, v1.4s }, [x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st2:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    lsr x8, x1, #2
+; IA-DISABLE-NEXT:    zip2 v2.4s, v0.4s, v1.4s
+; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v1.4s
+; IA-DISABLE-NEXT:    add x8, x0, x8, lsl #4
+; IA-DISABLE-NEXT:    stp q0, q2, [x8]
+; IA-DISABLE-NEXT:    ret
+entry:
+  %idx1 = lshr i64 %idx, 2
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+
+  %interleave = call <8 x float> @llvm.vector.interleave2.v8f32(<4 x float> %v0, <4 x float> %v1)
+  store <8 x float> %interleave, ptr %gep1, align 16
+  ret void
+}
+
+define void @aarch64_vector_interleave_idx_st3(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1, <4 x float> %v2) {
+; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st3:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsr x8, x1, #2
+; IA-ENABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
+; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
+; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
+; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
+; IA-ENABLE-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st3:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    sub sp, sp, #48
+; IA-DISABLE-NEXT:    .cfi_def_cfa_offset 48
+; IA-DISABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
+; IA-DISABLE-NEXT:    mov x8, sp
+; IA-DISABLE-NEXT:    lsr x9, x1, #2
+; IA-DISABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
+; IA-DISABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
+; IA-DISABLE-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
+; IA-DISABLE-NEXT:    add x8, x0, x9, lsl #4
+; IA-DISABLE-NEXT:    ldp q1, q0, [sp, #16]
+; IA-DISABLE-NEXT:    ldr q2, [sp]
+; IA-DISABLE-NEXT:    stp q1, q0, [x8, #16]
+; IA-DISABLE-NEXT:    str q2, [x8]
+; IA-DISABLE-NEXT:    add sp, sp, #48
+; IA-DISABLE-NEXT:    ret
+entry:
+  %idx1 = lshr i64 %idx, 2
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+
+  %interleave = call <12 x float> @llvm.vector.interleave3.v12f32(<4 x float> %v0, <4 x float> %v1, <4 x float> %v2)
+  store <12 x float> %interleave, ptr %gep1, align 16
+  ret void
+}
+
+define void @aarch64_vector_interleave_idx_st4(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1, <4 x float> %v2, <4 x float> %v3) {
+; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st4:
+; IA-ENABLE:       // %bb.0: // %entry
+; IA-ENABLE-NEXT:    lsr x8, x1, #2
+; IA-ENABLE-NEXT:    // kill: def $q3 killed $q3 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; IA-ENABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
+; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; IA-ENABLE-NEXT:    st4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x8]
+; IA-ENABLE-NEXT:    ret
+;
+; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st4:
+; IA-DISABLE:       // %bb.0: // %entry
+; IA-DISABLE-NEXT:    zip2 v4.4s, v1.4s, v3.4s
+; IA-DISABLE-NEXT:    zip2 v5.4s, v0.4s, v2.4s
+; IA-DISABLE-NEXT:    lsr x8, x1, #2
+; IA-DISABLE-NEXT:    zip1 v1.4s, v1.4s, v3.4s
+; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v2.4s
+; IA-DISABLE-NEXT:    add x8, x0, x8, lsl #4
+; IA-DISABLE-NEXT:    zip2 v2.4s, v5.4s, v4.4s
+; IA-DISABLE-NEXT:    zip1 v3.4s, v5.4s, v4.4s
+; IA-DISABLE-NEXT:    zip2 v4.4s, v0.4s, v1.4s
+; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v1.4s
+; IA-DISABLE-NEXT:    stp q3, q2, [x8, #32]
+; IA-DISABLE-NEXT:    stp q0, q4, [x8]
+; IA-DISABLE-NEXT:    ret
+entry:
+  %idx1 = lshr i64 %idx, 2
+  %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
+
+  %interleave = call <16 x float> @llvm.vector.interleave4.v16f32(<4 x float> %v0, <4 x float> %v1, <4 x float> %v2, <4 x float> %v3)
+  store <16 x float> %interleave, ptr %gep1, align 16
+  ret void
+}
+;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
+; CHECK: {{.*}}

>From 973e28048b04f41b8955b33621b48466bfaae408 Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Sat, 11 Jul 2026 15:02:46 +0100
Subject: [PATCH 2/4] [AArch64] Add DAG combines for fixed width (de)interleave

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 220 ++++++++++++------
 .../AArch64/fixed-vector-deinterleave.ll      |  84 ++++++-
 .../AArch64/fixed-vector-interleave.ll        | 126 +++++-----
 .../scalable_masked_interleaved_stores.ll     |   9 +-
 llvm/test/CodeGen/AArch64/sve-ldst-sext.ll    |   6 +-
 llvm/test/CodeGen/AArch64/sve-ldst-zext.ll    |   6 +-
 .../AArch64/vector-deinterleave-load.ll       | 154 ++++--------
 .../AArch64/vector-interleave-store.ll        | 100 +++-----
 8 files changed, 372 insertions(+), 333 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index a1cf0fd66feb1..cc680d45f891d 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -27384,6 +27384,10 @@ static unsigned getFPSubregForVT(EVT VT) {
   }
 }
 
+static SDValue
+performInterleavedStoreCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
+                               SelectionDAG &DAG);
+
 static SDValue performSTORECombine(SDNode *N,
                                    TargetLowering::DAGCombinerInfo &DCI,
                                    SelectionDAG &DAG,
@@ -27415,6 +27419,9 @@ static SDValue performSTORECombine(SDNode *N,
   if (SDValue Res = combineStoreValueFPToInt(ST, DCI, DAG, Subtarget))
     return Res;
 
+  if (SDValue Res = performInterleavedStoreCombine(N, DCI, DAG))
+    return Res;
+
   // Cast ptr32 and ptr64 pointers to the default address space before a store.
   unsigned AddrSpace = ST->getAddressSpace();
   if (AddrSpace == ARM64AS::PTR64 || AddrSpace == ARM64AS::PTR32_SPTR ||
@@ -27637,18 +27644,32 @@ static SDValue getNarrowMaskForInterleavedOps(SelectionDAG &DAG, SDLoc &DL,
                      WideMask->getOperand(0));
 }
 
-static SDValue performInterleavedMaskedStoreCombine(
-    SDNode *N, TargetLowering::DAGCombinerInfo &DCI, SelectionDAG &DAG) {
+static SDValue
+performInterleavedStoreCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
+                               SelectionDAG &DAG) {
   if (!DCI.isBeforeLegalize())
     return SDValue();
 
-  MaskedStoreSDNode *MST = cast<MaskedStoreSDNode>(N);
-  SDValue WideValue = MST->getValue();
-
-  // Discard masked stores that are truncating or indexed.
-  if (!ISD::isNormalMaskedStore(MST) || !MST->isSimple() ||
-      !MST->getOffset().isUndef())
-    return SDValue();
+  SDValue WideValue, Chain, BasePtr, Mask;
+  bool IsMasked = false;
+  if (auto *MST = dyn_cast<MaskedStoreSDNode>(N)) {
+    if (!ISD::isNormalMaskedStore(MST) || !MST->isSimple() ||
+        !MST->getOffset().isUndef())
+      return SDValue();
+    WideValue = MST->getValue();
+    Chain = MST->getChain();
+    BasePtr = MST->getBasePtr();
+    Mask = MST->getMask();
+    IsMasked = true;
+  } else {
+    auto *ST = cast<StoreSDNode>(N);
+    if (!ISD::isNormalStore(ST) || !ST->isSimple() ||
+        !ST->getOffset().isUndef())
+      return SDValue();
+    WideValue = ST->getValue();
+    Chain = ST->getChain();
+    BasePtr = ST->getBasePtr();
+  }
 
   SDLoc DL(N);
   SmallVector<SDValue, 4> ValueInterleaveOps;
@@ -27665,29 +27686,59 @@ static SDValue performInterleavedMaskedStoreCombine(
   }
 
   unsigned NumParts = ValueInterleaveOps.size();
-  if (NumParts != 2 && NumParts != 4)
+  if (NumParts != 2 && NumParts != 3 && NumParts != 4)
     return SDValue();
 
-  // At the moment we're unlikely to see a fixed-width vector interleave as
-  // we usually generate shuffles instead.
   EVT SubVecTy = ValueInterleaveOps[0].getValueType();
-  if (!SubVecTy.isScalableVT() ||
-      SubVecTy.getSizeInBits().getKnownMinValue() != 128 ||
-      !DAG.getTargetLoweringInfo().isTypeLegal(SubVecTy))
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
+  if (!TLI.isTypeLegal(SubVecTy))
     return SDValue();
-
-  SDValue NarrowMask =
-      getNarrowMaskForInterleavedOps(DAG, DL, MST->getMask(), NumParts);
-  if (!NarrowMask)
+  bool IsScalable = SubVecTy.isScalableVector();
+  unsigned SubBits = SubVecTy.getSizeInBits().getKnownMinValue();
+  if (IsScalable) {
+    if (SubBits != 128)
+      return SDValue();
+  } else if (SubBits != 64 && SubBits != 128) {
     return SDValue();
+  }
+
+  auto *MemN = cast<MemSDNode>(N);
+  if (IsScalable) {
+    if (NumParts == 3)
+      return SDValue();
+    SDValue Pred;
+    if (IsMasked) {
+      Pred = getNarrowMaskForInterleavedOps(DAG, DL, Mask, NumParts);
+      if (!Pred)
+        return SDValue();
+    } else {
+      EVT PredVT = SubVecTy.changeVectorElementType(*DAG.getContext(), MVT::i1);
+      Pred = DAG.getConstant(1, DL, PredVT);
+    }
 
-  const Intrinsic::ID IID =
-      NumParts == 2 ? Intrinsic::aarch64_sve_st2 : Intrinsic::aarch64_sve_st4;
-  SmallVector<SDValue, 8> NewStOps;
-  NewStOps.append({MST->getChain(), DAG.getConstant(IID, DL, MVT::i32)});
-  NewStOps.append(ValueInterleaveOps);
-  NewStOps.append({NarrowMask, MST->getBasePtr()});
-  return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, NewStOps);
+    const Intrinsic::ID IID =
+        NumParts == 2 ? Intrinsic::aarch64_sve_st2 : Intrinsic::aarch64_sve_st4;
+    SmallVector<SDValue, 8> Ops;
+    Ops.append({Chain, DAG.getConstant(IID, DL, MVT::i32)});
+    Ops.append(ValueInterleaveOps);
+    Ops.append({Pred, BasePtr});
+    return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops);
+  } else {
+
+    static constexpr Intrinsic::ID NEONStores[] = {Intrinsic::aarch64_neon_st2,
+                                                   Intrinsic::aarch64_neon_st3,
+                                                   Intrinsic::aarch64_neon_st4};
+    SmallVector<SDValue, 8> Ops;
+    Ops.push_back(Chain);
+    Ops.push_back(
+        DAG.getTargetConstant(NEONStores[NumParts - 2], DL, MVT::i64));
+    Ops.append(ValueInterleaveOps);
+    Ops.push_back(BasePtr);
+    auto *MemN = cast<MemSDNode>(N);
+    return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, DL,
+                                   DAG.getVTList(MVT::Other), Ops,
+                                   MemN->getMemoryVT(), MemN->getMemOperand());
+  }
 }
 
 static SDValue performMSTORECombine(SDNode *N,
@@ -27699,7 +27750,7 @@ static SDValue performMSTORECombine(SDNode *N,
   SDValue Mask = MST->getMask();
   SDLoc DL(N);
 
-  if (SDValue Res = performInterleavedMaskedStoreCombine(N, DCI, DAG))
+  if (SDValue Res = performInterleavedStoreCombine(N, DCI, DAG))
     return Res;
 
   // If this is a UZP1 followed by a masked store, fold this into a masked
@@ -30570,21 +30621,26 @@ static SDValue performVectorDeinterleaveCombine(
     return SDValue();
 
   unsigned NumParts = N->getNumOperands();
-  if (NumParts != 2 && NumParts != 4)
+  if (NumParts != 2 && NumParts != 3 && NumParts != 4)
     return SDValue();
 
   EVT SubVecTy = N->getValueType(0);
+  const TargetLowering &TLI = DAG.getTargetLoweringInfo();
 
-  // At the moment we're unlikely to see a fixed-width vector deinterleave as
-  // we usually generate shuffles instead.
-  unsigned MinNumElements = SubVecTy.getVectorMinNumElements();
-  if (!SubVecTy.isScalableVector() ||
-      SubVecTy.getSizeInBits().getKnownMinValue() != 128 ||
-      !DAG.getTargetLoweringInfo().isTypeLegal(SubVecTy))
+  bool IsScalable = SubVecTy.isScalableVector();
+  unsigned SubVecBits = SubVecTy.getSizeInBits().getKnownMinValue();
+  if (!TLI.isTypeLegal(SubVecTy))
+    return SDValue();
+  if (IsScalable) {
+    if (SubVecBits != 128)
+      return SDValue();
+  } else if (SubVecBits != 64 && SubVecBits != 128) {
     return SDValue();
+  }
 
   // Make sure each input operand is the correct extract_subvector of the same
   // wider vector.
+  unsigned MinNumElements = SubVecTy.getVectorMinNumElements();
   SDValue Op0 = N->getOperand(0);
   for (unsigned I = 0; I < NumParts; I++) {
     SDValue OpI = N->getOperand(I);
@@ -30595,40 +30651,72 @@ static SDValue performVectorDeinterleaveCombine(
       return SDValue();
   }
 
-  // Normal loads are currently already handled by the InterleavedAccessPass so
-  // we don't expect to see them here. Bail out if the masked load has an
-  // unexpected number of uses, since we want to avoid a situation where we have
-  // both deinterleaving loads and normal loads in the same block. Also, discard
-  // masked loads that are extending, indexed, have an unexpected offset or have
-  // an unsupported passthru value until we find a valid use case.
-  auto MaskedLoad = dyn_cast<MaskedLoadSDNode>(Op0->getOperand(0));
-  if (!MaskedLoad || !MaskedLoad->hasNUsesOfValue(NumParts, 0) ||
-      !MaskedLoad->isSimple() || !ISD::isNormalMaskedLoad(MaskedLoad) ||
-      !MaskedLoad->getOffset().isUndef() ||
-      (!MaskedLoad->getPassThru()->isUndef() &&
-       !isZerosVector(MaskedLoad->getPassThru().getNode())))
-    return SDValue();
-
-  // Now prove that the mask is an interleave of identical masks.
+  SDValue WideVec = Op0->getOperand(0);
   SDLoc DL(N);
-  SDValue NarrowMask =
-      getNarrowMaskForInterleavedOps(DAG, DL, MaskedLoad->getMask(), NumParts);
-  if (!NarrowMask)
-    return SDValue();
 
-  const Intrinsic::ID IID = NumParts == 2 ? Intrinsic::aarch64_sve_ld2_sret
-                                          : Intrinsic::aarch64_sve_ld4_sret;
-  SDValue NewLdOps[] = {MaskedLoad->getChain(),
-                        DAG.getConstant(IID, DL, MVT::i32), NarrowMask,
-                        MaskedLoad->getBasePtr()};
+  SmallVector<EVT, 5> ResVTs(NumParts, SubVecTy);
+  ResVTs.push_back(MVT::Other);
+  SDVTList ResVTList = DAG.getVTList(ResVTs);
+
   SDValue Res;
-  if (NumParts == 2)
-    Res = DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL,
-                      {SubVecTy, SubVecTy, MVT::Other}, NewLdOps);
-  else
-    Res = DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL,
-                      {SubVecTy, SubVecTy, SubVecTy, SubVecTy, MVT::Other},
-                      NewLdOps);
+  if (IsScalable) {
+    if (NumParts == 3)
+      return SDValue();
+    SDValue Chain, BasePtr, Pred;
+    if (auto *MaskedLoad = dyn_cast<MaskedLoadSDNode>(WideVec)) {
+      // Bail out if the masked load has an unexpected number of uses, since we
+      // want to avoid a situation where we have both deinterleaving loads and
+      // normal loads in the same block. Also, discard masked loads that are
+      // extending, indexed, have an unexpected offset or have an unsupported
+      // passthru value until we find a valid use case.
+      if (!MaskedLoad->hasNUsesOfValue(NumParts, 0) ||
+          !MaskedLoad->isSimple() || !ISD::isNormalMaskedLoad(MaskedLoad) ||
+          !MaskedLoad->getOffset().isUndef() ||
+          (!MaskedLoad->getPassThru()->isUndef() &&
+           !isZerosVector(MaskedLoad->getPassThru().getNode())))
+        return SDValue();
+
+      // Now prove that the mask is an interleave of identical masks.
+      Pred = getNarrowMaskForInterleavedOps(DAG, DL, MaskedLoad->getMask(),
+                                            NumParts);
+      if (!Pred)
+        return SDValue();
+      Chain = MaskedLoad->getChain();
+      BasePtr = MaskedLoad->getBasePtr();
+    } else {
+      auto *Load = dyn_cast<LoadSDNode>(WideVec);
+      if (!Load || !Load->hasNUsesOfValue(NumParts, 0) || !Load->isSimple() ||
+          !ISD::isNormalLoad(Load) || !Load->getOffset().isUndef())
+        return SDValue();
+
+      EVT PredVT = SubVecTy.changeVectorElementType(*DAG.getContext(), MVT::i1);
+      Pred = DAG.getConstant(1, DL, PredVT);
+      Chain = Load->getChain();
+      BasePtr = Load->getBasePtr();
+    }
+
+    const Intrinsic::ID IID = NumParts == 2 ? Intrinsic::aarch64_sve_ld2_sret
+                                            : Intrinsic::aarch64_sve_ld4_sret;
+    SDValue NewLdOps[] = {Chain, DAG.getConstant(IID, DL, MVT::i32), Pred,
+                          BasePtr};
+    Res = DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList, NewLdOps);
+  } else {
+    auto *Load = dyn_cast<LoadSDNode>(WideVec);
+    if (!Load || !Load->hasNUsesOfValue(NumParts, 0) || !Load->isSimple() ||
+        !ISD::isNormalLoad(Load) || !Load->getOffset().isUndef())
+      return SDValue();
+
+    static constexpr Intrinsic::ID NEONLoads[] = {Intrinsic::aarch64_neon_ld2,
+                                                  Intrinsic::aarch64_neon_ld3,
+                                                  Intrinsic::aarch64_neon_ld4};
+    SDValue NewLdOps[] = {
+        Load->getChain(),
+        DAG.getTargetConstant(NEONLoads[NumParts - 2], DL, MVT::i64),
+        Load->getBasePtr()};
+    Res =
+        DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList, NewLdOps,
+                                Load->getMemoryVT(), Load->getMemOperand());
+  }
 
   // We can now generate a structured load!
   SmallVector<SDValue, 4> ResOps(NumParts);
@@ -30636,7 +30724,7 @@ static SDValue performVectorDeinterleaveCombine(
     ResOps[Idx] = SDValue(Res.getNode(), Idx);
 
   // Replace uses of the original chain result with the new chain result.
-  DAG.ReplaceAllUsesOfValueWith(SDValue(MaskedLoad, 1),
+  DAG.ReplaceAllUsesOfValueWith(WideVec.getValue(1),
                                 SDValue(Res.getNode(), NumParts));
   return DCI.CombineTo(N, ResOps, false);
 }
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index 8c48cc609c75a..abb112a360181 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-SD
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false -global-isel -global-isel-abort=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-GI
 
 define {<2 x half>, <2 x half>} @vector_deinterleave_v2f16_v4f16(<4 x half> %vec) {
 ; CHECK-SD-LABEL: vector_deinterleave_v2f16_v4f16:
@@ -61,6 +63,22 @@ define {<2 x float>, <2 x float>} @vector_deinterleave_v2f32_v4f32(<4 x float> %
 ; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 killed $q1
 ; CHECK-GI-NEXT:    fmov d0, d2
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2f32_v4f32:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    mov d1, v0.d[1]
+; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2s, v0.2s, v1.2s
+; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2s, v0.2s, v1.2s
+; CHECK-IA-DISABLE-SD-NEXT:    fmov d0, d2
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2f32_v4f32:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    uzp1 v2.4s, v0.4s, v0.4s
+; CHECK-IA-DISABLE-GI-NEXT:    uzp2 v1.4s, v0.4s, v0.4s
+; CHECK-IA-DISABLE-GI-NEXT:    // kill: def $d1 killed $d1 killed $q1
+; CHECK-IA-DISABLE-GI-NEXT:    fmov d0, d2
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x float>, <2 x float>} @llvm.vector.deinterleave2.v4f32(<4 x float> %vec)
   ret {<2 x float>, <2 x float>}   %retval
 }
@@ -77,12 +95,33 @@ ret  {<4 x float>, <4 x float>}   %retval
 }
 
 define {<2 x double>, <2 x double>} @vector_deinterleave_v2f64_v4f64(<4 x double> %vec) {
-; CHECK-LABEL: vector_deinterleave_v2f64_v4f64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-NEXT:    mov v0.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vector_deinterleave_v2f64_v4f64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    mov v0.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vector_deinterleave_v2f64_v4f64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    mov v0.16b, v2.16b
+; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2f64_v4f64:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-SD-NEXT:    mov v0.16b, v2.16b
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2f64_v4f64:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-GI-NEXT:    mov v0.16b, v2.16b
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x double>, <2 x double>} @llvm.vector.deinterleave2.v4f64(<4 x double> %vec)
   ret {<2 x double>, <2 x double>}   %retval
 }
@@ -123,12 +162,33 @@ define {<4 x i32>, <4 x i32>} @vector_deinterleave_v4i32_v8i32(<8 x i32> %vec) {
 }
 
 define {<2 x i64>, <2 x i64>} @vector_deinterleave_v2i64_v4i64(<4 x i64> %vec) {
-; CHECK-LABEL: vector_deinterleave_v2i64_v4i64:
-; CHECK:       // %bb.0:
-; CHECK-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-NEXT:    mov v0.16b, v2.16b
-; CHECK-NEXT:    ret
+; CHECK-SD-LABEL: vector_deinterleave_v2i64_v4i64:
+; CHECK-SD:       // %bb.0:
+; CHECK-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
+; CHECK-SD-NEXT:    mov v0.16b, v2.16b
+; CHECK-SD-NEXT:    ret
+;
+; CHECK-GI-LABEL: vector_deinterleave_v2i64_v4i64:
+; CHECK-GI:       // %bb.0:
+; CHECK-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-GI-NEXT:    mov v0.16b, v2.16b
+; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2i64_v4i64:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-SD-NEXT:    mov v0.16b, v2.16b
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2i64_v4i64:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-IA-DISABLE-GI-NEXT:    mov v0.16b, v2.16b
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x i64>, <2 x i64>} @llvm.vector.deinterleave2.v4i64(<4 x i64> %vec)
   ret {<2 x i64>, <2 x i64>}   %retval
 }
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
index 2d368c0ec456f..61789d787279d 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
@@ -1,6 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-SD
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  -global-isel -global-isel-abort=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-GI
 
 define <4 x half> @interleave2_v4f16(<2 x half> %vec0, <2 x half> %vec1) {
 ; CHECK-LABEL: interleave2_v4f16:
@@ -142,6 +144,17 @@ define <4 x i16> @interleave2_same_const_splat_v4i16() {
 ; CHECK-GI-NEXT:    movi v0.4h, #3
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: interleave2_same_const_splat_v4i16:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    movi v0.4h, #3
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: interleave2_same_const_splat_v4i16:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    movi v0.4h, #3
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> splat(i16 3), <2 x i16> splat(i16 3))
   ret <4 x i16> %retval
 }
@@ -160,6 +173,21 @@ define <4 x i16> @interleave2_diff_const_splat_v4i16() {
 ; CHECK-GI-NEXT:    movi v1.4h, #4
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: interleave2_diff_const_splat_v4i16:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    movi v0.2s, #4
+; CHECK-IA-DISABLE-SD-NEXT:    movi v1.2s, #3
+; CHECK-IA-DISABLE-SD-NEXT:    zip1 v0.4s, v1.4s, v0.4s
+; CHECK-IA-DISABLE-SD-NEXT:    xtn v0.4h, v0.4s
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: interleave2_diff_const_splat_v4i16:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    movi v0.4h, #3
+; CHECK-IA-DISABLE-GI-NEXT:    movi v1.4h, #4
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> splat(i16 3), <2 x i16> splat(i16 4))
   ret <4 x i16> %retval
 }
@@ -175,6 +203,17 @@ define <4 x i16> @interleave2_same_nonconst_splat_v4i16(i16 %a) {
 ; CHECK-GI-NEXT:    dup v0.4h, w0
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: interleave2_same_nonconst_splat_v4i16:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    dup v0.4h, w0
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: interleave2_same_nonconst_splat_v4i16:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    dup v0.4h, w0
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %ins = insertelement <2 x i16> poison, i16 %a, i32 0
   %splat = shufflevector <2 x i16> %ins, <2 x i16> poison, <2 x i32> <i32 0, i32 0>
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> %splat, <2 x i16> %splat)
@@ -198,6 +237,21 @@ define <4 x i16> @interleave2_diff_nonconst_splat_v4i16(i16 %a, i16 %b) {
 ; CHECK-GI-NEXT:    dup v1.4h, w1
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    ret
+;
+; CHECK-IA-DISABLE-SD-LABEL: interleave2_diff_nonconst_splat_v4i16:
+; CHECK-IA-DISABLE-SD:       // %bb.0:
+; CHECK-IA-DISABLE-SD-NEXT:    dup v0.2s, w0
+; CHECK-IA-DISABLE-SD-NEXT:    dup v1.2s, w1
+; CHECK-IA-DISABLE-SD-NEXT:    zip1 v0.4s, v0.4s, v1.4s
+; CHECK-IA-DISABLE-SD-NEXT:    xtn v0.4h, v0.4s
+; CHECK-IA-DISABLE-SD-NEXT:    ret
+;
+; CHECK-IA-DISABLE-GI-LABEL: interleave2_diff_nonconst_splat_v4i16:
+; CHECK-IA-DISABLE-GI:       // %bb.0:
+; CHECK-IA-DISABLE-GI-NEXT:    dup v0.4h, w0
+; CHECK-IA-DISABLE-GI-NEXT:    dup v1.4h, w1
+; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
+; CHECK-IA-DISABLE-GI-NEXT:    ret
   %ins1 = insertelement <2 x i16> poison, i16 %a, i32 0
   %splat1 = shufflevector <2 x i16> %ins1, <2 x i16> poison, <2 x i32> <i32 0, i32 0>
   %ins2 = insertelement <2 x i16> poison, i16 %b, i32 0
@@ -475,18 +529,10 @@ define <6 x double> @interleave3_v6f64(<2 x double> %vec0, <2 x double> %vec1, <
 define <12 x float> @interleave3_v12f32(<4 x float> %vec0, <4 x float> %vec1, <4 x float> %vec2) {
 ; CHECK-LABEL: interleave3_v12f32:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #48
-; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    mov x9, sp
 ; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
 ; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x9]
-; CHECK-NEXT:    ldp q1, q0, [sp, #16]
-; CHECK-NEXT:    ldr q2, [sp]
-; CHECK-NEXT:    stp q1, q0, [x8, #16]
-; CHECK-NEXT:    str q2, [x8]
-; CHECK-NEXT:    add sp, sp, #48
+; CHECK-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <12 x float> @llvm.vector.interleave3.v12f32(<4 x float> %vec0, <4 x float> %vec1, <4 x float> %vec2)
   ret <12 x float> %retval
@@ -495,18 +541,10 @@ define <12 x float> @interleave3_v12f32(<4 x float> %vec0, <4 x float> %vec1, <4
 define <24 x i16> @interleave3_v24i16(<8 x i16> %vec0, <8 x i16> %vec1, <8 x i16> %vec2) {
 ; CHECK-LABEL: interleave3_v24i16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #48
-; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    mov x9, sp
 ; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
 ; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x9]
-; CHECK-NEXT:    ldp q1, q0, [sp, #16]
-; CHECK-NEXT:    ldr q2, [sp]
-; CHECK-NEXT:    stp q1, q0, [x8, #16]
-; CHECK-NEXT:    str q2, [x8]
-; CHECK-NEXT:    add sp, sp, #48
+; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <24 x i16> @llvm.vector.interleave3.v24i16(<8 x i16> %vec0, <8 x i16> %vec1, <8 x i16> %vec2)
   ret <24 x i16> %retval
@@ -515,18 +553,10 @@ define <24 x i16> @interleave3_v24i16(<8 x i16> %vec0, <8 x i16> %vec1, <8 x i16
 define <24 x half> @interleave3_v24f16(<8 x half> %vec0, <8 x half> %vec1, <8 x half> %vec2) {
 ; CHECK-LABEL: interleave3_v24f16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #48
-; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    mov x9, sp
 ; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
 ; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x9]
-; CHECK-NEXT:    ldp q1, q0, [sp, #16]
-; CHECK-NEXT:    ldr q2, [sp]
-; CHECK-NEXT:    stp q1, q0, [x8, #16]
-; CHECK-NEXT:    str q2, [x8]
-; CHECK-NEXT:    add sp, sp, #48
+; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <24 x half> @llvm.vector.interleave3.v24f16(<8 x half> %vec0, <8 x half> %vec1, <8 x half> %vec2)
   ret <24 x half> %retval
@@ -535,18 +565,10 @@ define <24 x half> @interleave3_v24f16(<8 x half> %vec0, <8 x half> %vec1, <8 x
 define <24 x bfloat> @interleave3_v24bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1, <8 x bfloat> %vec2) {
 ; CHECK-LABEL: interleave3_v24bf16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #48
-; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    mov x9, sp
 ; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
 ; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x9]
-; CHECK-NEXT:    ldp q1, q0, [sp, #16]
-; CHECK-NEXT:    ldr q2, [sp]
-; CHECK-NEXT:    stp q1, q0, [x8, #16]
-; CHECK-NEXT:    str q2, [x8]
-; CHECK-NEXT:    add sp, sp, #48
+; CHECK-NEXT:    st3 { v0.8h, v1.8h, v2.8h }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <24 x bfloat> @llvm.vector.interleave3.v24bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1, <8 x bfloat> %vec2)
   ret <24 x bfloat> %retval
@@ -555,18 +577,10 @@ define <24 x bfloat> @interleave3_v24bf16(<8 x bfloat> %vec0, <8 x bfloat> %vec1
 define <48 x i8> @interleave3_v48i8(<16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2) {
 ; CHECK-LABEL: interleave3_v48i8:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #48
-; CHECK-NEXT:    .cfi_def_cfa_offset 48
 ; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    mov x9, sp
 ; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
 ; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; CHECK-NEXT:    st3 { v0.16b, v1.16b, v2.16b }, [x9]
-; CHECK-NEXT:    ldp q1, q0, [sp, #16]
-; CHECK-NEXT:    ldr q2, [sp]
-; CHECK-NEXT:    stp q1, q0, [x8, #16]
-; CHECK-NEXT:    str q2, [x8]
-; CHECK-NEXT:    add sp, sp, #48
+; CHECK-NEXT:    st3 { v0.16b, v1.16b, v2.16b }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <48 x i8> @llvm.vector.interleave3.v48i8(<16 x i8> %vec0, <16 x i8> %vec1, <16 x i8> %vec2)
   ret <48 x i8> %retval
@@ -575,19 +589,10 @@ define <48 x i8> @interleave3_v48i8(<16 x i8> %vec0, <16 x i8> %vec1, <16 x i8>
 define <12 x i16> @interleave3_v12i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16> %vec2) {
 ; CHECK-LABEL: interleave3_v12i16:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #32
-; CHECK-NEXT:    .cfi_def_cfa_offset 32
 ; CHECK-NEXT:    // kill: def $d2 killed $d2 killed $d0_d1_d2 def $d0_d1_d2
-; CHECK-NEXT:    add x9, sp, #8
 ; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $d0_d1_d2 def $d0_d1_d2
 ; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $d0_d1_d2 def $d0_d1_d2
-; CHECK-NEXT:    st3 { v0.4h, v1.4h, v2.4h }, [x9]
-; CHECK-NEXT:    ldp d1, d0, [sp, #8]
-; CHECK-NEXT:    mov v1.d[1], v0.d[0]
-; CHECK-NEXT:    ldr d0, [sp, #24]
-; CHECK-NEXT:    str d0, [x8, #16]
-; CHECK-NEXT:    str q1, [x8]
-; CHECK-NEXT:    add sp, sp, #32
+; CHECK-NEXT:    st3 { v0.4h, v1.4h, v2.4h }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <12 x i16> @llvm.vector.interleave3.v12i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16> %vec2)
   ret <12 x i16> %retval
@@ -596,19 +601,10 @@ define <12 x i16> @interleave3_v12i16(<4 x i16> %vec0, <4 x i16> %vec1, <4 x i16
 define <24 x i8> @interleave3_v24i8(<8 x i8> %vec0, <8 x i8> %vec1, <8 x i8> %vec2) {
 ; CHECK-LABEL: interleave3_v24i8:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    sub sp, sp, #32
-; CHECK-NEXT:    .cfi_def_cfa_offset 32
 ; CHECK-NEXT:    // kill: def $d2 killed $d2 killed $d0_d1_d2 def $d0_d1_d2
-; CHECK-NEXT:    add x9, sp, #8
 ; CHECK-NEXT:    // kill: def $d1 killed $d1 killed $d0_d1_d2 def $d0_d1_d2
 ; CHECK-NEXT:    // kill: def $d0 killed $d0 killed $d0_d1_d2 def $d0_d1_d2
-; CHECK-NEXT:    st3 { v0.8b, v1.8b, v2.8b }, [x9]
-; CHECK-NEXT:    ldp d1, d0, [sp, #8]
-; CHECK-NEXT:    mov v1.d[1], v0.d[0]
-; CHECK-NEXT:    ldr d0, [sp, #24]
-; CHECK-NEXT:    str d0, [x8, #16]
-; CHECK-NEXT:    str q1, [x8]
-; CHECK-NEXT:    add sp, sp, #32
+; CHECK-NEXT:    st3 { v0.8b, v1.8b, v2.8b }, [x8]
 ; CHECK-NEXT:    ret
   %retval = call <24 x i8> @llvm.vector.interleave3.v24i8(<8 x i8> %vec0, <8 x i8> %vec1, <8 x i8> %vec2)
   ret <24 x i8> %retval
diff --git a/llvm/test/CodeGen/AArch64/scalable_masked_interleaved_stores.ll b/llvm/test/CodeGen/AArch64/scalable_masked_interleaved_stores.ll
index 87833306571c2..fc2f64b756959 100644
--- a/llvm/test/CodeGen/AArch64/scalable_masked_interleaved_stores.ll
+++ b/llvm/test/CodeGen/AArch64/scalable_masked_interleaved_stores.ll
@@ -1,5 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
 ; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false -mattr=+sve < %s | FileCheck %s
 
 define void @foo_st2_nxv16i8(<vscale x 16 x i1> %mask, <vscale x 16 x i8> %val1, <vscale x 16 x i8> %val2, ptr %p) {
 ; CHECK-LABEL: foo_st2_nxv16i8:
@@ -159,10 +160,10 @@ define void @foo_st2_nxv16i8_all_false_mask(<vscale x 16 x i8> %val1, <vscale x
 define void @foo_st2_nxv16i8_all_true_mask(<vscale x 16 x i8> %val1, <vscale x 16 x i8> %val2, ptr %p) {
 ; CHECK-LABEL: foo_st2_nxv16i8_all_true_mask:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    zip2 z2.b, z0.b, z1.b
-; CHECK-NEXT:    zip1 z0.b, z0.b, z1.b
-; CHECK-NEXT:    str z2, [x0, #1, mul vl]
-; CHECK-NEXT:    str z0, [x0]
+; CHECK-NEXT:    ptrue p0.b
+; CHECK-NEXT:    // kill: def $z1 killed $z1 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    // kill: def $z0 killed $z0 killed $z0_z1 def $z0_z1
+; CHECK-NEXT:    st2b { z0.b, z1.b }, p0, [x0]
 ; CHECK-NEXT:    ret
   %interleaved.value = call <vscale x 32 x i8> @llvm.vector.interleave2.nxv32i8(<vscale x 16 x i8> %val1, <vscale x 16 x i8> %val2)
   call void @llvm.masked.store.nxv32i8.p0(<vscale x 32 x i8> %interleaved.value, ptr %p, i32 1, <vscale x 32 x i1> splat(i1 1))
diff --git a/llvm/test/CodeGen/AArch64/sve-ldst-sext.ll b/llvm/test/CodeGen/AArch64/sve-ldst-sext.ll
index bce17b8566922..78abf3239343c 100644
--- a/llvm/test/CodeGen/AArch64/sve-ldst-sext.ll
+++ b/llvm/test/CodeGen/AArch64/sve-ldst-sext.ll
@@ -420,12 +420,12 @@ define <vscale x 2 x i64> @load_frozen_before_sext_multiuse5_src_illegal(ptr %sr
 define <vscale x 4 x i64> @load_frozen_before_sext_multiuse5_both_illegal(ptr %src, ptr %dst) {
 ; CHECK-LABEL: load_frozen_before_sext_multiuse5_both_illegal:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.d
 ; CHECK-NEXT:    mov z2.d, #3 // =0x3
+; CHECK-NEXT:    ptrue p0.d
 ; CHECK-NEXT:    ld1sb { z0.d }, p0/z, [x0]
 ; CHECK-NEXT:    ld1sb { z1.d }, p0/z, [x0, #1, mul vl]
-; CHECK-NEXT:    str z2, [x1, #1, mul vl]
-; CHECK-NEXT:    str z2, [x1]
+; CHECK-NEXT:    mov z3.d, z2.d
+; CHECK-NEXT:    st2d { z2.d, z3.d }, p0, [x1]
 ; CHECK-NEXT:    ret
   %load = load <vscale x 4 x i8>, ptr %src, align 1
   %load.frozen = freeze <vscale x 4 x i8> %load
diff --git a/llvm/test/CodeGen/AArch64/sve-ldst-zext.ll b/llvm/test/CodeGen/AArch64/sve-ldst-zext.ll
index f862479943186..0a1cf0cacbf2f 100644
--- a/llvm/test/CodeGen/AArch64/sve-ldst-zext.ll
+++ b/llvm/test/CodeGen/AArch64/sve-ldst-zext.ll
@@ -411,12 +411,12 @@ define <vscale x 2 x i64> @load_frozen_before_zext_multiuse5_src_illegal(ptr %sr
 define <vscale x 4 x i64> @load_frozen_before_zext_multiuse5_both_illegal(ptr %src, ptr %dst) {
 ; CHECK-LABEL: load_frozen_before_zext_multiuse5_both_illegal:
 ; CHECK:       // %bb.0:
-; CHECK-NEXT:    ptrue p0.d
 ; CHECK-NEXT:    mov z2.d, #3 // =0x3
+; CHECK-NEXT:    ptrue p0.d
 ; CHECK-NEXT:    ld1b { z0.d }, p0/z, [x0]
 ; CHECK-NEXT:    ld1b { z1.d }, p0/z, [x0, #1, mul vl]
-; CHECK-NEXT:    str z2, [x1, #1, mul vl]
-; CHECK-NEXT:    str z2, [x1]
+; CHECK-NEXT:    mov z3.d, z2.d
+; CHECK-NEXT:    st2d { z2.d, z3.d }, p0, [x1]
 ; CHECK-NEXT:    ret
   %load = load <vscale x 4 x i8>, ptr %src, align 1
   %load.frozen = freeze <vscale x 4 x i8> %load
diff --git a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
index c79dc0624b5c3..a7ad6906ed7e2 100644
--- a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
+++ b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
@@ -3,31 +3,17 @@
 ; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
 
 define void @aarch64_vector_deinterleave_idx_ld2(ptr %ptr, i64 %idx) {
-; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld2:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsl x8, x1, #2
-; IA-ENABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    add x8, x8, #16
-; IA-ENABLE-NEXT:    add x10, x0, x9
-; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    ld2 { v0.4s, v1.4s }, [x10]
-; IA-ENABLE-NEXT:    str q0, [x0, x9]
-; IA-ENABLE-NEXT:    str q1, [x0, x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld2:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    lsl x8, x1, #2
-; IA-DISABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    add x8, x8, #16
-; IA-DISABLE-NEXT:    add x9, x0, x9
-; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    ldp q1, q0, [x9]
-; IA-DISABLE-NEXT:    uzp1 v2.4s, v1.4s, v0.4s
-; IA-DISABLE-NEXT:    uzp2 v0.4s, v1.4s, v0.4s
-; IA-DISABLE-NEXT:    str q2, [x9]
-; IA-DISABLE-NEXT:    str q0, [x0, x8]
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_deinterleave_idx_ld2:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsl x8, x1, #2
+; CHECK-NEXT:    and x9, x8, #0xfffffffffffffff0
+; CHECK-NEXT:    add x8, x8, #16
+; CHECK-NEXT:    add x10, x0, x9
+; CHECK-NEXT:    and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT:    ld2 { v0.4s, v1.4s }, [x10]
+; CHECK-NEXT:    str q0, [x0, x9]
+; CHECK-NEXT:    str q1, [x0, x8]
+; CHECK-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %a1 = add i64 %idx, 4
@@ -47,43 +33,20 @@ entry:
 }
 
 define void @aarch64_vector_deinterleave_idx_ld3(ptr %ptr, i64 %idx) {
-; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld3:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsl x8, x1, #2
-; IA-ENABLE-NEXT:    and x9, x8, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    add x10, x0, x9
-; IA-ENABLE-NEXT:    ld3 { v0.4s, v1.4s, v2.4s }, [x10]
-; IA-ENABLE-NEXT:    add x10, x8, #16
-; IA-ENABLE-NEXT:    add x8, x8, #32
-; IA-ENABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    str q0, [x0, x9]
-; IA-ENABLE-NEXT:    str q1, [x0, x10]
-; IA-ENABLE-NEXT:    str q2, [x0, x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld3:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    sub sp, sp, #48
-; IA-DISABLE-NEXT:    .cfi_def_cfa_offset 48
-; IA-DISABLE-NEXT:    lsl x9, x1, #2
-; IA-DISABLE-NEXT:    mov x8, sp
-; IA-DISABLE-NEXT:    and x10, x9, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    add x10, x0, x10
-; IA-DISABLE-NEXT:    ldp q1, q0, [x10, #16]
-; IA-DISABLE-NEXT:    ldr q2, [x10]
-; IA-DISABLE-NEXT:    str q2, [sp]
-; IA-DISABLE-NEXT:    stp q1, q0, [sp, #16]
-; IA-DISABLE-NEXT:    ld3 { v0.4s, v1.4s, v2.4s }, [x8]
-; IA-DISABLE-NEXT:    add x8, x9, #16
-; IA-DISABLE-NEXT:    add x9, x9, #32
-; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    str q0, [x10]
-; IA-DISABLE-NEXT:    str q1, [x0, x8]
-; IA-DISABLE-NEXT:    str q2, [x0, x9]
-; IA-DISABLE-NEXT:    add sp, sp, #48
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_deinterleave_idx_ld3:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsl x8, x1, #2
+; CHECK-NEXT:    and x9, x8, #0xfffffffffffffff0
+; CHECK-NEXT:    add x10, x0, x9
+; CHECK-NEXT:    ld3 { v0.4s, v1.4s, v2.4s }, [x10]
+; CHECK-NEXT:    add x10, x8, #16
+; CHECK-NEXT:    add x8, x8, #32
+; CHECK-NEXT:    and x10, x10, #0xfffffffffffffff0
+; CHECK-NEXT:    and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT:    str q0, [x0, x9]
+; CHECK-NEXT:    str q1, [x0, x10]
+; CHECK-NEXT:    str q2, [x0, x8]
+; CHECK-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %a1 = add i64 %idx, 4
@@ -108,52 +71,24 @@ entry:
 }
 
 define void @aarch64_vector_deinterleave_idx_ld4(ptr %ptr, i64 %idx) {
-; IA-ENABLE-LABEL: aarch64_vector_deinterleave_idx_ld4:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsl x8, x1, #2
-; IA-ENABLE-NEXT:    add x9, x8, #64
-; IA-ENABLE-NEXT:    add x11, x8, #96
-; IA-ENABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    add x10, x0, x9
-; IA-ENABLE-NEXT:    ld4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x10]
-; IA-ENABLE-NEXT:    add x10, x8, #80
-; IA-ENABLE-NEXT:    add x8, x8, #112
-; IA-ENABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    str q0, [x0, x9]
-; IA-ENABLE-NEXT:    and x9, x11, #0xfffffffffffffff0
-; IA-ENABLE-NEXT:    str q1, [x0, x10]
-; IA-ENABLE-NEXT:    str q2, [x0, x9]
-; IA-ENABLE-NEXT:    str q3, [x0, x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_deinterleave_idx_ld4:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    lsl x8, x1, #2
-; IA-DISABLE-NEXT:    add x9, x8, #64
-; IA-DISABLE-NEXT:    add x10, x8, #80
-; IA-DISABLE-NEXT:    add x11, x8, #96
-; IA-DISABLE-NEXT:    and x9, x9, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    add x8, x8, #112
-; IA-DISABLE-NEXT:    and x10, x10, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    add x9, x0, x9
-; IA-DISABLE-NEXT:    and x8, x8, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    ldp q1, q0, [x9]
-; IA-DISABLE-NEXT:    ldp q3, q2, [x9, #32]
-; IA-DISABLE-NEXT:    uzp1 v5.4s, v1.4s, v0.4s
-; IA-DISABLE-NEXT:    uzp2 v0.4s, v1.4s, v0.4s
-; IA-DISABLE-NEXT:    uzp1 v4.4s, v3.4s, v2.4s
-; IA-DISABLE-NEXT:    uzp2 v2.4s, v3.4s, v2.4s
-; IA-DISABLE-NEXT:    uzp1 v1.4s, v5.4s, v4.4s
-; IA-DISABLE-NEXT:    uzp1 v3.4s, v0.4s, v2.4s
-; IA-DISABLE-NEXT:    uzp2 v4.4s, v5.4s, v4.4s
-; IA-DISABLE-NEXT:    uzp2 v0.4s, v0.4s, v2.4s
-; IA-DISABLE-NEXT:    str q1, [x9]
-; IA-DISABLE-NEXT:    and x9, x11, #0xfffffffffffffff0
-; IA-DISABLE-NEXT:    str q3, [x0, x10]
-; IA-DISABLE-NEXT:    str q4, [x0, x9]
-; IA-DISABLE-NEXT:    str q0, [x0, x8]
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_deinterleave_idx_ld4:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsl x8, x1, #2
+; CHECK-NEXT:    add x9, x8, #64
+; CHECK-NEXT:    add x11, x8, #96
+; CHECK-NEXT:    and x9, x9, #0xfffffffffffffff0
+; CHECK-NEXT:    add x10, x0, x9
+; CHECK-NEXT:    ld4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x10]
+; CHECK-NEXT:    add x10, x8, #80
+; CHECK-NEXT:    add x8, x8, #112
+; CHECK-NEXT:    and x10, x10, #0xfffffffffffffff0
+; CHECK-NEXT:    and x8, x8, #0xfffffffffffffff0
+; CHECK-NEXT:    str q0, [x0, x9]
+; CHECK-NEXT:    and x9, x11, #0xfffffffffffffff0
+; CHECK-NEXT:    str q1, [x0, x10]
+; CHECK-NEXT:    str q2, [x0, x9]
+; CHECK-NEXT:    str q3, [x0, x8]
+; CHECK-NEXT:    ret
 entry:
   %a1 = add i64 %idx, 16
   %idx1 = lshr i64 %a1, 2
@@ -183,4 +118,5 @@ entry:
   ret void
 }
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
+; IA-DISABLE: {{.*}}
+; IA-ENABLE: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
index c5edb6cf82984..a7c16fda11478 100644
--- a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
+++ b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
@@ -2,23 +2,14 @@
 ; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,IA-ENABLE
 ; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
 define void @aarch64_vector_interleave_idx_st2(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1) {
-; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st2:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsr x8, x1, #2
-; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
-; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
-; IA-ENABLE-NEXT:    st2 { v0.4s, v1.4s }, [x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st2:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    lsr x8, x1, #2
-; IA-DISABLE-NEXT:    zip2 v2.4s, v0.4s, v1.4s
-; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v1.4s
-; IA-DISABLE-NEXT:    add x8, x0, x8, lsl #4
-; IA-DISABLE-NEXT:    stp q0, q2, [x8]
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_interleave_idx_st2:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsr x8, x1, #2
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; CHECK-NEXT:    add x8, x0, x8, lsl #4
+; CHECK-NEXT:    st2 { v0.4s, v1.4s }, [x8]
+; CHECK-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
@@ -29,33 +20,15 @@ entry:
 }
 
 define void @aarch64_vector_interleave_idx_st3(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1, <4 x float> %v2) {
-; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st3:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsr x8, x1, #2
-; IA-ENABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
-; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
-; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; IA-ENABLE-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st3:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    sub sp, sp, #48
-; IA-DISABLE-NEXT:    .cfi_def_cfa_offset 48
-; IA-DISABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
-; IA-DISABLE-NEXT:    mov x8, sp
-; IA-DISABLE-NEXT:    lsr x9, x1, #2
-; IA-DISABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
-; IA-DISABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
-; IA-DISABLE-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
-; IA-DISABLE-NEXT:    add x8, x0, x9, lsl #4
-; IA-DISABLE-NEXT:    ldp q1, q0, [sp, #16]
-; IA-DISABLE-NEXT:    ldr q2, [sp]
-; IA-DISABLE-NEXT:    stp q1, q0, [x8, #16]
-; IA-DISABLE-NEXT:    str q2, [x8]
-; IA-DISABLE-NEXT:    add sp, sp, #48
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_interleave_idx_st3:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsr x8, x1, #2
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2 def $q0_q1_q2
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2 def $q0_q1_q2
+; CHECK-NEXT:    add x8, x0, x8, lsl #4
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2 def $q0_q1_q2
+; CHECK-NEXT:    st3 { v0.4s, v1.4s, v2.4s }, [x8]
+; CHECK-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
@@ -66,32 +39,16 @@ entry:
 }
 
 define void @aarch64_vector_interleave_idx_st4(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1, <4 x float> %v2, <4 x float> %v3) {
-; IA-ENABLE-LABEL: aarch64_vector_interleave_idx_st4:
-; IA-ENABLE:       // %bb.0: // %entry
-; IA-ENABLE-NEXT:    lsr x8, x1, #2
-; IA-ENABLE-NEXT:    // kill: def $q3 killed $q3 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
-; IA-ENABLE-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
-; IA-ENABLE-NEXT:    add x8, x0, x8, lsl #4
-; IA-ENABLE-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
-; IA-ENABLE-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
-; IA-ENABLE-NEXT:    st4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x8]
-; IA-ENABLE-NEXT:    ret
-;
-; IA-DISABLE-LABEL: aarch64_vector_interleave_idx_st4:
-; IA-DISABLE:       // %bb.0: // %entry
-; IA-DISABLE-NEXT:    zip2 v4.4s, v1.4s, v3.4s
-; IA-DISABLE-NEXT:    zip2 v5.4s, v0.4s, v2.4s
-; IA-DISABLE-NEXT:    lsr x8, x1, #2
-; IA-DISABLE-NEXT:    zip1 v1.4s, v1.4s, v3.4s
-; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v2.4s
-; IA-DISABLE-NEXT:    add x8, x0, x8, lsl #4
-; IA-DISABLE-NEXT:    zip2 v2.4s, v5.4s, v4.4s
-; IA-DISABLE-NEXT:    zip1 v3.4s, v5.4s, v4.4s
-; IA-DISABLE-NEXT:    zip2 v4.4s, v0.4s, v1.4s
-; IA-DISABLE-NEXT:    zip1 v0.4s, v0.4s, v1.4s
-; IA-DISABLE-NEXT:    stp q3, q2, [x8, #32]
-; IA-DISABLE-NEXT:    stp q0, q4, [x8]
-; IA-DISABLE-NEXT:    ret
+; CHECK-LABEL: aarch64_vector_interleave_idx_st4:
+; CHECK:       // %bb.0: // %entry
+; CHECK-NEXT:    lsr x8, x1, #2
+; CHECK-NEXT:    // kill: def $q3 killed $q3 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; CHECK-NEXT:    // kill: def $q2 killed $q2 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; CHECK-NEXT:    add x8, x0, x8, lsl #4
+; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1_q2_q3 def $q0_q1_q2_q3
+; CHECK-NEXT:    st4 { v0.4s, v1.4s, v2.4s, v3.4s }, [x8]
+; CHECK-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1
@@ -101,4 +58,5 @@ entry:
   ret void
 }
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; CHECK: {{.*}}
+; IA-DISABLE: {{.*}}
+; IA-ENABLE: {{.*}}

>From 72b17bafea869881d0f1e38cc7a161a8af0b3333 Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Thu, 16 Jul 2026 12:28:50 +0000
Subject: [PATCH 3/4] use getmemintrinsicnode

---
 .../Target/AArch64/AArch64ISelLowering.cpp    | 16 ++++--
 .../AArch64/fixed-vector-deinterleave.ll      | 48 +---------------
 .../AArch64/fixed-vector-interleave.ll        | 56 +------------------
 .../AArch64/vector-deinterleave-load.ll       |  7 +--
 .../AArch64/vector-interleave-store.ll        |  7 +--
 5 files changed, 18 insertions(+), 116 deletions(-)

diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
index cc680d45f891d..b560db7460638 100644
--- a/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
+++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
@@ -27722,7 +27722,9 @@ performInterleavedStoreCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
     Ops.append({Chain, DAG.getConstant(IID, DL, MVT::i32)});
     Ops.append(ValueInterleaveOps);
     Ops.append({Pred, BasePtr});
-    return DAG.getNode(ISD::INTRINSIC_VOID, DL, MVT::Other, Ops);
+    return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, DL,
+                                   DAG.getVTList(MVT::Other), Ops,
+                                   MemN->getMemoryVT(), MemN->getMemOperand());
   } else {
 
     static constexpr Intrinsic::ID NEONStores[] = {Intrinsic::aarch64_neon_st2,
@@ -27734,7 +27736,6 @@ performInterleavedStoreCombine(SDNode *N, TargetLowering::DAGCombinerInfo &DCI,
         DAG.getTargetConstant(NEONStores[NumParts - 2], DL, MVT::i64));
     Ops.append(ValueInterleaveOps);
     Ops.push_back(BasePtr);
-    auto *MemN = cast<MemSDNode>(N);
     return DAG.getMemIntrinsicNode(ISD::INTRINSIC_VOID, DL,
                                    DAG.getVTList(MVT::Other), Ops,
                                    MemN->getMemoryVT(), MemN->getMemOperand());
@@ -30659,6 +30660,7 @@ static SDValue performVectorDeinterleaveCombine(
   SDVTList ResVTList = DAG.getVTList(ResVTs);
 
   SDValue Res;
+  MemSDNode *MemNode = dyn_cast<MemSDNode>(WideVec);
   if (IsScalable) {
     if (NumParts == 3)
       return SDValue();
@@ -30699,7 +30701,9 @@ static SDValue performVectorDeinterleaveCombine(
                                             : Intrinsic::aarch64_sve_ld4_sret;
     SDValue NewLdOps[] = {Chain, DAG.getConstant(IID, DL, MVT::i32), Pred,
                           BasePtr};
-    Res = DAG.getNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList, NewLdOps);
+    Res = DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList,
+                                  NewLdOps, MemNode->getMemoryVT(),
+                                  MemNode->getMemOperand());
   } else {
     auto *Load = dyn_cast<LoadSDNode>(WideVec);
     if (!Load || !Load->hasNUsesOfValue(NumParts, 0) || !Load->isSimple() ||
@@ -30713,9 +30717,9 @@ static SDValue performVectorDeinterleaveCombine(
         Load->getChain(),
         DAG.getTargetConstant(NEONLoads[NumParts - 2], DL, MVT::i64),
         Load->getBasePtr()};
-    Res =
-        DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList, NewLdOps,
-                                Load->getMemoryVT(), Load->getMemOperand());
+    Res = DAG.getMemIntrinsicNode(ISD::INTRINSIC_W_CHAIN, DL, ResVTList,
+                                  NewLdOps, MemNode->getMemoryVT(),
+                                  MemNode->getMemOperand());
   }
 
   // We can now generate a structured load!
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index abb112a360181..3fe10a4b37917 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-SD
-; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false -global-isel -global-isel-abort=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-GI
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false -global-isel -global-isel-abort=0 %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define {<2 x half>, <2 x half>} @vector_deinterleave_v2f16_v4f16(<4 x half> %vec) {
 ; CHECK-SD-LABEL: vector_deinterleave_v2f16_v4f16:
@@ -63,22 +63,6 @@ define {<2 x float>, <2 x float>} @vector_deinterleave_v2f32_v4f32(<4 x float> %
 ; CHECK-GI-NEXT:    // kill: def $d1 killed $d1 killed $q1
 ; CHECK-GI-NEXT:    fmov d0, d2
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2f32_v4f32:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    mov d1, v0.d[1]
-; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2s, v0.2s, v1.2s
-; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2s, v0.2s, v1.2s
-; CHECK-IA-DISABLE-SD-NEXT:    fmov d0, d2
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2f32_v4f32:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    uzp1 v2.4s, v0.4s, v0.4s
-; CHECK-IA-DISABLE-GI-NEXT:    uzp2 v1.4s, v0.4s, v0.4s
-; CHECK-IA-DISABLE-GI-NEXT:    // kill: def $d1 killed $d1 killed $q1
-; CHECK-IA-DISABLE-GI-NEXT:    fmov d0, d2
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x float>, <2 x float>} @llvm.vector.deinterleave2.v4f32(<4 x float> %vec)
   ret {<2 x float>, <2 x float>}   %retval
 }
@@ -108,20 +92,6 @@ define {<2 x double>, <2 x double>} @vector_deinterleave_v2f64_v4f64(<4 x double
 ; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
 ; CHECK-GI-NEXT:    mov v0.16b, v2.16b
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2f64_v4f64:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-SD-NEXT:    mov v0.16b, v2.16b
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2f64_v4f64:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-GI-NEXT:    mov v0.16b, v2.16b
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x double>, <2 x double>} @llvm.vector.deinterleave2.v4f64(<4 x double> %vec)
   ret {<2 x double>, <2 x double>}   %retval
 }
@@ -175,20 +145,6 @@ define {<2 x i64>, <2 x i64>} @vector_deinterleave_v2i64_v4i64(<4 x i64> %vec) {
 ; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
 ; CHECK-GI-NEXT:    mov v0.16b, v2.16b
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: vector_deinterleave_v2i64_v4i64:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-SD-NEXT:    mov v0.16b, v2.16b
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: vector_deinterleave_v2i64_v4i64:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-IA-DISABLE-GI-NEXT:    mov v0.16b, v2.16b
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call {<2 x i64>, <2 x i64>} @llvm.vector.deinterleave2.v4i64(<4 x i64> %vec)
   ret {<2 x i64>, <2 x i64>}   %retval
 }
diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
index 61789d787279d..ab06111fb52ff 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-interleave.ll
@@ -1,8 +1,8 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
 ; RUN: llc -mtriple=aarch64-none-linux-gnu %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
 ; RUN: llc -mtriple=aarch64-none-linux-gnu -global-isel -global-isel-abort=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
-; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-SD
-; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  -global-isel -global-isel-abort=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-IA-DISABLE-GI
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  %s -o - | FileCheck %s --check-prefixes=CHECK,CHECK-SD
+; RUN: llc -mtriple=aarch64-none-linux-gnu -lower-interleaved-accesses=false  -global-isel -global-isel-abort=0 %s -o - 2>&1 | FileCheck %s --check-prefixes=CHECK,CHECK-GI
 
 define <4 x half> @interleave2_v4f16(<2 x half> %vec0, <2 x half> %vec1) {
 ; CHECK-LABEL: interleave2_v4f16:
@@ -144,17 +144,6 @@ define <4 x i16> @interleave2_same_const_splat_v4i16() {
 ; CHECK-GI-NEXT:    movi v0.4h, #3
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: interleave2_same_const_splat_v4i16:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    movi v0.4h, #3
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: interleave2_same_const_splat_v4i16:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    movi v0.4h, #3
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> splat(i16 3), <2 x i16> splat(i16 3))
   ret <4 x i16> %retval
 }
@@ -173,21 +162,6 @@ define <4 x i16> @interleave2_diff_const_splat_v4i16() {
 ; CHECK-GI-NEXT:    movi v1.4h, #4
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: interleave2_diff_const_splat_v4i16:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    movi v0.2s, #4
-; CHECK-IA-DISABLE-SD-NEXT:    movi v1.2s, #3
-; CHECK-IA-DISABLE-SD-NEXT:    zip1 v0.4s, v1.4s, v0.4s
-; CHECK-IA-DISABLE-SD-NEXT:    xtn v0.4h, v0.4s
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: interleave2_diff_const_splat_v4i16:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    movi v0.4h, #3
-; CHECK-IA-DISABLE-GI-NEXT:    movi v1.4h, #4
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> splat(i16 3), <2 x i16> splat(i16 4))
   ret <4 x i16> %retval
 }
@@ -203,17 +177,6 @@ define <4 x i16> @interleave2_same_nonconst_splat_v4i16(i16 %a) {
 ; CHECK-GI-NEXT:    dup v0.4h, w0
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: interleave2_same_nonconst_splat_v4i16:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    dup v0.4h, w0
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: interleave2_same_nonconst_splat_v4i16:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    dup v0.4h, w0
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v0.4h
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %ins = insertelement <2 x i16> poison, i16 %a, i32 0
   %splat = shufflevector <2 x i16> %ins, <2 x i16> poison, <2 x i32> <i32 0, i32 0>
   %retval = call <4 x i16> @llvm.vector.interleave2.v4i16(<2 x i16> %splat, <2 x i16> %splat)
@@ -237,21 +200,6 @@ define <4 x i16> @interleave2_diff_nonconst_splat_v4i16(i16 %a, i16 %b) {
 ; CHECK-GI-NEXT:    dup v1.4h, w1
 ; CHECK-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
 ; CHECK-GI-NEXT:    ret
-;
-; CHECK-IA-DISABLE-SD-LABEL: interleave2_diff_nonconst_splat_v4i16:
-; CHECK-IA-DISABLE-SD:       // %bb.0:
-; CHECK-IA-DISABLE-SD-NEXT:    dup v0.2s, w0
-; CHECK-IA-DISABLE-SD-NEXT:    dup v1.2s, w1
-; CHECK-IA-DISABLE-SD-NEXT:    zip1 v0.4s, v0.4s, v1.4s
-; CHECK-IA-DISABLE-SD-NEXT:    xtn v0.4h, v0.4s
-; CHECK-IA-DISABLE-SD-NEXT:    ret
-;
-; CHECK-IA-DISABLE-GI-LABEL: interleave2_diff_nonconst_splat_v4i16:
-; CHECK-IA-DISABLE-GI:       // %bb.0:
-; CHECK-IA-DISABLE-GI-NEXT:    dup v0.4h, w0
-; CHECK-IA-DISABLE-GI-NEXT:    dup v1.4h, w1
-; CHECK-IA-DISABLE-GI-NEXT:    zip1 v0.4h, v0.4h, v1.4h
-; CHECK-IA-DISABLE-GI-NEXT:    ret
   %ins1 = insertelement <2 x i16> poison, i16 %a, i32 0
   %splat1 = shufflevector <2 x i16> %ins1, <2 x i16> poison, <2 x i32> <i32 0, i32 0>
   %ins2 = insertelement <2 x i16> poison, i16 %b, i32 0
diff --git a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
index a7ad6906ed7e2..995e73861f248 100644
--- a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
+++ b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,IA-ENABLE
-; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s
 
 define void @aarch64_vector_deinterleave_idx_ld2(ptr %ptr, i64 %idx) {
 ; CHECK-LABEL: aarch64_vector_deinterleave_idx_ld2:
@@ -117,6 +117,3 @@ entry:
   store <4 x float> %m12_15, ptr %gep4, align 16
   ret void
 }
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; IA-DISABLE: {{.*}}
-; IA-ENABLE: {{.*}}
diff --git a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
index a7c16fda11478..d2332d9e08bbd 100644
--- a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
+++ b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
@@ -1,6 +1,6 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,IA-ENABLE
-; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,IA-DISABLE
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s
 define void @aarch64_vector_interleave_idx_st2(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1) {
 ; CHECK-LABEL: aarch64_vector_interleave_idx_st2:
 ; CHECK:       // %bb.0: // %entry
@@ -57,6 +57,3 @@ entry:
   store <16 x float> %interleave, ptr %gep1, align 16
   ret void
 }
-;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
-; IA-DISABLE: {{.*}}
-; IA-ENABLE: {{.*}}

>From d5b5a2c21a87ada0d3512af8346de139edc07a1b Mon Sep 17 00:00:00 2001
From: Kamlesh Kumar <kamlesh.kumar at arm.com>
Date: Mon, 20 Jul 2026 06:29:54 +0000
Subject: [PATCH 4/4] Fixup

---
 .../AArch64/fixed-vector-deinterleave.ll      | 38 ++++++------------
 .../AArch64/vector-deinterleave-load.ll       | 40 +++++++++++++------
 .../AArch64/vector-interleave-store.ll        | 29 +++++++++-----
 3 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
index 3fe10a4b37917..426fb4b472cbe 100644
--- a/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
+++ b/llvm/test/CodeGen/AArch64/fixed-vector-deinterleave.ll
@@ -79,19 +79,12 @@ ret  {<4 x float>, <4 x float>}   %retval
 }
 
 define {<2 x double>, <2 x double>} @vector_deinterleave_v2f64_v4f64(<4 x double> %vec) {
-; CHECK-SD-LABEL: vector_deinterleave_v2f64_v4f64:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
-; CHECK-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
-; CHECK-SD-NEXT:    mov v0.16b, v2.16b
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: vector_deinterleave_v2f64_v4f64:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-GI-NEXT:    mov v0.16b, v2.16b
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: vector_deinterleave_v2f64_v4f64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-NEXT:    mov v0.16b, v2.16b
+; CHECK-NEXT:    ret
   %retval = call {<2 x double>, <2 x double>} @llvm.vector.deinterleave2.v4f64(<4 x double> %vec)
   ret {<2 x double>, <2 x double>}   %retval
 }
@@ -132,19 +125,12 @@ define {<4 x i32>, <4 x i32>} @vector_deinterleave_v4i32_v8i32(<8 x i32> %vec) {
 }
 
 define {<2 x i64>, <2 x i64>} @vector_deinterleave_v2i64_v4i64(<4 x i64> %vec) {
-; CHECK-SD-LABEL: vector_deinterleave_v2i64_v4i64:
-; CHECK-SD:       // %bb.0:
-; CHECK-SD-NEXT:    uzp1 v2.2d, v0.2d, v1.2d
-; CHECK-SD-NEXT:    uzp2 v1.2d, v0.2d, v1.2d
-; CHECK-SD-NEXT:    mov v0.16b, v2.16b
-; CHECK-SD-NEXT:    ret
-;
-; CHECK-GI-LABEL: vector_deinterleave_v2i64_v4i64:
-; CHECK-GI:       // %bb.0:
-; CHECK-GI-NEXT:    zip1 v2.2d, v0.2d, v1.2d
-; CHECK-GI-NEXT:    zip2 v1.2d, v0.2d, v1.2d
-; CHECK-GI-NEXT:    mov v0.16b, v2.16b
-; CHECK-GI-NEXT:    ret
+; CHECK-LABEL: vector_deinterleave_v2i64_v4i64:
+; CHECK:       // %bb.0:
+; CHECK-NEXT:    zip1 v2.2d, v0.2d, v1.2d
+; CHECK-NEXT:    zip2 v1.2d, v0.2d, v1.2d
+; CHECK-NEXT:    mov v0.16b, v2.16b
+; CHECK-NEXT:    ret
   %retval = call {<2 x i64>, <2 x i64>} @llvm.vector.deinterleave2.v4i64(<4 x i64> %vec)
   ret {<2 x i64>, <2 x i64>}   %retval
 }
diff --git a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
index 995e73861f248..b63448c643074 100644
--- a/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
+++ b/llvm/test/CodeGen/AArch64/vector-deinterleave-load.ll
@@ -1,19 +1,33 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s
-; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s  --check-prefixes=CHECK,CHECK-IAENABLED
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,CHECK-IADISABLED
 
 define void @aarch64_vector_deinterleave_idx_ld2(ptr %ptr, i64 %idx) {
-; CHECK-LABEL: aarch64_vector_deinterleave_idx_ld2:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    lsl x8, x1, #2
-; CHECK-NEXT:    and x9, x8, #0xfffffffffffffff0
-; CHECK-NEXT:    add x8, x8, #16
-; CHECK-NEXT:    add x10, x0, x9
-; CHECK-NEXT:    and x8, x8, #0xfffffffffffffff0
-; CHECK-NEXT:    ld2 { v0.4s, v1.4s }, [x10]
-; CHECK-NEXT:    str q0, [x0, x9]
-; CHECK-NEXT:    str q1, [x0, x8]
-; CHECK-NEXT:    ret
+; CHECK-IAENABLED-LABEL: aarch64_vector_deinterleave_idx_ld2:
+; CHECK-IAENABLED:       // %bb.0: // %entry
+; CHECK-IAENABLED-NEXT:    lsl x8, x1, #2
+; CHECK-IAENABLED-NEXT:    and x9, x8, #0xfffffffffffffff0
+; CHECK-IAENABLED-NEXT:    add x8, x8, #16
+; CHECK-IAENABLED-NEXT:    add x10, x0, x9
+; CHECK-IAENABLED-NEXT:    and x8, x8, #0xfffffffffffffff0
+; CHECK-IAENABLED-NEXT:    ld2 { v0.4s, v1.4s }, [x10]
+; CHECK-IAENABLED-NEXT:    str q0, [x0, x9]
+; CHECK-IAENABLED-NEXT:    str q1, [x0, x8]
+; CHECK-IAENABLED-NEXT:    ret
+;
+; CHECK-IADISABLED-LABEL: aarch64_vector_deinterleave_idx_ld2:
+; CHECK-IADISABLED:       // %bb.0: // %entry
+; CHECK-IADISABLED-NEXT:    lsl x8, x1, #2
+; CHECK-IADISABLED-NEXT:    and x9, x8, #0xfffffffffffffff0
+; CHECK-IADISABLED-NEXT:    add x8, x8, #16
+; CHECK-IADISABLED-NEXT:    add x9, x0, x9
+; CHECK-IADISABLED-NEXT:    and x8, x8, #0xfffffffffffffff0
+; CHECK-IADISABLED-NEXT:    ldp q1, q0, [x9]
+; CHECK-IADISABLED-NEXT:    uzp1 v2.4s, v1.4s, v0.4s
+; CHECK-IADISABLED-NEXT:    uzp2 v0.4s, v1.4s, v0.4s
+; CHECK-IADISABLED-NEXT:    str q2, [x9]
+; CHECK-IADISABLED-NEXT:    str q0, [x0, x8]
+; CHECK-IADISABLED-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %a1 = add i64 %idx, 4
diff --git a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
index d2332d9e08bbd..d3985991af531 100644
--- a/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
+++ b/llvm/test/CodeGen/AArch64/vector-interleave-store.ll
@@ -1,15 +1,24 @@
 ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
-; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s
-; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s
+; RUN: llc -mtriple=aarch64-linux-gnu < %s | FileCheck %s --check-prefixes=CHECK,CHECK-IAENABLED
+; RUN: llc -mtriple=aarch64-linux-gnu -lower-interleaved-accesses=false < %s | FileCheck %s --check-prefixes=CHECK,CHECK-IADISABLED
 define void @aarch64_vector_interleave_idx_st2(ptr %ptr, i64 %idx, <4 x float> %v0, <4 x float> %v1) {
-; CHECK-LABEL: aarch64_vector_interleave_idx_st2:
-; CHECK:       // %bb.0: // %entry
-; CHECK-NEXT:    lsr x8, x1, #2
-; CHECK-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
-; CHECK-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
-; CHECK-NEXT:    add x8, x0, x8, lsl #4
-; CHECK-NEXT:    st2 { v0.4s, v1.4s }, [x8]
-; CHECK-NEXT:    ret
+; CHECK-IAENABLED-LABEL: aarch64_vector_interleave_idx_st2:
+; CHECK-IAENABLED:       // %bb.0: // %entry
+; CHECK-IAENABLED-NEXT:    lsr x8, x1, #2
+; CHECK-IAENABLED-NEXT:    // kill: def $q1 killed $q1 killed $q0_q1 def $q0_q1
+; CHECK-IAENABLED-NEXT:    // kill: def $q0 killed $q0 killed $q0_q1 def $q0_q1
+; CHECK-IAENABLED-NEXT:    add x8, x0, x8, lsl #4
+; CHECK-IAENABLED-NEXT:    st2 { v0.4s, v1.4s }, [x8]
+; CHECK-IAENABLED-NEXT:    ret
+;
+; CHECK-IADISABLED-LABEL: aarch64_vector_interleave_idx_st2:
+; CHECK-IADISABLED:       // %bb.0: // %entry
+; CHECK-IADISABLED-NEXT:    lsr x8, x1, #2
+; CHECK-IADISABLED-NEXT:    zip2 v2.4s, v0.4s, v1.4s
+; CHECK-IADISABLED-NEXT:    zip1 v0.4s, v0.4s, v1.4s
+; CHECK-IADISABLED-NEXT:    add x8, x0, x8, lsl #4
+; CHECK-IADISABLED-NEXT:    stp q0, q2, [x8]
+; CHECK-IADISABLED-NEXT:    ret
 entry:
   %idx1 = lshr i64 %idx, 2
   %gep1 = getelementptr inbounds <4 x float>, ptr %ptr, i64 %idx1



More information about the llvm-commits mailing list