Index: lib/Transforms/Utils/LoopUnroll.cpp =================================================================== --- lib/Transforms/Utils/LoopUnroll.cpp +++ lib/Transforms/Utils/LoopUnroll.cpp @@ -73,8 +73,9 @@ /// of loops that have already been forgotten to prevent redundant, expensive /// calls to ScalarEvolution::forgetLoop. Returns the new combined block. static BasicBlock * -FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo* LI, ScalarEvolution *SE, - SmallPtrSetImpl &ForgottenLoops) { +FoldBlockIntoPredecessor(BasicBlock *BB, LoopInfo *LI, ScalarEvolution *SE, + SmallPtrSetImpl &ForgottenLoops, + DominatorTree *DT) { // Merge basic blocks into their predecessor if there is only one distinct // pred, and if there is only one distinct successor of the predecessor, and // if there are no PHI nodes. @@ -106,7 +107,18 @@ // OldName will be valid until erased. StringRef OldName = BB->getName(); - // Erase basic block from the function... + // Erase the old block and update dominator info. + if (DT) + if (DomTreeNode *DTN = DT->getNode(BB)) { + DomTreeNode *PredDTN = DT->getNode(OnlyPred); + SmallVector Children(DTN->begin(), DTN->end()); + for (SmallVectorImpl::iterator DI = Children.begin(), + DE = Children.end(); + DI != DE; ++DI) + DT->changeImmediateDominator(*DI, PredDTN); + + DT->eraseNode(BB); + } // ScalarEvolution holds references to loop exit blocks. if (SE) { @@ -420,6 +432,19 @@ NewBlocks.push_back(New); UnrolledLoopBlocks.push_back(New); + + // Update DomTree + if (DT) { + if (*BB == Header) + DT->addNewBlock(New, Latches[It - 1]); + else { + auto BBDomNode = DT->getNode(*BB); + auto BBIDom = BBDomNode->getIDom(); + BasicBlock *OriginalBBIDom = BBIDom->getBlock(); + DT->addNewBlock( + New, cast(LastValueMap[cast(OriginalBBIDom)])); + } + } } // Remap all instructions in the most recent iteration @@ -501,6 +526,18 @@ Term->eraseFromParent(); } } + // Update dominators of loop exit blocks + if (DT) { + for (auto UniqueExit : ExitBlocks) { + BasicBlock *ExitIDom = nullptr; + for (auto BI = pred_begin(UniqueExit), BE = pred_end(UniqueExit); + BI != BE; BI++) { + ExitIDom = + ExitIDom ? DT->findNearestCommonDominator(ExitIDom, *BI) : *BI; + } + DT->changeImmediateDominator(UniqueExit, ExitIDom); + } + } // Merge adjacent basic blocks, if possible. SmallPtrSet ForgottenLoops; @@ -508,8 +545,8 @@ BranchInst *Term = cast(Latches[i]->getTerminator()); if (Term->isUnconditional()) { BasicBlock *Dest = Term->getSuccessor(0); - if (BasicBlock *Fold = FoldBlockIntoPredecessor(Dest, LI, SE, - ForgottenLoops)) { + if (BasicBlock *Fold = + FoldBlockIntoPredecessor(Dest, LI, SE, ForgottenLoops, DT)) { // Dest has been folded into Fold. Update our worklists accordingly. std::replace(Latches.begin(), Latches.end(), Dest, Fold); UnrolledLoopBlocks.erase(std::remove(UnrolledLoopBlocks.begin(), @@ -523,10 +560,12 @@ // whole function's cache. AC->clear(); - // FIXME: Reconstruct dom info, because it is not preserved properly. - // Incrementally updating domtree after loop unrolling would be easy. - if (DT) - DT->recalculate(*L->getHeader()->getParent()); + if (DT) { + // FIXME: Reconstruct dom info, because it is not preserved properly. + // Incrementally updating domtree after loop unrolling would be easy. + if (!CompletelyUnroll) + DT->recalculate(*L->getHeader()->getParent()); + } // Simplify any new induction variables in the partially unrolled loop. if (SE && !CompletelyUnroll) {