Changing cost propagation and ordering colorable bucket heuristics for PR93564.

2020-02-23  Vladimir Makarov  <vmakarov@redhat.com>

	PR rtl-optimization/93564
	* ira-color.c (struct update_cost_queue_elem): New member start.
	(queue_update_cost, get_next_update_cost): Add new arg start.
	(allocnos_conflict_p): New function.
	(update_costs_from_allocno): Add new arg conflict_cost_update_p.
	Add checking conflicts with allocnos_conflict_p.
	(update_costs_from_prefs, restore_costs_from_copies): Adjust
	update_costs_from_allocno calls.
	(update_conflict_hard_regno_costs): Add checking conflicts with
	allocnos_conflict_p.  Adjust calls of queue_update_cost and
	get_next_update_cost.
	(assign_hard_reg): Adjust calls of queue_update_cost.  Add
	debugging print.
	(bucket_allocno_compare_func): Restore previous version.
This commit is contained in:
Vladimir N. Makarov 2020-02-23 16:20:05 -05:00
parent 92e8508eda
commit 3133bed5d0
2 changed files with 81 additions and 33 deletions

View file

@ -1,3 +1,20 @@
2020-02-23 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/93564
* ira-color.c (struct update_cost_queue_elem): New member start.
(queue_update_cost, get_next_update_cost): Add new arg start.
(allocnos_conflict_p): New function.
(update_costs_from_allocno): Add new arg conflict_cost_update_p.
Add checking conflicts with allocnos_conflict_p.
(update_costs_from_prefs, restore_costs_from_copies): Adjust
update_costs_from_allocno calls.
(update_conflict_hard_regno_costs): Add checking conflicts with
allocnos_conflict_p. Adjust calls of queue_update_cost and
get_next_update_cost.
(assign_hard_reg): Adjust calls of queue_update_cost. Add
debugging print.
(bucket_allocno_compare_func): Restore previous version.
2020-02-21 John David Anglin <danglin@gcc.gnu.org>
* gcc/config/pa/pa.c (pa_function_value): Fix check for word and

View file

@ -1199,6 +1199,10 @@ struct update_cost_queue_elem
connecting this allocno to the one being allocated. */
int divisor;
/* Allocno from which we started chaining costs of connected
allocnos. */
ira_allocno_t start;
/* Allocno from which we are chaining costs of connected allocnos.
It is used not go back in graph of allocnos connected by
copies. */
@ -1258,10 +1262,11 @@ start_update_cost (void)
update_cost_queue = NULL;
}
/* Add (ALLOCNO, FROM, DIVISOR) to the end of update_cost_queue, unless
/* Add (ALLOCNO, START, FROM, DIVISOR) to the end of update_cost_queue, unless
ALLOCNO is already in the queue, or has NO_REGS class. */
static inline void
queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
queue_update_cost (ira_allocno_t allocno, ira_allocno_t start,
ira_allocno_t from, int divisor)
{
struct update_cost_queue_elem *elem;
@ -1270,6 +1275,7 @@ queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
&& ALLOCNO_CLASS (allocno) != NO_REGS)
{
elem->check = update_cost_check;
elem->start = start;
elem->from = from;
elem->divisor = divisor;
elem->next = NULL;
@ -1282,10 +1288,11 @@ queue_update_cost (ira_allocno_t allocno, ira_allocno_t from, int divisor)
}
/* Try to remove the first element from update_cost_queue. Return
false if the queue was empty, otherwise make (*ALLOCNO, *FROM,
*DIVISOR) describe the removed element. */
false if the queue was empty, otherwise make (*ALLOCNO, *START,
*FROM, *DIVISOR) describe the removed element. */
static inline bool
get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor)
get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *start,
ira_allocno_t *from, int *divisor)
{
struct update_cost_queue_elem *elem;
@ -1294,6 +1301,7 @@ get_next_update_cost (ira_allocno_t *allocno, ira_allocno_t *from, int *divisor)
*allocno = update_cost_queue;
elem = &update_cost_queue_elems[ALLOCNO_NUM (*allocno)];
*start = elem->start;
*from = elem->from;
*divisor = elem->divisor;
update_cost_queue = elem->next;
@ -1325,18 +1333,41 @@ update_allocno_cost (ira_allocno_t allocno, int hard_regno,
return true;
}
/* Return TRUE if allocnos A1 and A2 conflicts. Here we are
interesting only in conflicts of allocnos with intersected allocno
classes. */
static bool
allocnos_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
{
ira_object_t obj, conflict_obj;
ira_object_conflict_iterator oci;
int word, nwords = ALLOCNO_NUM_OBJECTS (a1);
for (word = 0; word < nwords; word++)
{
obj = ALLOCNO_OBJECT (a1, word);
/* Take preferences of conflicting allocnos into account. */
FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci)
if (OBJECT_ALLOCNO (conflict_obj) == a2)
return true;
}
return false;
}
/* Update (decrease if DECR_P) HARD_REGNO cost of allocnos connected
by copies to ALLOCNO to increase chances to remove some copies as
the result of subsequent assignment. Record cost updates if
RECORD_P is true. */
the result of subsequent assignment. Update conflict costs only
for true CONFLICT_COST_UPDATE_P. Record cost updates if RECORD_P is
true. */
static void
update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
int divisor, bool decr_p, bool record_p)
int divisor, bool decr_p, bool record_p,
bool conflict_cost_update_p)
{
int cost, update_cost, update_conflict_cost;
machine_mode mode;
enum reg_class rclass, aclass;
ira_allocno_t another_allocno, from = NULL;
ira_allocno_t another_allocno, start = allocno, from = NULL;
ira_copy_t cp, next_cp;
rclass = REGNO_REG_CLASS (hard_regno);
@ -1359,7 +1390,8 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
else
gcc_unreachable ();
if (another_allocno == from)
if (another_allocno == from
|| allocnos_conflict_p (another_allocno, start))
continue;
aclass = ALLOCNO_CLASS (another_allocno);
@ -1384,7 +1416,8 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
if (decr_p)
cost = -cost;
update_conflict_cost = update_cost = cp->freq * cost / divisor;
update_cost = cp->freq * cost / divisor;
update_conflict_cost = conflict_cost_update_p ? update_cost : 0;
if (ALLOCNO_COLOR_DATA (another_allocno) != NULL
&& (ALLOCNO_COLOR_DATA (allocno)->first_thread_allocno
@ -1399,7 +1432,8 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
if (! update_allocno_cost (another_allocno, hard_regno,
update_cost, update_conflict_cost))
continue;
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
queue_update_cost (another_allocno, start, allocno,
divisor * COST_HOP_DIVISOR);
if (record_p && ALLOCNO_COLOR_DATA (another_allocno) != NULL)
ALLOCNO_COLOR_DATA (another_allocno)->update_cost_records
= get_update_cost_record (hard_regno, divisor,
@ -1407,7 +1441,7 @@ update_costs_from_allocno (ira_allocno_t allocno, int hard_regno,
->update_cost_records);
}
}
while (get_next_update_cost (&allocno, &from, &divisor));
while (get_next_update_cost (&allocno, &start, &from, &divisor));
}
/* Decrease preferred ALLOCNO hard register costs and costs of
@ -1420,7 +1454,7 @@ update_costs_from_prefs (ira_allocno_t allocno)
start_update_cost ();
for (pref = ALLOCNO_PREFS (allocno); pref != NULL; pref = pref->next_pref)
update_costs_from_allocno (allocno, pref->hard_regno,
COST_HOP_DIVISOR, true, true);
COST_HOP_DIVISOR, true, true, false);
}
/* Update (decrease if DECR_P) the cost of allocnos connected to
@ -1435,7 +1469,7 @@ update_costs_from_copies (ira_allocno_t allocno, bool decr_p, bool record_p)
hard_regno = ALLOCNO_HARD_REGNO (allocno);
ira_assert (hard_regno >= 0 && ALLOCNO_CLASS (allocno) != NO_REGS);
start_update_cost ();
update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p);
update_costs_from_allocno (allocno, hard_regno, 1, decr_p, record_p, true);
}
/* Update conflict_allocno_hard_prefs of allocnos conflicting with
@ -1485,7 +1519,7 @@ restore_costs_from_copies (ira_allocno_t allocno)
start_update_cost ();
for (curr = records; curr != NULL; curr = curr->next)
update_costs_from_allocno (allocno, curr->hard_regno,
curr->divisor, true, false);
curr->divisor, true, false, true);
free_update_cost_record_list (records);
ALLOCNO_COLOR_DATA (allocno)->update_cost_records = NULL;
}
@ -1503,10 +1537,10 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
int *conflict_costs;
bool cont_p;
enum reg_class another_aclass;
ira_allocno_t allocno, another_allocno, from;
ira_allocno_t allocno, another_allocno, start, from;
ira_copy_t cp, next_cp;
while (get_next_update_cost (&allocno, &from, &divisor))
while (get_next_update_cost (&allocno, &start, &from, &divisor))
for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
{
if (cp->first == allocno)
@ -1522,7 +1556,8 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
else
gcc_unreachable ();
if (another_allocno == from)
if (another_allocno == from
|| allocnos_conflict_p (another_allocno, start))
continue;
another_aclass = ALLOCNO_CLASS (another_allocno);
@ -1568,7 +1603,7 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
* COST_HOP_DIVISOR
* COST_HOP_DIVISOR
* COST_HOP_DIVISOR))
queue_update_cost (another_allocno, allocno, divisor * COST_HOP_DIVISOR);
queue_update_cost (another_allocno, start, from, divisor * COST_HOP_DIVISOR);
}
}
@ -1837,8 +1872,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
continue;
full_costs[j] -= conflict_costs[k];
}
queue_update_cost (conflict_a, NULL, COST_HOP_DIVISOR);
queue_update_cost (conflict_a, conflict_a, NULL, COST_HOP_DIVISOR);
}
}
}
@ -1852,7 +1886,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
if (! retry_p)
{
start_update_cost ();
queue_update_cost (a, NULL, COST_HOP_DIVISOR);
queue_update_cost (a, a, NULL, COST_HOP_DIVISOR);
update_conflict_hard_regno_costs (full_costs, aclass, false);
}
min_cost = min_full_cost = INT_MAX;
@ -1897,6 +1931,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p)
best_hard_regno = hard_regno;
ira_assert (hard_regno >= 0);
}
if (internal_flag_ira_verbose > 5 && ira_dump_file != NULL)
fprintf (ira_dump_file, "(%d=%d,%d) ", hard_regno, cost, full_cost);
}
if (min_full_cost > mem_cost
/* Do not spill static chain pointer pseudo when non-local goto
@ -2259,16 +2295,6 @@ bucket_allocno_compare_func (const void *v1p, const void *v2p)
ira_allocno_t t2 = ALLOCNO_COLOR_DATA (a2)->first_thread_allocno;
int cl1 = ALLOCNO_CLASS (a1), cl2 = ALLOCNO_CLASS (a2);
/* Push allocnos with minimal hard_reg_prefs first. */
pref1 = ALLOCNO_COLOR_DATA (a1)->hard_reg_prefs;
pref2 = ALLOCNO_COLOR_DATA (a2)->hard_reg_prefs;
if ((diff = pref1 - pref2) != 0)
return diff;
/* Push allocnos with minimal conflict_allocno_hard_prefs first. */
pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs;
pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs;
if ((diff = pref1 - pref2) != 0)
return diff;
freq1 = ALLOCNO_COLOR_DATA (t1)->thread_freq;
freq2 = ALLOCNO_COLOR_DATA (t2)->thread_freq;
if ((diff = freq1 - freq2) != 0)
@ -2294,6 +2320,11 @@ bucket_allocno_compare_func (const void *v1p, const void *v2p)
a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
if ((diff = a2_num - a1_num) != 0)
return diff;
/* Push allocnos with minimal conflict_allocno_hard_prefs first. */
pref1 = ALLOCNO_COLOR_DATA (a1)->conflict_allocno_hard_prefs;
pref2 = ALLOCNO_COLOR_DATA (a2)->conflict_allocno_hard_prefs;
if ((diff = pref1 - pref2) != 0)
return diff;
return ALLOCNO_NUM (a2) - ALLOCNO_NUM (a1);
}