diff options
author | Devang Patel <dpatel@apple.com> | 2007-08-01 22:23:50 +0000 |
---|---|---|
committer | Devang Patel <dpatel@apple.com> | 2007-08-01 22:23:50 +0000 |
commit | 28ae151c48df634b4df5b3630a9a65021574fb4c (patch) | |
tree | e5bc2fabca7ef9269a73b29f26ff29c8e6bf8e90 /lib/Transforms/Scalar/LoopUnswitch.cpp | |
parent | 9066020993695a690c1f979f9cac4e14d325e237 (diff) |
Update dominator info for the middle blocks created while spliting
exit edge to preserve LCSSA.
Fix dominance frontier update during loop unswitch. This fixes PR 1589.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@40695 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Scalar/LoopUnswitch.cpp')
-rw-r--r-- | lib/Transforms/Scalar/LoopUnswitch.cpp | 97 |
1 files changed, 76 insertions, 21 deletions
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp index 3a10bd7ae5..f787b82582 100644 --- a/lib/Transforms/Scalar/LoopUnswitch.cpp +++ b/lib/Transforms/Scalar/LoopUnswitch.cpp @@ -543,17 +543,8 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val, std::swap(TrueDest, FalseDest); // Insert the new branch. - BranchInst *BRI = new BranchInst(TrueDest, FalseDest, BranchVal, InsertPt); - - // Update dominator info. - // BranchVal is a new preheader so it dominates true and false destination - // loop headers. - if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>()) { - DT->changeImmediateDominator(TrueDest, BRI->getParent()); - DT->changeImmediateDominator(FalseDest, BRI->getParent()); - } - // No need to update DominanceFrontier. BRI->getParent() dominated TrueDest - // and FalseDest anyway. Now it immediately dominates them. + new BranchInst(TrueDest, FalseDest, BranchVal, InsertPt); + } @@ -635,12 +626,14 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, // Split all of the edges from inside the loop to their exit blocks. Update // the appropriate Phi nodes as we do so. + SmallVector<BasicBlock *,8> MiddleBlocks; for (unsigned i = 0, e = ExitBlocks.size(); i != e; ++i) { BasicBlock *ExitBlock = ExitBlocks[i]; std::vector<BasicBlock*> Preds(pred_begin(ExitBlock), pred_end(ExitBlock)); for (unsigned j = 0, e = Preds.size(); j != e; ++j) { BasicBlock* MiddleBlock = SplitEdge(Preds[j], ExitBlock, this); + MiddleBlocks.push_back(MiddleBlock); BasicBlock* StartBlock = Preds[j]; BasicBlock* EndBlock; if (MiddleBlock->getSinglePredecessor() == ExitBlock) { @@ -685,6 +678,9 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, // Add exit blocks to the loop blocks. LoopBlocks.insert(LoopBlocks.end(), ExitBlocks.begin(), ExitBlocks.end()); + DominanceFrontier *DF = getAnalysisToUpdate<DominanceFrontier>(); + DominatorTree *DT = getAnalysisToUpdate<DominatorTree>(); + // Next step, clone all of the basic blocks that make up the loop (including // the loop preheader and exit blocks), keeping track of the mapping between // the instructions and blocks. @@ -698,16 +694,21 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, LPM->cloneBasicBlockSimpleAnalysis(LoopBlocks[i], New, L); } - // Update dominator info - DominanceFrontier *DF = getAnalysisToUpdate<DominanceFrontier>(); - if (DominatorTree *DT = getAnalysisToUpdate<DominatorTree>()) - for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) { - BasicBlock *LBB = LoopBlocks[i]; - BasicBlock *NBB = NewBlocks[i]; - CloneDomInfo(NBB, LBB, NewPreheader, OrigPreheader, - OrigHeader, DT, DF, ValueMap); + // OutSiders are basic block that are dominated by original header and + // at the same time they are not part of loop. + SmallPtrSet<BasicBlock *, 8> OutSiders; + if (DT) { + DomTreeNode *OrigHeaderNode = DT->getNode(OrigHeader); + for(std::vector<DomTreeNode*>::iterator DI = OrigHeaderNode->begin(), + DE = OrigHeaderNode->end(); DI != DE; ++DI) { + BasicBlock *B = (*DI)->getBlock(); + + DenseMap<const Value*, Value*>::iterator VI = ValueMap.find(B); + if (VI == ValueMap.end()) + OutSiders.insert(B); } - + } + // Splice the newly inserted blocks into the function right before the // original preheader. F->getBasicBlockList().splice(LoopBlocks[0], F->getBasicBlockList(), @@ -759,7 +760,61 @@ void LoopUnswitch::UnswitchNontrivialCondition(Value *LIC, Constant *Val, EmitPreheaderBranchOnCondition(LIC, Val, NewBlocks[0], LoopBlocks[0], OldBR); OldBR->eraseFromParent(); LPM->deleteSimpleAnalysisValue(OldBR, L); - + + // Update dominator info + if (DF && DT) { + + // Clone dominator info for all cloned basic block. + for (unsigned i = 0, e = LoopBlocks.size(); i != e; ++i) { + BasicBlock *LBB = LoopBlocks[i]; + BasicBlock *NBB = NewBlocks[i]; + CloneDomInfo(NBB, LBB, NewPreheader, OrigPreheader, + OrigHeader, DT, DF, ValueMap); + + // Remove any OutSiders from LBB and NBB's dominance frontier. + DominanceFrontier::iterator LBBI = DF->find(LBB); + if (LBBI != DF->end()) { + DominanceFrontier::DomSetType &LBSet = LBBI->second; + for (DominanceFrontier::DomSetType::iterator LI = LBSet.begin(), + LE = LBSet.end(); LI != LE; ++LI) { + BasicBlock *B = *LI; + if (OutSiders.count(B)) + DF->removeFromFrontier(LBBI, B); + } + } + + // Remove any OutSiders from LBB and NBB's dominance frontier. + DominanceFrontier::iterator NBBI = DF->find(NBB); + if (NBBI != DF->end()) { + DominanceFrontier::DomSetType NBSet = NBBI->second; + for (DominanceFrontier::DomSetType::iterator NI = NBSet.begin(), + NE = NBSet.end(); NI != NE; ++NI) { + BasicBlock *B = *NI; + if (OutSiders.count(B)) + DF->removeFromFrontier(NBBI, B); + } + } + } + + // MiddleBlocks are dominated by original pre header. SplitEdge updated + // MiddleBlocks' dominance frontier appropriately. + for (unsigned i = 0, e = MiddleBlocks.size(); i != e; ++i) { + BasicBlock *MBB = MiddleBlocks[i]; + DT->changeImmediateDominator(MBB, OrigPreheader); + } + + // All Outsiders are now dominated by original pre header. + for (SmallPtrSet<BasicBlock *, 8>::iterator OI = OutSiders.begin(), + OE = OutSiders.end(); OI != OE; ++OI) { + BasicBlock *OB = *OI; + DT->changeImmediateDominator(OB, OrigPreheader); + } + + // New loop headers are dominated by original preheader + DT->changeImmediateDominator(NewBlocks[0], OrigPreheader); + DT->changeImmediateDominator(LoopBlocks[0], OrigPreheader); + } + LoopProcessWorklist.push_back(NewLoop); redoLoop = true; |