Fix dominator tree update in array specialization

We need to walk the dominator tree starting at the header and update the
dominator of all nodes outside the loop we hit i.e the dominator tree nodes that
are immediately dominated 'by the loop' instead of only updating dominated exit
blocks.

rdar://34523864
This commit is contained in:
Arnold Schwaighofer
2017-09-25 20:04:58 -07:00
parent d417281ed9
commit 71a7252424
2 changed files with 94 additions and 12 deletions

View File

@@ -2219,6 +2219,24 @@ static void replaceArrayPropsCall(SILBuilder &B, ArraySemanticsCall C) {
C.removeCall();
}
/// Collects all loop dominated blocks outside the loop that are immediately
/// dominated by the loop.
static void
collectImmediateLoopDominatedBlocks(const SILLoop *Lp, DominanceInfoNode *Node,
SmallVectorImpl<SILBasicBlock *> &Blocks) {
SILBasicBlock *BB = Node->getBlock();
// Base case: First loop dominated block outside of loop.
if (!Lp->contains(BB)) {
Blocks.push_back(BB);
return;
}
// Loop contains the basic block. Look at immediately dominated nodes.
for (auto *Child : *Node)
collectImmediateLoopDominatedBlocks(Lp, Child, Blocks);
}
void ArrayPropertiesSpecializer::specializeLoopNest() {
auto *Lp = getLoop();
assert(Lp);
@@ -2231,22 +2249,19 @@ void ArrayPropertiesSpecializer::specializeLoopNest() {
auto *CheckBlock = splitBasicBlockAndBranch(B,
HoistableLoopPreheader->getTerminator(), DomTree, nullptr);
// Get the exit blocks of the original loop.
auto *Header = CheckBlock->getSingleSuccessorBlock();
assert(Header);
// Our loop info is not really completely valid anymore since the cloner does
// not update it. However, exit blocks of the original loop are still valid.
// Collect all loop dominated blocks (e.g exit blocks could be among them). We
// need to update their dominator.
SmallVector<SILBasicBlock *, 16> LoopDominatedBlocks;
collectImmediateLoopDominatedBlocks(Lp, DomTree->getNode(Header),
LoopDominatedBlocks);
// Collect all exit blocks.
SmallVector<SILBasicBlock *, 16> ExitBlocks;
Lp->getExitBlocks(ExitBlocks);
// Collect the exit blocks dominated by the loop - they will be dominated by
// the check block.
SmallVector<SILBasicBlock *, 16> ExitBlocksDominatedByPreheader;
for (auto *ExitBlock: ExitBlocks)
if (DomTree->dominates(CheckBlock, ExitBlock))
ExitBlocksDominatedByPreheader.push_back(ExitBlock);
// Split the preheader before the first instruction.
SILBasicBlock *NewPreheader =
splitBasicBlockAndBranch(B, &*CheckBlock->begin(), DomTree, nullptr);
@@ -2275,8 +2290,8 @@ void ArrayPropertiesSpecializer::specializeLoopNest() {
IsFastNativeArray, ClonedPreheader, NewPreheader);
CheckBlock->getTerminator()->eraseFromParent();
// Fixup the exit blocks. They are now dominated by the check block.
for (auto *BB : ExitBlocksDominatedByPreheader)
// Fixup the loop dominated blocks. They are now dominated by the check block.
for (auto *BB : LoopDominatedBlocks)
DomTree->changeImmediateDominator(DomTree->getNode(BB),
DomTree->getNode(CheckBlock));