[llvm-commits] [llvm] r50199 - in /llvm/trunk: lib/Transforms/Utils/SimplifyCFG.cpp test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll

Chris Lattner sabre at nondot.org
Wed Apr 23 17:01:20 PDT 2008


Author: lattner
Date: Wed Apr 23 19:01:19 2008
New Revision: 50199

URL: http://llvm.org/viewvc/llvm-project?rev=50199&view=rev
Log:
Split some code out of the main SimplifyCFG loop into its own function.
Fix said code to handle merging return instructions together correctly
when handling multiple return values.

Added:
    llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll
Modified:
    llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp

Modified: llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp?rev=50199&r1=50198&r2=50199&view=diff

==============================================================================
--- llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/SimplifyCFG.cpp Wed Apr 23 19:01:19 2008
@@ -1165,6 +1165,105 @@
   return true;
 }
 
+/// SimplifyCondBranchToTwoReturns - If we found a conditional branch that goes
+/// to two returning blocks, try to merge them together into one return,
+/// introducing a select if the return values disagree.
+static bool SimplifyCondBranchToTwoReturns(BranchInst *BI) {
+  assert(BI->isConditional() && "Must be a conditional branch");
+  BasicBlock *TrueSucc = BI->getSuccessor(0);
+  BasicBlock *FalseSucc = BI->getSuccessor(1);
+  ReturnInst *TrueRet = cast<ReturnInst>(TrueSucc->getTerminator());
+  ReturnInst *FalseRet = cast<ReturnInst>(FalseSucc->getTerminator());
+  
+  // Check to ensure both blocks are empty (just a return) or optionally empty
+  // with PHI nodes.  If there are other instructions, merging would cause extra
+  // computation on one path or the other.
+  BasicBlock::iterator BBI = TrueRet;
+  if (BBI != TrueSucc->begin() && !isa<PHINode>(--BBI))
+    return false;  // Not empty with optional phi nodes.
+  BBI = FalseRet;
+  if (BBI != FalseSucc->begin() && !isa<PHINode>(--BBI))
+    return false;  // Not empty with optional phi nodes.
+
+  // 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 (FalseRet->getNumOperands() == 0) {
+    TrueSucc->removePredecessor(BI->getParent());
+    FalseSucc->removePredecessor(BI->getParent());
+    ReturnInst::Create(0, BI);
+    BI->eraseFromParent();
+    return true;
+  }
+    
+  // Otherwise, build up the result values for the new return.
+  SmallVector<Value*, 4> TrueResult;
+  SmallVector<Value*, 4> FalseResult;
+  
+  for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) {
+    // Otherwise, figure out what the true and false return values are
+    // so we can insert a new select instruction.
+    Value *TrueValue = TrueRet->getOperand(i);
+    Value *FalseValue = FalseRet->getOperand(i);
+    
+    // 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());
+    
+    // In order for this transformation to be safe, we must be able to
+    // unconditionally execute both operands to the return.  This is
+    // normally the case, but we could have a potentially-trapping
+    // constant expression that prevents this transformation from being
+    // safe.
+    if (ConstantExpr *TCV = dyn_cast<ConstantExpr>(TrueValue))
+      if (TCV->canTrap())
+        return false;
+    if (ConstantExpr *FCV = dyn_cast<ConstantExpr>(FalseValue))
+      if (FCV->canTrap())
+        return false;
+    
+    TrueResult.push_back(TrueValue);
+    FalseResult.push_back(FalseValue);
+  }
+
+  // Okay, we collected all the mapped values and checked them for sanity, and
+  // defined to really do this transformation.  First, update the CFG.
+  TrueSucc->removePredecessor(BI->getParent());
+  FalseSucc->removePredecessor(BI->getParent());
+  
+  // Insert select instructions where needed.
+  Value *BrCond = BI->getCondition();
+  for (unsigned i = 0, e = TrueRet->getNumOperands(); i != e; ++i) {
+    // Insert a select if the results differ.
+    if (TrueResult[i] == FalseResult[i] || isa<UndefValue>(FalseResult[i]))
+      continue;
+    if (isa<UndefValue>(TrueResult[i])) {
+      TrueResult[i] = FalseResult[i];
+      continue;
+    }
+    
+    TrueResult[i] = SelectInst::Create(BrCond, TrueResult[i],
+                                       FalseResult[i], "retval", BI);
+  }
+
+  Value *RI = ReturnInst::Create(&TrueResult[0], TrueResult.size(), BI);
+      
+  DOUT << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
+       << "\n  " << *BI << "NewRet = " << *RI
+       << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc;
+      
+  BI->eraseFromParent();
+  
+  if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
+    ErasePossiblyDeadInstructionTree(BrCondI);
+  return true;
+}
+
+
 namespace {
   /// ConstantIntOrdering - This class implements a stable ordering of constant
   /// integers that does not depend on their address.  This is important for
@@ -1292,73 +1391,12 @@
       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());
-              ReturnInst::Create(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());
-
-            // In order for this transformation to be safe, we must be able to
-            // unconditionally execute both operands to the return.  This is
-            // normally the case, but we could have a potentially-trapping
-            // constant expression that prevents this transformation from being
-            // safe.
-            if ((!isa<ConstantExpr>(TrueValue) ||
-                 !cast<ConstantExpr>(TrueValue)->canTrap()) &&
-                (!isa<ConstantExpr>(TrueValue) ||
-                 !cast<ConstantExpr>(TrueValue)->canTrap())) {
-              TrueSucc->removePredecessor(BI->getParent());
-              FalseSucc->removePredecessor(BI->getParent());
-
-              // Insert a new select instruction.
-              Value *NewRetVal;
-              Value *BrCond = BI->getCondition();
-              if (TrueValue != FalseValue)
-                NewRetVal = SelectInst::Create(BrCond, TrueValue,
-                                               FalseValue, "retval", BI);
-              else
-                NewRetVal = TrueValue;
-              
-              DOUT << "\nCHANGING BRANCH TO TWO RETURNS INTO SELECT:"
-                   << "\n  " << *BI << "Select = " << *NewRetVal
-                   << "TRUEBLOCK: " << *TrueSucc << "FALSEBLOCK: "<< *FalseSucc;
-
-              ReturnInst::Create(NewRetVal, BI);
-              BI->eraseFromParent();
-              if (Instruction *BrCondI = dyn_cast<Instruction>(BrCond))
-                if (isInstructionTriviallyDead(BrCondI))
-                  BrCondI->eraseFromParent();
-              return true;
-            }
-          }
-        }
+        if (isa<ReturnInst>(BI->getSuccessor(0)->getTerminator()) &&
+            isa<ReturnInst>(BI->getSuccessor(1)->getTerminator()) &&
+            SimplifyCondBranchToTwoReturns(BI))
+          return true;
       }
     }
   } else if (isa<UnwindInst>(BB->begin())) {

Added: llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll?rev=50199&view=auto

==============================================================================
--- llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll (added)
+++ llvm/trunk/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll Wed Apr 23 19:01:19 2008
@@ -0,0 +1,43 @@
+; RUN: llvm-as < %s | opt -simplifycfg -disable-output
+; rdar://5882392
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128"
+target triple = "x86_64-apple-darwin9"
+	%struct.Py_complex = type { double, double }
+
+define %struct.Py_complex @_Py_c_pow(double %a.0, double %a.1, double %b.0, double %b.1) nounwind  {
+entry:
+	%tmp7 = fcmp une double %b.0, 0.000000e+00		; <i1> [#uses=1]
+	%tmp11 = fcmp une double %b.1, 0.000000e+00		; <i1> [#uses=1]
+	%bothcond = or i1 %tmp7, %tmp11		; <i1> [#uses=1]
+	br i1 %bothcond, label %bb15, label %bb53
+
+bb15:		; preds = %entry
+	%tmp18 = fcmp une double %a.0, 0.000000e+00		; <i1> [#uses=1]
+	%tmp24 = fcmp une double %a.1, 0.000000e+00		; <i1> [#uses=1]
+	%bothcond1 = or i1 %tmp18, %tmp24		; <i1> [#uses=1]
+	br i1 %bothcond1, label %bb29, label %bb27
+
+bb27:		; preds = %bb15
+	%tmp28 = call i32* @__error( ) nounwind 		; <i32*> [#uses=1]
+	store i32 33, i32* %tmp28, align 4
+	ret double undef, double undef
+
+bb29:		; preds = %bb15
+	%tmp36 = fcmp une double %b.1, 0.000000e+00		; <i1> [#uses=1]
+	br i1 %tmp36, label %bb39, label %bb47
+
+bb39:		; preds = %bb29
+	br label %bb47
+
+bb47:		; preds = %bb39, %bb29
+	ret double undef, double undef
+
+bb53:		; preds = %entry
+	ret double undef, double undef
+}
+
+declare i32* @__error()
+
+declare double @pow(double, double) nounwind readonly 
+
+declare double @cos(double) nounwind readonly 





More information about the llvm-commits mailing list