diff options
author | Philip Reames <listmail@philipreames.com> | 2019-11-06 12:36:28 -0800 |
---|---|---|
committer | Philip Reames <listmail@philipreames.com> | 2019-11-06 14:04:45 -0800 |
commit | 9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e (patch) | |
tree | aef1dff69b0dc2c363f04591f97b7d23f99c7522 /llvm/lib | |
parent | 6cecd3c3dbef48eca6c4cf2dcc2df3290ab91488 (diff) | |
download | bcm5719-llvm-9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e.tar.gz bcm5719-llvm-9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e.zip |
[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
Diffstat (limited to 'llvm/lib')
-rw-r--r-- | llvm/lib/Analysis/ScalarEvolution.cpp | 11 | ||||
-rw-r--r-- | llvm/lib/Transforms/Scalar/IndVarSimplify.cpp | 34 |
2 files changed, 37 insertions, 8 deletions
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp index e4295f64dca..ebdaf4eda07 100644 --- a/llvm/lib/Analysis/ScalarEvolution.cpp +++ b/llvm/lib/Analysis/ScalarEvolution.cpp @@ -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()) && diff --git a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp index 4520a468aca..f00b6a5ce3f 100644 --- a/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp +++ b/llvm/lib/Transforms/Scalar/IndVarSimplify.cpp @@ -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 |