Commit b748fbd6 by Paul Brook Committed by Paul Brook

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
parent 9888e9cf
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> 2010-05-24 Ralf Wildenhues <Ralf.Wildenhues@gmx.de>
* doc/makefile.texi (Makefile): Mention stages 'profile' * doc/makefile.texi (Makefile): Mention stages 'profile'
......
...@@ -8423,6 +8423,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode, ...@@ -8423,6 +8423,19 @@ expand_expr_real_1 (tree exp, rtx target, enum machine_mode tmode,
expand_decl_rtl: expand_decl_rtl:
gcc_assert (decl_rtl); gcc_assert (decl_rtl);
decl_rtl = copy_rtx (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 /* 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 a parser. If it hasn't be used yet, write out an external
......
...@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see ...@@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see
#include "hashtab.h" #include "hashtab.h"
#include "vecprim.h" #include "vecprim.h"
#include "tm.h" /* For CUMULATIVE_ARGS. */ #include "tm.h" /* For CUMULATIVE_ARGS. */
#include "hard-reg-set.h"
/* Stack of pending (incomplete) sequences saved by `start_sequence'. /* Stack of pending (incomplete) sequences saved by `start_sequence'.
Each element describes one pending sequence. Each element describes one pending sequence.
...@@ -437,6 +438,12 @@ struct GTY(()) rtl_data { ...@@ -437,6 +438,12 @@ struct GTY(()) rtl_data {
TREE_NOTHROW (current_function_decl) it is set even for overwritable TREE_NOTHROW (current_function_decl) it is set even for overwritable
function where currently compiled version of it is nothrow. */ function where currently compiled version of it is nothrow. */
bool 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) #define return_label (crtl->x_return_label)
......
...@@ -49,7 +49,7 @@ update_lineno (const char *l, size_t len) ...@@ -49,7 +49,7 @@ update_lineno (const char *l, size_t len)
ID [[:alpha:]_][[:alnum:]_]* ID [[:alpha:]_][[:alnum:]_]*
WS [[:space:]]+ WS [[:space:]]+
HWS [ \t\r\v\f]* 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})* ITYPE {IWORD}({WS}{IWORD})*
EOID [^[:alnum:]_] EOID [^[:alnum:]_]
......
...@@ -1397,14 +1397,12 @@ insn_contains_asm (rtx insn) ...@@ -1397,14 +1397,12 @@ insn_contains_asm (rtx insn)
return for_each_rtx (&insn, insn_contains_asm_1, NULL); return for_each_rtx (&insn, insn_contains_asm_1, NULL);
} }
/* Set up regs_asm_clobbered. */ /* Add register clobbers from asm statements. */
static void static void
compute_regs_asm_clobbered (char *regs_asm_clobbered) compute_regs_asm_clobbered (void)
{ {
basic_block bb; basic_block bb;
memset (regs_asm_clobbered, 0, sizeof (char) * FIRST_PSEUDO_REGISTER);
FOR_EACH_BB (bb) FOR_EACH_BB (bb)
{ {
rtx insn; rtx insn;
...@@ -1425,7 +1423,7 @@ compute_regs_asm_clobbered (char *regs_asm_clobbered) ...@@ -1425,7 +1423,7 @@ compute_regs_asm_clobbered (char *regs_asm_clobbered)
+ hard_regno_nregs[dregno][mode] - 1; + hard_regno_nregs[dregno][mode] - 1;
for (i = dregno; i <= end; ++i) 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) ...@@ -1437,12 +1435,6 @@ compute_regs_asm_clobbered (char *regs_asm_clobbered)
void void
ira_setup_eliminable_regset (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 #ifdef ELIMINABLE_REGS
int i; int i;
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS; static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
...@@ -1466,7 +1458,8 @@ ira_setup_eliminable_regset (void) ...@@ -1466,7 +1458,8 @@ ira_setup_eliminable_regset (void)
COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs); COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
CLEAR_HARD_REG_SET (eliminable_regset); 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 /* Build the regset of all eliminable registers and show we can't
use those that we already know won't be eliminated. */ use those that we already know won't be eliminated. */
#ifdef ELIMINABLE_REGS #ifdef ELIMINABLE_REGS
...@@ -1476,7 +1469,7 @@ ira_setup_eliminable_regset (void) ...@@ -1476,7 +1469,7 @@ ira_setup_eliminable_regset (void)
= (! targetm.can_eliminate (eliminables[i].from, eliminables[i].to) = (! targetm.can_eliminate (eliminables[i].from, eliminables[i].to)
|| (eliminables[i].to == STACK_POINTER_REGNUM && need_fp)); || (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); SET_HARD_REG_BIT (eliminable_regset, eliminables[i].from);
...@@ -1490,7 +1483,7 @@ ira_setup_eliminable_regset (void) ...@@ -1490,7 +1483,7 @@ ira_setup_eliminable_regset (void)
df_set_regs_ever_live (eliminables[i].from, true); df_set_regs_ever_live (eliminables[i].from, true);
} }
#if FRAME_POINTER_REGNUM != HARD_FRAME_POINTER_REGNUM #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); SET_HARD_REG_BIT (eliminable_regset, HARD_FRAME_POINTER_REGNUM);
if (need_fp) if (need_fp)
...@@ -1504,7 +1497,7 @@ ira_setup_eliminable_regset (void) ...@@ -1504,7 +1497,7 @@ ira_setup_eliminable_regset (void)
#endif #endif
#else #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); SET_HARD_REG_BIT (eliminable_regset, FRAME_POINTER_REGNUM);
if (need_fp) if (need_fp)
......
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> 2010-05-23 H.J. Lu <hongjiu.lu@intel.com>
PR target/44245 PR target/44245
......
/* 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;
}
...@@ -28,7 +28,10 @@ void foo() ...@@ -28,7 +28,10 @@ void foo()
*adr = save; *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; B = &x;
...@@ -42,3 +45,9 @@ int main() ...@@ -42,3 +45,9 @@ int main()
exit(0); exit(0);
} }
int main()
{
test();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment