Skip to content

Commit 2cc5362

Browse files
dtcxzywtstellar
authored andcommitted
[SCEV] Check whether the start is non-zero in ScalarEvolution::howFarToZero (llvm#131522)
llvm#94525 assumes that the loop will be infinite when the stride is zero. However, it doesn't hold when the start value of addrec is also zero. Closes llvm#131465. (cherry picked from commit c5a491e)
1 parent 0619bbc commit 2cc5362

File tree

3 files changed

+74
-12
lines changed

3 files changed

+74
-12
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -10635,10 +10635,11 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
1063510635
if (ControlsOnlyExit && AddRec->hasNoSelfWrap() &&
1063610636
loopHasNoAbnormalExits(AddRec->getLoop())) {
1063710637

10638-
// If the stride is zero, the loop must be infinite. In C++, most loops
10639-
// are finite by assumption, in which case the step being zero implies
10640-
// UB must execute if the loop is entered.
10641-
if (!loopIsFiniteByAssumption(L) && !isKnownNonZero(StepWLG))
10638+
// If the stride is zero and the start is non-zero, the loop must be
10639+
// infinite. In C++, most loops are finite by assumption, in which case the
10640+
// step being zero implies UB must execute if the loop is entered.
10641+
if (!(loopIsFiniteByAssumption(L) && isKnownNonZero(Start)) &&
10642+
!isKnownNonZero(StepWLG))
1064210643
return getCouldNotCompute();
1064310644

1064410645
const SCEV *Exact =

llvm/test/Analysis/ScalarEvolution/trip-count-unknown-stride.ll

+26-8
Original file line numberDiff line numberDiff line change
@@ -329,10 +329,9 @@ define void @ne_nsw_nonneg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
329329
;
330330
; CHECK-LABEL: 'ne_nsw_nonneg_step'
331331
; CHECK-NEXT: Determining loop execution counts for: @ne_nsw_nonneg_step
332-
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %s) + %n) /u %s)
333-
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -1
334-
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %s) + %n) /u %s)
335-
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
332+
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
333+
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
334+
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
336335
;
337336
entry:
338337
%nonneg_step = icmp sge i32 %s, 0
@@ -442,10 +441,9 @@ define void @ne_nuw_nonneg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
442441
;
443442
; CHECK-LABEL: 'ne_nuw_nonneg_step'
444443
; CHECK-NEXT: Determining loop execution counts for: @ne_nuw_nonneg_step
445-
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %s) + %n) /u %s)
446-
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -1
447-
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %s) + %n) /u %s)
448-
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
444+
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
445+
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
446+
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
449447
;
450448
entry:
451449
%nonneg_step = icmp sge i32 %s, 0
@@ -493,6 +491,26 @@ for.end: ; preds = %for.body, %entry
493491
ret void
494492
}
495493

494+
define i32 @pr131465(i1 %x) mustprogress {
495+
; CHECK-LABEL: 'pr131465'
496+
; CHECK-NEXT: Determining loop execution counts for: @pr131465
497+
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
498+
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
499+
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
500+
;
501+
entry:
502+
%inc = zext i1 %x to i32
503+
br label %for.body
504+
505+
for.body:
506+
%indvar = phi i32 [ 2, %entry ], [ %next, %for.body ]
507+
%next = add nsw i32 %indvar, %inc
508+
%exitcond = icmp eq i32 %next, 2
509+
br i1 %exitcond, label %for.end, label %for.body
510+
511+
for.end:
512+
ret i32 0
513+
}
496514

497515
declare void @llvm.assume(i1)
498516

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2+
; RUN: opt -S -passes=loop-unroll -unroll-runtime %s | FileCheck %s
3+
4+
define i32 @pr131465(i1 %x) mustprogress {
5+
; CHECK-LABEL: define i32 @pr131465(
6+
; CHECK-SAME: i1 [[X:%.*]]) #[[ATTR0:[0-9]+]] {
7+
; CHECK-NEXT: [[ENTRY:.*]]:
8+
; CHECK-NEXT: [[INC:%.*]] = zext i1 [[X]] to i32
9+
; CHECK-NEXT: br label %[[FOR_BODY:.*]]
10+
; CHECK: [[FOR_BODY]]:
11+
; CHECK-NEXT: [[INDVAR:%.*]] = phi i32 [ 2, %[[ENTRY]] ], [ [[NEXT_1:%.*]], %[[FOR_BODY_1:.*]] ]
12+
; CHECK-NEXT: [[NEXT:%.*]] = add nsw i32 [[INDVAR]], [[INC]]
13+
; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[NEXT]], 2
14+
; CHECK-NEXT: br i1 [[EXITCOND]], label %[[FOR_END:.*]], label %[[FOR_BODY_1]], !llvm.loop [[LOOP0:![0-9]+]]
15+
; CHECK: [[FOR_BODY_1]]:
16+
; CHECK-NEXT: [[NEXT_1]] = add nsw i32 [[NEXT]], [[INC]]
17+
; CHECK-NEXT: [[EXITCOND_1:%.*]] = icmp eq i32 [[NEXT_1]], 2
18+
; CHECK-NEXT: br i1 [[EXITCOND_1]], label %[[FOR_END]], label %[[FOR_BODY]], !llvm.loop [[LOOP2:![0-9]+]]
19+
; CHECK: [[FOR_END]]:
20+
; CHECK-NEXT: ret i32 0
21+
;
22+
entry:
23+
%inc = zext i1 %x to i32
24+
br label %for.body
25+
26+
for.body:
27+
%indvar = phi i32 [ 2, %entry ], [ %next, %for.body ]
28+
%next = add nsw i32 %indvar, %inc
29+
%exitcond = icmp eq i32 %next, 2
30+
br i1 %exitcond, label %for.end, label %for.body, !llvm.loop !0
31+
32+
for.end:
33+
ret i32 0
34+
}
35+
36+
; Force runtime unrolling.
37+
!0 = !{!0, !{!"llvm.loop.unroll.count", i32 2}}
38+
;.
39+
; CHECK: [[LOOP0]] = distinct !{[[LOOP0]], [[META1:![0-9]+]]}
40+
; CHECK: [[META1]] = !{!"llvm.loop.unroll.count", i32 2}
41+
; CHECK: [[LOOP2]] = distinct !{[[LOOP2]], [[META3:![0-9]+]]}
42+
; CHECK: [[META3]] = !{!"llvm.loop.unroll.disable"}
43+
;.

0 commit comments

Comments
 (0)