diff --git a/lib/Transforms/Utils/SimplifyCFG.cpp b/lib/Transforms/Utils/SimplifyCFG.cpp index d11bbb0b647..8b8195ef1e3 100644 --- a/lib/Transforms/Utils/SimplifyCFG.cpp +++ b/lib/Transforms/Utils/SimplifyCFG.cpp @@ -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(TrueSucc->getTerminator()); + ReturnInst *FalseRet = cast(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(--BBI)) + return false; // Not empty with optional phi nodes. + BBI = FalseRet; + if (BBI != FalseSucc->begin() && !isa(--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 TrueResult; + SmallVector 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(TrueValue)) + if (TVPN->getParent() == TrueSucc) + TrueValue = TVPN->getIncomingValueForBlock(BI->getParent()); + if (PHINode *FVPN = dyn_cast(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(TrueValue)) + if (TCV->canTrap()) + return false; + if (ConstantExpr *FCV = dyn_cast(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(FalseResult[i])) + continue; + if (isa(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(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(OtherSucc->getTerminator())) { - // Check to see if there are only PHI instructions in this block. - BasicBlock::iterator OSI = OtherSucc->getTerminator(); - if (OSI == OtherSucc->begin() || isa(--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(TrueValue)) - if (TVPN->getParent() == TrueSucc) - TrueValue = TVPN->getIncomingValueForBlock(BI->getParent()); - if (PHINode *FVPN = dyn_cast(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(TrueValue) || - !cast(TrueValue)->canTrap()) && - (!isa(TrueValue) || - !cast(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(BrCond)) - if (isInstructionTriviallyDead(BrCondI)) - BrCondI->eraseFromParent(); - return true; - } - } - } + if (isa(BI->getSuccessor(0)->getTerminator()) && + isa(BI->getSuccessor(1)->getTerminator()) && + SimplifyCondBranchToTwoReturns(BI)) + return true; } } } else if (isa(BB->begin())) { diff --git a/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll b/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll new file mode 100644 index 00000000000..5ee13526785 --- /dev/null +++ b/test/Transforms/SimplifyCFG/2008-04-23-MergeMultipleResultRet.ll @@ -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 ; [#uses=1] + %tmp11 = fcmp une double %b.1, 0.000000e+00 ; [#uses=1] + %bothcond = or i1 %tmp7, %tmp11 ; [#uses=1] + br i1 %bothcond, label %bb15, label %bb53 + +bb15: ; preds = %entry + %tmp18 = fcmp une double %a.0, 0.000000e+00 ; [#uses=1] + %tmp24 = fcmp une double %a.1, 0.000000e+00 ; [#uses=1] + %bothcond1 = or i1 %tmp18, %tmp24 ; [#uses=1] + br i1 %bothcond1, label %bb29, label %bb27 + +bb27: ; preds = %bb15 + %tmp28 = call i32* @__error( ) nounwind ; [#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 ; [#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