[LoopRotate][Dominators] Use the incremental API to update DomTree

Summary: This patch teaches LoopRotate to use the new incremental API to update the DominatorTree.

Reviewers: dberlin, davide, grosser, sanjoy

Reviewed By: dberlin, davide

Subscribers: hiraditya, llvm-commits, mzolotukhin

Differential Revision: https://reviews.llvm.org/D35581

llvm-svn: 311125
This commit is contained in:
Jakub Kuderski 2017-08-17 21:48:19 +00:00
parent 6e07bfd0d9
commit e608ef7635
1 changed files with 13 additions and 66 deletions

View File

@ -395,6 +395,17 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
L->moveToHeader(NewHeader);
assert(L->getHeader() == NewHeader && "Latch block is our new header");
// Inform DT about changes to the CFG.
if (DT) {
// The OrigPreheader branches to the NewHeader and Exit now. Then, inform
// the DT about the removed edge to the OrigHeader (that got removed).
SmallVector<DominatorTree::UpdateType, 3> Updates;
Updates.push_back({DominatorTree::Insert, OrigPreheader, Exit});
Updates.push_back({DominatorTree::Insert, OrigPreheader, NewHeader});
Updates.push_back({DominatorTree::Delete, OrigPreheader, OrigHeader});
DT->applyUpdates(Updates);
}
// At this point, we've finished our major CFG changes. As part of cloning
// the loop into the preheader we've simplified instructions and the
// duplicated conditional branch may now be branching on a constant. If it is
@ -408,26 +419,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
PHBI->getSuccessor(cast<ConstantInt>(PHBI->getCondition())->isZero()) !=
NewHeader) {
// The conditional branch can't be folded, handle the general case.
// Update DominatorTree to reflect the CFG change we just made. Then split
// edges as necessary to preserve LoopSimplify form.
if (DT) {
// Everything that was dominated by the old loop header is now dominated
// by the original loop preheader. Conceptually the header was merged
// into the preheader, even though we reuse the actual block as a new
// loop latch.
DomTreeNode *OrigHeaderNode = DT->getNode(OrigHeader);
SmallVector<DomTreeNode *, 8> HeaderChildren(OrigHeaderNode->begin(),
OrigHeaderNode->end());
DomTreeNode *OrigPreheaderNode = DT->getNode(OrigPreheader);
for (unsigned I = 0, E = HeaderChildren.size(); I != E; ++I)
DT->changeImmediateDominator(HeaderChildren[I], OrigPreheaderNode);
assert(DT->getNode(Exit)->getIDom() == OrigPreheaderNode);
assert(DT->getNode(NewHeader)->getIDom() == OrigPreheaderNode);
// Update OrigHeader to be dominated by the new header block.
DT->changeImmediateDominator(OrigHeader, OrigLatch);
}
// Split edges as necessary to preserve LoopSimplify form.
// Right now OrigPreHeader has two successors, NewHeader and ExitBlock, and
// thus is not a preheader anymore.
@ -467,52 +459,7 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) {
PHBI->eraseFromParent();
// With our CFG finalized, update DomTree if it is available.
if (DT) {
// Update OrigHeader to be dominated by the new header block.
DT->changeImmediateDominator(NewHeader, OrigPreheader);
DT->changeImmediateDominator(OrigHeader, OrigLatch);
// Brute force incremental dominator tree update. Call
// findNearestCommonDominator on all CFG predecessors of each child of the
// original header.
DomTreeNode *OrigHeaderNode = DT->getNode(OrigHeader);
SmallVector<DomTreeNode *, 8> HeaderChildren(OrigHeaderNode->begin(),
OrigHeaderNode->end());
bool Changed;
do {
Changed = false;
for (unsigned I = 0, E = HeaderChildren.size(); I != E; ++I) {
DomTreeNode *Node = HeaderChildren[I];
BasicBlock *BB = Node->getBlock();
BasicBlock *NearestDom = nullptr;
for (BasicBlock *Pred : predecessors(BB)) {
// Consider only reachable basic blocks.
if (!DT->getNode(Pred))
continue;
if (!NearestDom) {
NearestDom = Pred;
continue;
}
NearestDom = DT->findNearestCommonDominator(NearestDom, Pred);
assert(NearestDom && "No NearestCommonDominator found");
}
assert(NearestDom && "Nearest dominator not found");
// Remember if this changes the DomTree.
if (Node->getIDom()->getBlock() != NearestDom) {
DT->changeImmediateDominator(BB, NearestDom);
Changed = true;
}
}
// If the dominator changed, this may have an effect on other
// predecessors, continue until we reach a fixpoint.
} while (Changed);
}
if (DT) DT->deleteEdge(OrigPreheader, Exit);
}
assert(L->getLoopPreheader() && "Invalid loop preheader after loop rotation");