OSDN Git Service

2010-05-25 Paul Brook <paul@codesourcery.com>
authorpbrook <pbrook@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 May 2010 12:24:00 +0000 (12:24 +0000)
committerpbrook <pbrook@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 24 May 2010 12:24:00 +0000 (12:24 +0000)
gcc/
* gengtype-lex.l: Add HARD_REG_SET.
* expr.c (expand_expr_real_1): Record writes to hard registers.
* function.c (rtl_data): Add asm_clobbers.
* ira.c (compute_regs_asm_clobbered): Use crtl->asm_clobbers.
(ira_setup_eliminable_regset): Remove regs_asm_clobbered.
Use crtl->asm_clobbers.

gcc/testsuite/
* gcc.target/arm/frame-pointer-1.c: New test.
* gcc.target/i386/pr9771-1.c: Move code out of main to allow frame
pointer elimination.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@159776 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/expr.c
gcc/function.h
gcc/gengtype-lex.l
gcc/ira.c
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/arm/frame-pointer-1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/pr9771-1.c

index e74c4c5..80c8ff6 100644 (file)
@@ -1,3 +1,12 @@
+2010-05-24  Paul Brook  <paul@codesourcery.com>
+
+       * gengtype-lex.l: Add HARD_REG_SET.
+       * expr.c (expand_expr_real_1): Record writes to hard registers.
+       * function.c (rtl_data): Add asm_clobbers.
+       * ira.c (compute_regs_asm_clobbered): Use crtl->asm_clobbers.
+       (ira_setup_eliminable_regset): Remove regs_asm_clobbered.
+       Use crtl->asm_clobbers.
+
 2010-05-24  Ralf Wildenhues  <Ralf.Wildenhues@gmx.de>
 
        * doc/makefile.texi (Makefile): Mention stages 'profile'
index 50a2035..82c0371 100644 (file)
@@ -8423,6 +8423,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
     expand_decl_rtl:
       gcc_assert (decl_rtl);
       decl_rtl = copy_rtx (decl_rtl);
+      /* Record writes to register variables.  */
+      if (modifier == EXPAND_WRITE && REG_P (decl_rtl)
+         && REGNO (decl_rtl) < FIRST_PSEUDO_REGISTER)
+       {
+           int i = REGNO (decl_rtl);
+           int nregs = hard_regno_nregs[i][GET_MODE (decl_rtl)];
+           while (nregs)
+             {
+               SET_HARD_REG_BIT (crtl->asm_clobbers, i);
+               i++;
+               nregs--;
+             }
+       }
 
       /* Ensure variable marked as used even if it doesn't go through
         a parser.  If it hasn't be used yet, write out an external
index 6e15092..072da58 100644 (file)
@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "hashtab.h"
 #include "vecprim.h"
 #include "tm.h"                /* For CUMULATIVE_ARGS.  */
+#include "hard-reg-set.h"
 
 /* Stack of pending (incomplete) sequences saved by `start_sequence'.
    Each element describes one pending sequence.
@@ -437,6 +438,12 @@ struct GTY(()) rtl_data {
      TREE_NOTHROW (current_function_decl) it is set even for overwritable
      function where currently compiled version of it is nothrow.  */
   bool nothrow;
+
+  /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
+     asm.  Unlike regs_ever_live, elements of this array corresponding
+     to eliminable regs (like the frame pointer) are set if an asm
+     sets them.  */
+  HARD_REG_SET asm_clobbers;
 };
 
 #define return_label (crtl->x_return_label)
index 297ebf8..8159ef8 100644 (file)
@@ -49,7 +49,7 @@ update_lineno (const char *l, size_t len)
 ID     [[:alpha:]_][[:alnum:]_]*
 WS     [[:space:]]+
 HWS    [ \t\r\v\f]*
-IWORD  short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t
+IWORD  short|long|(un)?signed|char|int|HOST_WIDE_INT|HOST_WIDEST_INT|bool|size_t|BOOL_BITFIELD|CPPCHAR_SIGNED_T|ino_t|dev_t|HARD_REG_SET
 ITYPE  {IWORD}({WS}{IWORD})*
 EOID   [^[:alnum:]_]
 
index 574fe07..10be6da 100644 (file)
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -1397,14 +1397,12 @@ insn_contains_asm (rtx insn)
   return for_each_rtx (&insn, insn_contains_asm_1, NULL);
 }
 
-/* Set up regs_asm_clobbered.  */
+/* Add register clobbers from asm statements.  */
 static void
-compute_regs_asm_clobbered (char *regs_asm_clobbered)
+compute_regs_asm_clobbered (void)
 {
   basic_block bb;
 
-  memset (regs_asm_clobbered, 0, sizeof (char) * FIRST_PSEUDO_REGISTER);
-
   FOR_EACH_BB (bb)
     {
       rtx insn;
@@ -1425,7 +1423,7 @@ compute_regs_asm_clobbered (char *regs_asm_clobbered)
                      + hard_regno_nregs[dregno][mode] - 1;
 
                    for (i = dregno; i <= end; ++i)
-                     regs_asm_clobbered[i] = 1;
+                     SET_HARD_REG_BIT(crtl->asm_clobbers, i);
                  }
              }
        }
@@ -1437,12 +1435,6 @@ compute_regs_asm_clobbered (char *regs_asm_clobbered)
 void
 ira_setup_eliminable_regset (void)
 {
-  /* Like regs_ever_live, but 1 if a reg is set or clobbered from an
-     asm.  Unlike regs_ever_live, elements of this array corresponding
-     to eliminable regs (like the frame pointer) are set if an asm
-     sets them.  */
-  char *regs_asm_clobbered
-    = (char *) alloca (FIRST_PSEUDO_REGISTER * sizeof (char));
 #ifdef ELIMINABLE_REGS
   int i;
   static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
@@ -1466,7 +1458,8 @@ ira_setup_eliminable_regset (void)
   COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
   CLEAR_HARD_REG_SET (eliminable_regset);
 
-  compute_regs_asm_clobbered (regs_asm_clobbered);
+  compute_regs_asm_clobbered ();
+
   /* Build the regset of all eliminable registers and show we can't
      use those that we already know won't be eliminated.  */
 #ifdef ELIMINABLE_REGS
@@ -1476,7 +1469,7 @@ ira_setup_eliminable_regset (void)
        = (! targetm.can_eliminate (eliminables[i].from, eliminables[i].to)
           || (eliminables[i].to == STACK_POINTER_REGNUM && need_fp));
 
-      if (! regs_asm_clobbered[eliminables[i].from])
+      if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, eliminables[i].from))
        {
            SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
 
@@ -1490,7 +1483,7 @@ ira_setup_eliminable_regset (void)
        df_set_regs_ever_live (eliminables[i].from, true);
     }
 #if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM
-  if (! regs_asm_clobbered[HARD_FRAME_POINTER_REGNUM])
+  if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
     {
       SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
       if (need_fp)
@@ -1504,7 +1497,7 @@ ira_setup_eliminable_regset (void)
 #endif
 
 #else
-  if (! regs_asm_clobbered[FRAME_POINTER_REGNUM])
+  if (!TEST_HARD_REG_BIT (crtl->asm_clobbers, HARD_FRAME_POINTER_REGNUM))
     {
       SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
       if (need_fp)
index 4f8e6a2..a0b34c9 100644 (file)
@@ -1,3 +1,9 @@
+2010-05-24  Paul Brook  <paul@codesourcery.com>
+
+       * gcc.target/arm/frame-pointer-1.c: New test.
+       * gcc.target/i386/pr9771-1.c: Move code out of main to allow frame
+       pointer elimination.
+
 2010-05-23  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR target/44245
diff --git a/gcc/testsuite/gcc.target/arm/frame-pointer-1.c b/gcc/testsuite/gcc.target/arm/frame-pointer-1.c
new file mode 100644 (file)
index 0000000..bb1888e
--- /dev/null
@@ -0,0 +1,42 @@
+/* Check local register variables using a register conventionally 
+   used as the frame pointer aren't clobbered under high register pressure.  */
+/* { dg-do run } */
+/* { dg-options "-Os -mthumb -fomit-frame-pointer" } */
+
+#include <stdlib.h>
+
+int global=5;
+
+void __attribute__((noinline)) foo(int p1, int p2, int p3, int p4)
+{
+  if (global != 5 || p1 != 1 || p2 != 2 || p3 != 3 || p4 != 4)
+    abort();
+}
+
+int __attribute__((noinline)) test(int a, int b, int c, int d)
+{
+  register unsigned long r __asm__("r7") = 0xdeadbeef;
+  int e;
+
+  /* ABCD are live after the call which should be enough
+     to cause r7 to be used if it weren't for the register variable.  */
+  foo(a,b,c,d);
+
+  e = 0;
+  __asm__ __volatile__ ("mov %0, %2"
+                       : "=r" (e)
+                       : "0" (e), "r" (r));
+
+  global = a+b+c+d;
+
+  return e;
+}
+
+int main()
+{
+  if (test(1, 2, 3, 4) != 0xdeadbeef)
+    abort();
+  if (global != 10)
+    abort();
+  return 0;
+}
index 01f2f29..37ec490 100644 (file)
@@ -28,7 +28,10 @@ void foo()
   *adr = save;
 }
 
-int main()
+/* This must not be inlined becuase main() requires the frame pointer
+   for stack alignment.  */
+void test(void) __attribute__((noinline));
+void test(void)
 {
   B = &x;
 
@@ -42,3 +45,9 @@ int main()
   exit(0);
 }
 
+int main()
+{
+  test();
+  return 0;
+
+}