OSDN Git Service

Catch more trivial tail call opportunities: no inputs and output types match.
authorEvan Cheng <evan.cheng@apple.com>
Fri, 29 Jan 2010 06:45:59 +0000 (06:45 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Fri, 29 Jan 2010 06:45:59 +0000 (06:45 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94804 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
test/CodeGen/X86/tailcall2.ll

index f868b75..5dbe0bb 100644 (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 *
index 11d02da..bd21efb 100644 (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()