re PR target/45701 (Fail to prefer using r3 for padding a push/pop multiple to 8...
authorJakub Jelinek <jakub@gcc.gnu.org>
Tue, 25 Jan 2011 16:22:34 +0000 (17:22 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 25 Jan 2011 16:22:34 +0000 (17:22 +0100)
PR target/45701
* config/arm/arm.c (any_sibcall_uses_r3): New function.
(arm_get_frame_offsets): Use it.

2011-01-25  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.

From-SVN: r169240

gcc/ChangeLog
gcc/config/arm/arm.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/pr45701-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr45701-2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/arm/pr45701-3.c [new file with mode: 0644]

index ac512392e798fa4bab3333fba5d3ba8256c4ec78..9b9700ef27bae5d7f4ff35ade4eb395231ab2541 100644 (file)
@@ -1,3 +1,9 @@
+2011-01-25  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-25  Sebastian Pop  <sebastian.pop@amd.com>
            Jakub Jelinek  <jakub@redhat.com>
 
index 3e75d7c9c4d89b6bb0c1b7ad1a69fb4d18f3b8b5..be09282c17d5e6d12ae93b4e7d4a4cc22c93dc8b 100644 (file)
@@ -1,6 +1,6 @@
 /* Output routines for GCC for ARM.
    Copyright (C) 1991, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001,
-   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
+   2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
    Free Software Foundation, Inc.
    Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
    and Martin Simmons (@harleqn.co.uk).
@@ -15188,6 +15188,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).
@@ -15352,7 +15377,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)
            {
index 7b5efca3b62fe6bf8878683d763afb97c5b977b9..904695998877ce65eeb232f9ec8b2edad0da87fc 100644 (file)
@@ -1,3 +1,10 @@
+2011-01-25  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.
+
 2011-01-25  Sebastian Pop  <sebastian.pop@amd.com>
            Jakub Jelinek  <jakub@redhat.com>
 
diff --git a/gcc/testsuite/gcc.target/arm/pr45701-1.c b/gcc/testsuite/gcc.target/arm/pr45701-1.c
new file mode 100644 (file)
index 0000000..f94f578
--- /dev/null
@@ -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;
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr45701-2.c b/gcc/testsuite/gcc.target/arm/pr45701-2.c
new file mode 100644 (file)
index 0000000..68d5178
--- /dev/null
@@ -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);
+}
diff --git a/gcc/testsuite/gcc.target/arm/pr45701-3.c b/gcc/testsuite/gcc.target/arm/pr45701-3.c
new file mode 100644 (file)
index 0000000..8255bae
--- /dev/null
@@ -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);
+}