summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/Utils/LoopSimplify.cpp
diff options
context:
space:
mode:
authorAndrew Trick <atrick@apple.com>2014-01-04 05:52:49 +0000
committerAndrew Trick <atrick@apple.com>2014-01-04 05:52:49 +0000
commitaceac9746da3d4a8547aaaedd9d763a9638c1b5c (patch)
treef579b760874d8908e399cf2a19de4169441368f1 /llvm/lib/Transforms/Utils/LoopSimplify.cpp
parentc19df037745e31f0a9ad47b1e413f4d0746da9d9 (diff)
downloadbcm5719-llvm-aceac9746da3d4a8547aaaedd9d763a9638c1b5c.tar.gz
bcm5719-llvm-aceac9746da3d4a8547aaaedd9d763a9638c1b5c.zip
Fix PR18361: Invalidate LoopDispositions after LoopSimplify hoists things.
getSCEV for an ashr instruction creates an intermediate zext expression when it truncates its operand. The operand is initially inside the loop, so the narrow zext expression has a non-loop-invariant loop disposition. LoopSimplify then runs on an outer loop, hoists the ashr operand, and properly invalidate the SCEVs that are mapped to value. The SCEV expression for the ashr is now an AddRec with the hoisted value as the now loop-invariant start value. The LoopDisposition of this wide value was properly invalidated during LoopSimplify. However, if we later get the ashr SCEV again, we again try to create the intermediate zext expression. We get the same SCEV that we did earlier, and it is still cached because it was never mapped to a Value. When we try to create a new AddRec we abort because we're using the old non-loop-invariant LoopDisposition. I don't have a solution for this other than to clear LoopDisposition when LoopSimplify hoists things. I think the long-term strategy should be to perform LoopSimplify on all loops before computing SCEV and before running any loop opts on individual loops. It's possible we may want to rerun LoopSimplify on individual loops, but it should rarely do anything, so rarely require invalidating SCEV. llvm-svn: 198478
Diffstat (limited to 'llvm/lib/Transforms/Utils/LoopSimplify.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/LoopSimplify.cpp27
1 files changed, 17 insertions, 10 deletions
diff --git a/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/llvm/lib/Transforms/Utils/LoopSimplify.cpp
index 6d5f16ca333..1927d288d43 100644
--- a/llvm/lib/Transforms/Utils/LoopSimplify.cpp
+++ b/llvm/lib/Transforms/Utils/LoopSimplify.cpp
@@ -309,6 +309,7 @@ ReprocessLoop:
// Attempt to hoist out all instructions except for the
// comparison and the branch.
bool AllInvariant = true;
+ bool AnyInvariant = false;
for (BasicBlock::iterator I = ExitingBlock->begin(); &*I != BI; ) {
Instruction *Inst = I++;
// Skip debug info intrinsics.
@@ -316,12 +317,26 @@ ReprocessLoop:
continue;
if (Inst == CI)
continue;
- if (!L->makeLoopInvariant(Inst, Changed,
- Preheader ? Preheader->getTerminator() : 0)) {
+ if (!L->makeLoopInvariant(Inst, AnyInvariant,
+ Preheader ? Preheader->getTerminator() : 0)) {
AllInvariant = false;
break;
}
}
+ if (AnyInvariant) {
+ Changed = true;
+ // If any reachable control flow within this loop has changed, notify
+ // ScalarEvolution. Currently assume the parent loop doesn't change
+ // (spliting edges doesn't count). If blocks, CFG edges, or other values
+ // in the parent loop change, then we need call to forgetLoop() for the
+ // parent instead.
+ if (SE) {
+ SE->forgetLoop(L);
+ // The loop disposition of all SCEV expressions that depend on any
+ // hoisted values have also changed.
+ SE->forgetLoopDispositions(L);
+ }
+ }
if (!AllInvariant) continue;
// The block has now been cleared of all instructions except for
@@ -334,14 +349,6 @@ ReprocessLoop:
DEBUG(dbgs() << "LoopSimplify: Eliminating exiting block "
<< ExitingBlock->getName() << "\n");
- // If any reachable control flow within this loop has changed, notify
- // ScalarEvolution. Currently assume the parent loop doesn't change
- // (spliting edges doesn't count). If blocks, CFG edges, or other values
- // in the parent loop change, then we need call to forgetLoop() for the
- // parent instead.
- if (SE)
- SE->forgetLoop(L);
-
assert(pred_begin(ExitingBlock) == pred_end(ExitingBlock));
Changed = true;
LI->removeBlock(ExitingBlock);
OpenPOWER on IntegriCloud