mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-02-01 05:01:59 +01:00
[LoopPred] Fix two subtle issues found by inspection
This patch fixes two issues noticed by inspection when going to enable the loop predication code in IndVarSimplify. Issue 1 - Both the LoopPredication transform, and the already on by default optimizeLoopExits transform, modify the exit count of the exits they modify. (either to 0 or Infinity) Looking at the code more closely, this was not reflected into SCEV and we were instead running later transforms with incorrect SCEVs. Fixing this requires forgetting the loop, weakening a too strong assert, and updating SCEV to not pessimize results when a loop is provable untaken. I haven't been able to find a test case to demonstrate the miscompile. Issue 2 - For modules without a data layout, we can end up with unsized pointer typed exit counts. Just bail out of this case. I think these are the last two issues which need addressed before we enable this by default. The code has already survived a decent amount of fuzzing without revealing either of the above. Differential Revision: https://reviews.llvm.org/D69695
This commit is contained in:
parent
7fc52c9da6
commit
a4e77afd7b
@ -7075,6 +7075,17 @@ ScalarEvolution::computeBackedgeTakenCount(const Loop *L,
|
||||
// Do a union of all the predicates here.
|
||||
for (unsigned i = 0, e = ExitingBlocks.size(); i != e; ++i) {
|
||||
BasicBlock *ExitBB = ExitingBlocks[i];
|
||||
|
||||
// We canonicalize untaken exits to br (constant), ignore them so that
|
||||
// proving an exit untaken doesn't negatively impact our ability to reason
|
||||
// about the loop as whole.
|
||||
if (auto *BI = dyn_cast<BranchInst>(ExitBB->getTerminator()))
|
||||
if (auto *CI = dyn_cast<ConstantInt>(BI->getCondition())) {
|
||||
bool ExitIfTrue = !L->contains(BI->getSuccessor(0));
|
||||
if ((ExitIfTrue && CI->isZero()) || (!ExitIfTrue && CI->isOne()))
|
||||
continue;
|
||||
}
|
||||
|
||||
ExitLimit EL = computeExitLimit(L, ExitBB, AllowPredicates);
|
||||
|
||||
assert((AllowPredicates || EL.Predicates.empty()) &&
|
||||
|
@ -2834,6 +2834,10 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
|
||||
!isSafeToExpand(ExactBTC, *SE))
|
||||
return Changed;
|
||||
|
||||
// If we end up with a pointer exit count, bail. It may be unsized.
|
||||
if (!ExactBTC->getType()->isIntegerTy())
|
||||
return Changed;
|
||||
|
||||
auto BadExit = [&](BasicBlock *ExitingBB) {
|
||||
// If our exiting block exits multiple loops, we can only rewrite the
|
||||
// innermost one. Otherwise, we're changing how many times the innermost
|
||||
@ -2864,6 +2868,10 @@ bool IndVarSimplify::predicateLoopExits(Loop *L, SCEVExpander &Rewriter) {
|
||||
!isSafeToExpand(ExitCount, *SE))
|
||||
return true;
|
||||
|
||||
// If we end up with a pointer exit count, bail. It may be unsized.
|
||||
if (!ExitCount->getType()->isIntegerTy())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
@ -2990,15 +2998,15 @@ bool IndVarSimplify::run(Loop *L) {
|
||||
if (!L->isLoopSimplifyForm())
|
||||
return false;
|
||||
|
||||
// If there are any floating-point recurrences, attempt to
|
||||
// transform them to use integer recurrences.
|
||||
Changed |= rewriteNonIntegerIVs(L);
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Used below for a consistency check only
|
||||
const SCEV *BackedgeTakenCount = SE->getBackedgeTakenCount(L);
|
||||
#endif
|
||||
|
||||
// If there are any floating-point recurrences, attempt to
|
||||
// transform them to use integer recurrences.
|
||||
Changed |= rewriteNonIntegerIVs(L);
|
||||
|
||||
// Create a rewriter object which we'll use to transform the code with.
|
||||
SCEVExpander Rewriter(*SE, DL, "indvars");
|
||||
#ifndef NDEBUG
|
||||
@ -3025,11 +3033,19 @@ bool IndVarSimplify::run(Loop *L) {
|
||||
NumElimIV += Rewriter.replaceCongruentIVs(L, DT, DeadInsts);
|
||||
|
||||
// Try to eliminate loop exits based on analyzeable exit counts
|
||||
Changed |= optimizeLoopExits(L, Rewriter);
|
||||
if (optimizeLoopExits(L, Rewriter)) {
|
||||
Changed = true;
|
||||
// Given we've changed exit counts, notify SCEV
|
||||
SE->forgetLoop(L);
|
||||
}
|
||||
|
||||
// Try to form loop invariant tests for loop exits by changing how many
|
||||
// iterations of the loop run when that is unobservable.
|
||||
Changed |= predicateLoopExits(L, Rewriter);
|
||||
if (predicateLoopExits(L, Rewriter)) {
|
||||
Changed = true;
|
||||
// Given we've changed exit counts, notify SCEV
|
||||
SE->forgetLoop(L);
|
||||
}
|
||||
|
||||
// If we have a trip count expression, rewrite the loop's exit condition
|
||||
// using it.
|
||||
@ -3117,7 +3133,8 @@ bool IndVarSimplify::run(Loop *L) {
|
||||
"Indvars did not preserve LCSSA!");
|
||||
|
||||
// Verify that LFTR, and any other change have not interfered with SCEV's
|
||||
// ability to compute trip count.
|
||||
// ability to compute trip count. We may have *changed* the exit count, but
|
||||
// only by reducing it.
|
||||
#ifndef NDEBUG
|
||||
if (VerifyIndvars && !isa<SCEVCouldNotCompute>(BackedgeTakenCount)) {
|
||||
SE->forgetLoop(L);
|
||||
@ -3129,7 +3146,8 @@ bool IndVarSimplify::run(Loop *L) {
|
||||
else
|
||||
BackedgeTakenCount = SE->getTruncateOrNoop(BackedgeTakenCount,
|
||||
NewBECount->getType());
|
||||
assert(BackedgeTakenCount == NewBECount && "indvars must preserve SCEV");
|
||||
assert(!SE->isKnownPredicate(ICmpInst::ICMP_ULT, BackedgeTakenCount,
|
||||
NewBECount) && "indvars must preserve SCEV");
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user