[llvm] [LV] Add more tests with low trip counts. (NFC) (PR #226298)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Thu Sep 24 14:08:20 PDT 2026
https://github.com/fhahn created https://github.com/llvm/llvm-project/pull/226298
Add additional tests with low trip counts where TC == VF.
>From 03f6a3ccdb4c813cff7664ad09dea96ee29963ac Mon Sep 17 00:00:00 2001
From: Florian Hahn <flo at fhahn.com>
Date: Tue, 22 Sep 2026 22:57:04 +0000
Subject: [PATCH] [LV] Add more tests with low trip counts. (NFC)
Add additional tests with low trip counts where TC == VF.
---
.../AArch64/sve-low-trip-count.ll | 75 ++++++++++++++++
.../RISCV/countable-early-exit-no-epilogue.ll | 87 +++++++++++++++++++
.../LoopVectorize/RISCV/short-trip-count.ll | 38 ++++----
3 files changed, 182 insertions(+), 18 deletions(-)
diff --git a/llvm/test/Transforms/LoopVectorize/AArch64/sve-low-trip-count.ll b/llvm/test/Transforms/LoopVectorize/AArch64/sve-low-trip-count.ll
index db84daf324337..be740c8f0fa16 100644
--- a/llvm/test/Transforms/LoopVectorize/AArch64/sve-low-trip-count.ll
+++ b/llvm/test/Transforms/LoopVectorize/AArch64/sve-low-trip-count.ll
@@ -615,6 +615,81 @@ exit:
ret void
}
+define void @tc4_vf4(ptr noalias %a, ptr noalias %b) #0 {
+; CHECK-LABEL: define void @tc4_vf4(
+; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
+; CHECK: [[VECTOR_PH]]:
+; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
+; CHECK: [[VECTOR_BODY]]:
+; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <4 x i32>, ptr [[A]], align 4
+; CHECK-NEXT: [[TMP0:%.*]] = add nsw <4 x i32> [[WIDE_LOAD]], splat (i32 1)
+; CHECK-NEXT: store <4 x i32> [[TMP0]], ptr [[B]], align 4
+; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]
+; CHECK: [[MIDDLE_BLOCK]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
+ %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
+ %val = load i32, ptr %gep.a, align 4
+ %add = add nsw i32 %val, 1
+ store i32 %add, ptr %gep.b, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond = icmp eq i64 %iv.next, 4
+ br i1 %exitcond, label %exit, label %loop
+
+exit:
+ ret void
+}
+
+define void @tc4_vf2_ic2(ptr noalias %a, ptr noalias %b) #0 {
+; CHECK-LABEL: define void @tc4_vf2_ic2(
+; CHECK-SAME: ptr noalias [[A:%.*]], ptr noalias [[B:%.*]]) #[[ATTR0]] {
+; CHECK-NEXT: [[ENTRY:.*:]]
+; CHECK-NEXT: br label %[[VECTOR_PH:.*]]
+; CHECK: [[VECTOR_PH]]:
+; CHECK-NEXT: br label %[[VECTOR_BODY:.*]]
+; CHECK: [[VECTOR_BODY]]:
+; CHECK-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 2
+; CHECK-NEXT: [[WIDE_LOAD:%.*]] = load <2 x i32>, ptr [[A]], align 4
+; CHECK-NEXT: [[WIDE_LOAD1:%.*]] = load <2 x i32>, ptr [[TMP0]], align 4
+; CHECK-NEXT: [[TMP1:%.*]] = add nsw <2 x i32> [[WIDE_LOAD]], splat (i32 1)
+; CHECK-NEXT: [[TMP2:%.*]] = add nsw <2 x i32> [[WIDE_LOAD1]], splat (i32 1)
+; CHECK-NEXT: [[TMP3:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 2
+; CHECK-NEXT: store <2 x i32> [[TMP1]], ptr [[B]], align 4
+; CHECK-NEXT: store <2 x i32> [[TMP2]], ptr [[TMP3]], align 4
+; CHECK-NEXT: br label %[[MIDDLE_BLOCK:.*]]
+; CHECK: [[MIDDLE_BLOCK]]:
+; CHECK-NEXT: br label %[[EXIT:.*]]
+; CHECK: [[EXIT]]:
+; CHECK-NEXT: ret void
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %loop ]
+ %gep.a = getelementptr inbounds i32, ptr %a, i64 %iv
+ %gep.b = getelementptr inbounds i32, ptr %b, i64 %iv
+ %val = load i32, ptr %gep.a, align 4
+ %add = add nsw i32 %val, 1
+ store i32 %add, ptr %gep.b, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %exitcond = icmp eq i64 %iv.next, 4
+ br i1 %exitcond, label %exit, label %loop, !llvm.loop !0
+
+exit:
+ ret void
+}
+
attributes #0 = { vscale_range(1,16) "target-features"="+sve" }
attributes #1 = { vscale_range(1,16) "target-features"="+sve" minsize }
attributes #2 = { vscale_range(1,16) "target-features"="+sve" optsize }
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/countable-early-exit-no-epilogue.ll b/llvm/test/Transforms/LoopVectorize/RISCV/countable-early-exit-no-epilogue.ll
index 349a026cc1b4a..01cc2c2f7cff0 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/countable-early-exit-no-epilogue.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/countable-early-exit-no-epilogue.ll
@@ -74,3 +74,90 @@ exit1:
exit2:
ret i32 2
}
+
+; The trip count (5) is VF + 1. The final iteration, which takes the early exit,
+; must execute in the scalar loop.
+define i32 @countable_early_exit_tc_vf_plus_one(ptr noalias %b) {
+; NO-EPILOGUE-LABEL: define i32 @countable_early_exit_tc_vf_plus_one(
+; NO-EPILOGUE-SAME: ptr noalias [[B:%.*]]) #[[ATTR0]] {
+; NO-EPILOGUE-NEXT: [[ENTRY:.*:]]
+; NO-EPILOGUE-NEXT: br label %[[VECTOR_PH:.*]]
+; NO-EPILOGUE: [[VECTOR_PH]]:
+; NO-EPILOGUE-NEXT: br label %[[VECTOR_BODY:.*]]
+; NO-EPILOGUE: [[VECTOR_BODY]]:
+; NO-EPILOGUE-NEXT: store <4 x i32> splat (i32 1), ptr [[B]], align 4
+; NO-EPILOGUE-NEXT: br label %[[MIDDLE_BLOCK:.*]]
+; NO-EPILOGUE: [[MIDDLE_BLOCK]]:
+; NO-EPILOGUE-NEXT: br label %[[SCALAR_PH:.*]]
+; NO-EPILOGUE: [[SCALAR_PH]]:
+; NO-EPILOGUE-NEXT: br label %[[LOOP:.*]]
+; NO-EPILOGUE: [[LOOP]]:
+; NO-EPILOGUE-NEXT: [[IV:%.*]] = phi i64 [ 4, %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]
+; NO-EPILOGUE-NEXT: [[C:%.*]] = icmp eq i64 [[IV]], 4
+; NO-EPILOGUE-NEXT: br i1 [[C]], label %[[EXIT1:.*]], label %[[LATCH]]
+; NO-EPILOGUE: [[LATCH]]:
+; NO-EPILOGUE-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
+; NO-EPILOGUE-NEXT: store i32 1, ptr [[GEP]], align 4
+; NO-EPILOGUE-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; NO-EPILOGUE-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 100
+; NO-EPILOGUE-NEXT: br i1 [[EC]], label %[[EXIT2:.*]], label %[[LOOP]], !llvm.loop [[LOOP0:![0-9]+]]
+; NO-EPILOGUE: [[EXIT1]]:
+; NO-EPILOGUE-NEXT: ret i32 1
+; NO-EPILOGUE: [[EXIT2]]:
+; NO-EPILOGUE-NEXT: ret i32 2
+;
+; EPILOGUE-LABEL: define i32 @countable_early_exit_tc_vf_plus_one(
+; EPILOGUE-SAME: ptr noalias [[B:%.*]]) #[[ATTR0]] {
+; EPILOGUE-NEXT: [[ENTRY:.*:]]
+; EPILOGUE-NEXT: br label %[[VECTOR_PH:.*]]
+; EPILOGUE: [[VECTOR_PH]]:
+; EPILOGUE-NEXT: br label %[[VECTOR_BODY:.*]]
+; EPILOGUE: [[VECTOR_BODY]]:
+; EPILOGUE-NEXT: [[INDEX:%.*]] = phi i64 [ 0, %[[VECTOR_PH]] ], [ [[INDEX_NEXT:%.*]], %[[VECTOR_BODY]] ]
+; EPILOGUE-NEXT: [[TMP0:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[INDEX]]
+; EPILOGUE-NEXT: [[TMP1:%.*]] = getelementptr inbounds i32, ptr [[TMP0]], i64 2
+; EPILOGUE-NEXT: store <2 x i32> splat (i32 1), ptr [[TMP0]], align 4
+; EPILOGUE-NEXT: store <2 x i32> splat (i32 1), ptr [[TMP1]], align 4
+; EPILOGUE-NEXT: [[INDEX_NEXT]] = add nuw i64 [[INDEX]], 4
+; EPILOGUE-NEXT: [[TMP2:%.*]] = icmp eq i64 [[INDEX_NEXT]], 4
+; EPILOGUE-NEXT: br i1 [[TMP2]], label %[[MIDDLE_BLOCK:.*]], label %[[VECTOR_BODY]], !llvm.loop [[LOOP4:![0-9]+]]
+; EPILOGUE: [[MIDDLE_BLOCK]]:
+; EPILOGUE-NEXT: br label %[[SCALAR_PH:.*]]
+; EPILOGUE: [[SCALAR_PH]]:
+; EPILOGUE-NEXT: br label %[[LOOP:.*]]
+; EPILOGUE: [[LOOP]]:
+; EPILOGUE-NEXT: [[IV:%.*]] = phi i64 [ 4, %[[SCALAR_PH]] ], [ [[IV_NEXT:%.*]], %[[LATCH:.*]] ]
+; EPILOGUE-NEXT: [[C:%.*]] = icmp eq i64 [[IV]], 4
+; EPILOGUE-NEXT: br i1 [[C]], label %[[EXIT1:.*]], label %[[LATCH]]
+; EPILOGUE: [[LATCH]]:
+; EPILOGUE-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[B]], i64 [[IV]]
+; EPILOGUE-NEXT: store i32 1, ptr [[GEP]], align 4
+; EPILOGUE-NEXT: [[IV_NEXT]] = add nuw nsw i64 [[IV]], 1
+; EPILOGUE-NEXT: [[EC:%.*]] = icmp eq i64 [[IV_NEXT]], 100
+; EPILOGUE-NEXT: br i1 [[EC]], label %[[EXIT2:.*]], label %[[LOOP]], !llvm.loop [[LOOP5:![0-9]+]]
+; EPILOGUE: [[EXIT1]]:
+; EPILOGUE-NEXT: ret i32 1
+; EPILOGUE: [[EXIT2]]:
+; EPILOGUE-NEXT: ret i32 2
+;
+entry:
+ br label %loop
+
+loop:
+ %iv = phi i64 [ 0, %entry ], [ %iv.next, %latch ]
+ %c = icmp eq i64 %iv, 4
+ br i1 %c, label %exit1, label %latch
+
+latch:
+ %gep = getelementptr inbounds i32, ptr %b, i64 %iv
+ store i32 1, ptr %gep, align 4
+ %iv.next = add nuw nsw i64 %iv, 1
+ %ec = icmp eq i64 %iv.next, 100
+ br i1 %ec, label %exit2, label %loop
+
+exit1:
+ ret i32 1
+
+exit2:
+ ret i32 2
+}
diff --git a/llvm/test/Transforms/LoopVectorize/RISCV/short-trip-count.ll b/llvm/test/Transforms/LoopVectorize/RISCV/short-trip-count.ll
index 74675437fae51..b370fbe2da777 100644
--- a/llvm/test/Transforms/LoopVectorize/RISCV/short-trip-count.ll
+++ b/llvm/test/Transforms/LoopVectorize/RISCV/short-trip-count.ll
@@ -1,20 +1,21 @@
-; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
-; RUN: opt -S -mtriple=riscv64 -mattr=+zve32x -passes=loop-vectorize < %s | FileCheck %s
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 6
+; RUN: opt -mtriple=riscv64 -mattr=+zve32x -passes=loop-vectorize -S %s | FileCheck %s
define void @small_trip_count_min_vlen_128(ptr nocapture %a) vscale_range(4,1024) {
-; CHECK-LABEL: @small_trip_count_min_vlen_128(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[LOOP1:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP1]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[TMP1:%.*]], i32 [[IV]]
+; CHECK-LABEL: define void @small_trip_count_min_vlen_128(
+; CHECK-SAME: ptr captures(none) [[A:%.*]]) #[[ATTR0:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[IV]]
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[V]], 1
; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP]], align 4
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 3
-; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP1]]
-; CHECK: exit:
+; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
@@ -35,19 +36,20 @@ exit:
}
define void @small_trip_count_min_vlen_32(ptr nocapture %a) vscale_range(1,1024) {
-; CHECK-LABEL: @small_trip_count_min_vlen_32(
-; CHECK-NEXT: entry:
-; CHECK-NEXT: br label [[LOOP1:%.*]]
-; CHECK: loop:
-; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP1]] ], [ 0, [[ENTRY:%.*]] ]
-; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[TMP1:%.*]], i32 [[IV]]
+; CHECK-LABEL: define void @small_trip_count_min_vlen_32(
+; CHECK-SAME: ptr captures(none) [[A:%.*]]) #[[ATTR1:[0-9]+]] {
+; CHECK-NEXT: [[ENTRY:.*]]:
+; CHECK-NEXT: br label %[[LOOP:.*]]
+; CHECK: [[LOOP]]:
+; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], %[[LOOP]] ], [ 0, %[[ENTRY]] ]
+; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds i32, ptr [[A]], i32 [[IV]]
; CHECK-NEXT: [[V:%.*]] = load i32, ptr [[GEP]], align 4
; CHECK-NEXT: [[ADD:%.*]] = add nsw i32 [[V]], 1
; CHECK-NEXT: store i32 [[ADD]], ptr [[GEP]], align 4
; CHECK-NEXT: [[IV_NEXT]] = add i32 [[IV]], 1
; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 3
-; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[LOOP1]]
-; CHECK: exit:
+; CHECK-NEXT: br i1 [[COND]], label %[[EXIT:.*]], label %[[LOOP]]
+; CHECK: [[EXIT]]:
; CHECK-NEXT: ret void
;
entry:
More information about the llvm-commits
mailing list