Perform trivial tail call optimization for callees with "C" ABI. These are done

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
This commit is contained in:
Evan Cheng 2010-01-27 06:25:16 +00:00
parent 0a65a14417
commit b17124553d
5 changed files with 45 additions and 8 deletions

View 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;
}

View 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,

View 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

View 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()

View File

@ -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()