Catch more trivial tail call opportunities: no inputs and output types match.

llvm-svn: 94804
This commit is contained in:
Evan Cheng 2010-01-29 06:45:59 +00:00
parent 385ab187e6
commit 297a494f55
2 changed files with 42 additions and 14 deletions

View File

@ -2246,27 +2246,35 @@ X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
const SmallVectorImpl<ISD::OutputArg> &Outs,
const SmallVectorImpl<ISD::InputArg> &Ins,
SelectionDAG& DAG) const {
// If -tailcallopt is specified, make fastcc functions tail-callable.
const Function *F = DAG.getMachineFunction().getFunction();
if (PerformTailCallOpt &&
CalleeCC == CallingConv::Fast && F->getCallingConv() == CalleeCC)
return true;
if (CalleeCC != CallingConv::Fast &&
CalleeCC != CallingConv::C)
return false;
// If -tailcallopt is specified, make fastcc functions tail-callable.
const Function *CallerF = DAG.getMachineFunction().getFunction();
if (PerformTailCallOpt &&
CalleeCC == CallingConv::Fast &&
CallerF->getCallingConv() == CalleeCC)
return true;
// Look for obvious safe cases to perform tail call optimization.
// For now, only consider callees which take no arguments and no return
// values.
// For now, only consider callees which take no arguments.
if (!Outs.empty())
return false;
if (Ins.empty())
// If the caller does not return a value, then this is obviously safe.
return F->getReturnType()->isVoidTy();
// If the caller does not return a value, then this is obviously safe.
// This is one case where it's safe to perform this optimization even
// if the return types do not match.
const Type *CallerRetTy = CallerF->getReturnType();
if (CallerRetTy->isVoidTy())
return true;
return false;
// If the return types match, then it's safe.
GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee);
if (!G) return false; // FIXME: common external symbols?
Function *CalleeF = cast<Function>(G->getGlobal());
const Type *CalleeRetTy = CalleeF->getReturnType();
return CallerRetTy == CalleeRetTy;
}
FastISel *

View File

@ -1,12 +1,32 @@
; RUN: llc < %s -march=x86 -asm-verbose=false | FileCheck %s
; RUN: llc < %s -march=x86-64 -asm-verbose=false | FileCheck %s
define void @bar(i32 %x) nounwind ssp {
define void @t1(i32 %x) nounwind ssp {
entry:
; CHECK: bar:
; CHECK: t1:
; CHECK: jmp {{_?}}foo
tail call void @foo() nounwind
ret void
}
declare void @foo()
define void @t2() nounwind ssp {
entry:
; CHECK: t2:
; CHECK: jmp {{_?}}foo2
%0 = tail call i32 @foo2() nounwind
ret void
}
declare i32 @foo2()
define void @t3() nounwind ssp {
entry:
; CHECK: t3:
; CHECK: jmp {{_?}}foo3
%0 = tail call i32 @foo3() nounwind
ret void
}
declare i32 @foo3()