[llvm] [LV] Avoid collapsing VF to zero when a loop has no memory ops or reductions (PR #216266)
Pengcheng Wang via llvm-commits
llvm-commits at lists.llvm.org
Sun Aug 16 21:01:49 PDT 2026
================
@@ -0,0 +1,53 @@
+; NOTE: Assertions have been autogenerated by utils/update_analyze_test_checks.py UTC_ARGS: --filter "The Smallest and Widest types" --filter "Selecting VF" --filter "Vectorization is possible but not beneficial" --version 6
+; REQUIRES: asserts
+; RUN: opt -passes=loop-vectorize -mtriple riscv64 -mattr=+v \
+; RUN: -debug-only=loop-vectorize -disable-output -S < %s 2>&1 | \
+; RUN: FileCheck %s --check-prefix=DEFAULT
+; RUN: opt -passes=loop-vectorize -mtriple riscv64 -mattr=+v \
+; RUN: -vectorizer-maximize-bandwidth \
+; RUN: -debug-only=loop-vectorize -disable-output -S < %s 2>&1 | \
+; RUN: FileCheck %s --check-prefix=MAXBW
+
+; This is an early-exit search loop with no loads/stores and no reductions, so
+; getSmallestAndWidestTypes() cannot observe any element type. The smallest type
+; is reported as equal to the widest type instead of the -1U sentinel, so the
+; max-bandwidth VF computation does not divide the register width by the
+; sentinel and collapse the VF to zero. With and without
+; -vectorizer-maximize-bandwidth we pick the same VF.
+
+define i32 @find_first_ge(i32 %n, i32 %target) {
+; DEFAULT-LABEL: 'find_first_ge'
+; DEFAULT: LV: The Smallest and Widest types: 8 / 8 bits.
+; DEFAULT: LV: Selecting VF: vscale x 16.
+;
+; MAXBW-LABEL: 'find_first_ge'
+; MAXBW: LV: The Smallest and Widest types: 8 / 8 bits.
+; MAXBW: LV: Selecting VF: vscale x 16.
+;
+entry:
+ %cmp.not = icmp eq i32 %n, 0
+ br i1 %cmp.not, label %cleanup, label %for.body
+
+for.body: ; preds = %entry, %for.inc
+ %i = phi i32 [ %inc, %for.inc ], [ 0, %entry ]
+ %shl = shl i32 %i, 1
+ %add = add i32 %shl, 512
+ %cmp1.not = icmp ult i32 %add, %target
+ br i1 %cmp1.not, label %for.inc, label %cleanup.loopexit
+
+for.inc: ; preds = %for.body
+ %inc = add nuw i32 %i, 1
+ %exitcond.not = icmp eq i32 %inc, %n
+ br i1 %exitcond.not, label %cleanup.loopexit, label %for.body
+
+cleanup.loopexit: ; preds = %for.body, %for.inc
+ %i.lcssa.ph = phi i32 [ %n, %for.inc ], [ %i, %for.body ]
+ %umin = tail call i32 @llvm.umin.i32(i32 %i.lcssa.ph, i32 %n)
+ br label %cleanup
+
+cleanup: ; preds = %cleanup.loopexit, %entry
+ %i.lcssa = phi i32 [ 0, %entry ], [ %umin, %cleanup.loopexit ]
+ ret i32 %i.lcssa
+}
----------------
wangpc-pp wrote:
Done. Renamed to `loop.header`/`loop.latch`/`%iv`/`%iv.next` and the early exit returns `%iv` directly.
https://github.com/llvm/llvm-project/pull/216266
More information about the llvm-commits
mailing list