This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Prefer to use r3 even in some cases where tail calls were emitted (PR target/45701)


Hi!

As discussed in the PR, the !crtl->tail_call_emit test
in arm_get_frame_offsets is unnecessarily conservative.  The idea is
from Yao Qi, I've just implemented it differently so that no unnecessary
middle-end changes are needed.

Bootstrapped/regtested by Ramana (thanks), ok for trunk?

2011-01-19  Jakub Jelinek  <jakub@redhat.com>

	PR target/45701
	* config/arm/arm.c (any_sibcall_uses_r3): New function.
	(arm_get_frame_offsets): Use it.

2011-01-19  Yao Qi  <yao@codesourcery.com>

        PR target/45701
        * gcc.target/arm/pr45701-1.c: New test.
        * gcc.target/arm/pr45701-2.c: New test.
	* gcc.target/arm/pr45701-3.c: New test.

--- gcc/config/arm/arm.c.jj	2010-12-21 12:23:35.000000000 +0100
+++ gcc/config/arm/arm.c	2010-12-21 12:58:43.000000000 +0100
@@ -15184,6 +15184,31 @@ thumb_force_lr_save (void)
 }
 
 
+/* Return true if r3 is used by any of the tail call insns in the
+   current function.  */
+
+static bool
+any_sibcall_uses_r3 (void)
+{
+  edge_iterator ei;
+  edge e;
+
+  if (!crtl->tail_call_emit)
+    return false;
+  FOR_EACH_EDGE (e, ei, EXIT_BLOCK_PTR->preds)
+    if (e->flags & EDGE_SIBCALL)
+      {
+	rtx call = BB_END (e->src);
+	if (!CALL_P (call))
+	  call = prev_nonnote_nondebug_insn (call);
+	gcc_assert (CALL_P (call) && SIBLING_CALL_P (call));
+	if (find_regno_fusage (call, USE, 3))
+	  return true;
+      }
+  return false;
+}
+
+
 /* Compute the distance from register FROM to register TO.
    These can be the arg pointer (26), the soft frame pointer (25),
    the stack pointer (13) or the hard frame pointer (11).
@@ -15348,7 +15373,7 @@ 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 (! any_sibcall_uses_r3 ()
 	      && arm_size_return_regs () <= 12
 	      && (offsets->saved_regs_mask & (1 << 3)) == 0)
 	    {
--- gcc/testsuite/gcc.target/arm/pr45701-1.c
+++ gcc/testsuite/gcc.target/arm/pr45701-1.c
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mthumb -Os" }  */
+/* { dg-final { scan-assembler "push\t\{r3" } } */
+/* { dg-final { scan-assembler-not "r8" } } */
+
+extern int hist_verify;
+extern char *pre_process_line (char*);
+extern char* str_cpy (char*, char*);
+extern int str_len (char*);
+extern char* x_malloc (int);
+#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x))
+
+char *
+history_expand_line_internal (char* line)
+{
+  char *new_line;
+  int old_verify;
+
+  old_verify = hist_verify;
+  hist_verify = 0;
+  new_line = pre_process_line (line);
+  hist_verify = old_verify;
+  return (new_line == line) ? savestring (line) : new_line;
+}
--- gcc/testsuite/gcc.target/arm/pr45701-2.c
+++ gcc/testsuite/gcc.target/arm/pr45701-2.c
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mthumb -Os" }  */
+/* { dg-final { scan-assembler "push\t\{r3" } } */
+/* { dg-final { scan-assembler-not "r8" } } */
+
+extern int hist_verify;
+extern char *pre_process_line (char*);
+extern char* savestring1 (char*, char*);
+extern char* str_cpy (char*, char*);
+extern int str_len (char*);
+extern char* x_malloc (int);
+#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x))
+
+char *
+history_expand_line_internal (char* line)
+{
+  char *new_line;
+  int old_verify;
+
+  old_verify = hist_verify;
+  hist_verify = 0;
+  new_line = pre_process_line (line);
+  hist_verify = old_verify;
+  /* Two tail calls here, but r3 is not used to pass values.  */
+  return (new_line == line) ? savestring (line) : savestring1 (new_line, line);
+}
--- gcc/testsuite/gcc.target/arm/pr45701-3.c
+++ gcc/testsuite/gcc.target/arm/pr45701-3.c
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-march=armv7-a -mthumb -Os" }  */
+/* { dg-final { scan-assembler "push\t.*r8" } } */
+/* { dg-final { scan-assembler-not "push\t*r3" } } */
+
+extern int hist_verify;
+extern char *pre_process_line (char*);
+extern char* savestring1 (char*, char*, int, int);
+extern char* str_cpy (char*, char*);
+extern int str_len (char*);
+extern char* x_malloc (int);
+#define savestring(x) (char *)str_cpy (x_malloc (1 + str_len (x)), (x))
+
+char *
+history_expand_line_internal (char* line)
+{
+  char *new_line;
+  int old_verify;
+
+  old_verify = hist_verify;
+  hist_verify = 0;
+  new_line = pre_process_line (line);
+  hist_verify = old_verify;
+  /* Two tail calls here, but r3 is used to pass values.  */
+  return (new_line == line) ? savestring (line) : 
+    savestring1 (new_line, line, 0, old_verify+1);
+}

	Jakub


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]