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

Chris Lattner lattner at cs.uiuc.edu
Fri Apr 2 14:38:26 PST 2004


Changes in directory llvm/lib/Transforms/Utils:

SimplifyCFG.cpp updated: 1.32 -> 1.33

---
Log message:

Implement Transforms/SimplifyCFG/return-merge.ll

This actually causes us to turn code like:

  return C ? A : B; 

into a select instruction.



---
Diffs of the changes:  (+57 -1)

Index: llvm/lib/Transforms/Utils/SimplifyCFG.cpp
diff -u llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.32 llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.33
--- llvm/lib/Transforms/Utils/SimplifyCFG.cpp:1.32	Tue Mar 30 13:44:05 2004
+++ llvm/lib/Transforms/Utils/SimplifyCFG.cpp	Fri Apr  2 12:13:43 2004
@@ -613,16 +613,23 @@
 
   // If this is a returning block with only PHI nodes in it, fold the return
   // instruction into any unconditional branch predecessors.
+  //
+  // If any predecessor is a conditional branch that just selects among
+  // different return values, fold the replace the branch/return with a select
+  // and return.
   if (ReturnInst *RI = dyn_cast<ReturnInst>(BB->getTerminator())) {
     BasicBlock::iterator BBI = BB->getTerminator();
     if (BBI == BB->begin() || isa<PHINode>(--BBI)) {
-      // Find predecessors that end with unconditional branches.
+      // Find predecessors that end with branches.
       std::vector<BasicBlock*> UncondBranchPreds;
+      std::vector<BranchInst*> CondBranchPreds;
       for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
         TerminatorInst *PTI = (*PI)->getTerminator();
         if (BranchInst *BI = dyn_cast<BranchInst>(PTI))
           if (BI->isUnconditional())
             UncondBranchPreds.push_back(*PI);
+          else
+            CondBranchPreds.push_back(BI);
       }
       
       // If we found some, do the transformation!
@@ -653,6 +660,55 @@
           M->getBasicBlockList().erase(BB);
 
         return true;
+      }
+
+      // Check out all of the conditional branches going to this return
+      // instruction.  If any of them just select between returns, change the
+      // branch itself into a select/return pair.
+      while (!CondBranchPreds.empty()) {
+        BranchInst *BI = CondBranchPreds.back();
+        CondBranchPreds.pop_back();
+        BasicBlock *TrueSucc = BI->getSuccessor(0);
+        BasicBlock *FalseSucc = BI->getSuccessor(1);
+        BasicBlock *OtherSucc = TrueSucc == BB ? FalseSucc : TrueSucc;
+
+        // Check to see if the non-BB successor is also a return block.
+        if (isa<ReturnInst>(OtherSucc->getTerminator())) {
+          // Check to see if there are only PHI instructions in this block.
+          BasicBlock::iterator OSI = OtherSucc->getTerminator();
+          if (OSI == OtherSucc->begin() || isa<PHINode>(--OSI)) {
+            // Okay, we found a branch that is going to two return nodes.  If
+            // there is no return value for this function, just change the
+            // branch into a return.
+            if (RI->getNumOperands() == 0) {
+              TrueSucc->removePredecessor(BI->getParent());
+              FalseSucc->removePredecessor(BI->getParent());
+              new ReturnInst(0, BI);
+              BI->getParent()->getInstList().erase(BI);
+              return true;
+            }
+
+            // Otherwise, figure out what the true and false return values are
+            // so we can insert a new select instruction.
+            Value *TrueValue = TrueSucc->getTerminator()->getOperand(0);
+            Value *FalseValue = FalseSucc->getTerminator()->getOperand(0);
+
+            // Unwrap any PHI nodes in the return blocks.
+            if (PHINode *TVPN = dyn_cast<PHINode>(TrueValue))
+              if (TVPN->getParent() == TrueSucc)
+                TrueValue = TVPN->getIncomingValueForBlock(BI->getParent());
+            if (PHINode *FVPN = dyn_cast<PHINode>(FalseValue))
+              if (FVPN->getParent() == FalseSucc)
+                FalseValue = FVPN->getIncomingValueForBlock(BI->getParent());
+
+            // Insert a new select instruction.
+            Value *NewRetVal = new SelectInst(BI->getCondition(), TrueValue,
+                                              FalseValue, "retval", BI);
+            new ReturnInst(NewRetVal, BI);
+            BI->getParent()->getInstList().erase(BI);
+            return true;
+          }
+        }
       }
     }
   } else if (UnwindInst *UI = dyn_cast<UnwindInst>(BB->begin())) {





More information about the llvm-commits mailing list