aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoern Rennecke <joern.rennecke@embecosm.com>2013-10-30 23:55:46 +0000
committerJoern Rennecke <amylaar@gcc.gnu.org>2013-10-30 23:55:46 +0000
commite27a6430c798dd3dbbb0683287cbd4fb134ec362 (patch)
tree5c9f15cee17124d1c53762cc0c992f3ca37b151b
parentfbdec79172bf97c510d5c436732e120e0f497c25 (diff)
downloadgcc-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/ChangeLog9
-rw-r--r--gcc/reload1.c73
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.target/avr/pr58545.c23
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);
+}