From: Roger Sayle Date: Tue, 14 Sep 2004 22:52:41 +0000 (+0000) Subject: re PR rtl-optimization/9771 ([x86] wrong ebp optimisation) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f6ae6c51dfff2dc6fd23a2a09c8fe831e8cdcbba;p=gcc.git re PR rtl-optimization/9771 ([x86] wrong ebp optimisation) PR rtl-optimization/9771 * regclass.c (CALL_REALLY_USED_REGNO_P): New macro to eliminate conditional compilation in init_reg_sets_1. (init_reg_sets_1): Let global_regs[i] take priority over the frame (but not stack) pointer exceptions to regs_invalidated_by_call. (globalize_reg): Globalizing a fixed register may need to update regs_invalidated_by_call. * gcc.dg/pr9771-1.c: New test case. From-SVN: r87516 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eb5533dbddc..2ce328f08b6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,13 @@ +2004-09-14 Roger Sayle + + PR rtl-optimization/9771 + * regclass.c (CALL_REALLY_USED_REGNO_P): New macro to eliminate + conditional compilation in init_reg_sets_1. + (init_reg_sets_1): Let global_regs[i] take priority over the frame + (but not stack) pointer exceptions to regs_invalidated_by_call. + (globalize_reg): Globalizing a fixed register may need to update + regs_invalidated_by_call. + 2004-09-14 Diego Novillo PR tree-optimization/15262 diff --git a/gcc/regclass.c b/gcc/regclass.c index a73d8865bac..3d5a5f8dddd 100644 --- a/gcc/regclass.c +++ b/gcc/regclass.c @@ -104,6 +104,13 @@ static const char initial_call_used_regs[] = CALL_USED_REGISTERS; char call_really_used_regs[] = CALL_REALLY_USED_REGISTERS; #endif +#ifdef CALL_REALLY_USED_REGISTERS +#define CALL_REALLY_USED_REGNO_P(X) call_really_used_regs[X] +#else +#define CALL_REALLY_USED_REGNO_P(X) call_used_regs[X] +#endif + + /* Indexed by hard register number, contains 1 for registers that are fixed use or call used registers that cannot hold quantities across calls even if we are willing to save and restore them. call fixed @@ -454,7 +461,11 @@ init_reg_sets_1 (void) If we are generating PIC code, the PIC offset table register is preserved across calls, though the target can override that. */ - if (i == STACK_POINTER_REGNUM || i == FRAME_POINTER_REGNUM) + if (i == STACK_POINTER_REGNUM) + ; + else if (global_regs[i]) + SET_HARD_REG_BIT (regs_invalidated_by_call, i); + else if (i == FRAME_POINTER_REGNUM) ; #if HARD_FRAME_POINTER_REGNUM != FRAME_POINTER_REGNUM else if (i == HARD_FRAME_POINTER_REGNUM) @@ -468,13 +479,7 @@ init_reg_sets_1 (void) else if (i == (unsigned) PIC_OFFSET_TABLE_REGNUM && fixed_regs[i]) ; #endif - else if (0 -#ifdef CALL_REALLY_USED_REGISTERS - || call_really_used_regs[i] -#else - || call_used_regs[i] -#endif - || global_regs[i]) + else if (CALL_REALLY_USED_REGNO_P (i)) SET_HARD_REG_BIT (regs_invalidated_by_call, i); } @@ -800,6 +805,12 @@ globalize_reg (int i) global_regs[i] = 1; + /* If we're globalizing the frame pointer, we need to set the + appropriate regs_invalidated_by_call bit, even if it's already + set in fixed_regs. */ + if (i != STACK_POINTER_REGNUM) + SET_HARD_REG_BIT (regs_invalidated_by_call, i); + /* If already fixed, nothing else to do. */ if (fixed_regs[i]) return; @@ -813,7 +824,6 @@ globalize_reg (int i) SET_HARD_REG_BIT (fixed_reg_set, i); SET_HARD_REG_BIT (call_used_reg_set, i); SET_HARD_REG_BIT (call_fixed_reg_set, i); - SET_HARD_REG_BIT (regs_invalidated_by_call, i); } /* Now the data and code for the `regclass' pass, which happens diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6ac93c8b42f..a8f7e5d393e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2004-09-14 Roger Sayle + + PR rtl-optimization/9771 + * gcc.dg/pr9771-1.c: New test case. + 2004-09-14 Diego Novillo PR tree-optimization/15262 diff --git a/gcc/testsuite/gcc.dg/pr9771-1.c b/gcc/testsuite/gcc.dg/pr9771-1.c new file mode 100644 index 00000000000..1e3bc036aee --- /dev/null +++ b/gcc/testsuite/gcc.dg/pr9771-1.c @@ -0,0 +1,43 @@ +/* PR rtl-optimization/9771 */ +/* { dg-do run { target i?86-*-* } } */ +/* { dg-options "-O2 -fomit-frame-pointer -ffixed-ebp" } */ + +extern void abort(void); +extern void exit(int); + +register long *B asm ("ebp"); + +long x = 10; +long y = 20; + +void bar(void) +{ + B = &y; +} + +void foo() +{ + long *adr = B; + long save = *adr; + + *adr = 123; + + bar(); + + *adr = save; +} + +int main() +{ + B = &x; + + foo(); + + if (x != 10 || y != 20) + abort(); + + /* We can't return, as our caller may assume %ebp is preserved! */ + /* We could save/restore it (like foo), but its easier to exit. */ + exit(0); +} +