mirror of
				https://github.com/c64scene-ar/llvm-6502.git
				synced 2025-10-31 08:16:47 +00:00 
			
		
		
		
	[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
This commit is contained in:
		| @@ -2660,8 +2660,9 @@ static unsigned getNextIntArgReg(unsigned Reg) { | |||||||
| /// IsEligibleForTailCallOptimization - Check whether the call is eligible | /// IsEligibleForTailCallOptimization - Check whether the call is eligible | ||||||
| /// for tail call optimization. | /// for tail call optimization. | ||||||
| bool MipsTargetLowering:: | bool MipsTargetLowering:: | ||||||
| IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, bool IsVarArg, | IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, | ||||||
|                                   unsigned NextStackOffset) const { |                                   unsigned NextStackOffset, | ||||||
|  |                                   const MipsFunctionInfo& FI) const { | ||||||
|   if (!EnableMipsTailCalls) |   if (!EnableMipsTailCalls) | ||||||
|     return false; |     return false; | ||||||
|  |  | ||||||
| @@ -2669,11 +2670,13 @@ IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, bool IsVarArg, | |||||||
|   if (Subtarget->inMips16Mode()) |   if (Subtarget->inMips16Mode()) | ||||||
|     return false; |     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 false; | ||||||
|  |  | ||||||
|   // Return true if no arguments are passed on stack. |   // Return true if the callee's next stack offset is no larger than the | ||||||
|   return MipsCCInfo.reservedArgArea() == NextStackOffset; |   // caller's. | ||||||
|  |   return NextStackOffset <= FI.nextStackOffset(); | ||||||
| } | } | ||||||
|  |  | ||||||
| SDValue | SDValue | ||||||
| @@ -2725,13 +2728,12 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | |||||||
|  |  | ||||||
|   // Get a count of how many bytes are to be pushed on the stack. |   // Get a count of how many bytes are to be pushed on the stack. | ||||||
|   unsigned NextStackOffset = CCInfo.getNextStackOffset(); |   unsigned NextStackOffset = CCInfo.getNextStackOffset(); | ||||||
|   unsigned StackAlignment = TFL->getStackAlignment(); |  | ||||||
|   NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); |  | ||||||
|  |  | ||||||
|   // Check if it's really possible to do a tail call. |   // Check if it's really possible to do a tail call. | ||||||
|   if (isTailCall) |   if (isTailCall) | ||||||
|     isTailCall = IsEligibleForTailCallOptimization(MipsCCInfo, isVarArg, |     isTailCall = | ||||||
|                                                    NextStackOffset); |       IsEligibleForTailCallOptimization(MipsCCInfo, NextStackOffset, | ||||||
|  |                                         *MF.getInfo<MipsFunctionInfo>()); | ||||||
|  |  | ||||||
|   if (isTailCall) |   if (isTailCall) | ||||||
|     ++NumTailCalls; |     ++NumTailCalls; | ||||||
| @@ -2739,6 +2741,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | |||||||
|   // Chain is the output chain of the last Load/Store or CopyToReg node. |   // 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 |   // ByValChain is the output chain of the last Memcpy node created for copying | ||||||
|   // byval arguments to the stack. |   // byval arguments to the stack. | ||||||
|  |   unsigned StackAlignment = TFL->getStackAlignment(); | ||||||
|  |   NextStackOffset = RoundUpToAlignment(NextStackOffset, StackAlignment); | ||||||
|   SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); |   SDValue NextStackOffsetVal = DAG.getIntPtrConstant(NextStackOffset, true); | ||||||
|  |  | ||||||
|   if (!isTailCall) |   if (!isTailCall) | ||||||
| @@ -2765,6 +2769,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | |||||||
|       assert(Flags.getByValSize() && |       assert(Flags.getByValSize() && | ||||||
|              "ByVal args of size 0 should have been ignored by front-end."); |              "ByVal args of size 0 should have been ignored by front-end."); | ||||||
|       assert(ByValArg != MipsCCInfo.byval_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, |       passByValArg(Chain, dl, RegsToPass, MemOpChains, StackPtr, MFI, DAG, Arg, | ||||||
|                    MipsCCInfo, *ByValArg, Flags, Subtarget->isLittle()); |                    MipsCCInfo, *ByValArg, Flags, Subtarget->isLittle()); | ||||||
|       ++ByValArg; |       ++ByValArg; | ||||||
| @@ -2817,10 +2823,8 @@ MipsTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, | |||||||
|  |  | ||||||
|     // emit ISD::STORE whichs stores the |     // emit ISD::STORE whichs stores the | ||||||
|     // parameter value to a stack Location |     // parameter value to a stack Location | ||||||
|     SDValue PtrOff = DAG.getNode(ISD::ADD, dl, getPointerTy(), StackPtr, |     MemOpChains.push_back(passArgOnStack(StackPtr, VA.getLocMemOffset(), | ||||||
|                                  DAG.getIntPtrConstant(VA.getLocMemOffset())); |                                          Chain, Arg, dl, isTailCall, DAG)); | ||||||
|     MemOpChains.push_back(DAG.getStore(Chain, dl, Arg, PtrOff, |  | ||||||
|                                        MachinePointerInfo(), false, false, 0)); |  | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   // Transform all store nodes into one single node because all store |   // Transform all store nodes into one single node because all store | ||||||
|   | |||||||
| @@ -141,6 +141,7 @@ namespace llvm { | |||||||
|   //===--------------------------------------------------------------------===// |   //===--------------------------------------------------------------------===// | ||||||
|   // TargetLowering Implementation |   // TargetLowering Implementation | ||||||
|   //===--------------------------------------------------------------------===// |   //===--------------------------------------------------------------------===// | ||||||
|  |   class MipsFunctionInfo; | ||||||
|  |  | ||||||
|   class MipsTargetLowering : public TargetLowering  { |   class MipsTargetLowering : public TargetLowering  { | ||||||
|   public: |   public: | ||||||
| @@ -275,8 +276,8 @@ namespace llvm { | |||||||
|     /// IsEligibleForTailCallOptimization - Check whether the call is eligible |     /// IsEligibleForTailCallOptimization - Check whether the call is eligible | ||||||
|     /// for tail call optimization. |     /// for tail call optimization. | ||||||
|     bool IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, |     bool IsEligibleForTailCallOptimization(const MipsCC &MipsCCInfo, | ||||||
|                                            bool IsVarArg, |                                            unsigned NextStackOffset, | ||||||
|                                            unsigned NextStackOffset) const; |                                            const MipsFunctionInfo& FI) const; | ||||||
|  |  | ||||||
|     /// copyByValArg - Copy argument registers which were used to pass a byval |     /// copyByValArg - Copy argument registers which were used to pass a byval | ||||||
|     /// argument to the stack. Create a stack frame object for the byval |     /// argument to the stack. Create a stack frame object for the byval | ||||||
|   | |||||||
| @@ -121,7 +121,7 @@ entry: | |||||||
| ; STATIC32: jal | ; STATIC32: jal | ||||||
| ; STATIC32: .end caller8_1 | ; STATIC32: .end caller8_1 | ||||||
| ; N64: .ent caller8_1 | ; N64: .ent caller8_1 | ||||||
| ; N64: jalr | ; N64-NOT: jalr | ||||||
| ; N64: .end caller8_1 | ; N64: .end caller8_1 | ||||||
|  |  | ||||||
|   %call = tail call i32 (i32, ...)* @callee8(i32 2, i32 1) nounwind |   %call = tail call i32 (i32, ...)* @callee8(i32 2, i32 1) nounwind | ||||||
| @@ -156,3 +156,67 @@ entry: | |||||||
|   ret i32 %call |   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 | ||||||
|  | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user