To make sure that reloading is done with up-to-date register eliminations,
I call update_eliminables also in the code path that continues for a frame
size change.  Not directly, since I need the code to spill the no longer
eliminated registers; I've factored out this code into a new function
update_eliminables_and_spill.
Also, I move the frame size alignment code before the code that tests for
a frame size change so that this is also covered with the enhanced check.

In principle, we could inline update_eliminables into update_eliminables_and_spill now, since the former is only called from the
latter, but I leave this to the bootstrap compiler so as not to break the
connection between init_elim_table and update_eliminables.

Regression tested on avr atmega128-sim.

Bootstrapped and regtested on i686-pc-linux-gnu.

OK to apply?
2013-10-02  Joern Rennecke  <joern.renne...@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.

Index: reload1.c
===================================================================
--- reload1.c   (revision 203159)
+++ reload1.c   (working copy)
@@ -373,6 +373,7 @@ static void init_eliminable_invariants (
 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

Reply via email to