Expose a smarter way to break critical edges.
authorChris Lattner <sabre@nondot.org>
Sat, 28 Oct 2006 06:44:56 +0000 (06:44 +0000)
committerChris Lattner <sabre@nondot.org>
Sat, 28 Oct 2006 06:44:56 +0000 (06:44 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@31256 91177308-0d34-0410-b5e6-96231b3b80d8

include/llvm/Transforms/Utils/BasicBlockUtils.h
lib/Transforms/Utils/BreakCriticalEdges.cpp

index 3853901b30caa8366478fd94e5a3fde5e2cf6267..0bfb6f750aa97f1adf050454c7f8cfca2e8d8b07 100644 (file)
@@ -63,9 +63,15 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum);
 /// split the critical edge.  This will update DominatorSet, ImmediateDominator,
 /// DominatorTree, and DominatorFrontier information if it is available, thus
 /// calling this pass will not invalidate either of them.  This returns true if
-/// the edge was split, false otherwise.
+/// the edge was split, false otherwise.  If MergeIdenticalEdges is true (the
+/// default), *all* edges from TI to the specified successor will be merged into
+/// the same critical edge block.  This is most commonly interesting with switch
+/// instructions, which may have many edges to any one destination.  This
+/// ensures that all edges to that dest go to one block instead of each going to
+/// a different block, but isn't the standard definition of a "critical edge".
 ///
-bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0);
+bool SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P = 0,
+                       bool MergeIdenticalEdges = false);
 
 inline bool SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, Pass *P = 0) {
   return SplitCriticalEdge(BB->getTerminator(), SI.getSuccessorIndex(), P);
@@ -89,13 +95,14 @@ inline bool SplitCriticalEdge(BasicBlock *Succ, pred_iterator PI, Pass *P = 0) {
 /// and return true, otherwise return false.  This method requires that there be
 /// an edge between the two blocks.  If P is specified, it updates the analyses
 /// described above.
-inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0) {
+inline bool SplitCriticalEdge(BasicBlock *Src, BasicBlock *Dst, Pass *P = 0,
+                              bool MergeIdenticalEdges = false) {
   TerminatorInst *TI = Src->getTerminator();
   unsigned i = 0;
   while (1) {
     assert(i != TI->getNumSuccessors() && "Edge doesn't exist!");
     if (TI->getSuccessor(i) == Dst)
-      return SplitCriticalEdge(TI, i, P);
+      return SplitCriticalEdge(TI, i, P, MergeIdenticalEdges);
     ++i;
   }
 }
index d4e186cabb2cb1cbba40b356aca74a1b18b7cb21..5bb513fc3bd3fed14d08959bf90afceb8838fafd 100644 (file)
@@ -100,10 +100,12 @@ bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum) {
 // SplitCriticalEdge - If this edge is a critical edge, insert a new node to
 // split the critical edge.  This will update DominatorSet, ImmediateDominator,
 // DominatorTree, and DominatorFrontier information if it is available, thus
-// calling this pass will not invalidate either of them.  This returns true if
-// the edge was split, false otherwise.
+// calling this pass will not invalidate any of them.  This returns true if
+// the edge was split, false otherwise.  This ensures that all edges to that
+// dest go to one block instead of each going to a different block.
 //
-bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) {
+bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P,
+                             bool MergeIdenticalEdges) {
   if (!isCriticalEdge(TI, SuccNum)) return false;
   BasicBlock *TIBB = TI->getParent();
   BasicBlock *DestBB = TI->getSuccessor(SuccNum);
@@ -114,13 +116,13 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) {
   // Create our unconditional branch...
   new BranchInst(DestBB, NewBB);
 
-  // Branch to the new block, breaking the edge...
+  // Branch to the new block, breaking the edge.
   TI->setSuccessor(SuccNum, NewBB);
 
   // Insert the block into the function... right after the block TI lives in.
   Function &F = *TIBB->getParent();
   F.getBasicBlockList().insert(TIBB->getNext(), NewBB);
-
+  
   // If there are any PHI nodes in DestBB, we need to update them so that they
   // merge incoming values from NewBB instead of from TIBB.
   //
@@ -132,6 +134,23 @@ bool llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, Pass *P) {
     int BBIdx = PN->getBasicBlockIndex(TIBB);
     PN->setIncomingBlock(BBIdx, NewBB);
   }
+  
+  // If there are any other edges from TIBB to DestBB, update those to go
+  // through the split block, making those edges non-critical as well (and
+  // reducing the number of phi entries in the DestBB if relevant).
+  if (MergeIdenticalEdges) {
+    for (unsigned i = SuccNum+1, e = TI->getNumSuccessors(); i != e; ++i) {
+      if (TI->getSuccessor(i) != DestBB) continue;
+      
+      // Remove an entry for TIBB from DestBB phi nodes.
+      DestBB->removePredecessor(TIBB);
+      
+      // We found another edge to DestBB, go to NewBB instead.
+      TI->setSuccessor(i, NewBB);
+    }
+  }
+  
+  
 
   // If we don't have a pass object, we can't update anything...
   if (P == 0) return true;