aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2010-01-29 06:45:59 +0000
committerEvan Cheng <evan.cheng@apple.com>2010-01-29 06:45:59 +0000
commit7096ae48c931cf42babef061375e5b02840c8957 (patch)
tree76caeadefd5de37a27a4a0f698fe38beae8a099c
parentac512171ff12829c5961ca2614dfaf4b37bf8c2e (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.cpp32
-rw-r--r--test/CodeGen/X86/tailcall2.ll24
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()