Perform trivial tail call optimization for callees with "C" ABI. These are done
authorEvan Cheng <evan.cheng@apple.com>
Wed, 27 Jan 2010 06:25:16 +0000 (06:25 +0000)
committerEvan Cheng <evan.cheng@apple.com>
Wed, 27 Jan 2010 06:25:16 +0000 (06:25 +0000)
even when -tailcallopt is not specified and it does not require changing ABI.
First case is the most trivial one. Perform tail call optimization when both
the caller and callee do not return values and when the callee does not take
any input arguments.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@94664 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
test/CodeGen/X86/pic.ll
test/CodeGen/X86/tailcall1.ll
test/CodeGen/X86/tailcall2.ll [new file with mode: 0644]

index 6e6447574e4917ace6a45e518e07e23a22e3b537..eb7f4815915292bfbe8e4330f28920f766a9f3af 100644 (file)
@@ -12,6 +12,7 @@
 //
 //===----------------------------------------------------------------------===//
 
+#define DEBUG_TYPE "x86-isel"
 #include "X86.h"
 #include "X86InstrBuilder.h"
 #include "X86ISelLowering.h"
@@ -39,6 +40,7 @@
 #include "llvm/MC/MCSymbol.h"
 #include "llvm/ADT/BitVector.h"
 #include "llvm/ADT/SmallSet.h"
+#include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/VectorExtras.h"
 #include "llvm/Support/CommandLine.h"
@@ -48,6 +50,8 @@
 #include "llvm/Support/raw_ostream.h"
 using namespace llvm;
 
+STATISTIC(NumTailCalls, "Number of tail calls");
+
 static cl::opt<bool>
 DisableMMX("disable-mmx", cl::Hidden, cl::desc("Disable use of MMX"));
 
@@ -1788,7 +1792,7 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
   if (isTailCall)
     // Check if it's really possible to do a tail call.
     isTailCall = IsEligibleForTailCallOptimization(Callee, CallConv, isVarArg,
-                                                   Ins, DAG);
+                                                   Outs, Ins, DAG);
 
   assert(!(isVarArg && CallConv == CallingConv::Fast) &&
          "Var args not supported with calling convention fastcc");
@@ -1806,6 +1810,8 @@ X86TargetLowering::LowerCall(SDValue Chain, SDValue Callee,
 
   int FPDiff = 0;
   if (isTailCall) {
+    ++NumTailCalls;
+
     // Lower arguments at fp - stackoffset + fpdiff.
     unsigned NumBytesCallerPushed =
       MF.getInfo<X86MachineFunctionInfo>()->getBytesToPopOnReturn();
@@ -2237,11 +2243,29 @@ bool
 X86TargetLowering::IsEligibleForTailCallOptimization(SDValue Callee,
                                                      CallingConv::ID CalleeCC,
                                                      bool isVarArg,
-                                      const SmallVectorImpl<ISD::InputArg> &Ins,
+                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    const SmallVectorImpl<ISD::InputArg> &Ins,
                                                      SelectionDAG& DAG) const {
-  if (CalleeCC == CallingConv::Fast &&
-      DAG.getMachineFunction().getFunction()->getCallingConv() == CalleeCC)
+  // 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;
+
+  // Look for obvious safe cases to perform tail call optimization.
+  // For now, only consider callees which take no arguments and no return
+  // values.
+  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();
+
   return false;
 }
 
index 0642b392dd4c60ede5c9348891e786eaab57d866..193ef054c99794ab3e17caee2af45bf0ac4ce98a 100644 (file)
@@ -630,7 +630,8 @@ namespace llvm {
     bool IsEligibleForTailCallOptimization(SDValue Callee,
                                            CallingConv::ID CalleeCC,
                                            bool isVarArg,
-                                      const SmallVectorImpl<ISD::InputArg> &Ins,
+                                    const SmallVectorImpl<ISD::OutputArg> &Outs,
+                                    const SmallVectorImpl<ISD::InputArg> &Ins,
                                            SelectionDAG& DAG) const;
     bool IsCalleePop(bool isVarArg, CallingConv::ID CallConv);
     SDValue EmitTailCallLoadRetAddr(SelectionDAG &DAG, SDValue &OutRetAddr,
index e886ba06b7089b6e96df8c45b435c49ed6406d2e..d3c28a055aee703e5f303c64484d754246fc759c 100644 (file)
@@ -190,7 +190,7 @@ bb12:
 ; LINUX: .L8$pb:
 ; LINUX:   addl        $_GLOBAL_OFFSET_TABLE_+(.Lpicbaseref8-.L8$pb),
 ; LINUX:   addl        .LJTI8_0@GOTOFF(
-; LINUX:   jmpl        *%ecx
+; LINUX:   jmpl        *
 
 ; LINUX: .LJTI8_0:
 ; LINUX:   .long        .LBB8_2@GOTOFF
index 42f8cdd384130e4fec8e56c1a8fd9a85cc082090..96c4cad9799dd71a5c537ed07baa481c2a4e8a32 100644 (file)
@@ -4,8 +4,8 @@ declare fastcc i32 @tailcallee(i32 %a1, i32 %a2, i32 %a3, i32 %a4)
 
 define fastcc i32 @tailcaller(i32 %in1, i32 %in2) nounwind {
 entry:
-       %tmp11 = tail call fastcc i32 @tailcallee(i32 %in1, i32 %in2, i32 %in1, i32 %in2)
-       ret i32 %tmp11
+  %tmp11 = tail call fastcc i32 @tailcallee(i32 %in1, i32 %in2, i32 %in1, i32 %in2)
+  ret i32 %tmp11
 }
 
 declare fastcc i8* @alias_callee()
diff --git a/test/CodeGen/X86/tailcall2.ll b/test/CodeGen/X86/tailcall2.ll
new file mode 100644 (file)
index 0000000..f1eb152
--- /dev/null
@@ -0,0 +1,12 @@
+; 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 {
+entry:
+; CHECK: bar:
+; CHECK: jmp _foo
+  tail call void @foo() nounwind
+  ret void
+}
+
+declare void @foo()