The following patch finally fixes s390 bootstrap.
The patch was successfully bootstrapped on s390x, x86/x86-64, power7,
arm, sparc64, and ia64.
Committed as rev. 184749.
2012-03-01 Vladimir Makarov <vmaka...@redhat.com>
* lra-lives.c (pseudos_live_through_calls): New sparseset.
(pseudos_live_through_setjumps): Ditto.
(check_pseudos_live_through_calls): New function.
(process_bb_lives): Use the sparsesets and the function.
(lra_create_live_ranges): Allocate and free sparsesets
pseudos_live_through_calls and pseudos_live_through_setjumps.
* lra-constraints.c (check_and_process_move): Try secondary reload
for source and destination.
* jump.c (true_regnum): Use hard_regno for subreg_get_info when
lra is in progress.
Index: lra-lives.c
===================================================================
--- lra-lives.c (revision 184177)
+++ lra-lives.c (working copy)
@@ -69,6 +69,16 @@ static int curr_point;
/* Pseudos live at current point in the scan. */
static sparseset pseudos_live;
+/* Pseudos probably living through calls and setjumps. As setjump is
+ a call too, if a bit in PSEUDOS_LIVE_THROUGH_SETJUMPS is set up
+ then the corresponding bit in PSEUDOS_LIVE_THROUGH_CALLS is set up
+ too. These data are necessary for cases when only one subreg of a
+ multi-reg pseudo is set up after a call. So we decide it is
+ probably live when traversing bb backward. We are sure about
+ living when we see its usage or definition of the pseudo. */
+static sparseset pseudos_live_through_calls;
+static sparseset pseudos_live_through_setjumps;
+
/* Set of hard regs (except eliminable ones) currently live. */
static HARD_REG_SET hard_regs_live;
@@ -466,6 +476,28 @@ lra_setup_reload_pseudo_preferenced_hard
}
}
+/* Check that REGNO living through calls and setjumps, set up conflict
+ regs, and clear corresponding bits in PSEUDOS_LIVE_THROUGH_CALLS and
+ PSEUDOS_LIVE_THROUGH_SETJUMPS. */
+static inline void
+check_pseudos_live_through_calls (int regno)
+{
+ if (! sparseset_bit_p (pseudos_live_through_calls, regno))
+ return;
+ sparseset_clear_bit (pseudos_live_through_calls, regno);
+ IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
+ call_used_reg_set);
+#ifdef ENABLE_CHECKING
+ lra_reg_info[regno].call_p = true;
+#endif
+ if (! sparseset_bit_p (pseudos_live_through_setjumps, regno))
+ return;
+ sparseset_clear_bit (pseudos_live_through_setjumps, regno);
+ /* Don't allocate pseudos that cross setjmps or any call, if this
+ function receives a nonlocal goto. */
+ SET_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs);
+}
+
/* Process insns of the basic block BB to update pseudo live ranges,
pseudo hard register conflicts. */
static void
@@ -480,6 +512,8 @@ process_bb_lives (basic_block bb)
reg_live_out = DF_LR_OUT (bb);
sparseset_clear (pseudos_live);
+ sparseset_clear (pseudos_live_through_calls);
+ sparseset_clear (pseudos_live_through_setjumps);
REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
AND_COMPL_HARD_REG_SET (hard_regs_live, lra_no_alloc_regs);
@@ -571,7 +605,10 @@ process_bb_lives (basic_block bb)
that are live at the time of the definition. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN)
- mark_regno_live (reg->regno, reg->biggest_mode);
+ {
+ mark_regno_live (reg->regno, reg->biggest_mode);
+ check_pseudos_live_through_calls (reg->regno);
+ }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN)
@@ -596,22 +633,13 @@ process_bb_lives (basic_block bb)
if (call_p)
{
- /* The current set of live pseudos are live across the
- call. */
- EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
- {
- /* Don't allocate pseudos that cross setjmps or any
- call, if this function receives a nonlocal goto. */
- if (cfun->has_nonlocal_label
- || find_reg_note (curr_insn, REG_SETJMP,
- NULL_RTX) != NULL_RTX)
- SET_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
- IOR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs,
- call_used_reg_set);
-#ifdef ENABLE_CHECKING
- lra_reg_info[i].call_p = true;
-#endif
- }
+ sparseset_ior (pseudos_live_through_calls,
+ pseudos_live_through_calls, pseudos_live);
+ if (cfun->has_nonlocal_label
+ || find_reg_note (curr_insn, REG_SETJMP,
+ NULL_RTX) != NULL_RTX)
+ sparseset_ior (pseudos_live_through_setjumps,
+ pseudos_live_through_setjumps, pseudos_live);
}
incr_curr_point (freq);
@@ -621,7 +649,10 @@ process_bb_lives (basic_block bb)
/* Mark each used value as live. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type == OP_IN)
- mark_regno_live (reg->regno, reg->biggest_mode);
+ {
+ mark_regno_live (reg->regno, reg->biggest_mode);
+ check_pseudos_live_through_calls (reg->regno);
+ }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type == OP_IN)
@@ -711,6 +742,10 @@ process_bb_lives (basic_block bb)
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
mark_pseudo_dead (i);
+
+ EXECUTE_IF_SET_IN_SPARSESET (pseudos_live_through_calls, i)
+ if (bitmap_bit_p (DF_LR_IN (bb), i))
+ check_pseudos_live_through_calls (i);
incr_curr_point (freq);
}
@@ -943,6 +978,8 @@ lra_create_live_ranges (bool all_p)
}
lra_free_copies ();
pseudos_live = sparseset_alloc (max_regno);
+ pseudos_live_through_calls = sparseset_alloc (max_regno);
+ pseudos_live_through_setjumps = sparseset_alloc (max_regno);
start_living = sparseset_alloc (max_regno);
start_dying = sparseset_alloc (max_regno);
dead_set = sparseset_alloc (max_regno);
@@ -961,6 +998,8 @@ lra_create_live_ranges (bool all_p)
sparseset_free (dead_set);
sparseset_free (start_dying);
sparseset_free (start_living);
+ sparseset_free (pseudos_live_through_calls);
+ sparseset_free (pseudos_live_through_setjumps);
sparseset_free (pseudos_live);
compress_live_ranges ();
}
Index: lra-constraints.c
===================================================================
--- lra-constraints.c (revision 184637)
+++ lra-constraints.c (working copy)
@@ -1042,11 +1042,11 @@ emit_spill_move (bool to_p, rtx mem_pseu
static bool
check_and_process_move (bool *change_p, bool *sec_mem_p)
{
- int regno;
- rtx set, dest, src, dreg, sr, dr, sreg, new_reg, before, x, scratch_reg;
- enum reg_class dclass, sclass, xclass, rclass, secondary_class;
+ int sregno, dregno;
+ rtx set, dest, src, dreg, sr, dr, sreg, new_reg, before, scratch_reg;
+ enum reg_class dclass, sclass, secondary_class;
+ enum machine_mode sreg_mode;
secondary_reload_info sri;
- bool in_p, temp_assign_p;
*sec_mem_p = *change_p = false;
if ((set = single_set (curr_insn)) == NULL || side_effects_p (set))
@@ -1081,6 +1081,7 @@ check_and_process_move (bool *change_p,
work with such classes through their implementation of
machine-dependent hooks like secondary_memory_needed. */
return false;
+ sreg_mode = GET_MODE (sreg);
sr = get_equiv_substitution (sreg);
if (sr != sreg)
sreg = copy_rtx (sr);
@@ -1100,44 +1101,44 @@ check_and_process_move (bool *change_p,
sri.prev_sri = NULL;
sri.icode = CODE_FOR_nothing;
sri.extra_cost = 0;
- if (sclass != NO_REGS)
- {
- in_p = false;
- rclass = sclass;
- x = dreg;
- xclass = dclass;
- }
- else if (dclass != NO_REGS)
- {
- in_p = true;
- rclass = dclass;
- x = sreg;
- xclass = sclass;
- }
- else
- return false;
- temp_assign_p = false;
+ secondary_class = NO_REGS;
/* Set up hard register for a reload pseudo for hook
secondary_reload because some targets just ignore pseudos in the
hook. */
- if (xclass != NO_REGS
- && REG_P (x) && (regno = REGNO (x)) >= new_regno_start
- && lra_get_regno_hard_regno (regno) < 0)
- {
- reg_renumber[regno] = ira_class_hard_regs[xclass][0];
- temp_assign_p = true;
- }
- secondary_class
- = (enum reg_class) targetm.secondary_reload (in_p, x, (reg_class_t) rclass,
- GET_MODE (src), &sri);
- if (temp_assign_p)
- reg_renumber [REGNO (x)] = -1;
+ if (dclass != NO_REGS
+ && REG_P (dreg) && (dregno = REGNO (dreg)) >= new_regno_start
+ && lra_get_regno_hard_regno (dregno) < 0)
+ reg_renumber[dregno] = ira_class_hard_regs[dclass][0];
+ else
+ dregno = -1;
+ if (sclass != NO_REGS
+ && REG_P (sreg) && (sregno = REGNO (sreg)) >= new_regno_start
+ && lra_get_regno_hard_regno (sregno) < 0)
+ reg_renumber[sregno] = ira_class_hard_regs[sclass][0];
+ else
+ sregno = -1;
+ if (sclass != NO_REGS)
+ secondary_class
+ = (enum reg_class) targetm.secondary_reload (false, dest,
+ (reg_class_t) sclass,
+ GET_MODE (src), &sri);
+ if (sclass == NO_REGS
+ || ((secondary_class != NO_REGS || sri.icode != CODE_FOR_nothing)
+ && dclass != NO_REGS))
+ secondary_class
+ = (enum reg_class) targetm.secondary_reload (true, sreg,
+ (reg_class_t) dclass,
+ sreg_mode, &sri);
+ if (sregno >= 0)
+ reg_renumber [sregno] = -1;
+ if (dregno >= 0)
+ reg_renumber [dregno] = -1;
if (secondary_class == NO_REGS && sri.icode == CODE_FOR_nothing)
return false;
*change_p = true;
new_reg = NULL_RTX;
if (secondary_class != NO_REGS)
- new_reg = lra_create_new_reg_with_unique_value (GET_MODE (sreg), NULL_RTX,
+ new_reg = lra_create_new_reg_with_unique_value (sreg_mode, NULL_RTX,
secondary_class,
"secondary");
start_sequence ();
@@ -1160,8 +1161,8 @@ check_and_process_move (bool *change_p,
lra_process_new_insns (curr_insn, before, NULL_RTX, "Inserting the move");
if (new_reg != NULL_RTX)
{
- if (GET_CODE (SET_SRC (set)) == SUBREG)
- SUBREG_REG (SET_SRC (set)) = new_reg;
+ if (GET_CODE (src) == SUBREG)
+ SUBREG_REG (src) = new_reg;
else
SET_SRC (set) = new_reg;
}
Index: jump.c
===================================================================
--- jump.c (revision 184146)
+++ jump.c (working copy)
@@ -1866,7 +1866,8 @@ true_regnum (const_rtx x)
{
struct subreg_info info;
- subreg_get_info (REGNO (SUBREG_REG (x)),
+ subreg_get_info (lra_in_progress
+ ? (unsigned) base : REGNO (SUBREG_REG (x)),
GET_MODE (SUBREG_REG (x)),
SUBREG_BYTE (x), GET_MODE (x), &info);