This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Prefer to use r3 even in some cases where tail calls were emitted (PR target/45701)
- From: Jakub Jelinek <jakub at redhat dot com>
- To: Nick Clifton <nickc at redhat dot com>, Richard Earnshaw <richard dot earnshaw at arm dot com>
- Cc: gcc-patches at gcc dot gnu dot org, Ramana Radhakrishnan <ramana dot radhakrishnan at arm dot com>
- Date: Wed, 19 Jan 2011 11:57:55 +0100
- Subject: [PATCH] Prefer to use r3 even in some cases where tail calls were emitted (PR target/45701)
- Reply-to: Jakub Jelinek <jakub at redhat dot com>
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