diff options
author | Owen Anderson <resistor@mac.com> | 2008-07-17 00:01:40 +0000 |
---|---|---|
committer | Owen Anderson <resistor@mac.com> | 2008-07-17 00:01:40 +0000 |
commit | b31b06d04b81c5383e2fba0cd44d4ba3f324a794 (patch) | |
tree | 550a9ec8e53cd9d7eac0538e6b2322fed375d56e /lib/Transforms/Utils/BasicBlockUtils.cpp | |
parent | 413907000e6949849e4b9c2fabda7105f8bedabd (diff) |
Factor MergeBlockIntoPredecessor out into BasicBlockUtils.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@53705 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Transforms/Utils/BasicBlockUtils.cpp')
-rw-r--r-- | lib/Transforms/Utils/BasicBlockUtils.cpp | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/lib/Transforms/Utils/BasicBlockUtils.cpp b/lib/Transforms/Utils/BasicBlockUtils.cpp index 93a8c8e593..02eb4d6f60 100644 --- a/lib/Transforms/Utils/BasicBlockUtils.cpp +++ b/lib/Transforms/Utils/BasicBlockUtils.cpp @@ -23,6 +23,58 @@ #include <algorithm> using namespace llvm; +/// MergeBlockIntoPredecessor - Attempts to merge a block into its predecessor, +/// if possible. The return value indicates success or failure. +bool llvm::MergeBlockIntoPredecessor(BasicBlock* BB, Pass* P) { + // Can't merge the entry block. + if (pred_begin(BB) == pred_end(BB)) return false; + // Can't merge if there are multiple preds. + if (++pred_begin(BB) != pred_end(BB)) return false; + + BasicBlock* PredBB = *pred_begin(BB); + + // Can't merge if the edge is critical. + if (PredBB->getTerminator()->getNumSuccessors() != 1) return false; + + // Begin by getting rid of unneeded PHIs. + while (PHINode *PN = dyn_cast<PHINode>(&BB->front())) { + PN->replaceAllUsesWith(PN->getIncomingValue(0)); + BB->getInstList().pop_front(); // Delete the phi node... + } + + // Delete the unconditional branch from the predecessor... + PredBB->getInstList().pop_back(); + + // Move all definitions in the successor to the predecessor... + PredBB->getInstList().splice(PredBB->end(), BB->getInstList()); + + // Make all PHI nodes that referred to BB now refer to Pred as their + // source... + BB->replaceAllUsesWith(PredBB); + + // Finally, erase the old block and update dominator info. + if (P) { + if (DominatorTree* DT = P->getAnalysisToUpdate<DominatorTree>()) { + DomTreeNode* DTN = DT->getNode(BB); + DomTreeNode* PredDTN = DT->getNode(PredBB); + + if (DTN) { + SmallPtrSet<DomTreeNode*, 8> Children(DTN->begin(), DTN->end()); + for (SmallPtrSet<DomTreeNode*, 8>::iterator DI = Children.begin(), + DE = Children.end(); DI != DE; ++DI) + DT->changeImmediateDominator(*DI, PredDTN); + + DT->eraseNode(BB); + } + } + } + + BB->eraseFromParent(); + + + return true; +} + /// ReplaceInstWithValue - Replace all uses of an instruction (specified by BI) /// with a value, then remove and delete the original instruction. /// |