Patchwork [arm] Fix PR45701

login
register
mail settings
Submitter Yao Qi
Date Sept. 22, 2010, 2:16 a.m.
Message ID <4C9966FE.2050707@codesourcery.com>
Download mbox | patch
Permalink /patch/65393/
State New
Headers show

Comments

Yao Qi - Sept. 22, 2010, 2:16 a.m.
Hi,
We prefer using r3 to keep stack 8-byte alignment, as Richard E. did
here, and don't choose r3 if tail call insns are emitted, since it might
be used to pass value in a tail call.

2009-06-02 Richard Earnshaw <rearnsha@arm.com>

        * arm.c (arm_get_frame_offsets): Prefer using r3 for padding a
        push/pop multiple to 8-byte alignment.

In this patch, we can improve it a little bit, that is, we can still
choose r3 for stack padding, even tail call insns are emitted, if r3 is
*not* used to pass values to tail call.
New element 'rtx tail_call_insns' in struct rtl_data replaces 'bool
tail_call_emit' to track the tail call insns, so we can decide whether
or not use r3 in arm_get_frame_offsets.

Run regression test on arm-none-linux-gnueabi and i686-pc-linux-gnu.  No
regression.  OK for mainline?
Richard Earnshaw - Sept. 23, 2010, 4:11 p.m.
On Wed, 2010-09-22 at 10:16 +0800, Yao Qi wrote:
> Hi,
> We prefer using r3 to keep stack 8-byte alignment, as Richard E. did
> here, and don't choose r3 if tail call insns are emitted, since it might
> be used to pass value in a tail call.
> 
> 2009-06-02 Richard Earnshaw <rearnsha@arm.com>
> 
>         * arm.c (arm_get_frame_offsets): Prefer using r3 for padding a
>         push/pop multiple to 8-byte alignment.
> 
> In this patch, we can improve it a little bit, that is, we can still
> choose r3 for stack padding, even tail call insns are emitted, if r3 is
> *not* used to pass values to tail call.
> New element 'rtx tail_call_insns' in struct rtl_data replaces 'bool
> tail_call_emit' to track the tail call insns, so we can decide whether
> or not use r3 in arm_get_frame_offsets.
> 
> Run regression test on arm-none-linux-gnueabi and i686-pc-linux-gnu.  No
> regression.  OK for mainline?
> 

How does this track a function with more than one tailcall?  It seems
that it only keeps track of the last tail-call emitted.  What happens if
the first one uses R3, but the second one doesn't?

R.

Patch

2010-09-20  Yao Qi  <yao@codesourcery.com>

	* function.h (struct rtl_data): Replace field bool tail_call_emit
	by rtx tail_call_insns.
	* call.c (expand_call): Modified code to match new data structures.
	* cfgcleanup.c (rest_of_handle_jump): Likewise.
	* config/i386/i386.c (find_drap_reg): Likewise.
	* config/arm/arm.c (arm_output_epilogue):Likewise.
	(arm_get_frame_offsets): Use r3 for padding stack to 8-byte alignment
	if r3 is not used to pass values to tail call.

diff --git a/gcc/calls.c b/gcc/calls.c
index 3888831..92389fd 100644
--- a/gcc/calls.c
+++ b/gcc/calls.c
@@ -3195,7 +3195,7 @@  expand_call (tree exp, rtx target, int ignore)
   if (tail_call_insns)
     {
       emit_insn (tail_call_insns);
-      crtl->tail_call_emit = true;
+      crtl->tail_call_insns = tail_call_insns;
     }
   else
     emit_insn (normal_call_insns);
diff --git a/gcc/cfgcleanup.c b/gcc/cfgcleanup.c
index 9ded1e6..c6b8f28 100644
--- a/gcc/cfgcleanup.c
+++ b/gcc/cfgcleanup.c
@@ -2394,7 +2394,7 @@  cleanup_cfg (int mode)
 static unsigned int
 rest_of_handle_jump (void)
 {
-  if (crtl->tail_call_emit)
+  if (crtl->tail_call_insns)
     fixup_tail_calls ();
   return 0;
 }
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 6f260ec..7c45648 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -14490,7 +14490,7 @@  arm_output_epilogue (rtx sibling)
 		  && !crtl->calls_eh_return
 		  && bit_count(saved_regs_mask) * 4 == count
 		  && !IS_INTERRUPT (func_type)
-		  && !crtl->tail_call_emit)
+		  && !crtl->tail_call_insns)
 		{
 		  unsigned long mask;
                   /* Preserve return values, of any size.  */
@@ -15117,7 +15117,8 @@  arm_get_frame_offsets (void)
 	  /* If it is safe to use r3, then do so.  This sometimes 
 	     generates better code on Thumb-2 by avoiding the need to
 	     use 32-bit push/pop instructions.  */
-	  if (!crtl->tail_call_emit
+	  if (!(crtl->tail_call_insns 
+		&& find_regno_fusage (crtl->tail_call_insns, USE, 3))
 	      && arm_size_return_regs () <= 12
 	      && (offsets->saved_regs_mask & (1 << 3)) == 0)
 	    {
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 19d6387..973b8a7 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -8853,7 +8853,7 @@  find_drap_reg (void)
 	 Since function with tail call may use any caller-saved
 	 registers in epilogue, DRAP must not use caller-saved
 	 register in such case.  */
-      if (DECL_STATIC_CHAIN (decl) || crtl->tail_call_emit)
+      if (DECL_STATIC_CHAIN (decl) || crtl->tail_call_insns)
 	return R13_REG;
 
       return R10_REG;
@@ -8864,7 +8864,7 @@  find_drap_reg (void)
 	 Since function with tail call may use any caller-saved
 	 registers in epilogue, DRAP must not use caller-saved
 	 register in such case.  */
-      if (DECL_STATIC_CHAIN (decl) || crtl->tail_call_emit)
+      if (DECL_STATIC_CHAIN (decl) || crtl->tail_call_insns)
 	return DI_REG;
 
       /* Reuse static chain register if it isn't used for parameter
diff --git a/gcc/function.h b/gcc/function.h
index 93a9b82..7aebdfc 100644
--- a/gcc/function.h
+++ b/gcc/function.h
@@ -393,8 +393,9 @@  struct GTY(()) rtl_data {
   /* Nonzero if the current function needs an lsda for exception handling.  */
   bool uses_eh_lsda;
 
-  /* Set when the tail call has been produced.  */
-  bool tail_call_emit;
+  /* Insns that produced for tail call.  Set NULL_RTX when the tail call 
+     hasn't been produced.  */
+  rtx tail_call_insns;
 
   /* Nonzero if code to initialize arg_pointer_save_area has been emitted.  */
   bool arg_pointer_save_area_init;