[llvm] [RISCV][SLP] Precommit strided-load alignment tests (NFC) (PR #222863)
via llvm-commits
llvm-commits at lists.llvm.org
Fri Sep 11 00:14:23 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-transforms
Author: Kiva (imkiva)
<details>
<summary>Changes</summary>
Record SLP's current handling of adjacent load groups with different alignments on RV32 and RV64.
The RV64 strict-alignment case currently forms a widened i64 strided load with align 4 and a 28-byte stride. Mark this as a FIXME for the follow-up legality fix. Naturally aligned strided loads are also covered.
Precommit coverage for #<!-- -->222520.
---
Full diff: https://github.com/llvm/llvm-project/pull/222863.diff
1 Files Affected:
- (added) llvm/test/Transforms/SLPVectorizer/RISCV/strided-load-common-alignment.ll (+102)
``````````diff
diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/strided-load-common-alignment.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/strided-load-common-alignment.ll
new file mode 100644
index 0000000000000..81203dbb5a047
--- /dev/null
+++ b/llvm/test/Transforms/SLPVectorizer/RISCV/strided-load-common-alignment.ll
@@ -0,0 +1,102 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -S -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v,-unaligned-vector-mem < %s | FileCheck %s --check-prefix=RV64
+; RUN: opt -S -passes=slp-vectorizer -mtriple=riscv32 -mattr=+v,-unaligned-vector-mem < %s | FileCheck %s --check-prefix=RV32
+; RUN: opt -S -passes=slp-vectorizer -mtriple=riscv64 -mattr=+v,+unaligned-vector-mem < %s | FileCheck %s --check-prefix=UNALIGNED
+;
+; The first load's alignment does not describe every group. Widening each
+; adjacent pair to i64 would leave the group at byte offset 28 misaligned.
+; FIXME: Do not form an i64 strided load in the RV64 strict-alignment case.
+
+define void @gather_fields(ptr %base, ptr %out) {
+; RV64-LABEL: define void @gather_fields(
+; RV64-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0:[0-9]+]] {
+; RV64-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.experimental.vp.strided.load.v2i64.p0.i64(ptr align 4 [[BASE]], i64 28, <2 x i1> splat (i1 true), i32 2)
+; RV64-NEXT: [[TMP5:%.*]] = bitcast <2 x i64> [[TMP1]] to <4 x i32>
+; RV64-NEXT: [[TMP6:%.*]] = add <4 x i32> [[TMP5]], splat (i32 3)
+; RV64-NEXT: store <4 x i32> [[TMP6]], ptr [[OUT]], align 4
+; RV64-NEXT: ret void
+;
+; RV32-LABEL: define void @gather_fields(
+; RV32-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0:[0-9]+]] {
+; RV32-NEXT: [[P2:%.*]] = getelementptr inbounds i32, ptr [[BASE]], i64 7
+; RV32-NEXT: [[Q2:%.*]] = getelementptr inbounds i32, ptr [[OUT]], i64 2
+; RV32-NEXT: [[TMP1:%.*]] = load <2 x i32>, ptr [[BASE]], align 16
+; RV32-NEXT: [[TMP3:%.*]] = add <2 x i32> [[TMP1]], splat (i32 3)
+; RV32-NEXT: [[TMP2:%.*]] = load <2 x i32>, ptr [[P2]], align 4
+; RV32-NEXT: [[TMP4:%.*]] = add <2 x i32> [[TMP2]], splat (i32 3)
+; RV32-NEXT: store <2 x i32> [[TMP3]], ptr [[OUT]], align 4
+; RV32-NEXT: store <2 x i32> [[TMP4]], ptr [[Q2]], align 4
+; RV32-NEXT: ret void
+;
+; UNALIGNED-LABEL: define void @gather_fields(
+; UNALIGNED-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0:[0-9]+]] {
+; UNALIGNED-NEXT: [[TMP1:%.*]] = call <2 x i64> @llvm.experimental.vp.strided.load.v2i64.p0.i64(ptr align 4 [[BASE]], i64 28, <2 x i1> splat (i1 true), i32 2)
+; UNALIGNED-NEXT: [[TMP2:%.*]] = bitcast <2 x i64> [[TMP1]] to <4 x i32>
+; UNALIGNED-NEXT: [[TMP3:%.*]] = add <4 x i32> [[TMP2]], splat (i32 3)
+; UNALIGNED-NEXT: store <4 x i32> [[TMP3]], ptr [[OUT]], align 4
+; UNALIGNED-NEXT: ret void
+;
+ %p1 = getelementptr inbounds i32, ptr %base, i64 1
+ %p2 = getelementptr inbounds i32, ptr %base, i64 7
+ %p3 = getelementptr inbounds i32, ptr %base, i64 8
+ %a = load i32, ptr %base, align 16
+ %b = load i32, ptr %p1, align 4
+ %c = load i32, ptr %p2, align 4
+ %d = load i32, ptr %p3, align 16
+ %v0 = add i32 %a, 3
+ %v1 = add i32 %b, 3
+ %v2 = add i32 %c, 3
+ %v3 = add i32 %d, 3
+ %q1 = getelementptr inbounds i32, ptr %out, i64 1
+ %q2 = getelementptr inbounds i32, ptr %out, i64 2
+ %q3 = getelementptr inbounds i32, ptr %out, i64 3
+ store i32 %v0, ptr %out, align 4
+ store i32 %v1, ptr %q1, align 4
+ store i32 %v2, ptr %q2, align 4
+ store i32 %v3, ptr %q3, align 4
+ ret void
+}
+
+; Naturally aligned strided loads remain legal.
+define void @aligned_values(ptr %base, ptr %out) {
+; RV64-LABEL: define void @aligned_values(
+; RV64-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0]] {
+; RV64-NEXT: [[TMP1:%.*]] = call <4 x i64> @llvm.experimental.vp.strided.load.v4i64.p0.i64(ptr align 8 [[BASE]], i64 64, <4 x i1> splat (i1 true), i32 4)
+; RV64-NEXT: [[TMP2:%.*]] = add <4 x i64> [[TMP1]], splat (i64 3)
+; RV64-NEXT: store <4 x i64> [[TMP2]], ptr [[OUT]], align 8
+; RV64-NEXT: ret void
+;
+; RV32-LABEL: define void @aligned_values(
+; RV32-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0]] {
+; RV32-NEXT: [[TMP1:%.*]] = call <4 x i64> @llvm.experimental.vp.strided.load.v4i64.p0.i32(ptr align 8 [[BASE]], i32 64, <4 x i1> splat (i1 true), i32 4)
+; RV32-NEXT: [[TMP2:%.*]] = add <4 x i64> [[TMP1]], splat (i64 3)
+; RV32-NEXT: store <4 x i64> [[TMP2]], ptr [[OUT]], align 8
+; RV32-NEXT: ret void
+;
+; UNALIGNED-LABEL: define void @aligned_values(
+; UNALIGNED-SAME: ptr [[BASE:%.*]], ptr [[OUT:%.*]]) #[[ATTR0]] {
+; UNALIGNED-NEXT: [[TMP1:%.*]] = call <4 x i64> @llvm.experimental.vp.strided.load.v4i64.p0.i64(ptr align 8 [[BASE]], i64 64, <4 x i1> splat (i1 true), i32 4)
+; UNALIGNED-NEXT: [[TMP2:%.*]] = add <4 x i64> [[TMP1]], splat (i64 3)
+; UNALIGNED-NEXT: store <4 x i64> [[TMP2]], ptr [[OUT]], align 8
+; UNALIGNED-NEXT: ret void
+;
+ %p1 = getelementptr inbounds i64, ptr %base, i64 8
+ %p2 = getelementptr inbounds i64, ptr %base, i64 16
+ %p3 = getelementptr inbounds i64, ptr %base, i64 24
+ %a = load i64, ptr %base, align 16
+ %b = load i64, ptr %p1, align 8
+ %c = load i64, ptr %p2, align 8
+ %d = load i64, ptr %p3, align 8
+ %v0 = add i64 %a, 3
+ %v1 = add i64 %b, 3
+ %v2 = add i64 %c, 3
+ %v3 = add i64 %d, 3
+ %q1 = getelementptr inbounds i64, ptr %out, i64 1
+ %q2 = getelementptr inbounds i64, ptr %out, i64 2
+ %q3 = getelementptr inbounds i64, ptr %out, i64 3
+ store i64 %v0, ptr %out, align 8
+ store i64 %v1, ptr %q1, align 8
+ store i64 %v2, ptr %q2, align 8
+ store i64 %v3, ptr %q3, align 8
+ ret void
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/222863
More information about the llvm-commits
mailing list