mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-12 17:32:19 +00:00
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:
parent
3c02aca238
commit
c9e495c534
@ -1165,6 +1165,105 @@ static bool FoldTwoEntryPHINode(PHINode *PN) {
|
|||||||
return true;
|
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 {
|
namespace {
|
||||||
/// ConstantIntOrdering - This class implements a stable ordering of constant
|
/// ConstantIntOrdering - This class implements a stable ordering of constant
|
||||||
/// integers that does not depend on their address. This is important for
|
/// integers that does not depend on their address. This is important for
|
||||||
@ -1292,73 +1391,12 @@ bool llvm::SimplifyCFG(BasicBlock *BB) {
|
|||||||
while (!CondBranchPreds.empty()) {
|
while (!CondBranchPreds.empty()) {
|
||||||
BranchInst *BI = CondBranchPreds.back();
|
BranchInst *BI = CondBranchPreds.back();
|
||||||
CondBranchPreds.pop_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.
|
// Check to see if the non-BB successor is also a return block.
|
||||||
if (isa<ReturnInst>(OtherSucc->getTerminator())) {
|
if (isa<ReturnInst>(BI->getSuccessor(0)->getTerminator()) &&
|
||||||
// Check to see if there are only PHI instructions in this block.
|
isa<ReturnInst>(BI->getSuccessor(1)->getTerminator()) &&
|
||||||
BasicBlock::iterator OSI = OtherSucc->getTerminator();
|
SimplifyCondBranchToTwoReturns(BI))
|
||||||
if (OSI == OtherSucc->begin() || isa<PHINode>(--OSI)) {
|
return true;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (isa<UnwindInst>(BB->begin())) {
|
} else if (isa<UnwindInst>(BB->begin())) {
|
||||||
|
@ -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
|
Loading…
x
Reference in New Issue
Block a user