[llvm] [SLP][NFC] Add tests for runtime strided loads during revectorization (PR #191875)

via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 13 12:01:46 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-llvm-transforms

Author: Ryan Buchner (bababuck)

<details>
<summary>Changes</summary>

Depending on the case, we either miss optimizing re-vectorized runtime strided loads (and use a gather instead) or produces the incorrect strided load.

---
Full diff: https://github.com/llvm/llvm-project/pull/191875.diff


1 Files Affected:

- (modified) llvm/test/Transforms/SLPVectorizer/RISCV/revec-strided-load.ll (+101) 


``````````diff
diff --git a/llvm/test/Transforms/SLPVectorizer/RISCV/revec-strided-load.ll b/llvm/test/Transforms/SLPVectorizer/RISCV/revec-strided-load.ll
index 6d62659c2fef1..33c7858ee701d 100644
--- a/llvm/test/Transforms/SLPVectorizer/RISCV/revec-strided-load.ll
+++ b/llvm/test/Transforms/SLPVectorizer/RISCV/revec-strided-load.ll
@@ -20,6 +20,55 @@ entry:
   ret void
 }
 
+define void @widened_strided_load_runtime(ptr %in0, ptr %out0, i64 %stride) {
+; CHECK-LABEL: @widened_strided_load_runtime(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[IN1:%.*]] = getelementptr <8 x i8>, ptr [[IN0:%.*]], i64 [[STRIDE:%.*]]
+; CHECK-NEXT:    [[L0:%.*]] = load <8 x i8>, ptr [[IN0]], align 2
+; CHECK-NEXT:    [[L1:%.*]] = load <8 x i8>, ptr [[IN1]], align 2
+; CHECK-NEXT:    [[TMP0:%.*]] = shufflevector <8 x i8> [[L0]], <8 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i8> [[L1]], <8 x i8> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <16 x i8> [[TMP0]], <16 x i8> [[TMP1]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23>
+; CHECK-NEXT:    store <16 x i8> [[TMP2]], ptr [[OUT0:%.*]], align 2
+; CHECK-NEXT:    ret void
+;
+entry:
+  %in1 = getelementptr <8 x i8>, ptr %in0, i64 %stride
+  %l0 = load <8 x i8>, ptr %in0, align 2
+  %l1 = load <8 x i8>, ptr %in1, align 2
+  %out1 = getelementptr i8, ptr %out0, i64 8
+  store <8 x i8> %l0, ptr %out0, align 2
+  store <8 x i8> %l1, ptr %out1, align 2
+  ret void
+}
+
+; Base case of strided load, implicitly is widened
+define void @widened_strided_load_runtime_more_elements(ptr %in0, ptr %out0, i64 %stride) {
+; CHECK-LABEL: @widened_strided_load_runtime_more_elements(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[TMP0:%.*]] = mul i64 [[STRIDE:%.*]], 2
+; CHECK-NEXT:    [[TMP1:%.*]] = call <8 x i8> @llvm.experimental.vp.strided.load.v8i8.p0.i64(ptr align 2 [[IN0:%.*]], i64 [[TMP0]], <8 x i1> splat (i1 true), i32 8)
+; CHECK-NEXT:    store <8 x i8> [[TMP1]], ptr [[OUT0:%.*]], align 2
+; CHECK-NEXT:    ret void
+;
+entry:
+  %in1 = getelementptr <2 x i8>, ptr %in0, i64 %stride
+  %in2 = getelementptr <2 x i8>, ptr %in1, i64 %stride
+  %in3 = getelementptr <2 x i8>, ptr %in2, i64 %stride
+  %l0 = load <2 x i8>, ptr %in0, align 2
+  %l1 = load <2 x i8>, ptr %in1, align 2
+  %l2 = load <2 x i8>, ptr %in2, align 2
+  %l3 = load <2 x i8>, ptr %in3, align 2
+  %out1 = getelementptr i8, ptr %out0, i64 2
+  %out2 = getelementptr i8, ptr %out0, i64 4
+  %out3 = getelementptr i8, ptr %out0, i64 6
+  store <2 x i8> %l0, ptr %out0, align 2
+  store <2 x i8> %l1, ptr %out1, align 2
+  store <2 x i8> %l2, ptr %out2, align 2
+  store <2 x i8> %l3, ptr %out3, align 2
+  ret void
+}
+
 ; Widened strided load pattern but vectorized types
 define void @doubly_widened_strided_load(ptr %in0, ptr %out0) {
 ; CHECK-LABEL: @doubly_widened_strided_load(
@@ -47,6 +96,36 @@ entry:
   ret void
 }
 
+define void @doubly_widened_strided_load_runtime(ptr %in0, ptr %out0, i64 %stride) {
+; CHECK-LABEL: @doubly_widened_strided_load_runtime(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[IN2:%.*]] = getelementptr <2 x i8>, ptr [[IN0:%.*]], i64 [[STRIDE:%.*]]
+; CHECK-NEXT:    [[TMP0:%.*]] = load <4 x i8>, ptr [[IN0]], align 2
+; CHECK-NEXT:    [[TMP1:%.*]] = load <4 x i8>, ptr [[IN2]], align 2
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP3:%.*]] = shufflevector <4 x i8> [[TMP1]], <4 x i8> poison, <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP4:%.*]] = shufflevector <4 x i8> [[TMP0]], <4 x i8> [[TMP1]], <8 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7>
+; CHECK-NEXT:    store <8 x i8> [[TMP4]], ptr [[OUT0:%.*]], align 2
+; CHECK-NEXT:    ret void
+;
+entry:
+  %in1 = getelementptr <2 x i8>, ptr %in0, i64 1
+  %in2 = getelementptr <2 x i8>, ptr %in0, i64 %stride
+  %in3 = getelementptr <2 x i8>, ptr %in2, i64 1
+  %l0 = load <2 x i8>, ptr %in0, align 2
+  %l1 = load <2 x i8>, ptr %in1, align 2
+  %l2 = load <2 x i8>, ptr %in2, align 2
+  %l3 = load <2 x i8>, ptr %in3, align 2
+  %out1 = getelementptr i8, ptr %out0, i64 2
+  %out2 = getelementptr i8, ptr %out0, i64 4
+  %out3 = getelementptr i8, ptr %out0, i64 6
+  store <2 x i8> %l0, ptr %out0, align 2
+  store <2 x i8> %l1, ptr %out1, align 2
+  store <2 x i8> %l2, ptr %out2, align 2
+  store <2 x i8> %l3, ptr %out3, align 2
+  ret void
+}
+
 ; The resulting widened type isn't legal
 define void @too_wide(ptr %in0, ptr %out0) {
 ; CHECK-LABEL: @too_wide(
@@ -70,6 +149,28 @@ entry:
   ret void
 }
 
+define void @too_wide_runtime(ptr %in0, ptr %out0, i64 %stride) {
+; CHECK-LABEL: @too_wide_runtime(
+; CHECK-NEXT:  entry:
+; CHECK-NEXT:    [[IN1:%.*]] = getelementptr <8 x i16>, ptr [[IN0:%.*]], i64 [[STRIDE:%.*]]
+; CHECK-NEXT:    [[L0:%.*]] = load <8 x i16>, ptr [[IN0]], align 2
+; CHECK-NEXT:    [[L1:%.*]] = load <8 x i16>, ptr [[IN1]], align 2
+; CHECK-NEXT:    [[TMP0:%.*]] = shufflevector <8 x i16> [[L0]], <8 x i16> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <8 x i16> [[L1]], <8 x i16> poison, <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison, i32 poison>
+; CHECK-NEXT:    [[TMP2:%.*]] = shufflevector <16 x i16> [[TMP0]], <16 x i16> [[TMP1]], <16 x i32> <i32 0, i32 1, i32 2, i32 3, i32 4, i32 5, i32 6, i32 7, i32 16, i32 17, i32 18, i32 19, i32 20, i32 21, i32 22, i32 23>
+; CHECK-NEXT:    store <16 x i16> [[TMP2]], ptr [[OUT0:%.*]], align 2
+; CHECK-NEXT:    ret void
+;
+entry:
+  %in1 = getelementptr <8 x i16>, ptr %in0, i64 %stride
+  %l0 = load <8 x i16>, ptr %in0, align 2
+  %l1 = load <8 x i16>, ptr %in1, align 2
+  %out1 = getelementptr i16, ptr %out0, i64 8
+  store <8 x i16> %l0, ptr %out0, align 2
+  store <8 x i16> %l1, ptr %out1, align 2
+  ret void
+}
+
 ; Stride size isn't aligned to the vector size
 define void @non_aligned_stride(ptr %in0, ptr %out0) {
 ; CHECK-LABEL: @non_aligned_stride(

``````````

</details>


https://github.com/llvm/llvm-project/pull/191875


More information about the llvm-commits mailing list