[llvm-commits] CVS: llvm/lib/Transforms/Utils/SimplifyCFG.cpp

Chris Lattner lattner at cs.uiuc.edu
Mon Sep 19 17:43:28 PDT 2005



Changes in directory llvm/lib/Transforms/Utils:

SimplifyCFG.cpp updated: 1.85 -> 1.86
---
Log message:

Implement merging of blocks with the same condition if the block has multiple
predecessors.  This implements branch-phi-thread.ll::test1


---
Diffs of the changes:  (+59 -21)

 SimplifyCFG.cpp |   80 +++++++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 59 insertions(+), 21 deletions(-)


Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff -u llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.85 llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.86
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.85	Mon Sep 19 18:57:04 2005
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp	Mon Sep 19 19:43:16 2005
@@ -890,6 +890,26 @@
   return true;
 }
 
+/// BlockIsSimpleEnoughToThreadThrough - Return true if we can thread a branch
+/// across this block.
+static bool BlockIsSimpleEnoughToThreadThrough(BasicBlock *BB) {
+  BranchInst *BI = cast<BranchInst>(BB->getTerminator());
+  Value *Cond = BI->getCondition();
+  
+  // If this basic block contains anything other than a PHI (which controls the
+  // branch) and branch itself, bail out.  FIXME: improve this in the future.
+  for (BasicBlock::iterator BBI = BB->begin(); &*BBI != BI; ++BBI) {
+    if (!isa<PHINode>(BBI)) return false;
+    
+    if (&*BBI != Cond || !Cond->hasOneUse())
+      return false;
+    
+    // Looks ok, continue checking.
+  }
+  
+  return true;
+}
+
 /// FoldCondBranchOnPHI - If we have a conditional branch on a PHI node value
 /// that is defined in the same block as the branch and if any PHI entries are
 /// constants, thread edges corresponding to that entry to be branches to their
@@ -899,7 +919,8 @@
   PHINode *PN = dyn_cast<PHINode>(BI->getCondition());
   // NOTE: we currently cannot transform this case if the PHI node is used
   // outside of the block.
-  if (!PN || PN->getParent() != BB || !PN->hasOneUse()) return false;
+  if (!PN || PN->getParent() != BB || !PN->hasOneUse())
+    return false;
   
   // Degenerate case of a single entry PHI.
   if (PN->getNumIncomingValues() == 1) {
@@ -912,12 +933,7 @@
   }
 
   // Now we know that this block has multiple preds and two succs.
-
-  // If this basic block contains anything other than the PHI and branch, bail
-  // out.  FIXME: improve this in the future.
-  BasicBlock::iterator BBI = BB->begin();
-  if (&*BBI != PN || &*++BBI != BI)
-    return false;
+  if (!BlockIsSimpleEnoughToThreadThrough(BB)) return false;
   
   // Okay, this is a simple enough basic block.  See if any phi values are
   // constants.
@@ -1272,22 +1288,44 @@
                 }
               }
 
-      // If this block ends with a branch instruction, and if there is one
-      // predecessor, see if the previous block ended with a branch on the same
-      // condition, which makes this conditional branch redundant.
-      if (BasicBlock *OnlyPred = BB->getSinglePredecessor())
-        if (BranchInst *PBI = dyn_cast<BranchInst>(OnlyPred->getTerminator()))
-          if (PBI->isConditional() &&
+      // If this block ends with a branch instruction, and if there is a
+      // predecessor that ends on a branch of the same condition, make this 
+      // conditional branch redundant.
+      for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+        if (BranchInst *PBI = dyn_cast<BranchInst>((*PI)->getTerminator()))
+          if (PBI != BI && PBI->isConditional() &&
               PBI->getCondition() == BI->getCondition() &&
-              (PBI->getSuccessor(0) != BB || PBI->getSuccessor(1) != BB)) {
+              PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
             // Okay, the outcome of this conditional branch is statically
-            // knowable.  Delete the outgoing CFG edge that is impossible to
-            // execute.
-            bool CondIsTrue = PBI->getSuccessor(0) == BB;
-            BI->getSuccessor(CondIsTrue)->removePredecessor(BB);
-            new BranchInst(BI->getSuccessor(!CondIsTrue), BB);
-            BB->getInstList().erase(BI);
-            return SimplifyCFG(BB) | true;
+            // knowable.  If this block had a single pred, handle specially.
+            if (BB->getSinglePredecessor()) {
+              // Turn this into a branch on constant.
+              bool CondIsTrue = PBI->getSuccessor(0) == BB;
+              BI->setCondition(ConstantBool::get(CondIsTrue));
+              return SimplifyCFG(BB);  // Nuke the branch on constant.
+            }
+            
+            // Otherwise, if there are multiple predecessors, insert a PHI that
+            // merges in the constant and simplify the block result.
+            if (BlockIsSimpleEnoughToThreadThrough(BB)) {
+              PHINode *NewPN = new PHINode(Type::BoolTy,
+                                           BI->getCondition()->getName()+".pr",
+                                           BB->begin());
+              for (PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI)
+                if ((PBI = dyn_cast<BranchInst>((*PI)->getTerminator())) &&
+                    PBI != BI && PBI->isConditional() &&
+                    PBI->getCondition() == BI->getCondition() &&
+                    PBI->getSuccessor(0) != PBI->getSuccessor(1)) {
+                  bool CondIsTrue = PBI->getSuccessor(0) == BB;
+                  NewPN->addIncoming(ConstantBool::get(CondIsTrue), *PI);
+                } else {
+                  NewPN->addIncoming(BI->getCondition(), *PI);
+                }
+              
+              BI->setCondition(NewPN);
+              // This will thread the branch.
+              return SimplifyCFG(BB) | true;
+            }
           }
     }
   } else if (isa<UnreachableInst>(BB->getTerminator())) {






More information about the llvm-commits mailing list