diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-05-03 17:50:02 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2016-05-03 17:50:02 +0000 |
commit | 905fc27ebf9ec5a262dc320bb66e68f17d597248 (patch) | |
tree | d9ef19b195df25f735bc90385bee9b428f8c85e5 /llvm/lib/Transforms/Scalar/LoopDeletion.cpp | |
parent | 013a4ac4aa5da577fff807c44846eb6cfd6d32f4 (diff) | |
download | llvm-905fc27ebf9ec5a262dc320bb66e68f17d597248.zip llvm-905fc27ebf9ec5a262dc320bb66e68f17d597248.tar.gz llvm-905fc27ebf9ec5a262dc320bb66e68f17d597248.tar.bz2 |
[LoopDeletion] Clear SCEV loop dispositions
`Loop::makeLoopInvariant` can hoist instructions out of loops, so loop
dispositions for the loop it operated on may need to be cleared. We can
be smarter here (especially around how `forgetLoopDispositions` is
implemented), but let's be correct first.
Fixes PR27570.
llvm-svn: 268406
Diffstat (limited to 'llvm/lib/Transforms/Scalar/LoopDeletion.cpp')
-rw-r--r-- | llvm/lib/Transforms/Scalar/LoopDeletion.cpp | 38 |
1 files changed, 27 insertions, 11 deletions
diff --git a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp index 786cd72..f888ad9 100644 --- a/llvm/lib/Transforms/Scalar/LoopDeletion.cpp +++ b/llvm/lib/Transforms/Scalar/LoopDeletion.cpp @@ -44,10 +44,10 @@ namespace { } private: - bool isLoopDead(Loop *L, SmallVectorImpl<BasicBlock *> &exitingBlocks, - SmallVectorImpl<BasicBlock *> &exitBlocks, - bool &Changed, BasicBlock *Preheader); - + bool isLoopDead(Loop *L, ScalarEvolution &SE, + SmallVectorImpl<BasicBlock *> &exitingBlocks, + SmallVectorImpl<BasicBlock *> &exitBlocks, bool &Changed, + BasicBlock *Preheader); }; } @@ -65,7 +65,7 @@ Pass *llvm::createLoopDeletionPass() { /// isLoopDead - Determined if a loop is dead. This assumes that we've already /// checked for unique exit and exiting blocks, and that the code is in LCSSA /// form. -bool LoopDeletion::isLoopDead(Loop *L, +bool LoopDeletion::isLoopDead(Loop *L, ScalarEvolution &SE, SmallVectorImpl<BasicBlock *> &exitingBlocks, SmallVectorImpl<BasicBlock *> &exitBlocks, bool &Changed, BasicBlock *Preheader) { @@ -77,6 +77,8 @@ bool LoopDeletion::isLoopDead(Loop *L, // sufficient to guarantee that no loop-variant values are used outside // of the loop. BasicBlock::iterator BI = exitBlock->begin(); + bool AllEntriesInvariant = true; + bool AllOutgoingValuesSame = true; while (PHINode *P = dyn_cast<PHINode>(BI)) { Value *incoming = P->getIncomingValueForBlock(exitingBlocks[0]); @@ -85,17 +87,30 @@ bool LoopDeletion::isLoopDead(Loop *L, // blocks, then it is impossible to statically determine which value should // be used. for (unsigned i = 1, e = exitingBlocks.size(); i < e; ++i) { - if (incoming != P->getIncomingValueForBlock(exitingBlocks[i])) - return false; + if (incoming != P->getIncomingValueForBlock(exitingBlocks[i])) { + AllOutgoingValuesSame = false; + break; + } } + if (!AllOutgoingValuesSame) + break; + if (Instruction *I = dyn_cast<Instruction>(incoming)) - if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) - return false; + if (!L->makeLoopInvariant(I, Changed, Preheader->getTerminator())) { + AllEntriesInvariant = false; + break; + } ++BI; } + if (Changed) + SE.forgetLoopDispositions(L); + + if (!AllEntriesInvariant || !AllOutgoingValuesSame) + return false; + // Make sure that no instructions in the block have potential side-effects. // This includes instructions that could write to memory, and loads that are // marked volatile. This could be made more aggressive by using aliasing @@ -153,14 +168,15 @@ bool LoopDeletion::runOnLoop(Loop *L, LPPassManager &) { if (exitBlocks.size() != 1) return false; + ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); + // Finally, we have to check that the loop really is dead. bool Changed = false; - if (!isLoopDead(L, exitingBlocks, exitBlocks, Changed, preheader)) + if (!isLoopDead(L, SE, exitingBlocks, exitBlocks, Changed, preheader)) return Changed; // Don't remove loops for which we can't solve the trip count. // They could be infinite, in which case we'd be changing program behavior. - ScalarEvolution &SE = getAnalysis<ScalarEvolutionWrapperPass>().getSE(); const SCEV *S = SE.getMaxBackedgeTakenCount(L); if (isa<SCEVCouldNotCompute>(S)) return Changed; |