diff options
author | Joern Rennecke <joern.rennecke@embecosm.com> | 2013-10-30 23:55:46 +0000 |
---|---|---|
committer | Joern Rennecke <amylaar@gcc.gnu.org> | 2013-10-30 23:55:46 +0000 |
commit | e27a6430c798dd3dbbb0683287cbd4fb134ec362 (patch) | |
tree | 5c9f15cee17124d1c53762cc0c992f3ca37b151b | |
parent | fbdec79172bf97c510d5c436732e120e0f497c25 (diff) | |
download | gcc-e27a6430c798dd3dbbb0683287cbd4fb134ec362.zip gcc-e27a6430c798dd3dbbb0683287cbd4fb134ec362.tar.gz gcc-e27a6430c798dd3dbbb0683287cbd4fb134ec362.tar.bz2 |
re PR rtl-optimization/58545 (error: unable to find a register to spill in class 'POINTER_REGS')
gcc:
PR other/58545
* reload1.c (update_eliminables_and_spill): New function, broken
out of reload.
(reload): Use it. Check for frame size change after frame
size alignment, and call update_eliminables_and_spill first
if continue-ing.
gcc/testsuite:
PR other/58545
* gcc.target/avr/pr58545.c: New test.
From-SVN: r204234
-rw-r--r-- | gcc/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/reload1.c | 73 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/avr/pr58545.c | 23 |
4 files changed, 81 insertions, 29 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bf4cbc..60c58b6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com> + + PR other/58545 + * reload1.c (update_eliminables_and_spill): New function, broken + out of reload. + (reload): Use it. Check for frame size change after frame + size alignment, and call update_eliminables_and_spill first + if continue-ing. + 2013-10-30 Cong Hou <congh@google.com> PR target/58762 diff --git a/gcc/reload1.c b/gcc/reload1.c index b62b047..204685d 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -373,6 +373,7 @@ static void init_eliminable_invariants (rtx, bool); static void init_elim_table (void); static void free_reg_equiv (void); static void update_eliminables (HARD_REG_SET *); +static bool update_eliminables_and_spill (void); static void elimination_costs_in_insn (rtx); static void spill_hard_reg (unsigned int, int); static int finish_spills (int); @@ -913,9 +914,6 @@ reload (rtx first, int global) if (caller_save_needed) setup_save_areas (); - /* If we allocated another stack slot, redo elimination bookkeeping. */ - if (something_was_spilled || starting_frame_size != get_frame_size ()) - continue; if (starting_frame_size && crtl->stack_alignment_needed) { /* If we have a stack frame, we must align it now. The @@ -927,8 +925,12 @@ reload (rtx first, int global) STARTING_FRAME_OFFSET not be already aligned to STACK_BOUNDARY. */ assign_stack_local (BLKmode, 0, crtl->stack_alignment_needed); - if (starting_frame_size != get_frame_size ()) - continue; + } + /* If we allocated another stack slot, redo elimination bookkeeping. */ + if (something_was_spilled || starting_frame_size != get_frame_size ()) + { + update_eliminables_and_spill (); + continue; } if (caller_save_needed) @@ -962,30 +964,11 @@ reload (rtx first, int global) else if (!verify_initial_elim_offsets ()) something_changed = 1; - { - HARD_REG_SET to_spill; - CLEAR_HARD_REG_SET (to_spill); - update_eliminables (&to_spill); - AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill); - - for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) - if (TEST_HARD_REG_BIT (to_spill, i)) - { - spill_hard_reg (i, 1); - did_spill = 1; - - /* Regardless of the state of spills, if we previously had - a register that we thought we could eliminate, but now can - not eliminate, we must run another pass. - - Consider pseudos which have an entry in reg_equiv_* which - reference an eliminable register. We must make another pass - to update reg_equiv_* so that we do not substitute in the - old value from when we thought the elimination could be - performed. */ - something_changed = 1; - } - } + if (update_eliminables_and_spill ()) + { + did_spill = 1; + something_changed = 1; + } select_reload_regs (); if (failure) @@ -4031,6 +4014,38 @@ update_eliminables (HARD_REG_SET *pset) SET_HARD_REG_BIT (*pset, HARD_FRAME_POINTER_REGNUM); } +/* Call update_eliminables an spill any registers we can't eliminate anymore. + Return true iff a register was spilled. */ + +static bool +update_eliminables_and_spill (void) +{ + int i; + bool did_spill = false; + HARD_REG_SET to_spill; + CLEAR_HARD_REG_SET (to_spill); + update_eliminables (&to_spill); + AND_COMPL_HARD_REG_SET (used_spill_regs, to_spill); + + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + if (TEST_HARD_REG_BIT (to_spill, i)) + { + spill_hard_reg (i, 1); + did_spill = true; + + /* Regardless of the state of spills, if we previously had + a register that we thought we could eliminate, but now can + not eliminate, we must run another pass. + + Consider pseudos which have an entry in reg_equiv_* which + reference an eliminable register. We must make another pass + to update reg_equiv_* so that we do not substitute in the + old value from when we thought the elimination could be + performed. */ + } + return did_spill; +} + /* Return true if X is used as the target register of an elimination. */ bool diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 04e7d63..23b2a7e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2013-10-30 Joern Rennecke <joern.rennecke@embecosm.com> + + PR other/58545 + * gcc.target/avr/pr58545.c: New test. + 2013-10-30 Tobias Burnus <burnus@net-b.de> Revert: diff --git a/gcc/testsuite/gcc.target/avr/pr58545.c b/gcc/testsuite/gcc.target/avr/pr58545.c new file mode 100644 index 0000000..d1b8461 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/pr58545.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mmcu=atmega8" } */ + +typedef unsigned char uint8_t; +typedef unsigned int uint16_t; + +extern uint8_t f1 (const uint8_t*); +extern void f2 (uint8_t*, uint8_t); + +void func (uint16_t parameter, uint8_t *addr, uint8_t data) +{ + uint8_t status; + + status = f1 (addr + 8); + + addr++; + + if (*addr == parameter + 8) + *addr = parameter; + + f2 (addr, data); + f2 (addr + 8, status + 1); +} |