Commit 9e038952 by Vladimir Makarov Committed by Vladimir Makarov

re PR rtl-optimization/60650 ([ARM] LRA ICE in assign_by_spills)

2014-03-27  Vladimir Makarov  <vmakarov@redhat.com>

	PR rtl-optimization/60650
	* lra-asign.c (find_hard_regno_for, spill_for): Add parameter
	first_p.  Use it.
	(find_spills_for): New.
	(assign_by_spills): Pass the new parameter to find_hard_regno_for.
	Spill all pseudos on the second iteration.

2014-03-27  Vladimir Makarov  <vmakarov@redhat.com>

	PR rtl-optimization/60650
	* gcc.target/arm/pr60650.c: New.

From-SVN: r208876
parent ffcbf03f
2014-03-27 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/60650
* lra-asign.c (find_hard_regno_for, spill_for): Add parameter
first_p. Use it.
(find_spills_for): New.
(assign_by_spills): Pass the new parameter to find_hard_regno_for.
Spill all pseudos on the second iteration.
2014-03-27 Marek Polacek <polacek@redhat.com> 2014-03-27 Marek Polacek <polacek@redhat.com>
PR c/50347 PR c/50347
......
...@@ -451,10 +451,16 @@ adjust_hard_regno_cost (int hard_regno, int incr) ...@@ -451,10 +451,16 @@ adjust_hard_regno_cost (int hard_regno, int incr)
that register. (If several registers have equal cost, the one with that register. (If several registers have equal cost, the one with
the highest priority wins.) Return -1 on failure. the highest priority wins.) Return -1 on failure.
If FIRST_P, return the first available hard reg ignoring other
criteria, e.g. allocation cost. This approach results in less hard
reg pool fragmentation and permit to allocate hard regs to reload
pseudos in complicated situations where pseudo sizes are different.
If TRY_ONLY_HARD_REGNO >= 0, consider only that hard register, If TRY_ONLY_HARD_REGNO >= 0, consider only that hard register,
otherwise consider all hard registers in REGNO's class. */ otherwise consider all hard registers in REGNO's class. */
static int static int
find_hard_regno_for (int regno, int *cost, int try_only_hard_regno) find_hard_regno_for (int regno, int *cost, int try_only_hard_regno,
bool first_p)
{ {
HARD_REG_SET conflict_set; HARD_REG_SET conflict_set;
int best_cost = INT_MAX, best_priority = INT_MIN, best_usage = INT_MAX; int best_cost = INT_MAX, best_priority = INT_MIN, best_usage = INT_MAX;
...@@ -630,7 +636,7 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno) ...@@ -630,7 +636,7 @@ find_hard_regno_for (int regno, int *cost, int try_only_hard_regno)
best_usage = lra_hard_reg_usage[hard_regno]; best_usage = lra_hard_reg_usage[hard_regno];
} }
} }
if (try_only_hard_regno >= 0) if (try_only_hard_regno >= 0 || (first_p && best_hard_regno >= 0))
break; break;
} }
if (best_hard_regno >= 0) if (best_hard_regno >= 0)
...@@ -816,9 +822,15 @@ static int *sorted_reload_pseudos; ...@@ -816,9 +822,15 @@ static int *sorted_reload_pseudos;
to be spilled), we take into account not only how REGNO will to be spilled), we take into account not only how REGNO will
benefit from the spills but also how other reload pseudos not yet benefit from the spills but also how other reload pseudos not yet
assigned to hard registers benefit from the spills too. In very assigned to hard registers benefit from the spills too. In very
rare cases, the function can fail and return -1. */ rare cases, the function can fail and return -1.
If FIRST_P, return the first available hard reg ignoring other
criteria, e.g. allocation cost and cost of spilling non-reload
pseudos. This approach results in less hard reg pool fragmentation
and permit to allocate hard regs to reload pseudos in complicated
situations where pseudo sizes are different. */
static int static int
spill_for (int regno, bitmap spilled_pseudo_bitmap) spill_for (int regno, bitmap spilled_pseudo_bitmap, bool first_p)
{ {
int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size; int i, j, n, p, hard_regno, best_hard_regno, cost, best_cost, rclass_size;
int reload_hard_regno, reload_cost; int reload_hard_regno, reload_cost;
...@@ -905,7 +917,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap) ...@@ -905,7 +917,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
&& (ira_reg_classes_intersect_p && (ira_reg_classes_intersect_p
[rclass][regno_allocno_class_array[reload_regno]]) [rclass][regno_allocno_class_array[reload_regno]])
&& live_pseudos_reg_renumber[reload_regno] < 0 && live_pseudos_reg_renumber[reload_regno] < 0
&& find_hard_regno_for (reload_regno, &cost, -1) < 0) && find_hard_regno_for (reload_regno, &cost, -1, first_p) < 0)
sorted_reload_pseudos[n++] = reload_regno; sorted_reload_pseudos[n++] = reload_regno;
EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi) EXECUTE_IF_SET_IN_BITMAP (&spill_pseudos_bitmap, 0, spill_regno, bi)
{ {
...@@ -914,7 +926,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap) ...@@ -914,7 +926,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
fprintf (lra_dump_file, " spill %d(freq=%d)", fprintf (lra_dump_file, " spill %d(freq=%d)",
spill_regno, lra_reg_info[spill_regno].freq); spill_regno, lra_reg_info[spill_regno].freq);
} }
hard_regno = find_hard_regno_for (regno, &cost, -1); hard_regno = find_hard_regno_for (regno, &cost, -1, first_p);
if (hard_regno >= 0) if (hard_regno >= 0)
{ {
assign_temporarily (regno, hard_regno); assign_temporarily (regno, hard_regno);
...@@ -926,7 +938,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap) ...@@ -926,7 +938,7 @@ spill_for (int regno, bitmap spilled_pseudo_bitmap)
lra_assert (live_pseudos_reg_renumber[reload_regno] < 0); lra_assert (live_pseudos_reg_renumber[reload_regno] < 0);
if ((reload_hard_regno if ((reload_hard_regno
= find_hard_regno_for (reload_regno, = find_hard_regno_for (reload_regno,
&reload_cost, -1)) >= 0) &reload_cost, -1, first_p)) >= 0)
{ {
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " assign %d(cost=%d)", fprintf (lra_dump_file, " assign %d(cost=%d)",
...@@ -1148,8 +1160,8 @@ improve_inheritance (bitmap changed_pseudos) ...@@ -1148,8 +1160,8 @@ improve_inheritance (bitmap changed_pseudos)
regno, hard_regno, another_regno, another_hard_regno); regno, hard_regno, another_regno, another_hard_regno);
update_lives (another_regno, true); update_lives (another_regno, true);
lra_setup_reg_renumber (another_regno, -1, false); lra_setup_reg_renumber (another_regno, -1, false);
if (hard_regno if (hard_regno == find_hard_regno_for (another_regno, &cost,
== find_hard_regno_for (another_regno, &cost, hard_regno)) hard_regno, false))
assign_hard_regno (hard_regno, another_regno); assign_hard_regno (hard_regno, another_regno);
else else
assign_hard_regno (another_hard_regno, another_regno); assign_hard_regno (another_hard_regno, another_regno);
...@@ -1166,15 +1178,50 @@ static bitmap_head all_spilled_pseudos; ...@@ -1166,15 +1178,50 @@ static bitmap_head all_spilled_pseudos;
/* All pseudos whose allocation was changed. */ /* All pseudos whose allocation was changed. */
static bitmap_head changed_pseudo_bitmap; static bitmap_head changed_pseudo_bitmap;
/* Add to LIVE_RANGE_HARD_REG_PSEUDOS all pseudos conflicting with
REGNO and whose hard regs can be assigned to REGNO. */
static void
find_all_spills_for (int regno)
{
int p;
lra_live_range_t r;
unsigned int k;
bitmap_iterator bi;
enum reg_class rclass;
bool *rclass_intersect_p;
rclass = regno_allocno_class_array[regno];
rclass_intersect_p = ira_reg_classes_intersect_p[rclass];
for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
{
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);
for (p = r->start + 1; p <= r->finish; p++)
{
lra_live_range_t r2;
for (r2 = start_point_ranges[p];
r2 != NULL;
r2 = r2->start_next)
{
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);
}
}
}
}
/* Assign hard registers to reload pseudos and other pseudos. */ /* Assign hard registers to reload pseudos and other pseudos. */
static void static void
assign_by_spills (void) assign_by_spills (void)
{ {
int i, n, nfails, iter, regno, hard_regno, cost, restore_regno; int i, n, nfails, iter, regno, hard_regno, cost, restore_regno;
rtx insn; rtx insn;
basic_block bb;
bitmap_head changed_insns, do_not_assign_nonreload_pseudos; bitmap_head changed_insns, do_not_assign_nonreload_pseudos;
unsigned int u; unsigned int u, conflict_regno;
bitmap_iterator bi; bitmap_iterator bi;
bool reload_p; bool reload_p;
int max_regno = max_reg_num (); int max_regno = max_reg_num ();
...@@ -1211,10 +1258,10 @@ assign_by_spills (void) ...@@ -1211,10 +1258,10 @@ assign_by_spills (void)
ORIGINAL_REGNO (regno_reg_rtx[regno]), ORIGINAL_REGNO (regno_reg_rtx[regno]),
lra_reg_info[regno].freq, regno_assign_info[regno].first, lra_reg_info[regno].freq, regno_assign_info[regno].first,
regno_assign_info[regno_assign_info[regno].first].freq); regno_assign_info[regno_assign_info[regno].first].freq);
hard_regno = find_hard_regno_for (regno, &cost, -1); hard_regno = find_hard_regno_for (regno, &cost, -1, iter == 1);
reload_p = ! bitmap_bit_p (&non_reload_pseudos, regno); reload_p = ! bitmap_bit_p (&non_reload_pseudos, regno);
if (hard_regno < 0 && reload_p) if (hard_regno < 0 && reload_p)
hard_regno = spill_for (regno, &all_spilled_pseudos); hard_regno = spill_for (regno, &all_spilled_pseudos, iter == 1);
if (hard_regno < 0) if (hard_regno < 0)
{ {
if (reload_p) if (reload_p)
...@@ -1286,60 +1333,40 @@ assign_by_spills (void) ...@@ -1286,60 +1333,40 @@ assign_by_spills (void)
lra_assert (asm_p); lra_assert (asm_p);
break; break;
} }
/* This is a very rare event. We can not assign a hard /* This is a very rare event. We can not assign a hard register
register to reload pseudo because the hard register was to reload pseudo because the hard register was assigned to
assigned to another reload pseudo on a previous another reload pseudo on a previous assignment pass. For x86
assignment pass. For x86 example, on the 1st pass we example, on the 1st pass we assigned CX (although another
assigned CX (although another hard register could be used hard register could be used for this) to reload pseudo in an
for this) to reload pseudo in an insn, on the 2nd pass we insn, on the 2nd pass we need CX (and only this) hard
need CX (and only this) hard register for a new reload register for a new reload pseudo in the same insn. Another
pseudo in the same insn. */ possible situation may occur in assigning to multi-regs
reload pseudos when hard regs pool is too fragmented even
after spilling non-reload pseudos.
We should do something radical here to succeed. Here we
spill *all* conflicting pseudos and reassign them. */
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " 2nd iter for reload pseudo assignments:\n"); fprintf (lra_dump_file, " 2nd iter for reload pseudo assignments:\n");
sparseset_clear (live_range_hard_reg_pseudos);
for (i = 0; i < nfails; i++) for (i = 0; i < nfails; i++)
{ {
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Reload r%d assignment failure\n", fprintf (lra_dump_file, " Reload r%d assignment failure\n",
sorted_pseudos[i]); sorted_pseudos[i]);
bitmap_ior_into (&changed_insns, find_all_spills_for (sorted_pseudos[i]);
&lra_reg_info[sorted_pseudos[i]].insn_bitmap);
}
/* FIXME: Look up the changed insns in the cached LRA insn data using
an EXECUTE_IF_SET_IN_BITMAP over changed_insns. */
FOR_EACH_BB_FN (bb, cfun)
FOR_BB_INSNS (bb, insn)
if (bitmap_bit_p (&changed_insns, INSN_UID (insn)))
{
lra_insn_recog_data_t data;
struct lra_insn_reg *r;
data = lra_get_insn_recog_data (insn);
for (r = data->regs; r != NULL; r = r->next)
{
regno = r->regno;
/* A reload pseudo did not get a hard register on the
first iteration because of the conflict with
another reload pseudos in the same insn. So we
consider only reload pseudos assigned to hard
registers. We shall exclude inheritance pseudos as
they can occur in original insns (not reload ones).
We can omit the check for split pseudos because
they occur only in move insns containing non-reload
pseudos. */
if (regno < lra_constraint_new_regno_start
|| bitmap_bit_p (&lra_inheritance_pseudos, regno)
|| reg_renumber[regno] < 0)
continue;
sorted_pseudos[nfails++] = regno;
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
" Spill reload r%d(hr=%d, freq=%d)\n",
regno, reg_renumber[regno],
lra_reg_info[regno].freq);
update_lives (regno, true);
lra_setup_reg_renumber (regno, -1, false);
} }
EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
{
if ((int) conflict_regno >= lra_constraint_new_regno_start)
sorted_pseudos[nfails++] = conflict_regno;
if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Spill %s r%d(hr=%d, freq=%d)\n",
pseudo_prefix_title (conflict_regno), conflict_regno,
reg_renumber[conflict_regno],
lra_reg_info[conflict_regno].freq);
update_lives (conflict_regno, true);
lra_setup_reg_renumber (conflict_regno, -1, false);
} }
n = nfails; n = nfails;
} }
...@@ -1382,7 +1409,7 @@ assign_by_spills (void) ...@@ -1382,7 +1409,7 @@ assign_by_spills (void)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
regno = sorted_pseudos[i]; regno = sorted_pseudos[i];
hard_regno = find_hard_regno_for (regno, &cost, -1); hard_regno = find_hard_regno_for (regno, &cost, -1, false);
if (hard_regno >= 0) if (hard_regno >= 0)
{ {
assign_hard_regno (hard_regno, regno); assign_hard_regno (hard_regno, regno);
......
2014-03-27 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/60650
* gcc.target/arm/pr60650.c: New.
2014-03-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com> 2014-03-27 Andreas Krebbel <Andreas.Krebbel@de.ibm.com>
* gcc.target/s390/20140327-1.c: New testcase. * gcc.target/s390/20140327-1.c: New testcase.
......
/* { dg-do compile } */
/* { dg-options "-O2 -fno-omit-frame-pointer -mabi=apcs-gnu -march=armv7-a" } */
struct super_block
{
int s_blocksize_bits;
};
struct btrfs_fs_info
{
struct super_block *sb;
};
struct btrfs_root
{
struct btrfs_fs_info *fs_info;
} *b;
int a, c, d;
long long e;
truncate_one_csum (struct btrfs_root *p1, long long p2, long long p3)
{
int f, g, i = p1->fs_info->sb->s_blocksize_bits;
g = a;
long long h = p2 + p3;
f = foo1 (b, 0, c, 0);
e = f / g;
e <<= p1->fs_info->sb->s_blocksize_bits;
if (d < p2)
{
int j = e - h >> i;
foo2 (p1, 0, j);
}
else
{
asm ("1\t.long ");
__builtin_unreachable ();
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment