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
This commit is contained in:
Joern Rennecke 2013-10-30 23:55:46 +00:00 committed by Joern Rennecke
parent fbdec79172
commit e27a6430c7
4 changed files with 81 additions and 29 deletions

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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);
}