[SCEV] Fix predicate usage in computeExitLimitFromICmp

In this method, we invoke `SimplifyICmpOperands` which takes the `Cond` predicate
by reference and may change it along with `LHS` and `RHS` SCEVs. But then we invoke
`computeShiftCompareExitLimit` with Values from which the SCEVs have been derived,
these Values have not been modified while `Cond` could be.

One of possible outcomes of this is that we may falsely prove that an infinite loop ends
within some finite number of iterations.

In this patch, we save the original `Cond` and pass it along with original operands.
This logic may be removed in future once `computeShiftCompareExitLimit` works
with SCEVs instead of value operands.

Reviewed By: sanjoy
Differential Revision: https://reviews.llvm.org/D40953

llvm-svn: 320142
This commit is contained in:
Max Kazantsev 2017-12-08 12:19:45 +00:00
parent f4bd295576
commit 9c08b7a053
2 changed files with 21 additions and 1 deletions

View File

@ -7074,6 +7074,7 @@ ScalarEvolution::computeExitLimitFromICmp(const Loop *L,
Cond = ExitCond->getPredicate();
else
Cond = ExitCond->getInversePredicate();
const ICmpInst::Predicate OriginalCond = Cond;
// Handle common loops like: for (X = "string"; *X; ++X)
if (LoadInst *LI = dyn_cast<LoadInst>(ExitCond->getOperand(0)))
@ -7157,7 +7158,7 @@ ScalarEvolution::computeExitLimitFromICmp(const Loop *L,
return ExhaustiveCount;
return computeShiftCompareExitLimit(ExitCond->getOperand(0),
ExitCond->getOperand(1), L, Cond);
ExitCond->getOperand(1), L, OriginalCond);
}
ScalarEvolution::ExitLimit

View File

@ -160,5 +160,24 @@ define void @test8(i32 %init) {
ret void
}
define void @test9() {
; CHECK-LABEL: Determining loop execution counts for: @test9
; CHECK: Loop %loop: Unpredictable max backedge-taken count.
; This is an infinite loop, make sure that it recognized as such.
entry:
br label %loop
leave:
ret void
loop:
%iv = phi i32 [ -20, %entry ], [ %iv.shift, %loop ]
%iv.shift = ashr i32 %iv, 1
%exit.cond = icmp sgt i32 %iv, -1
br i1 %exit.cond, label %leave, label %loop
}
!0 = !{i32 0, i32 50000}
!1 = !{i32 -5000, i32 -1}