===================================================================
@@ -64,7 +64,7 @@ static struct regno_assign_info *regno_a
/* Process a pseudo copy with frequency COPY_FREQ connecting REGNO1
and REGNO2 to form threads. */
static void
-process_copy_to_form_allocno (int regno1, int regno2, int copy_freq)
+process_copy_to_form_thread (int regno1, int regno2, int copy_freq)
{
int last, regno1_first, regno2_first;
@@ -111,7 +111,7 @@ init_regno_assign_info (void)
&& reg_renumber[regno2] < 0 && lra_reg_info[regno2].nrefs != 0
&& (ira_available_class_regs[regno_allocno_class_array[regno1]]
== ira_available_class_regs[regno_allocno_class_array[regno2]]))
- process_copy_to_form_allocno (regno1, regno2, cp->freq);
+ process_copy_to_form_thread (regno1, regno2, cp->freq);
}
/* Free REGNO_ASSIGN_INFO. */
@@ -243,42 +243,42 @@ update_lives (int regno, bool free_p)
/* Sparseset used to calculate reload pseudos conflicting with a given
pseudo when we are trying to find a hard register for the given
pseudo. */
-static sparseset conflict_reload_pseudos;
+static sparseset conflict_reload_and_inheritance_pseudos;
-/* Map: program point -> bitmap of all reload pseudos living at the
- point. */
-static bitmap_head *live_reload_pseudos;
+/* Map: program point -> bitmap of all reload and inheritance pseudos
+ living at the point. */
+static bitmap_head *live_reload_and_inheritance_pseudos;
/* Allocate and initialize data about living reload pseudos at any
given program point. */
static void
-init_live_reload_pseudos (void)
+init_live_reload_and_inheritance_pseudos (void)
{
int i, p;
lra_live_range_t r;
- conflict_reload_pseudos = sparseset_alloc (max_reg_num ());
- live_reload_pseudos
+ conflict_reload_and_inheritance_pseudos = sparseset_alloc (max_reg_num ());
+ live_reload_and_inheritance_pseudos
= (bitmap_head *) xmalloc (sizeof (bitmap_head) * lra_live_max_point);
for (p = 0; p < lra_live_max_point; p++)
- bitmap_initialize (&live_reload_pseudos[p], ®_obstack);
+ bitmap_initialize (&live_reload_and_inheritance_pseudos[p], ®_obstack);
for (i = lra_constraint_new_regno_start; i < max_reg_num (); i++)
for (r = lra_reg_info[i].live_ranges; r != NULL; r = r->next)
for (p = r->start; p <= r->finish; p++)
- bitmap_set_bit (&live_reload_pseudos[p], i);
+ bitmap_set_bit (&live_reload_and_inheritance_pseudos[p], i);
}
/* Finalize data about living reload pseudos at any given program
point. */
static void
-finish_live_reload_pseudos (void)
+finish_live_reload_and_inheritance_pseudos (void)
{
int p;
- sparseset_free (conflict_reload_pseudos);
+ sparseset_free (conflict_reload_and_inheritance_pseudos);
for (p = 0; p < lra_live_max_point; p++)
- bitmap_clear (&live_reload_pseudos[p]);
- free (live_reload_pseudos);
+ bitmap_clear (&live_reload_and_inheritance_pseudos[p]);
+ free (live_reload_and_inheritance_pseudos);
}
/* The value used to check that cost of given hard reg is defined
@@ -292,13 +292,13 @@ static int hard_regno_costs_check[FIRST_
CURR_HARD_REGNO_COSTS_CHECK. */
static int hard_regno_costs[FIRST_PSEUDO_REGISTER];
-/* Find and return best free hard register for pseudo REGNO. In
- failure case, return a negative number. Return through *COST the
- cost of usage of the hard register for the pseudo. Best free hard
- register has smallest cost of usage for REGNO or smallest register
- bank if the cost is the same. */
+/* Find and return best (or TRY_ONLY_HARD_REGNO) free hard register
+ for pseudo REGNO. In failure case, return a negative number.
+ Return through *COST the cost of usage of the hard register for the
+ pseudo. Best free hard register has smallest cost of usage for
+ REGNO or smallest register bank if the cost is the same. */
static int
-find_hard_regno_for (int regno, int *cost)
+find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
{
HARD_REG_SET conflict_set;
int best_cost = INT_MAX, best_bank = INT_MAX, best_usage = INT_MAX;
@@ -314,7 +314,7 @@ find_hard_regno_for (int regno, int *cos
rclass = regno_allocno_class_array[regno];
rclass_intersect_p = ira_reg_classes_intersect_p[rclass];
curr_hard_regno_costs_check++;
- sparseset_clear (conflict_reload_pseudos);
+ sparseset_clear (conflict_reload_and_inheritance_pseudos);
sparseset_clear (live_range_hard_reg_pseudos);
IOR_HARD_REG_SET (conflict_set, lra_reg_info[regno].conflict_hard_regs);
for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
@@ -322,10 +322,12 @@ find_hard_regno_for (int regno, int *cos
EXECUTE_IF_SET_IN_BITMAP (&live_hard_reg_pseudos[r->start], 0, k, bi)
if (rclass_intersect_p[regno_allocno_class_array[k]])
sparseset_set_bit (live_range_hard_reg_pseudos, k);
- EXECUTE_IF_SET_IN_BITMAP (&live_reload_pseudos[r->start], 0, k, bi)
- if (reg_renumber[k] < 0
+ EXECUTE_IF_SET_IN_BITMAP (&live_reload_and_inheritance_pseudos[r->start],
+ 0, k, bi)
+ if (lra_reg_info[k].preferred_hard_regno1 >= 0
+ && live_pseudos_reg_renumber[k] < 0
&& rclass_intersect_p[regno_allocno_class_array[k]])
- sparseset_set_bit (conflict_reload_pseudos, k);
+ sparseset_set_bit (conflict_reload_and_inheritance_pseudos, k);
for (p = r->start + 1; p <= r->finish; p++)
{
lra_live_range_t r2;
@@ -333,9 +335,11 @@ find_hard_regno_for (int regno, int *cos
for (r2 = lra_start_point_ranges[p]; r2 != NULL; r2 = r2->start_next)
{
if (r2->regno >= lra_constraint_new_regno_start
- && reg_renumber[r2->regno] < 0
+ && lra_reg_info[r2->regno].preferred_hard_regno1 >= 0
+ && live_pseudos_reg_renumber[r2->regno] < 0
&& rclass_intersect_p[regno_allocno_class_array[r2->regno]])
- sparseset_set_bit (conflict_reload_pseudos, r2->regno);
+ sparseset_set_bit (conflict_reload_and_inheritance_pseudos,
+ r2->regno);
if (live_pseudos_reg_renumber[r2->regno] >= 0
&& rclass_intersect_p[regno_allocno_class_array[r2->regno]])
sparseset_set_bit (live_range_hard_reg_pseudos, r2->regno);
@@ -349,34 +353,38 @@ find_hard_regno_for (int regno, int *cos
hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
hard_regno_costs[hard_regno]
-= lra_reg_info[regno].preferred_hard_regno_profit1;
- }
- if ((hard_regno = lra_reg_info[regno].preferred_hard_regno2) >= 0)
- {
- if (hard_regno_costs_check[hard_regno] != curr_hard_regno_costs_check)
- hard_regno_costs[hard_regno] = 0;
- hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
- hard_regno_costs[hard_regno]
- -= lra_reg_info[regno].preferred_hard_regno_profit2;
+ if ((hard_regno = lra_reg_info[regno].preferred_hard_regno2) >= 0)
+ {
+ if (hard_regno_costs_check[hard_regno]
+ != curr_hard_regno_costs_check)
+ hard_regno_costs[hard_regno] = 0;
+ hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
+ hard_regno_costs[hard_regno]
+ -= lra_reg_info[regno].preferred_hard_regno_profit2;
+ }
}
#ifdef STACK_REGS
if (lra_reg_info[regno].no_stack_p)
for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
SET_HARD_REG_BIT (conflict_set, i);
#endif
- sparseset_clear_bit (conflict_reload_pseudos, regno);
+ sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno);
val = lra_reg_info[regno].val;
EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
if (val != lra_reg_info[conflict_regno].val)
- lra_add_hard_reg_set (reg_renumber[conflict_regno],
- lra_reg_info[conflict_regno].biggest_mode,
- &conflict_set);
- if (hard_reg_set_subset_p (reg_class_contents[rclass],
- conflict_set))
- return -1;
- EXECUTE_IF_SET_IN_SPARSESET (conflict_reload_pseudos, conflict_regno)
- if (reg_renumber[conflict_regno] < 0
- && val != lra_reg_info[conflict_regno].val)
{
+ lra_add_hard_reg_set (live_pseudos_reg_renumber[conflict_regno],
+ lra_reg_info[conflict_regno].biggest_mode,
+ &conflict_set);
+ if (hard_reg_set_subset_p (reg_class_contents[rclass],
+ conflict_set))
+ return -1;
+ }
+ EXECUTE_IF_SET_IN_SPARSESET (conflict_reload_and_inheritance_pseudos,
+ conflict_regno)
+ if (val != lra_reg_info[conflict_regno].val)
+ {
+ gcc_assert (live_pseudos_reg_renumber[conflict_regno] < 0);
if ((hard_regno
= lra_reg_info[conflict_regno].preferred_hard_regno1) >= 0)
{
@@ -386,16 +394,17 @@ find_hard_regno_for (int regno, int *cos
hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
hard_regno_costs[hard_regno]
+= lra_reg_info[conflict_regno].preferred_hard_regno_profit1;
- }
- if ((hard_regno
- = lra_reg_info[conflict_regno].preferred_hard_regno2) >= 0)
- {
- if (hard_regno_costs_check[hard_regno]
- != curr_hard_regno_costs_check)
- hard_regno_costs[hard_regno] = 0;
- hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
- hard_regno_costs[hard_regno]
- += lra_reg_info[conflict_regno].preferred_hard_regno_profit2;
+ if ((hard_regno
+ = lra_reg_info[conflict_regno].preferred_hard_regno2) >= 0)
+ {
+ if (hard_regno_costs_check[hard_regno]
+ != curr_hard_regno_costs_check)
+ hard_regno_costs[hard_regno] = 0;
+ hard_regno_costs_check[hard_regno]
+ = curr_hard_regno_costs_check;
+ hard_regno_costs[hard_regno]
+ += lra_reg_info[conflict_regno].preferred_hard_regno_profit2;
+ }
}
}
/* That is important for allocation of multi-word pseudos. */
@@ -406,44 +415,51 @@ find_hard_regno_for (int regno, int *cos
best_hard_regno = -1;
for (i = 0; i < rclass_size; i++)
{
- hard_regno = ira_class_hard_regs[rclass][i];
- if (lra_hard_reg_set_intersection_p (hard_regno,
- PSEUDO_REGNO_MODE (regno),
- conflict_set)
+ if (try_only_hard_regno >= 0)
+ hard_regno = try_only_hard_regno;
+ else
+ hard_regno = ira_class_hard_regs[rclass][i];
+ if (! lra_hard_reg_set_intersection_p (hard_regno,
+ PSEUDO_REGNO_MODE (regno),
+ conflict_set)
/* We can not use prohibited_class_mode_regs because it is
defined not for all classes. */
- || ! HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno)))
- continue;
- if (hard_regno_costs_check[hard_regno] != curr_hard_regno_costs_check)
+ && HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno)))
{
- hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
- hard_regno_costs[hard_regno] = 0;
- }
- for (j = 0;
- j < hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (regno)];
- j++)
- if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j)
- && ! df_regs_ever_live_p (hard_regno + j))
- /* It needs save restore. */
- hard_regno_costs[hard_regno]
- += 2 * ENTRY_BLOCK_PTR->next_bb->frequency;
- bank = targetm.register_bank (hard_regno);
- if (best_hard_regno < 0 || hard_regno_costs[hard_regno] < best_cost
- || (hard_regno_costs[hard_regno] == best_cost
- && (bank < best_bank
- /* Hard register usage leveling actually results
- in bigger code for targets with conditional
- execution like ARM because it reduces chance
- of if-conversion after LRA. */
- || (! targetm.have_conditional_execution ()
- && bank == best_bank
- && best_usage > lra_hard_reg_usage[hard_regno]))))
- {
- best_hard_regno = hard_regno;
- best_cost = hard_regno_costs[hard_regno];
- best_bank = bank;
- best_usage = lra_hard_reg_usage[hard_regno];
+ if (hard_regno_costs_check[hard_regno]
+ != curr_hard_regno_costs_check)
+ {
+ hard_regno_costs_check[hard_regno] = curr_hard_regno_costs_check;
+ hard_regno_costs[hard_regno] = 0;
+ }
+ for (j = 0;
+ j < hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (regno)];
+ j++)
+ if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j)
+ && ! df_regs_ever_live_p (hard_regno + j))
+ /* It needs save restore. */
+ hard_regno_costs[hard_regno]
+ += 2 * ENTRY_BLOCK_PTR->next_bb->frequency;
+ bank = targetm.register_bank (hard_regno);
+ if (best_hard_regno < 0 || hard_regno_costs[hard_regno] < best_cost
+ || (hard_regno_costs[hard_regno] == best_cost
+ && (bank < best_bank
+ /* Hard register usage leveling actually results
+ in bigger code for targets with conditional
+ execution like ARM because it reduces chance
+ of if-conversion after LRA. */
+ || (! targetm.have_conditional_execution ()
+ && bank == best_bank
+ && best_usage > lra_hard_reg_usage[hard_regno]))))
+ {
+ best_hard_regno = hard_regno;
+ best_cost = hard_regno_costs[hard_regno];
+ best_bank = bank;
+ best_usage = lra_hard_reg_usage[hard_regno];
+ }
}
+ if (try_only_hard_regno >= 0)
+ break;
}
if (best_hard_regno >= 0)
*cost = best_cost - lra_reg_info[regno].freq;
@@ -575,10 +591,10 @@ setup_try_hard_regno_pseudos (int p, enu
EXECUTE_IF_SET_IN_BITMAP (&live_hard_reg_pseudos[p], 0, spill_regno, bi)
{
mode = PSEUDO_REGNO_MODE (spill_regno);
- if (lra_hard_reg_set_intersection_p (reg_renumber[spill_regno], mode,
+ if (lra_hard_reg_set_intersection_p (live_pseudos_reg_renumber[spill_regno], mode,
reg_class_contents[rclass]))
{
- hard_regno = reg_renumber[spill_regno];
+ hard_regno = live_pseudos_reg_renumber[spill_regno];
for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
{
if (try_hard_reg_pseudos_check[hard_regno + i]
@@ -612,7 +628,6 @@ assign_temporarily (int regno, int hard_
bitmap_set_bit (&live_hard_reg_pseudos[p], regno);
}
live_pseudos_reg_renumber[regno] = hard_regno;
- reg_renumber[regno] = hard_regno;
}
/* Array used for sorting reload pseudos for subsequent allocation
@@ -711,24 +726,26 @@ spill_for (int regno, bitmap spilled_pse
/* We are trying to spill reload pseudo. That is wrong we
should assign all reload pseudos, otherwise we cannot reuse
selected alternativies. */
- hard_regno = find_hard_regno_for (regno, &cost);
+ 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_pseudos, reload_regno)
- if (reg_renumber[reload_regno] < 0
+ 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);
+ qsort (sorted_reload_pseudos, n, sizeof (int),
+ reload_pseudo_compare_func);
for (j = 0; j < n; j++)
{
reload_regno = sorted_reload_pseudos[j];
- if (reg_renumber[reload_regno] < 0
+ if (live_pseudos_reg_renumber[reload_regno] < 0
&& (reload_hard_regno
- = find_hard_regno_for (reload_regno, &reload_cost)) >= 0
+ = find_hard_regno_for (reload_regno,
+ &reload_cost, -1)) >= 0
&& (lra_hard_reg_set_intersection_p
(reload_hard_regno, PSEUDO_REGNO_MODE (reload_regno),
spilled_hard_regs)))
@@ -767,7 +784,7 @@ spill_for (int regno, bitmap spilled_pse
for (j = 0; j < n; j++)
{
reload_regno = sorted_reload_pseudos[j];
- if (reg_renumber[reload_regno] >= 0)
+ if (live_pseudos_reg_renumber[reload_regno] >= 0)
assign_temporarily (reload_regno, -1);
}
}
@@ -837,7 +854,14 @@ setup_live_pseudos_and_spill_after_equiv
for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
if (reg_renumber[i] >= 0 && lra_reg_info[i].nrefs > 0)
- sorted_pseudos[n++] = i;
+ {
+ if (lra_risky_equiv_subst_p)
+ sorted_pseudos[n++] = i;
+ else
+ update_lives (i, false);
+ }
+ if (! lra_risky_equiv_subst_p)
+ return;
qsort (sorted_pseudos, n, sizeof (int), pseudo_compare_func);
for (i = 0; i < n; i++)
{
@@ -884,6 +908,64 @@ setup_live_pseudos_and_spill_after_equiv
}
}
+/* Improve allocation by assigning the same hard regno of inheritance
+ pseudos to the connected pseudos. We need this because inheritance
+ pseudos are allocated after reload pseudos in the thread and when
+ we assign a hard register to a reload pseudo we don't know yet that
+ the connected inheritance pseudos can get the same hard
+ register. */
+static void
+improve_inheritance (void)
+{
+ unsigned int k;
+ int regno, another_regno, hard_regno, another_hard_regno, cost, i, n;
+ lra_copy_t cp, next_cp;
+ bitmap_iterator bi;
+
+ n = 0;
+ EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, k, bi)
+ if (reg_renumber[k] >= 0 && lra_reg_info[k].nrefs != 0)
+ sorted_pseudos[n++] = k;
+ qsort (sorted_pseudos, n, sizeof (int), pseudo_compare_func);
+ for (i = 0; i < n; i++)
+ {
+ regno = sorted_pseudos[i];
+ hard_regno = reg_renumber[regno];
+ gcc_assert (hard_regno >= 0);
+ for (cp = lra_reg_info[regno].copies; cp != NULL; cp = next_cp)
+ {
+ if (cp->regno1 == regno)
+ {
+ next_cp = cp->regno1_next;
+ another_regno = cp->regno2;
+ }
+ else if (cp->regno2 == regno)
+ {
+ next_cp = cp->regno2_next;
+ another_regno = cp->regno1;
+ }
+ else
+ gcc_unreachable ();
+ if ((another_hard_regno = reg_renumber[another_regno]) >= 0
+ && another_hard_regno != hard_regno)
+ {
+ if (lra_dump_file != NULL)
+ fprintf (lra_dump_file,
+ " Improving inheritance for %d(%d) and %d(%d)...\n",
+ regno, hard_regno, another_regno, another_hard_regno);
+ update_lives (another_regno, true);
+ lra_setup_reg_renumber (another_regno, -1, false);
+ if (hard_regno
+ == find_hard_regno_for (another_regno, &cost, hard_regno))
+ assign_hard_regno (hard_regno, another_regno);
+ else
+ assign_hard_regno (another_hard_regno, another_regno);
+ }
+ }
+ }
+}
+
+
/* Bitmap finaly containing all pseudos spilled on this assignment
pass. */
static bitmap_head all_spilled_pseudos;
@@ -935,8 +1017,9 @@ assign_by_spills (void)
ORIGINAL_REGNO (regno_reg_rtx[regno]),
lra_reg_info[regno].freq, regno_assign_info[regno].first,
regno_assign_info[regno_assign_info[regno].first].freq);
- hard_regno = find_hard_regno_for (regno, &cost);
- if (hard_regno < 0 && ! bitmap_bit_p (&lra_inheritance_pseudos, regno))
+ hard_regno = find_hard_regno_for (regno, &cost, -1);
+ if (hard_regno < 0
+ && ! bitmap_bit_p (&lra_inheritance_pseudos, regno))
hard_regno = spill_for (regno, &all_spilled_pseudos);
if (hard_regno < 0)
{
@@ -999,6 +1082,7 @@ assign_by_spills (void)
}
n = nfails;
}
+ improve_inheritance ();
bitmap_clear (&changed_insns);
/* Inheritance pseudo can be assigned and after that spilled. We
should look at the final result. */
@@ -1021,7 +1105,7 @@ assign_by_spills (void)
for (i = 0; i < n; i++)
{
regno = sorted_pseudos[i];
- hard_regno = find_hard_regno_for (regno, &cost);
+ hard_regno = find_hard_regno_for (regno, &cost, -1);
if (hard_regno >= 0)
{
bitmap_set_bit (&changed_pseudo_bitmap, regno);
@@ -1072,9 +1156,9 @@ lra_assign (void)
setup_live_pseudos_and_spill_after_equiv_moves (&all_spilled_pseudos);
/* Setup insns to process. */
bitmap_initialize (&changed_pseudo_bitmap, ®_obstack);
- init_live_reload_pseudos ();
+ init_live_reload_and_inheritance_pseudos ();
assign_by_spills ();
- finish_live_reload_pseudos ();
+ finish_live_reload_and_inheritance_pseudos ();
bitmap_ior_into (&changed_pseudo_bitmap, &all_spilled_pseudos);
no_spills_p = true;
EXECUTE_IF_SET_IN_BITMAP (&all_spilled_pseudos, 0, u, bi)
===================================================================
@@ -288,6 +288,7 @@ extern rtx lra_secondary_memory[NUM_MACH
extern int lra_constraint_offset (int, enum machine_mode);
extern int lra_constraint_iter;
+extern bool lra_risky_equiv_subst_p;
extern int lra_inheritance_iter;
extern int lra_undo_inheritance_iter;
extern bool lra_constraints (bool);
===================================================================
@@ -2154,6 +2154,15 @@ lra (FILE *f)
if (! lra_constraints (lra_constraint_iter == 0)
&& (lra_constraint_iter > 1 || ! scratch_p))
break;
+ /* Constraint transformations may result in that eliminable
+ hard regs become uneliminable and pseudos which use them
+ should be spilled. It is better to do it before pseudo
+ assignments.
+
+ For example, rs6000 can make
+ RS6000_PIC_OFFSET_TABLE_REGNUM uneliminable if we started
+ to use a constant pool. */
+ lra_eliminate (false);
lra_inheritance ();
/* We need live ranges for lra_assign -- so build them. */
lra_create_live_ranges (true);
@@ -2176,6 +2185,8 @@ lra (FILE *f)
if (! lra_spill ())
break;
coalesce_skip_p = true;
+ /* Assignment of stack slots changes elimination offsets for
+ some eliminations. So update the offsets here. */
lra_eliminate (false);
lra_constraint_new_regno_start = max_reg_num ();
lra_constraint_new_insn_uid_start = get_max_uid ();
===================================================================
@@ -20,7 +20,7 @@ You should have received a copy of the G
along with GCC; see the file COPYING3. If not see
<http://www.gnu.org/licenses/>. */
-extern void lra_init_elimination (HARD_REG_SET *);
+extern void lra_init_elimination (void);
extern rtx lra_eliminate_regs (rtx, enum machine_mode, rtx);
extern void lra (FILE *);
extern void lra_init_once (void);
===================================================================
@@ -763,9 +763,7 @@ static void
eliminate_regs_in_insn (rtx insn, bool replace_p)
{
int icode = recog_memoized (insn);
- rtx old_body = PATTERN (insn);
rtx old_set = single_set (insn);
- rtx new_body;
bool val;
int i, regno;
rtx substed_operand[MAX_RECOG_OPERANDS];
@@ -775,7 +773,7 @@ eliminate_regs_in_insn (rtx insn, bool r
lra_insn_recog_data_t id;
struct lra_static_insn_data *static_id;
- if (icode < 0 && asm_noperands (old_body) < 0 && ! DEBUG_INSN_P (insn))
+ if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
{
gcc_assert (GET_CODE (PATTERN (insn)) == USE
|| GET_CODE (PATTERN (insn)) == CLOBBER
@@ -834,14 +832,6 @@ eliminate_regs_in_insn (rtx insn, bool r
: offset);
src = plus_constant (ep->to_rtx, offset);
- new_body = old_body;
- if (0 && ! replace_p)
- {
- new_body = copy_insn (old_body);
- if (REG_NOTES (insn))
- REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn));
- }
- PATTERN (insn) = new_body;
old_set = single_set (insn);
/* First see if this insn remains valid when we make
@@ -930,14 +920,6 @@ eliminate_regs_in_insn (rtx insn, bool r
{
rtx new_src = plus_constant (to_rtx, offset);
- new_body = old_body;
- if (0 && ! replace_p)
- {
- new_body = copy_insn (old_body);
- if (REG_NOTES (insn))
- REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn));
- }
- PATTERN (insn) = new_body;
old_set = single_set (insn);
/* First see if this insn remains valid when we make the
@@ -1017,26 +999,11 @@ eliminate_regs_in_insn (rtx insn, bool r
if (val)
{
- /* If we aren't replacing things permanently and we changed something,
- make another copy to ensure that all the RTL is new. Otherwise
- things can go wrong if curr_insn_transform swaps commutative operands
- and one is inside RTL that has been copied while the other is not. */
- new_body = old_body;
- if (0 && ! replace_p)
- {
- new_body = copy_insn (old_body);
- if (REG_NOTES (insn))
- REG_NOTES (insn) = copy_insn_1 (REG_NOTES (insn));
- }
- PATTERN (insn) = new_body;
-
- val = false;
-
- /* If we had a move insn but now we don't, re-recognize it. This will
- cause spurious re-recognition if the old move had a PARALLEL since
- the new one still will, but we can't call single_set without
- having put NEW_BODY into the insn and the re-recognition won't
- hurt in this rare case. */
+ /* If we had a move insn but now we don't, re-recognize it.
+ This will cause spurious re-recognition if the old move had a
+ PARALLEL since the new one still will, but we can't call
+ single_set without having put new body into the insn and the
+ re-recognition won't hurt in this rare case. */
id = lra_update_insn_recog_data (insn);
static_id = id->insn_static_data;
}
@@ -1075,25 +1042,24 @@ spill_pseudos (HARD_REG_SET set)
bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
}
IOR_HARD_REG_SET (lra_no_alloc_regs, set);
- bitmap_clear (&to_process);
for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
if (bitmap_bit_p (&to_process, INSN_UID (insn)))
{
lra_push_insn (insn);
lra_set_used_insn_alternative (insn, -1);
}
+ bitmap_clear (&to_process);
}
/* Update all offsets and possibility for elimination on eliminable
- registers. See if anything that happened changes which
- eliminations are valid. If there are no any changes return false.
- Otherwise, spill pseudos assigned to not eliminable pseudos,
- restore offsets, and return true. */
-static bool
-update_reg_eliminate (void)
+ registers. Spill pseudos assigned to registers which became
+ uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET. Add
+ insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
+ registers whose offsets should be changed. */
+static void
+update_reg_eliminate (bitmap insns_with_changed_offsets)
{
bool prev;
- bool change_p = false;
struct elim_table *ep, *ep1;
HARD_REG_SET temp_hard_reg_set;
@@ -1127,7 +1093,6 @@ update_reg_eliminate (void)
fprintf (lra_dump_file,
" Elimination %d to %d is not possible anymore\n",
ep->from, ep->to);
- change_p = true;
/* Mark that is not eliminable anymore. */
elimination_map[ep->from] = NULL;
for (ep1 = ep + 1; ep1 < ®_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
@@ -1151,6 +1116,9 @@ update_reg_eliminate (void)
ep->from);
self_elim_offsets[ep->from] = -ep->offset;
SET_HARD_REG_BIT (temp_hard_reg_set, ep->from);
+ if (ep->offset != 0)
+ bitmap_ior_into (insns_with_changed_offsets,
+ &lra_reg_info[ep->from].insn_bitmap);
}
}
@@ -1159,15 +1127,15 @@ update_reg_eliminate (void)
#else
INITIAL_FRAME_POINTER_OFFSET (ep->offset);
#endif
- if (elimination_map[ep->from] == ep
- && ep->previous_offset != ep->offset)
- change_p = true;
}
- if (! change_p)
- return false;
+ IOR_HARD_REG_SET (lra_no_alloc_regs, temp_hard_reg_set);
+ AND_COMPL_HARD_REG_SET (eliminable_regset, temp_hard_reg_set);
spill_pseudos (temp_hard_reg_set);
setup_elimination_map ();
- return true;
+ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (elimination_map[ep->from] == ep && ep->previous_offset != ep->offset)
+ bitmap_ior_into (insns_with_changed_offsets,
+ &lra_reg_info[ep->from].insn_bitmap);
}
/* Initialize the table of registers to eliminate. Pre-condition:
@@ -1176,7 +1144,7 @@ update_reg_eliminate (void)
used for allocation because their identical elimination is not
possible. */
static void
-init_elim_table (HARD_REG_SET *dont_use_regs)
+init_elim_table (void)
{
bool value_p;
struct elim_table *ep;
@@ -1184,7 +1152,6 @@ init_elim_table (HARD_REG_SET *dont_use_
const struct elim_table_1 *ep1;
#endif
- CLEAR_HARD_REG_SET (*dont_use_regs);
if (!reg_eliminate)
reg_eliminate = XCNEWVEC (struct elim_table, NUM_ELIMINABLE_REGS);
@@ -1204,13 +1171,6 @@ init_elim_table (HARD_REG_SET *dont_use_
&& frame_pointer_needed
&& (! SUPPORTS_STACK_ALIGNMENT
|| ! stack_realign_fp)));
- if (value_p && ep->from == ep->to)
- {
- /* We do not support tricks to use elimination to find is
- the hard register needed. */
- value_p = false;
- SET_HARD_REG_BIT (*dont_use_regs, ep->from);
- }
setup_can_eliminate (ep, value_p);
}
#else
@@ -1232,22 +1192,19 @@ init_elim_table (HARD_REG_SET *dont_use_
}
}
-/* Entry function for initializeation of elimination once per
- function. Set up hard registers which can not be used in
- allocation in *DONT_USE_REGS. */
+/* Entry function for initialization of elimination once per
+ function. */
void
-lra_init_elimination (HARD_REG_SET *dont_use_regs)
+lra_init_elimination (void)
{
basic_block bb;
rtx insn;
- init_elim_table (dont_use_regs);
+ init_elim_table ();
FOR_EACH_BB (bb)
FOR_BB_INSNS (bb, insn)
if (NONDEBUG_INSN_P (insn))
mark_not_eliminable (PATTERN (insn));
- if (frame_pointer_needed)
- df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
setup_elimination_map ();
}
@@ -1299,17 +1256,35 @@ lra_eliminate (bool final_p)
int i;
basic_block bb;
rtx insn, temp, mem_loc, invariant;
- bitmap_head to_process;
+ bitmap_head insns_with_changed_offsets;
struct elim_table *ep;
int regs_num = max_reg_num ();
#ifdef SECONDARY_MEMORY_NEEDED
int mode;
#endif
+ bitmap_initialize (&insns_with_changed_offsets, ®_obstack);
if (final_p)
- gcc_assert (! update_reg_eliminate ());
- else if (! update_reg_eliminate ())
- return;
+ {
+#ifdef ENABLE_CHECKING
+ update_reg_eliminate (&insns_with_changed_offsets);
+ if (! bitmap_empty_p (&insns_with_changed_offsets))
+ gcc_unreachable ();
+#endif
+ /* We change eliminable hard registers in insns so we should do
+ this for all insns containing any eliminable hard
+ register. */
+ for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
+ if (elimination_map[ep->from] != NULL)
+ bitmap_ior_into (&insns_with_changed_offsets,
+ &lra_reg_info[ep->from].insn_bitmap);
+ }
+ else
+ {
+ update_reg_eliminate (&insns_with_changed_offsets);
+ if (bitmap_empty_p (&insns_with_changed_offsets))
+ return;
+ }
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file, "New elimination table:\n");
@@ -1339,15 +1314,11 @@ lra_eliminate (bool final_p)
= lra_eliminate_regs_1 (lra_secondary_memory[mode],
VOIDmode, final_p, ! final_p, false);
#endif
- bitmap_initialize (&to_process, ®_obstack);
- for (ep = reg_eliminate; ep < ®_eliminate[NUM_ELIMINABLE_REGS]; ep++)
- if (elimination_map[ep->from] != NULL)
- bitmap_ior_into (&to_process, &lra_reg_info[ep->from].insn_bitmap);
FOR_EACH_BB (bb)
FOR_BB_INSNS_SAFE (bb, insn, temp)
{
- if (bitmap_bit_p (&to_process, INSN_UID (insn)))
+ if (bitmap_bit_p (&insns_with_changed_offsets, INSN_UID (insn)))
process_insn_for_elimination (insn, final_p);
}
- bitmap_clear (&to_process);
+ bitmap_clear (&insns_with_changed_offsets);
}
===================================================================
@@ -1,3 +1,67 @@
+2011-10-13 Vladimir Makarov <vmakarov@redhat.com>
+
+ * lra-assign.c (process_copy_to_form_allocno): Rename to
+ process_copy_to_form_thread.
+ (conflict_reload_pseudos): Rename to
+ conflict_reload_and_inheritance_pseudos.
+ (live_reload_pseudos): Rename to
+ live_reload_and_inheritance_pseudos.
+ (init_live_reload_pseudos): Rename to
+ init_live_reload_and_inheritance_pseudos.
+ (finish_live_reload_and_inheritance_pseudos): Rename to
+ finish_live_reload_pseudos.
+ (find_hard_regno_for): Add new argument try_only_hard_regno. Use
+ live_pseudos_reg_renumber instead of reg_renumber. Check
+ live_pseudos_reg_renumber when adding to
+ conflict_reload_and_inheritance_pseudos. Process
+ preferred_hard_regno2 only if preferred_hard_regno1 is
+ non-negative.
+ (setup_try_hard_regno_pseudos): Use live_pseudos_reg_renumber
+ instead of reg_renumber.
+ (spill_for): Ditto. Pass new parameter to find_hard_regno_for.
+ (assign_temporarily): Don't change reg_renumber.
+ (setup_live_pseudos_and_spill_after_equiv_moves): Only call
+ update_lives if lra_risky_equiv_subst_p is false.
+ (improve_inheritance): New function.
+ (assign_by_spills): Call improve_inheritance.
+
+ * lra.c (lra): Call lra_eliminate after lra_constraints.
+
+ * lra-constraints.c (contains_pseudo_p): Rename to contains_reg_p.
+ Add a new argument. Modify it for new semantics.
+ (lra_risky_equiv_subst_p): New global var.
+ (lra_constraints): Set up lra_risky_equiv_subst_p. Compare
+ get_equiv_substitution with right value.
+
+ * lra-eliminations.c (eliminate_regs_in_insn): Remove a dead
+ code.
+ (spill_pseudos): Clear to_process after its processing.
+ (update_reg_eliminate): Add a new argument. Set it up. Modify
+ lra_no_alloc_regs and eliminable_regset.
+ (init_elim_table): Remove the argument. Permit elimination from a
+ register to itself.
+ (lra_init_elimination): Add a new argument. Set it up. Don't set
+ up liveness fo HARD_FRAME_POINTER_REGNUM.
+ (lra_eliminate): Rename to_process to insns_with_changed_offsets.
+ Call update_reg_eliminate with insns_with_changed_offsets.
+ Restructure code. Add additional assertion on
+ insns_with_changed_offsets.
+
+ * lra.h (lra_init_elimination): New argument.
+
+ * lra-int.h (lra_risky_equiv_subst_p): New flag declaration.
+
+ * ira.c (ira_setup_eliminable_regset): Add a new argument. Set
+ up liveness fo HARD_FRAME_POINTER_REGNUM if necessary.
+ (ira): Call ira_setup_eliminable_regset with a new parameter.
+
+ * ira.h (ira_setup_eliminable_regset): New argument.
+
+ * loop-invariant.c (calculate_loop_reg_pressure): Call
+ ira_setup_eliminable_regset with a new parameter.
+
+ * haifa-sched.c (sched_init): Ditto.
+
2011-09-29 Vladimir Makarov <vmakarov@redhat.com>
* lra-int.h (lra_get_copy): New prototype.
===================================================================
@@ -4440,7 +4440,7 @@ sched_init (void)
&& common_sched_info->sched_pass_id == SCHED_RGN_PASS);
if (sched_pressure_p)
- ira_setup_eliminable_regset ();
+ ira_setup_eliminable_regset (false);
/* Initialize SPEC_INFO. */
if (targetm.sched.set_sched_flags)
===================================================================
@@ -3165,9 +3165,10 @@ in_list_p (rtx x, rtx list)
return false;
}
-/* Return true if X contains a (spilled if SPILLED_P) pseudo. */
+/* Return true if X contains an allocatable hard register (if
+ HARD_REG_P) or a (spilled if SPILLED_P) pseudo. */
static bool
-contains_pseudo_p (rtx x, bool spilled_p)
+contains_reg_p (rtx x, bool hard_reg_p, bool spilled_p)
{
int i, j;
const char *fmt;
@@ -3176,24 +3177,40 @@ contains_pseudo_p (rtx x, bool spilled_p
code = GET_CODE (x);
if (REG_P (x))
{
- if (REGNO (x) < FIRST_PSEUDO_REGISTER)
- return false;
- if (! spilled_p)
- return true;
- return lra_get_regno_hard_regno (REGNO (x)) < 0;
+ int regno = REGNO (x);
+ HARD_REG_SET alloc_regs;
+
+ if (hard_reg_p)
+ {
+ if (regno >= FIRST_PSEUDO_REGISTER)
+ regno = lra_get_regno_hard_regno (regno);
+ if (regno < 0)
+ return false;
+ COMPL_HARD_REG_SET (alloc_regs, lra_no_alloc_regs);
+ return lra_hard_reg_set_intersection_p (regno, GET_MODE (x),
+ alloc_regs);
+ }
+ else
+ {
+ if (regno < FIRST_PSEUDO_REGISTER)
+ return false;
+ if (! spilled_p)
+ return true;
+ return lra_get_regno_hard_regno (regno) < 0;
+ }
}
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
{
- if (contains_pseudo_p (XEXP (x, i), spilled_p))
+ if (contains_reg_p (XEXP (x, i), hard_reg_p, spilled_p))
return true;
}
else if (fmt[i] == 'E')
{
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
- if (contains_pseudo_p (XVECEXP (x, i, j), spilled_p))
+ if (contains_reg_p (XVECEXP (x, i, j), hard_reg_p, spilled_p))
return true;
}
}
@@ -3255,6 +3272,11 @@ debug_loc_equivalence_change_p (rtx *loc
/* The current iteration number of this LRA pass. */
int lra_constraint_iter;
+/* True if we substituted equiv which needs checking register
+ allocation correctness because the equivalent value contains
+ allocatiable hard registers. */
+bool lra_risky_equiv_subst_p;
+
/* Entry function of LRA constraint pass. Return true if the
constraint pass did change the code. */
bool
@@ -3275,6 +3297,7 @@ lra_constraints (bool first_p)
("Maximum number of LRA constraint passes is achieved (%d)\n",
MAX_CONSTRAINT_ITERATION_NUMBER);
changed_p = false;
+ lra_risky_equiv_subst_p = false;
new_insn_uid_start = get_max_uid ();
new_regno_start = first_p ? lra_constraint_new_regno_start : max_reg_num ();
for (i = FIRST_PSEUDO_REGISTER; i < new_regno_start; i++)
@@ -3291,7 +3314,7 @@ lra_constraints (bool first_p)
}
else if ((x = get_equiv_substitution (regno_reg_rtx[i])) != NULL_RTX)
{
- if (! first_p && contains_pseudo_p (x, false))
+ if (! first_p && contains_reg_p (x, false, false))
/* After RTL transformation, we can not guarantee that
pseudo in the susbtitution was not reloaded which
might make equivalence invalid. For example, in
@@ -3304,7 +3327,7 @@ lra_constraints (bool first_p)
the memory address register was reloaded before the
2nd insn. */
ira_reg_equiv[i].defined_p = false;
- if (contains_pseudo_p (x, true))
+ if (contains_reg_p (x, false, true))
ira_reg_equiv[i].profitable_p = false;
}
}
@@ -3371,7 +3394,7 @@ lra_constraints (bool first_p)
|| in_list_p (curr_insn,
ira_reg_equiv
[REGNO (dest_reg)].init_insns)))
- || (SET_SRC (set) != get_equiv_substitution (SET_SRC (set))
+ || ((x = get_equiv_substitution (SET_SRC (set))) != SET_SRC (set)
&& in_list_p (curr_insn,
ira_reg_equiv
[REGNO (SET_SRC (set))].init_insns)))
@@ -3386,6 +3409,8 @@ lra_constraints (bool first_p)
BLOCK_FOR_INSN (curr_insn)->frequency);
print_rtl_slim (lra_dump_file, curr_insn, curr_insn, -1, 0);
}
+ if (contains_reg_p (x, true, false))
+ lra_risky_equiv_subst_p = true;
lra_set_insn_deleted (curr_insn);
continue;
}
===================================================================
@@ -1806,7 +1806,7 @@ calculate_loop_reg_pressure (void)
bitmap_initialize (&LOOP_DATA (loop)->regs_ref, ®_obstack);
bitmap_initialize (&LOOP_DATA (loop)->regs_live, ®_obstack);
}
- ira_setup_eliminable_regset ();
+ ira_setup_eliminable_regset (false);
bitmap_initialize (&curr_regs_live, ®_obstack);
FOR_EACH_BB (bb)
{
===================================================================
@@ -1797,11 +1797,12 @@ compute_regs_asm_clobbered (void)
}
-/* Set up ELIMINABLE_REGSET, IRA_NO_ALLOC_REGS, and REGS_EVER_LIVE. */
+/* Set up ELIMINABLE_REGSET, IRA_NO_ALLOC_REGS, and REGS_EVER_LIVE.
+ If the function is called from IRA (not from the insn scheduler or
+ RTL loop invariant motion), FROM_IRA_P is true. */
void
-ira_setup_eliminable_regset (void)
+ira_setup_eliminable_regset (bool from_ira_p)
{
- HARD_REG_SET dont_use_regs;
#ifdef ELIMINABLE_REGS
int i;
static const struct {const int from, to; } eliminables[] = ELIMINABLE_REGS;
@@ -1820,13 +1821,15 @@ ira_setup_eliminable_regset (void)
|| crtl->stack_realign_needed
|| targetm.frame_pointer_required ());
- if (flag_lra)
- lra_init_elimination (&dont_use_regs);
- else
- CLEAR_HARD_REG_SET (dont_use_regs);
+ if (from_ira_p && flag_lra)
+ /* It can change FRAME_POINTER_NEEDED. We call it only from IRA
+ because it is expensive. */
+ lra_init_elimination ();
+ if (frame_pointer_needed)
+ df_set_regs_ever_live (HARD_FRAME_POINTER_REGNUM, true);
+
COPY_HARD_REG_SET (ira_no_alloc_regs, no_unit_alloc_regs);
- IOR_HARD_REG_SET (ira_no_alloc_regs, dont_use_regs);
CLEAR_HARD_REG_SET (eliminable_regset);
compute_regs_asm_clobbered ();
@@ -3803,7 +3806,7 @@ ira (FILE *f)
}
max_regno_before_ira = allocated_reg_info_size = max_reg_num ();
- ira_setup_eliminable_regset ();
+ ira_setup_eliminable_regset (true);
ira_overall_cost = ira_reg_cost = ira_mem_cost = 0;
ira_load_cost = ira_store_cost = ira_shuffle_cost = 0;
===================================================================
@@ -175,7 +175,7 @@ extern struct ira_reg_equiv *ira_reg_equ
extern void ira_init_once (void);
extern void ira_init (void);
extern void ira_finish_once (void);
-extern void ira_setup_eliminable_regset (void);
+extern void ira_setup_eliminable_regset (bool);
extern rtx ira_eliminate_regs (rtx, enum machine_mode);
extern void ira_set_pseudo_classes (FILE *);
extern void ira_implicitly_set_insn_hard_regs (HARD_REG_SET *);