mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-09 13:21:30 +00:00
[mips] Allow tail-call optimization for vararg functions and functions which
use the caller's stack. llvm-svn: 167048
This commit is contained in:
parent
3f4e0f8e8e
commit
dbea525cfc
@ -2660,8 +2660,9 @@ static unsigned getNextIntArgReg(unsigned Reg) {
|
||||
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
|
||||
/// for tail call optimization.
|
||||
bool MipsTargetLowering::
|
||||
IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, bool IsVarArg,
|
||||
unsigned NextStackOffset) const {
|
||||
IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
|
||||
unsigned NextStackOffset,
|
||||
const MipsFunctionInfo& FI) const {
|
||||
if (!EnableMipsTailCalls)
|
||||
return false;
|
||||
|
||||
@ -2669,11 +2670,13 @@ IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, bool IsVarArg,
|
||||
if (Subtarget->inMips16Mode())
|
||||
return false;
|
||||
|
||||
if (MipsCCInfo.hasByValArg() || IsVarArg)
|
||||
// Return false if either the callee or caller has a byval argument.
|
||||
if (MipsCCInfo.hasByValArg() || FI.hasByvalArg())
|
||||
return false;
|
||||
|
||||
// Return true if no arguments are passed on stack.
|
||||
return MipsCCInfo.reservedArgArea() == NextStackOffset;
|
||||
// Return true if the callee's next stack offset is no larger than the
|
||||
// caller's.
|
||||
return NextStackOffset <= FI.nextStackOffset();
|
||||
}
|
||||
|
||||
SDValue
|
||||
@ -2725,13 +2728,12 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
|
||||
// Get a count of how many bytes are to be pushed on the stack.
|
||||
unsigned NextStackOffset = CCInfo.getNextStackOffset();
|
||||
unsigned StackAlignment = TFL->getStackAlignment();
|
||||
NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment);
|
||||
|
||||
// Check if it's really possible to do a tail call.
|
||||
if (isTailCall)
|
||||
isTailCall = IsEligibleForTailCallOptimization(MipsCCInfo, isVarArg,
|
||||
NextStackOffset);
|
||||
isTailCall =
|
||||
IsEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset,
|
||||
*MF.getInfo<MipsFunctionInfo>());
|
||||
|
||||
if (isTailCall)
|
||||
++NumTailCalls;
|
||||
@ -2739,6 +2741,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
// Chain is the output chain of the last Load/Store or CopyToReg node.
|
||||
// ByValChain is the output chain of the last Memcpy node created for copying
|
||||
// byval arguments to the stack.
|
||||
unsigned StackAlignment = TFL->getStackAlignment();
|
||||
NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment);
|
||||
SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true);
|
||||
|
||||
if (!isTailCall)
|
||||
@ -2765,6 +2769,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
assert(Flags.getByValSize() &&
|
||||
"ByVal args of size 0 should have been ignored by front-end.");
|
||||
assert(ByValArg != MipsCCInfo.byval_end());
|
||||
assert(!isTailCall &&
|
||||
"Do not tail-call optimize if there is a byval argument.");
|
||||
passByValArg(Chain, dl, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg,
|
||||
MipsCCInfo, *ByValArg, Flags, Subtarget->isLittle());
|
||||
++ByValArg;
|
||||
@ -2817,10 +2823,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
||||
|
||||
// emit ISD::STORE whichs stores the
|
||||
// parameter value to a stack Location
|
||||
SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr,
|
||||
DAG.getIntPtrConstant(VA.getLocMemOffset()));
|
||||
MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff,
|
||||
MachinePointerInfo(), false, false, 0));
|
||||
MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(),
|
||||
Chain, Arg, dl, isTailCall, DAG));
|
||||
}
|
||||
|
||||
// Transform all store nodes into one single node because all store
|
||||
|
@ -141,6 +141,7 @@ namespace llvm {
|
||||
//===--------------------------------------------------------------------===//
|
||||
// TargetLowering Implementation
|
||||
//===--------------------------------------------------------------------===//
|
||||
class MipsFunctionInfo;
|
||||
|
||||
class MipsTargetLowering : public TargetLowering {
|
||||
public:
|
||||
@ -275,8 +276,8 @@ namespace llvm {
|
||||
/// IsEligibleForTailCallOptimization - Check whether the call is eligible
|
||||
/// for tail call optimization.
|
||||
bool IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo,
|
||||
bool IsVarArg,
|
||||
unsigned NextStackOffset) const;
|
||||
unsigned NextStackOffset,
|
||||
const MipsFunctionInfo& FI) const;
|
||||
|
||||
/// copyByValArg - Copy argument registers which were used to pass a byval
|
||||
/// argument to the stack. Create a stack frame object for the byval
|
||||
|
@ -121,7 +121,7 @@ entry:
|
||||
; STATIC32: jal
|
||||
; STATIC32: .end caller8_1
|
||||
; N64: .ent caller8_1
|
||||
; N64: jalr
|
||||
; N64-NOT: jalr
|
||||
; N64: .end caller8_1
|
||||
|
||||
%call = tail call i32 (i32, ...)* @callee8(i32 2, i32 1) nounwind
|
||||
@ -156,3 +156,67 @@ entry:
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @callee10(i32, i32, i32, i32, i32, i32, i32, i32, i32)
|
||||
|
||||
define i32 @caller10(i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7, i32 %a8) nounwind {
|
||||
entry:
|
||||
; PIC32: .ent caller10
|
||||
; PIC32-NOT: jalr
|
||||
; STATIC32: .ent caller10
|
||||
; STATIC32-NOT: jal
|
||||
; N64: .ent caller10
|
||||
; N64-NOT: jalr
|
||||
|
||||
%call = tail call i32 @callee10(i32 %a8, i32 %a0, i32 %a1, i32 %a2, i32 %a3, i32 %a4, i32 %a5, i32 %a6, i32 %a7) nounwind
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @callee11(%struct.S* byval)
|
||||
|
||||
define i32 @caller11() nounwind noinline {
|
||||
entry:
|
||||
; PIC32: .ent caller11
|
||||
; PIC32: jalr
|
||||
; STATIC32: .ent caller11
|
||||
; STATIC32: jal
|
||||
; N64: .ent caller11
|
||||
; N64: jalr
|
||||
|
||||
%call = tail call i32 @callee11(%struct.S* byval @gs1) nounwind
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @callee12()
|
||||
|
||||
declare void @llvm.memcpy.p0i8.p0i8.i32(i8* nocapture, i8* nocapture, i32, i32, i1) nounwind
|
||||
|
||||
define i32 @caller12(%struct.S* nocapture byval %a0) nounwind {
|
||||
entry:
|
||||
; PIC32: .ent caller12
|
||||
; PIC32: jalr
|
||||
; STATIC32: .ent caller12
|
||||
; STATIC32: jal
|
||||
; N64: .ent caller12
|
||||
; N64: jalr
|
||||
|
||||
%0 = bitcast %struct.S* %a0 to i8*
|
||||
tail call void @llvm.memcpy.p0i8.p0i8.i32(i8* bitcast (%struct.S* @gs1 to i8*), i8* %0, i32 8, i32 4, i1 false)
|
||||
%call = tail call i32 @callee12() nounwind
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
declare i32 @callee13(i32, ...)
|
||||
|
||||
define i32 @caller13() nounwind {
|
||||
entry:
|
||||
; PIC32: .ent caller13
|
||||
; PIC32-NOT: jalr
|
||||
; STATIC32: .ent caller13
|
||||
; STATIC32-NOT: jal
|
||||
; N64: .ent caller13
|
||||
; N64-NOT: jalr
|
||||
|
||||
%call = tail call i32 (i32, ...)* @callee13(i32 1, i32 2) nounwind
|
||||
ret i32 %call
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user