The following patch solves
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=55342
LRA after spilling a pseudo tries to assign freed hard regno to other
reload pseudos and chooses the best. The more reload pseudos got the
freed hard regno, the less cost of spilling. But the reload pseudos
could get another hard regno without spilling. So LRA code before the
patch incorrectly evaluated the cost of spilling. The patch tries to
allocate a hard reg to the other reload pseudos before and after
spilling in order to correctly evaluate spilling cost.
The patch was successfully bootstrapped on x86/x86-64.
Committed as rev. 193588.
2012-11-17 Vladimir Makarov <[email protected]>
PR rtl-optimization/55342
* lra-assigns.c (spill_for): Try to allocate other reload pseudos
before and after spilling.
Index: lra-assigns.c
===================================================================
--- lra-assigns.c (revision 193557)
+++ lra-assigns.c (working copy)
@@ -795,9 +795,8 @@ spill_for (int regno, bitmap spilled_pse
{
int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size;
int reload_hard_regno, reload_cost;
- enum machine_mode mode, mode2;
+ enum machine_mode mode;
enum reg_class rclass;
- HARD_REG_SET spilled_hard_regs;
unsigned int spill_regno, reload_regno, uid;
int insn_pseudos_num, best_insn_pseudos_num;
lra_live_range_t r;
@@ -838,7 +837,6 @@ spill_for (int regno, bitmap spilled_pse
&try_hard_reg_pseudos[hard_regno + j]);
}
/* Spill pseudos. */
- CLEAR_HARD_REG_SET (spilled_hard_regs);
EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
if ((int) spill_regno >= lra_constraint_new_regno_start
&& ! bitmap_bit_p (&lra_inheritance_pseudos, spill_regno)
@@ -853,13 +851,6 @@ spill_for (int regno, bitmap spilled_pse
{
if (bitmap_bit_p (&insn_conflict_pseudos, spill_regno))
insn_pseudos_num++;
- mode2 = PSEUDO_REGNO_MODE (spill_regno);
- update_lives (spill_regno, true);
- if (lra_dump_file != NULL)
- fprintf (lra_dump_file, " spill %d(freq=%d)",
- spill_regno, lra_reg_info[spill_regno].freq);
- add_to_hard_reg_set (&spilled_hard_regs,
- mode2, reg_renumber[spill_regno]);
for (r = lra_reg_info[spill_regno].live_ranges;
r != NULL;
r = r->next)
@@ -877,19 +868,26 @@ spill_for (int regno, bitmap spilled_pse
}
}
}
+ n = 0;
+ EXECUTE_IF_SET_IN_SPARSESET (live_range_reload_inheritance_pseudos,
+ reload_regno)
+ if ((int) reload_regno != regno
+ && (ira_reg_classes_intersect_p
+ [rclass][regno_allocno_class_array[reload_regno]])
+ && live_pseudos_reg_renumber[reload_regno] < 0
+ && find_hard_regno_for (reload_regno, &cost, -1) < 0)
+ sorted_reload_pseudos[n++] = reload_regno;
+ EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
+ {
+ update_lives (spill_regno, true);
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file, " spill %d(freq=%d)",
+ spill_regno, lra_reg_info[spill_regno].freq);
+ }
hard_regno = find_hard_regno_for (regno, &cost, -1);
if (hard_regno >= 0)
{
assign_temporarily (regno, hard_regno);
- n = 0;
- EXECUTE_IF_SET_IN_SPARSESET (live_range_reload_inheritance_pseudos,
- reload_regno)
- if (live_pseudos_reg_renumber[reload_regno] < 0
- && (hard_reg_set_intersect_p
- (reg_class_contents
- [regno_allocno_class_array[reload_regno]],
- spilled_hard_regs)))
- sorted_reload_pseudos[n++] = reload_regno;
qsort (sorted_reload_pseudos, n, sizeof (int),
reload_pseudo_compare_func);
for (j = 0; j < n; j++)
@@ -898,10 +896,7 @@ spill_for (int regno, bitmap spilled_pse
lra_assert (live_pseudos_reg_renumber[reload_regno] < 0);
if ((reload_hard_regno
= find_hard_regno_for (reload_regno,
- &reload_cost, -1)) >= 0
- && (overlaps_hard_reg_set_p
- (spilled_hard_regs,
- PSEUDO_REGNO_MODE (reload_regno), reload_hard_regno)))
+ &reload_cost, -1)) >= 0)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " assign %d(cost=%d)",