mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
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:
@@ -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));
|
||||
|
||||
|
||||
Reference in New Issue
Block a user