Export ConstantFoldTerminator, allow it to fold conditional branches to
authorChris Lattner <sabre@nondot.org>
Fri, 29 Jun 2001 23:56:58 +0000 (23:56 +0000)
committerChris Lattner <sabre@nondot.org>
Fri, 29 Jun 2001 23:56:58 +0000 (23:56 +0000)
the same label.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@107 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ConstantProp.cpp

index 2df4f01a7e6c68df535b9c84203d5d0e60cc9617..51800f5a6b6cc9657855ac7b6be31c6c8a3cc79e 100644 (file)
@@ -120,28 +120,50 @@ ConstantFoldBinaryInst(Method *M, Method::inst_iterator &DI,
   return true;
 }
 
-inline static bool ConstantFoldTerminator(TerminatorInst *T) {
+// ConstantFoldTerminator - If a terminator instruction is predicated on a
+// constant value, convert it into an unconditional branch to the constant
+// destination.
+//
+bool ConstantFoldTerminator(TerminatorInst *T) {
   // Branch - See if we are conditional jumping on constant
   if (T->getInstType() == Instruction::Br) {
     BranchInst *BI = (BranchInst*)T;
-    if (!BI->isUnconditional() &&              // Are we branching on constant?
-        BI->getOperand(2)->isConstant()) {
+    if (BI->isUnconditional()) return false;  // Can't optimize uncond branch
+    BasicBlock *Dest1 = BI->getOperand(0)->castBasicBlockAsserting();
+    BasicBlock *Dest2 = BI->getOperand(1)->castBasicBlockAsserting();
+
+    if (BI->getOperand(2)->isConstant()) {    // Are we branching on constant?
       // YES.  Change to unconditional branch...
       ConstPoolBool *Cond = (ConstPoolBool*)BI->getOperand(2);
-      Value *Destination = BI->getOperand(Cond->getValue() ? 0 : 1);
-      Value *OldDest     = BI->getOperand(Cond->getValue() ? 1 : 0);
+      BasicBlock *Destination = Cond->getValue() ? Dest1 : Dest2;
+      BasicBlock *OldDest     = Cond->getValue() ? Dest2 : Dest1;
 
-      //cerr << "Method: " << T->getParent()->getParent() << "\nRemoving branch from " << T->getParent() << "\n\nTo: " << OldDest << endl;
+      //cerr << "Method: " << T->getParent()->getParent() 
+      //     << "\nRemoving branch from " << T->getParent() 
+      //     << "\n\nTo: " << OldDest << endl;
 
       // Let the basic block know that we are letting go of it.  Based on this,
       // it will adjust it's PHI nodes.
-      assert(T->getParent() && "Terminator not inserted in block!");
-      OldDest->castBasicBlockAsserting()->removePredecessor(T->getParent());
+      assert(BI->getParent() && "Terminator not inserted in block!");
+      OldDest->removePredecessor(BI->getParent());
 
       BI->setOperand(0, Destination);  // Set the unconditional destination
       BI->setOperand(1, 0);            // Clear the conditional destination
       BI->setOperand(2, 0);            // Clear the condition...
       return true;
+    } else if (Dest2 == Dest1) {       // Conditional branch to same location?
+      // This branch matches something like this:  
+      //     br bool %cond, label %Dest, label %Dest
+      // and changes it into:  br label %Dest
+
+      // Let the basic block know that we are letting go of one copy of it.
+      assert(BI->getParent() && "Terminator not inserted in block!");
+      Dest1->removePredecessor(BI->getParent());
+
+      // Nuke the second destination, and the use of the condition variable
+      BI->setOperand(1, 0);            // Clear the conditional destination
+      BI->setOperand(2, 0);            // Clear the condition...
+      return true;
     }
   }
   return false;