[llvm] 9bfa5ab - [LoopPred] Fix two subtle issues found by inspection
Philip Reames via llvm-commits
llvm-commits at lists.llvm.org
Wed Nov 6 14:04:52 PST 2019
Author: Philip Reames
Date: 2019-11-06T14:04:45-08:00
New Revision: 9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e
URL: https://github.com/llvm/llvm-project/commit/9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e
DIFF: https://github.com/llvm/llvm-project/commit/9bfa5ab3d1982a7cef60ee00b935f4ddc89fc98e.diff
LOG: [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
Added:
Modified:
llvm/lib/Analysis/ScalarEvolution.cpp
llvm/lib/Transforms/Scalar/IndVarSimplify.cpp
Removed:
################################################################################
diff --git a/llvm/lib/Analysis/ScalarEvolution.cpp b/llvm/lib/Analysis/ScalarEvolution.cpp
index e4295f64dcac..ebdaf4eda07d 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 4520a468acab..f00b6a5ce3f2 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
More information about the llvm-commits
mailing list