From: Akira Hatanaka Date: Tue, 30 Oct 2012 20:16:31 +0000 (+0000) Subject: [mips] Allow tail-call optimization for vararg functions and functions which X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=2f34d754d00fbe2e4a98762d71d0fae5f4b0cf45;p=oota-llvm.git [mips] Allow tail-call optimization for vararg functions and functions which use the caller's stack. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@167048 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Target/Mips/MipsISelLowering.cpp b/lib/Target/Mips/MipsISelLowering.cpp index 862790b4d2c..47a4f1a14a2 100644 --- a/lib/Target/Mips/MipsISelLowering.cpp +++ b/lib/Target/Mips/MipsISelLowering.cpp @@ -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()); 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 diff --git a/lib/Target/Mips/MipsISelLowering.h b/lib/Target/Mips/MipsISelLowering.h index 4f1ce0cd1c6..8b80dff89b8 100644 --- a/lib/Target/Mips/MipsISelLowering.h +++ b/lib/Target/Mips/MipsISelLowering.h @@ -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 diff --git a/test/CodeGen/Mips/tailcall.ll b/test/CodeGen/Mips/tailcall.ll index e82b1e3d510..f1aca689165 100644 --- a/test/CodeGen/Mips/tailcall.ll +++ b/test/CodeGen/Mips/tailcall.ll @@ -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 +} +