diff options
author | Evan Cheng <evan.cheng@apple.com> | 2010-01-29 06:45:59 +0000 |
---|---|---|
committer | Evan Cheng <evan.cheng@apple.com> | 2010-01-29 06:45:59 +0000 |
commit | 7096ae48c931cf42babef061375e5b02840c8957 (patch) | |
tree | 76caeadefd5de37a27a4a0f698fe38beae8a099c | |
parent | ac512171ff12829c5961ca2614dfaf4b37bf8c2e (diff) |
Catch more trivial tail call opportunities: no inputs and output types match.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94804 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/Target/X86/X86ISelLowering.cpp | 32 | ||||
-rw-r--r-- | test/CodeGen/X86/tailcall2.ll | 24 |
2 files changed, 42 insertions, 14 deletions
diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index f868b75bd8..5dbe0bb8f0 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -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 * diff --git a/test/CodeGen/X86/tailcall2.ll b/test/CodeGen/X86/tailcall2.ll index 11d02dabbc..bd21efb445 100644 --- a/test/CodeGen/X86/tailcall2.ll +++ b/test/CodeGen/X86/tailcall2.ll @@ -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() |