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.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50199 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Chris Lattner 2008-04-24 00:01:19 +00:00
parent 3c02aca238
commit c9e495c534
2 changed files with 146 additions and 65 deletions

View File

@ -1165,6 +1165,105 @@ static bool FoldTwoEntryPHINode(PHINode *PN) {
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 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
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())) {

View File

@ -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