[llvm] [AArch64][LSR] Prefer pointer IVs for SVE accesses that need splitting (PR #228510)
Benjamin Maxwell via llvm-commits
llvm-commits at lists.llvm.org
Sat Oct 3 07:10:59 PDT 2026
https://github.com/MacDue updated https://github.com/llvm/llvm-project/pull/228510
>From 81d3aad11b89244ef031cce38508de237a675db7 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Fri, 2 Oct 2026 10:37:03 +0000
Subject: [PATCH 1/3] Precommit test
---
.../AArch64/vscale-fixups.ll | 201 +++++++++++++++++-
1 file changed, 198 insertions(+), 3 deletions(-)
diff --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
index ef4e392e24f8ec..21898de51c2407 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
@@ -1,8 +1,8 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
-; RUN: llc %s -o - | FileCheck %s --check-prefixes=COMMON
+; RUN: llc %s -o - -aarch64-enable-subreg-liveness-tracking | FileCheck %s --check-prefixes=COMMON
;; Additional runlines to exercise lsr code which AArch64 normally wouldn't.
-; RUN: llc %s -o - -lsr-preferred-addressing-mode=preindexed | FileCheck %s --check-prefixes=COMMON
-; RUN: llc %s -o - -lsr-preferred-addressing-mode=postindexed | FileCheck %s --check-prefixes=COMMON
+; RUN: llc %s -o - -aarch64-enable-subreg-liveness-tracking -lsr-preferred-addressing-mode=preindexed | FileCheck %s --check-prefixes=COMMON
+; RUN: llc %s -o - -aarch64-enable-subreg-liveness-tracking -lsr-preferred-addressing-mode=postindexed | FileCheck %s --check-prefixes=COMMON
target triple = "aarch64-unknown-linux-gnu"
@@ -591,4 +591,199 @@ exit:
ret void
}
+define void @multivector_accesses(ptr noalias %x, ptr noalias %y, i64 %n) #1 {
+; COMMON-LABEL: multivector_accesses:
+; COMMON: // %bb.0: // %entry
+; COMMON-NEXT: mov x8, xzr
+; COMMON-NEXT: ptrue pn8.d
+; COMMON-NEXT: ptrue pn9.s
+; COMMON-NEXT: .LBB11_1: // %vector.body
+; COMMON-NEXT: // =>This Inner Loop Header: Depth=1
+; COMMON-NEXT: add x9, x0, x8, lsl #3
+; COMMON-NEXT: ld1d { z0.d - z3.d }, pn8/z, [x0, x8, lsl #3]
+; COMMON-NEXT: ld1d { z16.d - z19.d }, pn8/z, [x9, #4, mul vl]
+; COMMON-NEXT: movprfx z5, z1
+; COMMON-NEXT: add z5.d, z5.d, #1 // =0x1
+; COMMON-NEXT: movprfx z4, z0
+; COMMON-NEXT: add z4.d, z4.d, #1 // =0x1
+; COMMON-NEXT: movprfx z7, z3
+; COMMON-NEXT: add z7.d, z7.d, #1 // =0x1
+; COMMON-NEXT: movprfx z6, z2
+; COMMON-NEXT: add z6.d, z6.d, #1 // =0x1
+; COMMON-NEXT: movprfx z1, z17
+; COMMON-NEXT: add z1.d, z1.d, #1 // =0x1
+; COMMON-NEXT: movprfx z0, z16
+; COMMON-NEXT: add z0.d, z0.d, #1 // =0x1
+; COMMON-NEXT: movprfx z3, z19
+; COMMON-NEXT: add z3.d, z3.d, #1 // =0x1
+; COMMON-NEXT: movprfx z2, z18
+; COMMON-NEXT: add z2.d, z2.d, #1 // =0x1
+; COMMON-NEXT: st1d { z4.d - z7.d }, pn8, [x9]
+; COMMON-NEXT: st1d { z0.d - z3.d }, pn8, [x9, #4, mul vl]
+; COMMON-NEXT: add x9, x1, x8, lsl #2
+; COMMON-NEXT: ld1w { z0.s - z3.s }, pn9/z, [x1, x8, lsl #2]
+; COMMON-NEXT: incb x8
+; COMMON-NEXT: add z0.s, z0.s, #1 // =0x1
+; COMMON-NEXT: add z1.s, z1.s, #1 // =0x1
+; COMMON-NEXT: add z2.s, z2.s, #1 // =0x1
+; COMMON-NEXT: add z3.s, z3.s, #1 // =0x1
+; COMMON-NEXT: cmp x8, #1, lsl #12 // =4096
+; COMMON-NEXT: st1w { z0.s - z3.s }, pn9, [x9]
+; COMMON-NEXT: b.ne .LBB11_1
+; COMMON-NEXT: // %bb.2: // %exit
+; COMMON-NEXT: ret
+entry:
+ br label %vector.ph
+
+vector.ph:
+ %0 = call i64 @llvm.vscale.i64()
+ %1 = shl nuw i64 %0, 4
+ br label %vector.body
+
+vector.body:
+ %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+ %2 = getelementptr inbounds i64, ptr %x, i64 %index
+ %3 = load <vscale x 16 x i64>, ptr %2, align 8
+ %4 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 0)
+ %5 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 4)
+ %6 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 8)
+ %7 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 12)
+ %8 = add <vscale x 4 x i64> %4, splat (i64 1)
+ %9 = add <vscale x 4 x i64> %5, splat (i64 1)
+ %10 = add <vscale x 4 x i64> %6, splat (i64 1)
+ %11 = add <vscale x 4 x i64> %7, splat (i64 1)
+ %12 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> poison, <vscale x 4 x i64> %8, i64 0)
+ %13 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %12, <vscale x 4 x i64> %9, i64 4)
+ %14 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %13, <vscale x 4 x i64> %10, i64 8)
+ %15 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %14, <vscale x 4 x i64> %11, i64 12)
+ store <vscale x 16 x i64> %15, ptr %2, align 8
+ %16 = getelementptr inbounds i32, ptr %y, i64 %index
+ %17 = load <vscale x 16 x i32>, ptr %16, align 4
+ %18 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 0)
+ %19 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 4)
+ %20 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 8)
+ %21 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 12)
+ %22 = add <vscale x 4 x i32> %18, splat (i32 1)
+ %23 = add <vscale x 4 x i32> %19, splat (i32 1)
+ %24 = add <vscale x 4 x i32> %20, splat (i32 1)
+ %25 = add <vscale x 4 x i32> %21, splat (i32 1)
+ %26 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> poison, <vscale x 4 x i32> %22, i64 0)
+ %27 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %26, <vscale x 4 x i32> %23, i64 4)
+ %28 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %27, <vscale x 4 x i32> %24, i64 8)
+ %29 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %28, <vscale x 4 x i32> %25, i64 12)
+ store <vscale x 16 x i32> %29, ptr %16, align 4
+ %index.next = add nuw i64 %index, %1
+ %30 = icmp eq i64 %index.next, 4096
+ br i1 %30, label %middle.block, label %vector.body
+
+middle.block:
+ br label %exit
+
+exit:
+ ret void
+}
+
+; Same as before but we don't have +sve2p1, so all accesses will be split.
+define void @split_vector_accesses(ptr noalias %x, ptr noalias %y, i64 %n) #0 {
+; COMMON-LABEL: split_vector_accesses:
+; COMMON: // %bb.0: // %entry
+; COMMON-NEXT: ptrue p0.s
+; COMMON-NEXT: mov x8, xzr
+; COMMON-NEXT: .LBB12_1: // %vector.body
+; COMMON-NEXT: // =>This Inner Loop Header: Depth=1
+; COMMON-NEXT: add x9, x0, x8, lsl #3
+; COMMON-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
+; COMMON-NEXT: ldr z1, [x9, #6, mul vl]
+; COMMON-NEXT: ldr z2, [x9, #7, mul vl]
+; COMMON-NEXT: ldr z3, [x9, #4, mul vl]
+; COMMON-NEXT: ldr z4, [x9, #5, mul vl]
+; COMMON-NEXT: ldr z5, [x9, #2, mul vl]
+; COMMON-NEXT: ldr z6, [x9, #3, mul vl]
+; COMMON-NEXT: ldr z7, [x9, #1, mul vl]
+; COMMON-NEXT: add z0.d, z0.d, #1 // =0x1
+; COMMON-NEXT: add z1.d, z1.d, #1 // =0x1
+; COMMON-NEXT: add z2.d, z2.d, #1 // =0x1
+; COMMON-NEXT: add z3.d, z3.d, #1 // =0x1
+; COMMON-NEXT: add z4.d, z4.d, #1 // =0x1
+; COMMON-NEXT: add z5.d, z5.d, #1 // =0x1
+; COMMON-NEXT: add z6.d, z6.d, #1 // =0x1
+; COMMON-NEXT: add z7.d, z7.d, #1 // =0x1
+; COMMON-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3]
+; COMMON-NEXT: str z1, [x9, #6, mul vl]
+; COMMON-NEXT: str z2, [x9, #7, mul vl]
+; COMMON-NEXT: str z3, [x9, #4, mul vl]
+; COMMON-NEXT: str z4, [x9, #5, mul vl]
+; COMMON-NEXT: str z5, [x9, #2, mul vl]
+; COMMON-NEXT: str z6, [x9, #3, mul vl]
+; COMMON-NEXT: str z7, [x9, #1, mul vl]
+; COMMON-NEXT: add x9, x1, x8, lsl #2
+; COMMON-NEXT: ld1w { z0.s }, p0/z, [x1, x8, lsl #2]
+; COMMON-NEXT: ldr z1, [x9, #2, mul vl]
+; COMMON-NEXT: ldr z2, [x9, #3, mul vl]
+; COMMON-NEXT: ldr z3, [x9, #1, mul vl]
+; COMMON-NEXT: add z0.s, z0.s, #1 // =0x1
+; COMMON-NEXT: add z1.s, z1.s, #1 // =0x1
+; COMMON-NEXT: add z2.s, z2.s, #1 // =0x1
+; COMMON-NEXT: add z3.s, z3.s, #1 // =0x1
+; COMMON-NEXT: st1w { z0.s }, p0, [x1, x8, lsl #2]
+; COMMON-NEXT: incb x8
+; COMMON-NEXT: str z1, [x9, #2, mul vl]
+; COMMON-NEXT: str z2, [x9, #3, mul vl]
+; COMMON-NEXT: cmp x8, #1, lsl #12 // =4096
+; COMMON-NEXT: str z3, [x9, #1, mul vl]
+; COMMON-NEXT: b.ne .LBB12_1
+; COMMON-NEXT: // %bb.2: // %exit
+; COMMON-NEXT: ret
+entry:
+ br label %vector.ph
+
+vector.ph:
+ %0 = call i64 @llvm.vscale.i64()
+ %1 = shl nuw i64 %0, 4
+ br label %vector.body
+
+vector.body:
+ %index = phi i64 [ 0, %vector.ph ], [ %index.next, %vector.body ]
+ %2 = getelementptr inbounds i64, ptr %x, i64 %index
+ %3 = load <vscale x 16 x i64>, ptr %2, align 8
+ %4 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 0)
+ %5 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 4)
+ %6 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 8)
+ %7 = call <vscale x 4 x i64> @llvm.vector.extract.nxv4i64.nxv16i64(<vscale x 16 x i64> %3, i64 12)
+ %8 = add <vscale x 4 x i64> %4, splat (i64 1)
+ %9 = add <vscale x 4 x i64> %5, splat (i64 1)
+ %10 = add <vscale x 4 x i64> %6, splat (i64 1)
+ %11 = add <vscale x 4 x i64> %7, splat (i64 1)
+ %12 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> poison, <vscale x 4 x i64> %8, i64 0)
+ %13 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %12, <vscale x 4 x i64> %9, i64 4)
+ %14 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %13, <vscale x 4 x i64> %10, i64 8)
+ %15 = call <vscale x 16 x i64> @llvm.vector.insert.nxv16i64.nxv4i64(<vscale x 16 x i64> %14, <vscale x 4 x i64> %11, i64 12)
+ store <vscale x 16 x i64> %15, ptr %2, align 8
+ %16 = getelementptr inbounds i32, ptr %y, i64 %index
+ %17 = load <vscale x 16 x i32>, ptr %16, align 4
+ %18 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 0)
+ %19 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 4)
+ %20 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 8)
+ %21 = call <vscale x 4 x i32> @llvm.vector.extract.nxv4i32.nxv16i32(<vscale x 16 x i32> %17, i64 12)
+ %22 = add <vscale x 4 x i32> %18, splat (i32 1)
+ %23 = add <vscale x 4 x i32> %19, splat (i32 1)
+ %24 = add <vscale x 4 x i32> %20, splat (i32 1)
+ %25 = add <vscale x 4 x i32> %21, splat (i32 1)
+ %26 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> poison, <vscale x 4 x i32> %22, i64 0)
+ %27 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %26, <vscale x 4 x i32> %23, i64 4)
+ %28 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %27, <vscale x 4 x i32> %24, i64 8)
+ %29 = call <vscale x 16 x i32> @llvm.vector.insert.nxv16i32.nxv4i32(<vscale x 16 x i32> %28, <vscale x 4 x i32> %25, i64 12)
+ store <vscale x 16 x i32> %29, ptr %16, align 4
+ %index.next = add nuw i64 %index, %1
+ %30 = icmp eq i64 %index.next, 4096
+ br i1 %30, label %middle.block, label %vector.body
+
+middle.block:
+ br label %exit
+
+exit:
+ ret void
+}
+
attributes #0 = { "target-features"="+sve2" vscale_range(1,16) }
+attributes #1 = { "target-features"="+sve2p1" vscale_range(1,16) }
>From 37ce2fb4532d2007f481cf01ac12f81375e3ab5b Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <benjamin.maxwell at arm.com>
Date: Fri, 2 Oct 2026 16:12:51 +0000
Subject: [PATCH 2/3] [AArch64][LSR] Prefer pointer IVs for SVE accesses that
need splitting
Currently, it always prefers scaled accesses but that ends up doing more
work as only the first access can used the scaled register. Later split
accesses need to compute the base then another `mul vl` offset.
Assisted-by: Codex
---
.../AArch64/AArch64TargetTransformInfo.cpp | 33 ++++++
.../AArch64/AArch64TargetTransformInfo.h | 5 +
.../AArch64/vscale-fixups.ll | 101 ++++++++----------
3 files changed, 83 insertions(+), 56 deletions(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index ddea78fa4e8083..f5ed34231bc3f3 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -7452,6 +7452,39 @@ AArch64TTIImpl::getScalingFactorCost(Type *Ty, GlobalValue *BaseGV,
return InstructionCost::getInvalid();
}
+bool AArch64TTIImpl::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
+ int64_t BaseOffset, bool HasBaseReg,
+ int64_t Scale, unsigned AddrSpace,
+ Instruction *I,
+ int64_t ScalableOffset) const {
+ // LSR can make an illegal scalable vector access easier to split and combine
+ // by preferring a base+register+scalable-offset form. Note: This is an LSR
+ // preference rather than a legal machine addressing mode.
+ if (!BaseGV && !BaseOffset && HasBaseReg && isa<ScalableVectorType>(Ty)) {
+ EVT VT = getTLI()->getValueType(DL, Ty);
+ uint64_t AccessNumBytes = VT.getStoreSize().getKnownMinValue();
+ if (AccessNumBytes >= 16 && getTLI()->getTypeAction(Ty->getContext(), VT) ==
+ TargetLowering::TypeSplitVector) {
+ EVT LegalVT = getTLI()->getLegalTypeToTransformTo(Ty->getContext(), VT);
+ uint64_t VecNumBytes = LegalVT.getStoreSize().getKnownMinValue();
+ if (LegalVT.getVectorElementType() == VT.getVectorElementType() &&
+ VecNumBytes <= 16 && AccessNumBytes % VecNumBytes == 0 &&
+ isPowerOf2_64(VecNumBytes)) {
+ // Don't prefer scaled access if the type may need splitting. Only the
+ // first access can use the scaled offset. Latter accesses need to
+ // materialize a new base + mul vl offset.
+ if (Scale)
+ return false;
+ if (ScalableOffset && ScalableOffset % VecNumBytes == 0)
+ return true;
+ }
+ }
+ }
+
+ return BaseT::isLegalAddressingMode(Ty, BaseGV, BaseOffset, HasBaseReg, Scale,
+ AddrSpace, I, ScalableOffset);
+}
+
bool AArch64TTIImpl::shouldTreatInstructionLikeSelect(
const Instruction *I) const {
if (EnableOrLikeSelectOpt) {
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h
index d090f69c1476a4..8a7e0f068b13e6 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.h
@@ -531,6 +531,11 @@ class AArch64TTIImpl final : public BasicTTIImplBase<AArch64TTIImpl> {
int64_t Scale,
unsigned AddrSpace) const override;
+ bool isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV, int64_t BaseOffset,
+ bool HasBaseReg, int64_t Scale, unsigned AddrSpace,
+ Instruction *I = nullptr,
+ int64_t ScalableOffset = 0) const override;
+
bool enableSelectOptimize() const override {
return ST->enableSelectOptimize();
}
diff --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
index 21898de51c2407..f0ccc6e7627505 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
@@ -594,42 +594,33 @@ exit:
define void @multivector_accesses(ptr noalias %x, ptr noalias %y, i64 %n) #1 {
; COMMON-LABEL: multivector_accesses:
; COMMON: // %bb.0: // %entry
-; COMMON-NEXT: mov x8, xzr
+; COMMON-NEXT: mov w8, #4096 // =0x1000
; COMMON-NEXT: ptrue pn8.d
; COMMON-NEXT: ptrue pn9.s
; COMMON-NEXT: .LBB11_1: // %vector.body
; COMMON-NEXT: // =>This Inner Loop Header: Depth=1
-; COMMON-NEXT: add x9, x0, x8, lsl #3
-; COMMON-NEXT: ld1d { z0.d - z3.d }, pn8/z, [x0, x8, lsl #3]
-; COMMON-NEXT: ld1d { z16.d - z19.d }, pn8/z, [x9, #4, mul vl]
-; COMMON-NEXT: movprfx z5, z1
-; COMMON-NEXT: add z5.d, z5.d, #1 // =0x1
-; COMMON-NEXT: movprfx z4, z0
-; COMMON-NEXT: add z4.d, z4.d, #1 // =0x1
-; COMMON-NEXT: movprfx z7, z3
-; COMMON-NEXT: add z7.d, z7.d, #1 // =0x1
-; COMMON-NEXT: movprfx z6, z2
-; COMMON-NEXT: add z6.d, z6.d, #1 // =0x1
-; COMMON-NEXT: movprfx z1, z17
+; COMMON-NEXT: ld1d { z4.d - z7.d }, pn8/z, [x0, #4, mul vl]
+; COMMON-NEXT: ld1d { z0.d - z3.d }, pn8/z, [x0]
+; COMMON-NEXT: decb x8
; COMMON-NEXT: add z1.d, z1.d, #1 // =0x1
-; COMMON-NEXT: movprfx z0, z16
+; COMMON-NEXT: add z5.d, z5.d, #1 // =0x1
; COMMON-NEXT: add z0.d, z0.d, #1 // =0x1
-; COMMON-NEXT: movprfx z3, z19
+; COMMON-NEXT: add z4.d, z4.d, #1 // =0x1
; COMMON-NEXT: add z3.d, z3.d, #1 // =0x1
-; COMMON-NEXT: movprfx z2, z18
+; COMMON-NEXT: add z7.d, z7.d, #1 // =0x1
; COMMON-NEXT: add z2.d, z2.d, #1 // =0x1
-; COMMON-NEXT: st1d { z4.d - z7.d }, pn8, [x9]
-; COMMON-NEXT: st1d { z0.d - z3.d }, pn8, [x9, #4, mul vl]
-; COMMON-NEXT: add x9, x1, x8, lsl #2
-; COMMON-NEXT: ld1w { z0.s - z3.s }, pn9/z, [x1, x8, lsl #2]
-; COMMON-NEXT: incb x8
+; COMMON-NEXT: add z6.d, z6.d, #1 // =0x1
+; COMMON-NEXT: st1d { z4.d - z7.d }, pn8, [x0, #4, mul vl]
+; COMMON-NEXT: st1d { z0.d - z3.d }, pn8, [x0]
+; COMMON-NEXT: addvl x0, x0, #8
+; COMMON-NEXT: ld1w { z0.s - z3.s }, pn9/z, [x1]
; COMMON-NEXT: add z0.s, z0.s, #1 // =0x1
; COMMON-NEXT: add z1.s, z1.s, #1 // =0x1
; COMMON-NEXT: add z2.s, z2.s, #1 // =0x1
; COMMON-NEXT: add z3.s, z3.s, #1 // =0x1
-; COMMON-NEXT: cmp x8, #1, lsl #12 // =4096
-; COMMON-NEXT: st1w { z0.s - z3.s }, pn9, [x9]
-; COMMON-NEXT: b.ne .LBB11_1
+; COMMON-NEXT: st1w { z0.s - z3.s }, pn9, [x1]
+; COMMON-NEXT: incb x1, all, mul #4
+; COMMON-NEXT: cbnz x8, .LBB11_1
; COMMON-NEXT: // %bb.2: // %exit
; COMMON-NEXT: ret
entry:
@@ -687,19 +678,17 @@ exit:
define void @split_vector_accesses(ptr noalias %x, ptr noalias %y, i64 %n) #0 {
; COMMON-LABEL: split_vector_accesses:
; COMMON: // %bb.0: // %entry
-; COMMON-NEXT: ptrue p0.s
-; COMMON-NEXT: mov x8, xzr
+; COMMON-NEXT: mov w8, #4096 // =0x1000
; COMMON-NEXT: .LBB12_1: // %vector.body
; COMMON-NEXT: // =>This Inner Loop Header: Depth=1
-; COMMON-NEXT: add x9, x0, x8, lsl #3
-; COMMON-NEXT: ld1d { z0.d }, p0/z, [x0, x8, lsl #3]
-; COMMON-NEXT: ldr z1, [x9, #6, mul vl]
-; COMMON-NEXT: ldr z2, [x9, #7, mul vl]
-; COMMON-NEXT: ldr z3, [x9, #4, mul vl]
-; COMMON-NEXT: ldr z4, [x9, #5, mul vl]
-; COMMON-NEXT: ldr z5, [x9, #2, mul vl]
-; COMMON-NEXT: ldr z6, [x9, #3, mul vl]
-; COMMON-NEXT: ldr z7, [x9, #1, mul vl]
+; COMMON-NEXT: ldr z0, [x0, #6, mul vl]
+; COMMON-NEXT: ldr z1, [x0, #7, mul vl]
+; COMMON-NEXT: decb x8
+; COMMON-NEXT: ldr z2, [x0, #4, mul vl]
+; COMMON-NEXT: ldr z3, [x0, #5, mul vl]
+; COMMON-NEXT: ldr z4, [x0, #2, mul vl]
+; COMMON-NEXT: ldr z5, [x0, #3, mul vl]
+; COMMON-NEXT: ldr z6, [x0]
; COMMON-NEXT: add z0.d, z0.d, #1 // =0x1
; COMMON-NEXT: add z1.d, z1.d, #1 // =0x1
; COMMON-NEXT: add z2.d, z2.d, #1 // =0x1
@@ -707,31 +696,31 @@ define void @split_vector_accesses(ptr noalias %x, ptr noalias %y, i64 %n) #0 {
; COMMON-NEXT: add z4.d, z4.d, #1 // =0x1
; COMMON-NEXT: add z5.d, z5.d, #1 // =0x1
; COMMON-NEXT: add z6.d, z6.d, #1 // =0x1
-; COMMON-NEXT: add z7.d, z7.d, #1 // =0x1
-; COMMON-NEXT: st1d { z0.d }, p0, [x0, x8, lsl #3]
-; COMMON-NEXT: str z1, [x9, #6, mul vl]
-; COMMON-NEXT: str z2, [x9, #7, mul vl]
-; COMMON-NEXT: str z3, [x9, #4, mul vl]
-; COMMON-NEXT: str z4, [x9, #5, mul vl]
-; COMMON-NEXT: str z5, [x9, #2, mul vl]
-; COMMON-NEXT: str z6, [x9, #3, mul vl]
-; COMMON-NEXT: str z7, [x9, #1, mul vl]
-; COMMON-NEXT: add x9, x1, x8, lsl #2
-; COMMON-NEXT: ld1w { z0.s }, p0/z, [x1, x8, lsl #2]
-; COMMON-NEXT: ldr z1, [x9, #2, mul vl]
-; COMMON-NEXT: ldr z2, [x9, #3, mul vl]
-; COMMON-NEXT: ldr z3, [x9, #1, mul vl]
+; COMMON-NEXT: str z0, [x0, #6, mul vl]
+; COMMON-NEXT: ldr z0, [x0, #1, mul vl]
+; COMMON-NEXT: str z1, [x0, #7, mul vl]
+; COMMON-NEXT: str z2, [x0, #4, mul vl]
+; COMMON-NEXT: add z0.d, z0.d, #1 // =0x1
+; COMMON-NEXT: str z3, [x0, #5, mul vl]
+; COMMON-NEXT: str z4, [x0, #2, mul vl]
+; COMMON-NEXT: str z5, [x0, #3, mul vl]
+; COMMON-NEXT: str z6, [x0]
+; COMMON-NEXT: str z0, [x0, #1, mul vl]
+; COMMON-NEXT: addvl x0, x0, #8
+; COMMON-NEXT: ldr z0, [x1, #2, mul vl]
+; COMMON-NEXT: ldr z1, [x1, #3, mul vl]
+; COMMON-NEXT: ldr z2, [x1]
+; COMMON-NEXT: ldr z3, [x1, #1, mul vl]
; COMMON-NEXT: add z0.s, z0.s, #1 // =0x1
; COMMON-NEXT: add z1.s, z1.s, #1 // =0x1
; COMMON-NEXT: add z2.s, z2.s, #1 // =0x1
; COMMON-NEXT: add z3.s, z3.s, #1 // =0x1
-; COMMON-NEXT: st1w { z0.s }, p0, [x1, x8, lsl #2]
-; COMMON-NEXT: incb x8
-; COMMON-NEXT: str z1, [x9, #2, mul vl]
-; COMMON-NEXT: str z2, [x9, #3, mul vl]
-; COMMON-NEXT: cmp x8, #1, lsl #12 // =4096
-; COMMON-NEXT: str z3, [x9, #1, mul vl]
-; COMMON-NEXT: b.ne .LBB12_1
+; COMMON-NEXT: str z0, [x1, #2, mul vl]
+; COMMON-NEXT: str z1, [x1, #3, mul vl]
+; COMMON-NEXT: str z2, [x1]
+; COMMON-NEXT: str z3, [x1, #1, mul vl]
+; COMMON-NEXT: incb x1, all, mul #4
+; COMMON-NEXT: cbnz x8, .LBB12_1
; COMMON-NEXT: // %bb.2: // %exit
; COMMON-NEXT: ret
entry:
>From bad6c916c03a29c054feeeaaebb4e0d6b94f3259 Mon Sep 17 00:00:00 2001
From: Benjamin Maxwell <macdue at dueutil.tech>
Date: Sat, 3 Oct 2026 15:10:36 +0100
Subject: [PATCH 3/3] Update AArch64TargetTransformInfo.cpp
---
llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
index f5ed34231bc3f3..c4e1159b434472 100644
--- a/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
+++ b/llvm/lib/Target/AArch64/AArch64TargetTransformInfo.cpp
@@ -7463,7 +7463,7 @@ bool AArch64TTIImpl::isLegalAddressingMode(Type *Ty, GlobalValue *BaseGV,
if (!BaseGV && !BaseOffset && HasBaseReg && isa<ScalableVectorType>(Ty)) {
EVT VT = getTLI()->getValueType(DL, Ty);
uint64_t AccessNumBytes = VT.getStoreSize().getKnownMinValue();
- if (AccessNumBytes >= 16 && getTLI()->getTypeAction(Ty->getContext(), VT) ==
+ if (AccessNumBytes > 16 && getTLI()->getTypeAction(Ty->getContext(), VT) ==
TargetLowering::TypeSplitVector) {
EVT LegalVT = getTLI()->getLegalTypeToTransformTo(Ty->getContext(), VT);
uint64_t VecNumBytes = LegalVT.getStoreSize().getKnownMinValue();
More information about the llvm-commits
mailing list