summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.cpp32
-rw-r--r--llvm/lib/Target/X86/X86ISelLowering.h3
-rw-r--r--llvm/test/CodeGen/X86/pic.ll2
-rw-r--r--llvm/test/CodeGen/X86/tailcall1.ll4
-rw-r--r--llvm/test/CodeGen/X86/tailcall2.ll12
5 files changed, 45 insertions, 8 deletions
diff --git a/llvm/lib/Target/X86/X86ISelLowering.cpp b/llvm/lib/Target/X86/X86ISelLowering.cpp
index 6e6447574e4..eb7f4815915 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.cpp
+++ b/llvm/lib/Target/X86/X86ISelLowering.cpp
@@ -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;
}
diff --git a/llvm/lib/Target/X86/X86ISelLowering.h b/llvm/lib/Target/X86/X86ISelLowering.h
index 0642b392dd4..193ef054c99 100644
--- a/llvm/lib/Target/X86/X86ISelLowering.h
+++ b/llvm/lib/Target/X86/X86ISelLowering.h
@@ -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,
diff --git a/llvm/test/CodeGen/X86/pic.ll b/llvm/test/CodeGen/X86/pic.ll
index e886ba06b70..d3c28a055ae 100644
--- a/llvm/test/CodeGen/X86/pic.ll
+++ b/llvm/test/CodeGen/X86/pic.ll
@@ -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
diff --git a/llvm/test/CodeGen/X86/tailcall1.ll b/llvm/test/CodeGen/X86/tailcall1.ll
index 42f8cdd3841..96c4cad9799 100644
--- a/llvm/test/CodeGen/X86/tailcall1.ll
+++ b/llvm/test/CodeGen/X86/tailcall1.ll
@@ -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/llvm/test/CodeGen/X86/tailcall2.ll b/llvm/test/CodeGen/X86/tailcall2.ll
new file mode 100644
index 00000000000..f1eb1529c12
--- /dev/null
+++ b/llvm/test/CodeGen/X86/tailcall2.ll
@@ -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()
OpenPOWER on IntegriCloud