diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 02674f5d050..94e18689b73 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -2639,19 +2639,16 @@ static unsigned getNextIntArgReg(unsigned Reg) { /// IsEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. bool MipsTargetLowering:: -IsEligibleForTailCallOptimization(CallingConv::ID CalleeCC, +IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, bool IsVarArg, unsigned NextStackOffset) const { if (!EnableMipsTailCalls) return false; - // Do not tail-call optimize if there is an argument passed on stack. - if (IsO32 && (CalleeCC != CallingConv::Fast)) { - if (NextStackOffset > 16) - return false; - } else if (NextStackOffset) + if (MipsCCInfo.hasByValArg() || IsVarArg) return false; - return true; + // Return true if no arguments are passed on stack. + return MipsCCInfo.reservedArgArea() == NextStackOffset; } /// LowerCall - functions arguments are copied from virtual regs to @@ -2690,7 +2687,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, // Check if it's really possible to do a tail call. if (isTailCall) - isTailCall = IsEligibleForTailCallOptimization(CallConv, NextStackOffset); + isTailCall = IsEligibleForTailCallOptimization(MipsCCInfo, isVarArg, + NextStackOffset); if (isTailCall) ++NumTailCalls; diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 160349e4aaa..9e8c659829f 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -274,7 +274,8 @@ namespace llvm { /// IsEligibleForTailCallOptimization - Check whether the call is eligible /// for tail call optimization. - bool IsEligibleForTailCallOptimization(CallingConv::ID CalleeCC, + bool IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, + bool IsVarArg, unsigned NextStackOffset) const; /// copyByValArg - Copy argument registers which were used to pass a byval diff --git a/test/CodeGen/Mips/tailcall.ll b/test/CodeGen/Mips/tailcall.ll index 4989636a20d..e82b1e3d510 100644 --- a/test/CodeGen/Mips/tailcall.ll +++ b/test/CodeGen/Mips/tailcall.ll @@ -66,9 +66,15 @@ declare i32 @callee4(i32, i32, i32, i32, i32, i32, i32, i32, i32) define i32 @caller5() nounwind readonly { entry: +; PIC32: .ent caller5 ; PIC32-NOT: jalr +; PIC32: .end caller5 +; STATIC32: .ent caller5 ; STATIC32-NOT: jal +; STATIC32: .end caller5 +; N64: .ent caller5 ; N64-NOT: jalr +; N64: .end caller5 %0 = load i32* @g0, align 4 %1 = load i32* @g1, align 4 @@ -98,3 +104,55 @@ entry: ret i32 %add8 } +declare i32 @callee8(i32, ...) + +define i32 @caller8_0() nounwind { +entry: + %call = tail call fastcc i32 @caller8_1() + ret i32 %call +} + +define internal fastcc i32 @caller8_1() nounwind noinline { +entry: +; PIC32: .ent caller8_1 +; PIC32: jalr +; PIC32: .end caller8_1 +; STATIC32: .ent caller8_1 +; STATIC32: jal +; STATIC32: .end caller8_1 +; N64: .ent caller8_1 +; N64: jalr +; N64: .end caller8_1 + + %call = tail call i32 (i32, ...)* @callee8(i32 2, i32 1) nounwind + ret i32 %call +} + +%struct.S = type { [2 x i32] } + +@gs1 = external global %struct.S + +declare i32 @callee9(%struct.S* byval) + +define i32 @caller9_0() nounwind { +entry: + %call = tail call fastcc i32 @caller9_1() + ret i32 %call +} + +define internal fastcc i32 @caller9_1() nounwind noinline { +entry: +; PIC32: .ent caller9_1 +; PIC32: jalr +; PIC32: .end caller9_1 +; STATIC32: .ent caller9_1 +; STATIC32: jal +; STATIC32: .end caller9_1 +; N64: .ent caller9_1 +; N64: jalr +; N64: .end caller9_1 + + %call = tail call i32 @callee9(%struct.S* byval @gs1) nounwind + ret i32 %call +} +