diff options
author | Paul Brook <paul@codesourcery.com> | 2010-05-24 12:24:00 +0000 |
---|---|---|
committer | Paul Brook <pbrook@gcc.gnu.org> | 2010-05-24 12:24:00 +0000 |
commit | b748fbd6b981877caad2c6da42974610cdb53e01 (patch) | |
tree | a28ad2044f7bcf9c49f937d0bae49e03138a02f9 /gcc | |
parent | 9888e9cf854267265d6c59e3b01d15fe5cef5a35 (diff) | |
download | gcc-b748fbd6b981877caad2c6da42974610cdb53e01.zip gcc-b748fbd6b981877caad2c6da42974610cdb53e01.tar.gz gcc-b748fbd6b981877caad2c6da42974610cdb53e01.tar.bz2 |
gengtype-lex.l: Add HARD_REG_SET.
2010-05-25 Paul Brook <paul@codesourcery.com>
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.
From-SVN: r159776
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/expr.c | 13 | ||||
-rw-r--r-- | gcc/function.h | 7 | ||||
-rw-r--r-- | gcc/gengtype-lex.l | 2 | ||||
-rw-r--r-- | gcc/ira.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/arm/frame-pointer-1.c | 42 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/i386/pr9771-1.c | 11 |
8 files changed, 96 insertions, 17 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e74c4c5..80c8ff6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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' @@ -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 diff --git a/gcc/function.h b/gcc/function.h index 6e15092..072da58 100644 --- a/gcc/function.h +++ b/gcc/function.h @@ -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) diff --git a/gcc/gengtype-lex.l b/gcc/gengtype-lex.l index 297ebf8..8159ef8 100644 --- a/gcc/gengtype-lex.l +++ b/gcc/gengtype-lex.l @@ -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:]_] @@ -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) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4f8e6a2..a0b34c9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 0000000..bb1888e --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/frame-pointer-1.c @@ -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; +} diff --git a/gcc/testsuite/gcc.target/i386/pr9771-1.c b/gcc/testsuite/gcc.target/i386/pr9771-1.c index 01f2f29..37ec490 100644 --- a/gcc/testsuite/gcc.target/i386/pr9771-1.c +++ b/gcc/testsuite/gcc.target/i386/pr9771-1.c @@ -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; + +} |