mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-07-24 22:24:54 +00:00
[LCSSA] Handle PHI insertion in disjoint loops
Take two disjoint Loops L1 and L2. LoopSimplify fails to simplify some loops (e.g. when indirect branches are involved). In such situations, it can happen that an exit for L1 is the header of L2. Thus, when we create PHIs in one of such exits we are also inserting PHIs in L2 header. This could break LCSSA form for L2 because these inserted PHIs can also have uses in L2 exits, which are never handled in the current implementation. Provide a fix for this corner case and test that we don't assert/crash on that. Differential Revision: http://reviews.llvm.org/D6624 rdar://problem/19166231 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@224740 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -316,7 +316,8 @@ bool LICM::runOnLoop(Loop *L, LPPassManager &LPM) {
|
||||
// SSAUpdater strategy during promotion that was LCSSA aware and reformed
|
||||
// it as it went.
|
||||
if (Changed)
|
||||
formLCSSARecursively(*L, *DT, getAnalysisIfAvailable<ScalarEvolution>());
|
||||
formLCSSARecursively(*L, *DT, LI,
|
||||
getAnalysisIfAvailable<ScalarEvolution>());
|
||||
}
|
||||
|
||||
// Check that neither this loop nor its parent have had LCSSA broken. LICM is
|
||||
|
@@ -61,7 +61,7 @@ static bool isExitBlock(BasicBlock *BB,
|
||||
/// uses.
|
||||
static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT,
|
||||
const SmallVectorImpl<BasicBlock *> &ExitBlocks,
|
||||
PredIteratorCache &PredCache) {
|
||||
PredIteratorCache &PredCache, LoopInfo *LI) {
|
||||
SmallVector<Use *, 16> UsesToRewrite;
|
||||
|
||||
BasicBlock *InstBB = Inst.getParent();
|
||||
@@ -94,6 +94,7 @@ static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT,
|
||||
DomTreeNode *DomNode = DT.getNode(DomBB);
|
||||
|
||||
SmallVector<PHINode *, 16> AddedPHIs;
|
||||
SmallVector<PHINode *, 8> PostProcessPHIs;
|
||||
|
||||
SSAUpdater SSAUpdate;
|
||||
SSAUpdate.Initialize(Inst.getType(), Inst.getName());
|
||||
@@ -131,6 +132,18 @@ static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT,
|
||||
|
||||
// Remember that this phi makes the value alive in this block.
|
||||
SSAUpdate.AddAvailableValue(ExitBB, PN);
|
||||
|
||||
// LoopSimplify might fail to simplify some loops (e.g. when indirect
|
||||
// branches are involved). In such situations, it might happen that an exit
|
||||
// for Loop L1 is the header of a disjoint Loop L2. Thus, when we create
|
||||
// PHIs in such an exit block, we are also inserting PHIs into L2's header.
|
||||
// This could break LCSSA form for L2 because these inserted PHIs can also
|
||||
// have uses outside of L2. Remember all PHIs in such situation as to
|
||||
// revisit than later on. FIXME: Remove this if indirectbr support into
|
||||
// LoopSimplify gets improved.
|
||||
if (auto *OtherLoop = LI->getLoopFor(ExitBB))
|
||||
if (!L.contains(OtherLoop))
|
||||
PostProcessPHIs.push_back(PN);
|
||||
}
|
||||
|
||||
// Rewrite all uses outside the loop in terms of the new PHIs we just
|
||||
@@ -157,6 +170,25 @@ static bool processInstruction(Loop &L, Instruction &Inst, DominatorTree &DT,
|
||||
SSAUpdate.RewriteUse(*UsesToRewrite[i]);
|
||||
}
|
||||
|
||||
// Post process PHI instructions that were inserted into another disjoint loop
|
||||
// and update their exits properly.
|
||||
for (auto *I : PostProcessPHIs) {
|
||||
if (I->use_empty())
|
||||
continue;
|
||||
|
||||
BasicBlock *PHIBB = I->getParent();
|
||||
Loop *OtherLoop = LI->getLoopFor(PHIBB);
|
||||
SmallVector<BasicBlock *, 8> EBs;
|
||||
OtherLoop->getExitBlocks(EBs);
|
||||
if (EBs.empty())
|
||||
continue;
|
||||
|
||||
// Recurse and re-process each PHI instruction. FIXME: we should really
|
||||
// convert this entire thing to a worklist approach where we process a
|
||||
// vector of instructions...
|
||||
processInstruction(*OtherLoop, *I, DT, EBs, PredCache, LI);
|
||||
}
|
||||
|
||||
// Remove PHI nodes that did not have any uses rewritten.
|
||||
for (unsigned i = 0, e = AddedPHIs.size(); i != e; ++i) {
|
||||
if (AddedPHIs[i]->use_empty())
|
||||
@@ -180,7 +212,8 @@ blockDominatesAnExit(BasicBlock *BB,
|
||||
return false;
|
||||
}
|
||||
|
||||
bool llvm::formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE) {
|
||||
bool llvm::formLCSSA(Loop &L, DominatorTree &DT, LoopInfo *LI,
|
||||
ScalarEvolution *SE) {
|
||||
bool Changed = false;
|
||||
|
||||
// Get the set of exiting blocks.
|
||||
@@ -212,7 +245,7 @@ bool llvm::formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE) {
|
||||
!isa<PHINode>(I->user_back())))
|
||||
continue;
|
||||
|
||||
Changed |= processInstruction(L, *I, DT, ExitBlocks, PredCache);
|
||||
Changed |= processInstruction(L, *I, DT, ExitBlocks, PredCache, LI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,15 +261,15 @@ bool llvm::formLCSSA(Loop &L, DominatorTree &DT, ScalarEvolution *SE) {
|
||||
}
|
||||
|
||||
/// Process a loop nest depth first.
|
||||
bool llvm::formLCSSARecursively(Loop &L, DominatorTree &DT,
|
||||
bool llvm::formLCSSARecursively(Loop &L, DominatorTree &DT, LoopInfo *LI,
|
||||
ScalarEvolution *SE) {
|
||||
bool Changed = false;
|
||||
|
||||
// Recurse depth-first through inner loops.
|
||||
for (Loop::iterator LI = L.begin(), LE = L.end(); LI != LE; ++LI)
|
||||
Changed |= formLCSSARecursively(**LI, DT, SE);
|
||||
for (Loop::iterator I = L.begin(), E = L.end(); I != E; ++I)
|
||||
Changed |= formLCSSARecursively(**I, DT, LI, SE);
|
||||
|
||||
Changed |= formLCSSA(L, DT, SE);
|
||||
Changed |= formLCSSA(L, DT, LI, SE);
|
||||
return Changed;
|
||||
}
|
||||
|
||||
@@ -291,7 +324,7 @@ bool LCSSA::runOnFunction(Function &F) {
|
||||
|
||||
// Simplify each loop nest in the function.
|
||||
for (LoopInfo::iterator I = LI->begin(), E = LI->end(); I != E; ++I)
|
||||
Changed |= formLCSSARecursively(**I, *DT, SE);
|
||||
Changed |= formLCSSARecursively(**I, *DT, LI, SE);
|
||||
|
||||
return Changed;
|
||||
}
|
||||
|
@@ -544,7 +544,7 @@ bool llvm::UnrollLoop(Loop *L, unsigned Count, unsigned TripCount,
|
||||
while (OuterL->getParentLoop() != LatchLoop)
|
||||
OuterL = OuterL->getParentLoop();
|
||||
|
||||
formLCSSARecursively(*OuterL, *DT, SE);
|
||||
formLCSSARecursively(*OuterL, *DT, LI, SE);
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user