From 11ff97801b93af0d36244fd5877b1552cdfa0a86 Mon Sep 17 00:00:00 2001 From: Arnold Schwaighofer Date: Sat, 28 Mar 2009 12:36:29 +0000 Subject: [PATCH] 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 --- lib/CodeGen/SelectionDAG/TargetLowering.cpp | 50 +++++++++++++-------- test/CodeGen/X86/tailcall-void.ll | 6 +++ 2 files changed, 38 insertions(+), 18 deletions(-) create mode 100644 test/CodeGen/X86/tailcall-void.ll diff --git a/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/lib/CodeGen/SelectionDAG/TargetLowering.cpp index 1efc4a677f7..3f0bf5b1a9b 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; } diff --git a/test/CodeGen/X86/tailcall-void.ll b/test/CodeGen/X86/tailcall-void.ll new file mode 100644 index 00000000000..27b2a2856ad --- /dev/null +++ b/test/CodeGen/X86/tailcall-void.ll @@ -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 +}