Make check in CheckTailCallReturnConstraints for ignorable instructions between

a CALL and a RET node more generic. Add a test for tail calls with a void
return.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@67943 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Arnold Schwaighofer 2009-03-28 12:36:29 +00:00
parent bc14dd30a8
commit 11ff97801b
2 changed files with 38 additions and 18 deletions

View File

@ -2572,26 +2572,40 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG,
}
}
bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret) {
/// IgnoreHarmlessInstructions - Ignore instructions between a CALL and RET
/// node that don't prevent tail call optimization.
static SDValue IgnoreHarmlessInstructions(SDValue node) {
// Found call return.
if (node.getOpcode() == ISD::CALL) return node;
// Ignore MERGE_VALUES. Will have at least one operand.
if (node.getOpcode() == ISD::MERGE_VALUES)
return IgnoreHarmlessInstructions(node.getOperand(0));
// Ignore ANY_EXTEND node.
if (node.getOpcode() == ISD::ANY_EXTEND)
return IgnoreHarmlessInstructions(node.getOperand(0));
if (node.getOpcode() == ISD::TRUNCATE)
return IgnoreHarmlessInstructions(node.getOperand(0));
// Any other node type.
return node;
}
bool TargetLowering::CheckTailCallReturnConstraints(CallSDNode *TheCall,
SDValue Ret) {
unsigned NumOps = Ret.getNumOperands();
// Struct return.
if(NumOps >= 5&&
Ret.getOperand(1).getOpcode()==ISD::MERGE_VALUES &&
Ret.getOperand(1).getOperand(0) == SDValue(TheCall, 0))
// ISD::CALL results:(value0, ..., valuen, chain)
// ISD::RET operands:(chain, value0, flag0, ..., valuen, flagn)
// Value return:
// Check that operand of the RET node sources from the CALL node. The RET node
// has at least two operands. Operand 0 holds the chain. Operand 1 holds the
// value.
if (NumOps > 1 &&
IgnoreHarmlessInstructions(Ret.getOperand(1)) == SDValue(TheCall,0))
return true;
if ((NumOps == 1 &&
(Ret.getOperand(0) == SDValue(TheCall,1) ||
Ret.getOperand(0) == SDValue(TheCall,0))) ||
(NumOps == 3 &&
Ret.getOperand(1).getOpcode() == ISD::ANY_EXTEND &&
Ret.getOperand(1).getNumOperands()>0 &&
Ret.getOperand(1).getOperand(0).getOpcode() == ISD::TRUNCATE &&
Ret.getOperand(1).getOperand(0).getNumOperands()>0 &&
Ret.getOperand(1).getOperand(0).getOperand(0) == SDValue(TheCall, 0)) ||
(NumOps > 1 &&
Ret.getOperand(0) == SDValue(TheCall,
TheCall->getNumValues()-1) &&
Ret.getOperand(1) == SDValue(TheCall,0)))
// void return: The RET node has the chain result value of the CALL node as
// input.
if (NumOps == 1 &&
Ret.getOperand(0) == SDValue(TheCall, TheCall->getNumValues()-1))
return true;
return false;
}

View File

@ -0,0 +1,6 @@
; RUN: llvm-as < %s | llc -march=x86 -tailcallopt | grep TAILCALL
define fastcc void @i1test(i32, i32, i32, i32) {
entry:
tail call fastcc void @i1test( i32 %0, i32 %1, i32 %2, i32 %3)
ret void
}