[llvm-commits] [llvm] r167048 - in /llvm/trunk: lib/Target/Mips/MipsISelLowering.cpp lib/Target/Mips/MipsISelLowering.h test/CodeGen/Mips/tailcall.ll

Akira Hatanaka ahatanaka at mips.com
Tue Oct 30 13:16:31 PDT 2012


Author: ahatanak
Date: Tue Oct 30 15:16:31 2012
New Revision: 167048

URL: http://llvm.org/viewvc/llvm-project?rev=167048&view=rev
Log:
[mips] Allow tail-call optimization for vararg functions and functions which
use the caller's stack.


Modified:
    llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
    llvm/trunk/lib/Target/Mips/MipsISelLowering.h
    llvm/trunk/test/CodeGen/Mips/tailcall.ll

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp?rev=167048&r1=167047&r2=167048&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.cpp Tue Oct 30 15:16:31 2012
@@ -2660,8 +2660,9 @@
 /// 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 @@
   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 @@
 
   // 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 @@
   // 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 @@
       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 @@
 
     // 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

Modified: llvm/trunk/lib/Target/Mips/MipsISelLowering.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/Mips/MipsISelLowering.h?rev=167048&r1=167047&r2=167048&view=diff
==============================================================================
--- llvm/trunk/lib/Target/Mips/MipsISelLowering.h (original)
+++ llvm/trunk/lib/Target/Mips/MipsISelLowering.h Tue Oct 30 15:16:31 2012
@@ -141,6 +141,7 @@
   //===--------------------------------------------------------------------===//
   // TargetLowering Implementation
   //===--------------------------------------------------------------------===//
+  class MipsFunctionInfo;
 
   class MipsTargetLowering : public TargetLowering  {
   public:
@@ -275,8 +276,8 @@
     /// 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

Modified: llvm/trunk/test/CodeGen/Mips/tailcall.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/Mips/tailcall.ll?rev=167048&r1=167047&r2=167048&view=diff
==============================================================================
--- llvm/trunk/test/CodeGen/Mips/tailcall.ll (original)
+++ llvm/trunk/test/CodeGen/Mips/tailcall.ll Tue Oct 30 15:16:31 2012
@@ -121,7 +121,7 @@
 ; 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 @@
   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
+}
+





More information about the llvm-commits mailing list