aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/SelectionDAG
diff options
context:
space:
mode:
authorArnold Schwaighofer <arnold.schwaighofer@gmail.com>2009-03-28 12:36:29 +0000
committerArnold Schwaighofer <arnold.schwaighofer@gmail.com>2009-03-28 12:36:29 +0000
commit11ff97801b93af0d36244fd5877b1552cdfa0a86 (patch)
tree943fc04f501a9c9f37e4b825b4ad45f74f572b0f /lib/CodeGen/SelectionDAG
parentbc14dd30a8e03e28c9d28ab4c5b6e52e8d7c8d26 (diff)
downloadexternal_llvm-11ff97801b93af0d36244fd5877b1552cdfa0a86.zip
external_llvm-11ff97801b93af0d36244fd5877b1552cdfa0a86.tar.gz
external_llvm-11ff97801b93af0d36244fd5877b1552cdfa0a86.tar.bz2
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
Diffstat (limited to 'lib/CodeGen/SelectionDAG')
-rw-r--r--lib/CodeGen/SelectionDAG/TargetLowering.cpp50
1 files changed, 32 insertions, 18 deletions
diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
index 1efc4a6..3f0bf5b 100644
--- a/lib/CodeGen/SelectionDAG/TargetLowering.cpp
+++ b/lib/CodeGen/SelectionDAG/TargetLowering.cpp
@@ -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;
}