aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms/Utils/BasicBlockUtils.cpp
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2008-07-17 00:01:40 +0000
committerOwen Anderson <resistor@mac.com>2008-07-17 00:01:40 +0000
commitb31b06d04b81c5383e2fba0cd44d4ba3f324a794 (patch)
tree550a9ec8e53cd9d7eac0538e6b2322fed375d56e /lib/Transforms/Utils/BasicBlockUtils.cpp
parent413907000e6949849e4b9c2fabda7105f8bedabd (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.cpp52
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.
///