[llvm] 326a132 - [LSR][AArch64] Precommit tests showing lack of `mul vl` addressing (NFC) (#200149)
via llvm-commits
llvm-commits at lists.llvm.org
Thu May 28 03:46:47 PDT 2026
Author: Benjamin Maxwell
Date: 2026-05-28T11:46:40+01:00
New Revision: 326a1320dc98be6ce17270a2138b76f2036aaa5e
URL: https://github.com/llvm/llvm-project/commit/326a1320dc98be6ce17270a2138b76f2036aaa5e
DIFF: https://github.com/llvm/llvm-project/commit/326a1320dc98be6ce17270a2138b76f2036aaa5e.diff
LOG: [LSR][AArch64] Precommit tests showing lack of `mul vl` addressing (NFC) (#200149)
These loops could be using `mul vl` addressing in the loop and use fewer
base registers and have a smaller loop setup.
Added:
Modified:
llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
Removed:
################################################################################
diff --git a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
index dd347a7a6519d..04b920c1232bc 100644
--- a/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
+++ b/llvm/test/Transforms/LoopStrengthReduce/AArch64/vscale-fixups.ll
@@ -426,4 +426,212 @@ for.exit:
ret void
}
+; In this test the accesses are offset by the vector length (i.e, #1, mul vl apart),
+; but include a non-trival SCEV expression for the base address.
+; The SCEV expressions for the accesses are:
+; %gep.part0 =
+; {(324 + (4 * (sext i32 (3 + (-1 * %3)<nsw> + %0) to i64))<nsw> + %ptr),+,(32 * vscale)<nuw><nsw>}<%vector.body>
+; %gep.part1 =
+; {(324 + (4 * (sext i32 (3 + (-1 * %3)<nsw> + %0) to i64))<nsw> + (16 * vscale)<nuw><nsw> + %ptr),+,(32 * vscale)<nuw><nsw>}
+; This test checks that LSR can extract the offset of `(16 * vscale)` from the
+; expression for %gep.part1 (and use mul vl addressing from a common base for
+; both loads and stores).
+define void @vscale_complex_base_address(ptr %ptr, i32 %0, i64 %n) local_unnamed_addr #0 {
+; BASE-LABEL: vscale_complex_base_address:
+; BASE: // %bb.0: // %entry
+; BASE-NEXT: mov w9, #21846 // =0x5556
+; BASE-NEXT: sub w8, w1, #1
+; BASE-NEXT: ptrue p0.s
+; BASE-NEXT: movk w9, #21845, lsl #16
+; BASE-NEXT: mov x10, xzr
+; BASE-NEXT: smull x8, w8, w9
+; BASE-NEXT: lsr x9, x8, #32
+; BASE-NEXT: add x8, x9, x8, lsr #63
+; BASE-NEXT: add w8, w8, w8, lsl #1
+; BASE-NEXT: add w8, w8, #4
+; BASE-NEXT: add x8, x0, w8, sxtw #2
+; BASE-NEXT: add x8, x8, #324
+; BASE-NEXT: mov x9, x8
+; BASE-NEXT: incb x8
+; BASE-NEXT: .LBB7_1: // %vector.body
+; BASE-NEXT: // =>This Inner Loop Header: Depth=1
+; BASE-NEXT: ld1w { z0.s }, p0/z, [x9, x10, lsl #2]
+; BASE-NEXT: ld1w { z1.s }, p0/z, [x8, x10, lsl #2]
+; BASE-NEXT: sub z0.s, z0.s, #10 // =0xa
+; BASE-NEXT: sub z1.s, z1.s, #10 // =0xa
+; BASE-NEXT: st1w { z0.s }, p0, [x9, x10, lsl #2]
+; BASE-NEXT: st1w { z1.s }, p0, [x8, x10, lsl #2]
+; BASE-NEXT: inch x10
+; BASE-NEXT: cmp x2, x10
+; BASE-NEXT: b.ne .LBB7_1
+; BASE-NEXT: // %bb.2: // %exit
+; BASE-NEXT: ret
+;
+; PREINDEX-LABEL: vscale_complex_base_address:
+; PREINDEX: // %bb.0: // %entry
+; PREINDEX-NEXT: mov w9, #21846 // =0x5556
+; PREINDEX-NEXT: sub w8, w1, #1
+; PREINDEX-NEXT: ptrue p0.s
+; PREINDEX-NEXT: movk w9, #21845, lsl #16
+; PREINDEX-NEXT: mov x10, xzr
+; PREINDEX-NEXT: smull x8, w8, w9
+; PREINDEX-NEXT: lsr x9, x8, #32
+; PREINDEX-NEXT: add x8, x9, x8, lsr #63
+; PREINDEX-NEXT: add w8, w8, w8, lsl #1
+; PREINDEX-NEXT: add w8, w8, #4
+; PREINDEX-NEXT: add x8, x0, w8, sxtw #2
+; PREINDEX-NEXT: add x8, x8, #324
+; PREINDEX-NEXT: mov x9, x8
+; PREINDEX-NEXT: incb x8
+; PREINDEX-NEXT: .LBB7_1: // %vector.body
+; PREINDEX-NEXT: // =>This Inner Loop Header: Depth=1
+; PREINDEX-NEXT: ld1w { z0.s }, p0/z, [x9, x10, lsl #2]
+; PREINDEX-NEXT: ld1w { z1.s }, p0/z, [x8, x10, lsl #2]
+; PREINDEX-NEXT: sub z0.s, z0.s, #10 // =0xa
+; PREINDEX-NEXT: sub z1.s, z1.s, #10 // =0xa
+; PREINDEX-NEXT: st1w { z0.s }, p0, [x9, x10, lsl #2]
+; PREINDEX-NEXT: st1w { z1.s }, p0, [x8, x10, lsl #2]
+; PREINDEX-NEXT: inch x10
+; PREINDEX-NEXT: cmp x2, x10
+; PREINDEX-NEXT: b.ne .LBB7_1
+; PREINDEX-NEXT: // %bb.2: // %exit
+; PREINDEX-NEXT: ret
+;
+; POSTINDEX-LABEL: vscale_complex_base_address:
+; POSTINDEX: // %bb.0: // %entry
+; POSTINDEX-NEXT: mov w10, #21846 // =0x5556
+; POSTINDEX-NEXT: sub w9, w1, #1
+; POSTINDEX-NEXT: add x11, x0, #324
+; POSTINDEX-NEXT: movk w10, #21845, lsl #16
+; POSTINDEX-NEXT: ptrue p0.s
+; POSTINDEX-NEXT: mov x8, xzr
+; POSTINDEX-NEXT: smull x9, w9, w10
+; POSTINDEX-NEXT: lsr x10, x9, #32
+; POSTINDEX-NEXT: add x9, x10, x9, lsr #63
+; POSTINDEX-NEXT: add w9, w9, w9, lsl #1
+; POSTINDEX-NEXT: add w9, w9, #4
+; POSTINDEX-NEXT: sbfiz x10, x9, #2, #32
+; POSTINDEX-NEXT: add x9, x11, x10
+; POSTINDEX-NEXT: incb x10
+; POSTINDEX-NEXT: add x10, x11, x10
+; POSTINDEX-NEXT: .LBB7_1: // %vector.body
+; POSTINDEX-NEXT: // =>This Inner Loop Header: Depth=1
+; POSTINDEX-NEXT: ld1w { z0.s }, p0/z, [x9, x8, lsl #2]
+; POSTINDEX-NEXT: ld1w { z1.s }, p0/z, [x10, x8, lsl #2]
+; POSTINDEX-NEXT: sub z0.s, z0.s, #10 // =0xa
+; POSTINDEX-NEXT: sub z1.s, z1.s, #10 // =0xa
+; POSTINDEX-NEXT: st1w { z0.s }, p0, [x9, x8, lsl #2]
+; POSTINDEX-NEXT: st1w { z1.s }, p0, [x10, x8, lsl #2]
+; POSTINDEX-NEXT: inch x8
+; POSTINDEX-NEXT: cmp x2, x8
+; POSTINDEX-NEXT: b.ne .LBB7_1
+; POSTINDEX-NEXT: // %bb.2: // %exit
+; POSTINDEX-NEXT: ret
+entry:
+ %1 = add i32 %0, 3
+ %2 = add i32 %0, -1
+ %3 = srem i32 %2, 3
+ %4 = sub i32 %1, %3
+ %5 = sext i32 %4 to i64
+ %ptr.offset = getelementptr inbounds nuw i8, ptr %ptr, i64 324
+ %complex.base = getelementptr [4 x i8], ptr %ptr.offset, i64 %5
+ %vscale = tail call i64 @llvm.vscale.i64()
+ %VFxUF = shl nuw i64 %vscale, 3
+ %off = shl i64 %vscale, 4
+ br label %vector.body
+
+vector.body:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %vector.body ]
+ %gep.part0 = getelementptr [4 x i8], ptr %complex.base, i64 %iv
+ %gep.part1 = getelementptr i8, ptr %gep.part0, i64 %off
+ %data = load <vscale x 4 x i32>, ptr %gep.part0, align 4
+ %data2 = load <vscale x 4 x i32>, ptr %gep.part1, align 4
+ %add = add <vscale x 4 x i32> %data, splat (i32 -10)
+ %add2 = add <vscale x 4 x i32> %data2, splat (i32 -10)
+ store <vscale x 4 x i32> %add, ptr %gep.part0, align 4
+ store <vscale x 4 x i32> %add2, ptr %gep.part1, align 4
+ %iv.next = add nuw i64 %iv, %VFxUF
+ %exit.cond = icmp eq i64 %iv.next, %n
+ br i1 %exit.cond, label %exit, label %vector.body
+
+exit:
+ ret void
+}
+
+; Tests a simple memcpy-like routine where source and destination accesses are
+; offset by 8 bytes. That is the SCEV expression for any load/store is:
+; {(8 + ((16 * offset) * vscale) + %dst)<nuw>,+,(64 * vscale)}
+; where `offset` is 0, 1, 2, or 3. This should use be able to use `mul vl`
+; addressing (with the offset of 8 moved out of the loop).
+define void @offset_memcpy(ptr %src, ptr %dst, i64 %n.vec) "target-cpu"="neoverse-v2" nounwind {
+; COMMON-LABEL: offset_memcpy:
+; COMMON: // %bb.0: // %entry
+; COMMON-NEXT: rdvl x11, #3
+; COMMON-NEXT: rdvl x12, #2
+; COMMON-NEXT: add x10, x1, #8
+; COMMON-NEXT: add x17, x0, #8
+; COMMON-NEXT: mov x8, xzr
+; COMMON-NEXT: orr x14, x11, #0x8
+; COMMON-NEXT: rdvl x13, #1
+; COMMON-NEXT: cnth x9
+; COMMON-NEXT: orr x15, x12, #0x8
+; COMMON-NEXT: orr x16, x13, #0x8
+; COMMON-NEXT: ptrue p0.d
+; COMMON-NEXT: add x11, x1, x14
+; COMMON-NEXT: add x12, x1, x15
+; COMMON-NEXT: add x13, x1, x16
+; COMMON-NEXT: add x14, x0, x14
+; COMMON-NEXT: add x15, x0, x15
+; COMMON-NEXT: add x16, x0, x16
+; COMMON-NEXT: .p2align 5, , 16
+; COMMON-NEXT: .LBB8_1: // %vector.body
+; COMMON-NEXT: // =>This Inner Loop Header: Depth=1
+; COMMON-NEXT: ld1d { z0.d }, p0/z, [x17, x8, lsl #3]
+; COMMON-NEXT: ld1d { z1.d }, p0/z, [x16, x8, lsl #3]
+; COMMON-NEXT: ld1d { z2.d }, p0/z, [x15, x8, lsl #3]
+; COMMON-NEXT: ld1d { z3.d }, p0/z, [x14, x8, lsl #3]
+; COMMON-NEXT: st1d { z0.d }, p0, [x10, x8, lsl #3]
+; COMMON-NEXT: st1d { z1.d }, p0, [x13, x8, lsl #3]
+; COMMON-NEXT: st1d { z2.d }, p0, [x12, x8, lsl #3]
+; COMMON-NEXT: st1d { z3.d }, p0, [x11, x8, lsl #3]
+; COMMON-NEXT: add x8, x8, x9
+; COMMON-NEXT: cmp x2, x8
+; COMMON-NEXT: b.ne .LBB8_1
+; COMMON-NEXT: // %bb.2: // %exit
+; COMMON-NEXT: ret
+entry:
+ %7 = call i64 @llvm.vscale.i64()
+ %8 = shl nuw i64 %7, 1
+ %9 = shl nuw i64 %8, 2
+ br label %vector.body
+
+vector.body:
+ %index = phi i64 [ 0, %entry ], [ %index.next, %vector.body ]
+ %11 = add i64 1, %index
+ %12 = getelementptr inbounds nuw [8 x i8], ptr %src, i64 %11
+ %13 = shl nuw nsw i64 %8, 1
+ %14 = mul nuw nsw i64 %8, 3
+ %15 = getelementptr inbounds nuw ptr, ptr %12, i64 %8
+ %16 = getelementptr inbounds nuw ptr, ptr %12, i64 %13
+ %17 = getelementptr inbounds nuw ptr, ptr %12, i64 %14
+ %wide.load = load <vscale x 2 x ptr>, ptr %12, align 8
+ %wide.load3 = load <vscale x 2 x ptr>, ptr %15, align 8
+ %wide.load4 = load <vscale x 2 x ptr>, ptr %16, align 8
+ %wide.load5 = load <vscale x 2 x ptr>, ptr %17, align 8
+ %18 = getelementptr inbounds nuw [8 x i8], ptr %dst, i64 %11
+ %19 = getelementptr inbounds nuw ptr, ptr %18, i64 %8
+ %20 = getelementptr inbounds nuw ptr, ptr %18, i64 %13
+ %21 = getelementptr inbounds nuw ptr, ptr %18, i64 %14
+ store <vscale x 2 x ptr> %wide.load, ptr %18, align 8
+ store <vscale x 2 x ptr> %wide.load3, ptr %19, align 8
+ store <vscale x 2 x ptr> %wide.load4, ptr %20, align 8
+ store <vscale x 2 x ptr> %wide.load5, ptr %21, align 8
+ %index.next = add nuw i64 %index, %9
+ %22 = icmp eq i64 %index.next, %n.vec
+ br i1 %22, label %exit, label %vector.body
+
+exit:
+ ret void
+}
+
attributes #0 = { "target-features"="+sve2" vscale_range(1,16) }
More information about the llvm-commits
mailing list