diff --git a/llvm/include/llvm/Target/TargetLowering.h b/llvm/include/llvm/Target/TargetLowering.h index 587666f04a3f..cbe4ca4f5384 100644 --- a/llvm/include/llvm/Target/TargetLowering.h +++ b/llvm/include/llvm/Target/TargetLowering.h @@ -1206,18 +1206,7 @@ public: /// preceeds the RET node and whether the return uses the result of the node /// or is a void return. This function can be used by the target to determine /// eligiblity of tail call optimization. - static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret) { - unsigned NumOps = Ret.getNumOperands(); - if ((NumOps == 1 && - (Ret.getOperand(0) == SDValue(TheCall,1) || - Ret.getOperand(0) == SDValue(TheCall,0))) || - (NumOps > 1 && - Ret.getOperand(0) == SDValue(TheCall, - TheCall->getNumValues()-1) && - Ret.getOperand(1) == SDValue(TheCall,0))) - return true; - return false; - } + static bool CheckTailCallReturnConstraints(CallSDNode *TheCall, SDValue Ret); /// GetPossiblePreceedingTailCall - Get preceeding TailCallNodeOpCode node if /// it exists. Skip a possible ISD::TokenFactor. diff --git a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp index a08dcb2e49d4..1efc4a677f75 100644 --- a/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/TargetLowering.cpp @@ -2571,3 +2571,27 @@ SDValue TargetLowering::BuildUDIV(SDNode *N, SelectionDAG &DAG, DAG.getConstant(magics.s-1, getShiftAmountTy())); } } + +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)) + 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))) + return true; + return false; +} diff --git a/llvm/test/CodeGen/X86/tailcall-i1.ll b/llvm/test/CodeGen/X86/tailcall-i1.ll new file mode 100644 index 000000000000..0ec6a7780722 --- /dev/null +++ b/llvm/test/CodeGen/X86/tailcall-i1.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as < %s | llc -march=x86 -tailcallopt | grep TAILCALL +define fastcc i1 @i1test(i32, i32, i32, i32) { + entry: + %4 = tail call fastcc i1 @i1test( i32 %0, i32 %1, i32 %2, i32 %3) + ret i1 %4 +} diff --git a/llvm/test/CodeGen/X86/tailcall-structret.ll b/llvm/test/CodeGen/X86/tailcall-structret.ll new file mode 100644 index 000000000000..e94d7d8befaa --- /dev/null +++ b/llvm/test/CodeGen/X86/tailcall-structret.ll @@ -0,0 +1,6 @@ +; RUN: llvm-as < %s | llc -march=x86 -tailcallopt | grep TAILCALL +define fastcc { { i8*, i8* }*, i8*} @init({ { i8*, i8* }*, i8*}, i32) { +entry: + %2 = tail call fastcc { { i8*, i8* }*, i8* } @init({ { i8*, i8*}*, i8*} %0, i32 %1) + ret { { i8*, i8* }*, i8*} %2 +}