[LoopDeletion] Revert 3af8a11 and add test coverage for breakage

This reverts 3af8a11 because I'd used an upper bound where an lower bound was required.  The included reduced test case demonstrates the issue.
This commit is contained in:
Philip Reames 2022-01-17 11:39:19 -08:00
parent f40a579bea
commit 523573e90d
2 changed files with 58 additions and 18 deletions

View File

@ -407,25 +407,18 @@ breakBackedgeIfNotTaken(Loop *L, DominatorTree &DT, ScalarEvolution &SE,
if (!L->getLoopLatch())
return LoopDeletionResult::Unmodified;
auto *BTC = SE.getSymbolicMaxBackedgeTakenCount(L);
if (BTC->isZero()) {
// SCEV knows this backedge isn't taken!
breakLoopBackedge(L, DT, SE, LI, MSSA);
++NumBackedgesBroken;
return LoopDeletionResult::Deleted;
}
// If SCEV leaves open the possibility of a zero trip count, see if
// symbolically evaluating the first iteration lets us prove the backedge
// unreachable.
if (isa<SCEVCouldNotCompute>(BTC) || !SE.isKnownNonZero(BTC))
if (canProveExitOnFirstIteration(L, DT, LI)) {
breakLoopBackedge(L, DT, SE, LI, MSSA);
++NumBackedgesBroken;
return LoopDeletionResult::Deleted;
auto *BTCMax = SE.getConstantMaxBackedgeTakenCount(L);
if (!BTCMax->isZero()) {
auto *BTC = SE.getBackedgeTakenCount(L);
if (!BTC->isZero()) {
if (!isa<SCEVCouldNotCompute>(BTC) && SE.isKnownNonZero(BTC))
return LoopDeletionResult::Unmodified;
if (!canProveExitOnFirstIteration(L, DT, LI))
return LoopDeletionResult::Unmodified;
}
return LoopDeletionResult::Unmodified;
}
breakLoopBackedge(L, DT, SE, LI, MSSA);
return LoopDeletionResult::Deleted;
}
/// Remove a loop if it is dead.

View File

@ -0,0 +1,47 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt -loop-deletion -S < %s | FileCheck %s
@a = global i1 false, align 4
define i32 @main() {
; CHECK-LABEL: @main(
; CHECK-NEXT: entry:
; CHECK-NEXT: br label [[FOR_BODY:%.*]]
; CHECK: for.body:
; CHECK-NEXT: [[D_015:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ]
; CHECK-NEXT: call void @foo()
; CHECK-NEXT: [[DOTB:%.*]] = load i1, i1* @a, align 4
; CHECK-NEXT: [[CONV1:%.*]] = select i1 [[DOTB]], i32 -128, i32 1
; CHECK-NEXT: [[CMP2_NOT:%.*]] = icmp ugt i32 [[CONV1]], [[D_015]]
; CHECK-NEXT: br i1 [[CMP2_NOT]], label [[CLEANUP:%.*]], label [[FOR_INC8:%.*]]
; CHECK: for.inc8:
; CHECK-NEXT: [[INC9:%.*]] = add nuw nsw i32 [[D_015]], 1
; CHECK-NEXT: [[EXITCOND_NOT:%.*]] = icmp eq i32 [[INC9]], 19
; CHECK-NEXT: br label [[CLEANUP]]
; CHECK: cleanup:
; CHECK-NEXT: store i1 true, i1* @a, align 4
; CHECK-NEXT: ret i32 0
;
entry:
br label %for.body
for.body:
%d.015 = phi i32 [ 0, %entry ], [ %inc9, %for.inc8 ]
call void @foo()
%.b = load i1, i1* @a, align 4
%conv1 = select i1 %.b, i32 -128, i32 1
%cmp2.not = icmp ugt i32 %conv1, %d.015
br i1 %cmp2.not, label %cleanup, label %for.inc8
for.inc8:
%inc9 = add nuw nsw i32 %d.015, 1
%exitcond.not = icmp eq i32 %inc9, 19
br i1 %exitcond.not, label %cleanup, label %for.body
cleanup:
store i1 true, i1* @a, align 4
ret i32 0
}
declare void @foo()