Skip to content

Commit 04cd069

Browse files
authored
[SCEV] Use context sensitive reasoning in howFarToZero (#94525)
This change builds on 0a357ad which supported non-constant strides in howFarToZero, but used only context insensitive reasoning. This change does two things: 1) Directly use context sensitive queries to prove facts established before the loop. Note that we technically only need facts known at the latch, but using facts known on entry is a conservative approximation which will cover most everything. 2) For the non-zero check, we can usually prove non-zero from the finite assumption implied by mustprogress. This eliminates the need to do the context sensitive query in the common case.
1 parent f7c96d5 commit 04cd069

File tree

3 files changed

+39
-32
lines changed

3 files changed

+39
-32
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10485,16 +10485,19 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
1048510485
const SCEV *Step = getSCEVAtScope(AddRec->getOperand(1), L->getParentLoop());
1048610486
const SCEVConstant *StepC = dyn_cast<SCEVConstant>(Step);
1048710487

10488-
if (!isLoopInvariant(Step, L) || !isKnownNonZero(Step))
10488+
if (!isLoopInvariant(Step, L))
1048910489
return getCouldNotCompute();
1049010490

10491+
// Specialize step for this loop so we get context sensitive facts below.
10492+
const SCEV *StepWLG = applyLoopGuards(Step, L);
10493+
1049110494
// For positive steps (counting up until unsigned overflow):
1049210495
// N = -Start/Step (as unsigned)
1049310496
// For negative steps (counting down to zero):
1049410497
// N = Start/-Step
1049510498
// First compute the unsigned distance from zero in the direction of Step.
10496-
bool CountDown = isKnownNegative(Step);
10497-
if (!CountDown && !isKnownNonNegative(Step))
10499+
bool CountDown = isKnownNegative(StepWLG);
10500+
if (!CountDown && !isKnownNonNegative(StepWLG))
1049810501
return getCouldNotCompute();
1049910502

1050010503
const SCEV *Distance = CountDown ? Start : getNegativeSCEV(Start);
@@ -10533,6 +10536,13 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
1053310536
// will have undefined behavior due to wrapping.
1053410537
if (ControlsOnlyExit && AddRec->hasNoSelfWrap() &&
1053510538
loopHasNoAbnormalExits(AddRec->getLoop())) {
10539+
10540+
// If the stride is zero, the loop must be infinite. In C++, most loops
10541+
// are finite by assumption, in which case the step being zero implies
10542+
// UB must execute if the loop is entered.
10543+
if (!loopIsFiniteByAssumption(L) && !isKnownNonZero(StepWLG))
10544+
return getCouldNotCompute();
10545+
1053610546
const SCEV *Exact =
1053710547
getUDivExpr(Distance, CountDown ? getNegativeSCEV(Step) : Step);
1053810548
const SCEV *ConstantMax = getCouldNotCompute();
@@ -10547,7 +10557,7 @@ ScalarEvolution::ExitLimit ScalarEvolution::howFarToZero(const SCEV *V,
1054710557
}
1054810558

1054910559
// Solve the general equation.
10550-
if (!StepC)
10560+
if (!StepC || StepC->getValue()->isZero())
1055110561
return getCouldNotCompute();
1055210562
const SCEV *E = SolveLinEquationWithOverflow(StepC->getAPInt(),
1055310563
getNegativeSCEV(Start), *this);

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

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -271,9 +271,10 @@ define void @ne_nsw_pos_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
271271
;
272272
; CHECK-LABEL: 'ne_nsw_pos_step'
273273
; CHECK-NEXT: Determining loop execution counts for: @ne_nsw_pos_step
274-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
275-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
276-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
274+
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %s) + %n) /u %s)
275+
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -1
276+
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %s) + %n) /u %s)
277+
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
277278
;
278279
entry:
279280
%pos_step = icmp sgt i32 %s, 0
@@ -299,9 +300,10 @@ define void @ne_nsw_neg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
299300
;
300301
; CHECK-LABEL: 'ne_nsw_neg_step'
301302
; CHECK-NEXT: Determining loop execution counts for: @ne_nsw_neg_step
302-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
303-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
304-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
303+
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %n) + %s) /u (-1 * %s))
304+
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -2
305+
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %n) + %s) /u (-1 * %s))
306+
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
305307
;
306308
entry:
307309
%neg_step = icmp slt i32 %s, 0
@@ -327,9 +329,10 @@ define void @ne_nsw_nonneg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
327329
;
328330
; CHECK-LABEL: 'ne_nsw_nonneg_step'
329331
; CHECK-NEXT: Determining loop execution counts for: @ne_nsw_nonneg_step
330-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
331-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
332-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
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
333336
;
334337
entry:
335338
%nonneg_step = icmp sge i32 %s, 0
@@ -381,9 +384,10 @@ define void @ne_nuw_pos_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
381384
;
382385
; CHECK-LABEL: 'ne_nuw_pos_step'
383386
; CHECK-NEXT: Determining loop execution counts for: @ne_nuw_pos_step
384-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
385-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
386-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
387+
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %s) + %n) /u %s)
388+
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -1
389+
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %s) + %n) /u %s)
390+
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
387391
;
388392
entry:
389393
%pos_step = icmp sgt i32 %s, 0
@@ -409,9 +413,10 @@ define void @ne_nuw_neg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
409413
;
410414
; CHECK-LABEL: 'ne_nuw_neg_step'
411415
; CHECK-NEXT: Determining loop execution counts for: @ne_nuw_neg_step
412-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
413-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
414-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
416+
; CHECK-NEXT: Loop %for.body: backedge-taken count is (((-1 * %n) + %s) /u (-1 * %s))
417+
; CHECK-NEXT: Loop %for.body: constant max backedge-taken count is i32 -2
418+
; CHECK-NEXT: Loop %for.body: symbolic max backedge-taken count is (((-1 * %n) + %s) /u (-1 * %s))
419+
; CHECK-NEXT: Loop %for.body: Trip multiple is 1
415420
;
416421
entry:
417422
%neg_step = icmp slt i32 %s, 0
@@ -437,9 +442,10 @@ define void @ne_nuw_nonneg_step(ptr nocapture %A, i32 %n, i32 %s) mustprogress {
437442
;
438443
; CHECK-LABEL: 'ne_nuw_nonneg_step'
439444
; CHECK-NEXT: Determining loop execution counts for: @ne_nuw_nonneg_step
440-
; CHECK-NEXT: Loop %for.body: Unpredictable backedge-taken count.
441-
; CHECK-NEXT: Loop %for.body: Unpredictable constant max backedge-taken count.
442-
; CHECK-NEXT: Loop %for.body: Unpredictable symbolic max backedge-taken count.
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
443449
;
444450
entry:
445451
%nonneg_step = icmp sge i32 %s, 0

llvm/test/Transforms/LoopRotate/pr56260.ll

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,7 @@ define void @main() {
1717
; CHECK-NEXT: [[TOBOOL3_NOT1:%.*]] = icmp eq i32 [[INC]], 0
1818
; CHECK-NEXT: br i1 [[TOBOOL3_NOT1]], label [[L0_PREHEADER_LOOPEXIT]], label [[L1_PREHEADER_LR_PH:%.*]]
1919
; CHECK: L1.preheader.lr.ph:
20-
; CHECK-NEXT: br label [[L1_PREHEADER:%.*]]
21-
; CHECK: L1.preheader:
22-
; CHECK-NEXT: [[SPEC_SELECT3:%.*]] = phi i32 [ [[INC]], [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT:%.*]], [[L0_LATCH:%.*]] ]
23-
; CHECK-NEXT: [[K_02:%.*]] = phi i32 [ 0, [[L1_PREHEADER_LR_PH]] ], [ [[SPEC_SELECT3]], [[L0_LATCH]] ]
24-
; CHECK-NEXT: [[TOBOOL8_NOT:%.*]] = icmp eq i32 [[K_02]], 0
25-
; CHECK-NEXT: br label [[L0_LATCH]]
26-
; CHECK: L0.latch:
27-
; CHECK-NEXT: [[SPEC_SELECT]] = add nsw i32 [[SPEC_SELECT3]], [[INC]]
28-
; CHECK-NEXT: [[TOBOOL3_NOT:%.*]] = icmp eq i32 [[SPEC_SELECT]], 0
29-
; CHECK-NEXT: br i1 [[TOBOOL3_NOT]], label [[L0_L0_PREHEADER_LOOPEXIT_CRIT_EDGE:%.*]], label [[L1_PREHEADER]]
20+
; CHECK-NEXT: br label [[L0_L0_PREHEADER_LOOPEXIT_CRIT_EDGE:%.*]]
3021
;
3122
entry:
3223
br label %L0.preheader

0 commit comments

Comments
 (0)