Commit 3553f0bb by Vladimir Makarov Committed by Vladimir Makarov

re PR middle-end/37790 (limits-fnargs.c takes very long time to compile at -O2)

2008-11-15  Vladimir Makarov  <vmakarov@redhat.com>

	PR bootstrap/37790
	* ira-int.h (ira_copy_allocno_live_range_list,
	ira_merge_allocno_live_ranges,
	ira_allocno_live_ranges_intersect_p,
	ira_finish_allocno_live_range_list): New prototypes.
	(ira_allocno_live_ranges_intersect_p,
	ira_pseudo_live_ranges_intersect_p): Remove.
	
	* ira-conflicts.c (ira_allocno_live_ranges_intersect_p,
	ira_pseudo_live_ranges_intersect_p): Rename to
	allocnos_have_intersected_live_ranges_p and
	pseudos_have_intersected_live_ranges_p.  Move them from here to
	...

	* ira-color.c: ... here
	(coalesced_allocno_conflict_p): Use
	allocnos_have_intersected_live_ranges_p.
	(coalesced_allocnos_living_at_program_points,
	coalesced_allocnos_live_at_points_p,
	set_coalesced_allocnos_live_points): Remove.
	(slot_coalesced_allocnos_live_ranges,
	slot_coalesced_allocno_live_ranges_intersect_p,
	setup_slot_coalesced_allocno_live_ranges): New.
	(coalesce_spill_slots): Use ranges of coalesced allocnos.
	(ira_sort_regnos_for_alter_reg): Use
	allocnos_have_intersected_live_ranges_p.
	(ira_reuse_stack_slot): Use
	pseudos_have_intersected_live_ranges_p.

	* global.c (pseudo_for_reload_consideration_p): Check
	flag_ira_share_spill_slots too.

	* ira-build.c (copy_allocno_live_range_list): Rename to
	ira_copy_allocno_live_range_list.  Make it external.
	(merge_ranges): Rename to ira_merge_allocno_live_ranges.  Make it
	external.
	(ira_allocno_live_ranges_intersect_p): New.
	(ira_finish_allocno_live_range_list): New.
	(finish_allocno): Use it.
	(remove_unnecessary_allocnos): Use ira_merge_allocno_live_ranges.
	(copy_info_to_removed_store_destinations): Ditto.  Use
	ira_copy_allocno_live_range_list.
	(ira_flattening): Use ira_merge_allocno_live_ranges.
	
	* ira.c (too_high_register_pressure_p): New function.
	(ira): Switch off sharing spill slots if the pressure is too high.

From-SVN: r142017
parent 2de6c675
2008-11-15 Vladimir Makarov <vmakarov@redhat.com>
PR bootstrap/37790
* ira-int.h (ira_copy_allocno_live_range_list,
ira_merge_allocno_live_ranges,
ira_allocno_live_ranges_intersect_p,
ira_finish_allocno_live_range_list): New prototypes.
(ira_allocno_live_ranges_intersect_p,
ira_pseudo_live_ranges_intersect_p): Remove.
* ira-conflicts.c (ira_allocno_live_ranges_intersect_p,
ira_pseudo_live_ranges_intersect_p): Rename to
allocnos_have_intersected_live_ranges_p and
pseudos_have_intersected_live_ranges_p. Move them from here to
...
* ira-color.c: ... here
(coalesced_allocno_conflict_p): Use
allocnos_have_intersected_live_ranges_p.
(coalesced_allocnos_living_at_program_points,
coalesced_allocnos_live_at_points_p,
set_coalesced_allocnos_live_points): Remove.
(slot_coalesced_allocnos_live_ranges,
slot_coalesced_allocno_live_ranges_intersect_p,
setup_slot_coalesced_allocno_live_ranges): New.
(coalesce_spill_slots): Use ranges of coalesced allocnos.
(ira_sort_regnos_for_alter_reg): Use
allocnos_have_intersected_live_ranges_p.
(ira_reuse_stack_slot): Use
pseudos_have_intersected_live_ranges_p.
* global.c (pseudo_for_reload_consideration_p): Check
flag_ira_share_spill_slots too.
* ira-build.c (copy_allocno_live_range_list): Rename to
ira_copy_allocno_live_range_list. Make it external.
(merge_ranges): Rename to ira_merge_allocno_live_ranges. Make it
external.
(ira_allocno_live_ranges_intersect_p): New.
(ira_finish_allocno_live_range_list): New.
(finish_allocno): Use it.
(remove_unnecessary_allocnos): Use ira_merge_allocno_live_ranges.
(copy_info_to_removed_store_destinations): Ditto. Use
ira_copy_allocno_live_range_list.
(ira_flattening): Use ira_merge_allocno_live_ranges.
* ira.c (too_high_register_pressure_p): New function.
(ira): Switch off sharing spill slots if the pressure is too high.
2008-11-19 Richard Guenther <rguenther@suse.de> 2008-11-19 Richard Guenther <rguenther@suse.de>
* tree.c (build2_stat): Allow non-POINTER_PLUS_EXPRs with * tree.c (build2_stat): Allow non-POINTER_PLUS_EXPRs with
......
...@@ -1393,7 +1393,8 @@ pseudo_for_reload_consideration_p (int regno) ...@@ -1393,7 +1393,8 @@ pseudo_for_reload_consideration_p (int regno)
{ {
/* Consider spilled pseudos too for IRA because they still have a /* Consider spilled pseudos too for IRA because they still have a
chance to get hard-registers in the reload when IRA is used. */ chance to get hard-registers in the reload when IRA is used. */
return reg_renumber[regno] >= 0 || (flag_ira && optimize); return (reg_renumber[regno] >= 0
|| (flag_ira && optimize && flag_ira_share_spill_slots));
} }
/* Walk the insns of the current function and build reload_insn_chain, /* Walk the insns of the current function and build reload_insn_chain,
......
...@@ -826,8 +826,8 @@ copy_allocno_live_range (allocno_live_range_t r) ...@@ -826,8 +826,8 @@ copy_allocno_live_range (allocno_live_range_t r)
/* Copy allocno live range list given by its head R and return the /* Copy allocno live range list given by its head R and return the
result. */ result. */
static allocno_live_range_t allocno_live_range_t
copy_allocno_live_range_list (allocno_live_range_t r) ira_copy_allocno_live_range_list (allocno_live_range_t r)
{ {
allocno_live_range_t p, first, last; allocno_live_range_t p, first, last;
...@@ -845,6 +845,103 @@ copy_allocno_live_range_list (allocno_live_range_t r) ...@@ -845,6 +845,103 @@ copy_allocno_live_range_list (allocno_live_range_t r)
return first; return first;
} }
/* Merge ranges R1 and R2 and returns the result. The function
maintains the order of ranges and tries to minimize number of the
result ranges. */
allocno_live_range_t
ira_merge_allocno_live_ranges (allocno_live_range_t r1,
allocno_live_range_t r2)
{
allocno_live_range_t first, last, temp;
if (r1 == NULL)
return r2;
if (r2 == NULL)
return r1;
for (first = last = NULL; r1 != NULL && r2 != NULL;)
{
if (r1->start < r2->start)
{
temp = r1;
r1 = r2;
r2 = temp;
}
if (r1->start <= r2->finish + 1)
{
/* Intersected ranges: merge r1 and r2 into r1. */
r1->start = r2->start;
if (r1->finish < r2->finish)
r1->finish = r2->finish;
temp = r2;
r2 = r2->next;
ira_finish_allocno_live_range (temp);
if (r2 == NULL)
{
/* To try to merge with subsequent ranges in r1. */
r2 = r1->next;
r1->next = NULL;
}
}
else
{
/* Add r1 to the result. */
if (first == NULL)
first = last = r1;
else
{
last->next = r1;
last = r1;
}
r1 = r1->next;
if (r1 == NULL)
{
/* To try to merge with subsequent ranges in r2. */
r1 = r2->next;
r2->next = NULL;
}
}
}
if (r1 != NULL)
{
if (first == NULL)
first = r1;
else
last->next = r1;
ira_assert (r1->next == NULL);
}
else if (r2 != NULL)
{
if (first == NULL)
first = r2;
else
last->next = r2;
ira_assert (r2->next == NULL);
}
else
{
ira_assert (last->next == NULL);
}
return first;
}
/* Return TRUE if live ranges R1 and R2 intersect. */
bool
ira_allocno_live_ranges_intersect_p (allocno_live_range_t r1,
allocno_live_range_t r2)
{
/* Remember the live ranges are always kept ordered. */
while (r1 != NULL && r2 != NULL)
{
if (r1->start > r2->finish)
r1 = r1->next;
else if (r2->start > r1->finish)
r2 = r2->next;
else
return true;
}
return false;
}
/* Free allocno live range R. */ /* Free allocno live range R. */
void void
ira_finish_allocno_live_range (allocno_live_range_t r) ira_finish_allocno_live_range (allocno_live_range_t r)
...@@ -852,6 +949,19 @@ ira_finish_allocno_live_range (allocno_live_range_t r) ...@@ -852,6 +949,19 @@ ira_finish_allocno_live_range (allocno_live_range_t r)
pool_free (allocno_live_range_pool, r); pool_free (allocno_live_range_pool, r);
} }
/* Free list of allocno live ranges starting with R. */
void
ira_finish_allocno_live_range_list (allocno_live_range_t r)
{
allocno_live_range_t next_r;
for (; r != NULL; r = next_r)
{
next_r = r->next;
ira_finish_allocno_live_range (r);
}
}
/* Free updated register costs of allocno A. */ /* Free updated register costs of allocno A. */
void void
ira_free_allocno_updated_costs (ira_allocno_t a) ira_free_allocno_updated_costs (ira_allocno_t a)
...@@ -872,7 +982,6 @@ ira_free_allocno_updated_costs (ira_allocno_t a) ...@@ -872,7 +982,6 @@ ira_free_allocno_updated_costs (ira_allocno_t a)
static void static void
finish_allocno (ira_allocno_t a) finish_allocno (ira_allocno_t a)
{ {
allocno_live_range_t r, next_r;
enum reg_class cover_class = ALLOCNO_COVER_CLASS (a); enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
ira_allocnos[ALLOCNO_NUM (a)] = NULL; ira_allocnos[ALLOCNO_NUM (a)] = NULL;
...@@ -888,11 +997,7 @@ finish_allocno (ira_allocno_t a) ...@@ -888,11 +997,7 @@ finish_allocno (ira_allocno_t a)
if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL) if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a), ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
cover_class); cover_class);
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = next_r) ira_finish_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
{
next_r = r->next;
ira_finish_allocno_live_range (r);
}
pool_free (allocno_pool, a); pool_free (allocno_pool, a);
} }
...@@ -1543,84 +1648,6 @@ create_allocnos (void) ...@@ -1543,84 +1648,6 @@ create_allocnos (void)
will hardly improve the result. As a result we speed up regional will hardly improve the result. As a result we speed up regional
register allocation. */ register allocation. */
/* Merge ranges R1 and R2 and returns the result. The function
maintains the order of ranges and tries to minimize number of the
result ranges. */
static allocno_live_range_t
merge_ranges (allocno_live_range_t r1, allocno_live_range_t r2)
{
allocno_live_range_t first, last, temp;
if (r1 == NULL)
return r2;
if (r2 == NULL)
return r1;
for (first = last = NULL; r1 != NULL && r2 != NULL;)
{
if (r1->start < r2->start)
{
temp = r1;
r1 = r2;
r2 = temp;
}
if (r1->start <= r2->finish + 1)
{
/* Intersected ranges: merge r1 and r2 into r1. */
r1->start = r2->start;
if (r1->finish < r2->finish)
r1->finish = r2->finish;
temp = r2;
r2 = r2->next;
ira_finish_allocno_live_range (temp);
if (r2 == NULL)
{
/* To try to merge with subsequent ranges in r1. */
r2 = r1->next;
r1->next = NULL;
}
}
else
{
/* Add r1 to the result. */
if (first == NULL)
first = last = r1;
else
{
last->next = r1;
last = r1;
}
r1 = r1->next;
if (r1 == NULL)
{
/* To try to merge with subsequent ranges in r2. */
r1 = r2->next;
r2->next = NULL;
}
}
}
if (r1 != NULL)
{
if (first == NULL)
first = r1;
else
last->next = r1;
ira_assert (r1->next == NULL);
}
else if (r2 != NULL)
{
if (first == NULL)
first = r2;
else
last->next = r2;
ira_assert (r2->next == NULL);
}
else
{
ira_assert (last->next == NULL);
}
return first;
}
/* The function changes allocno in range list given by R onto A. */ /* The function changes allocno in range list given by R onto A. */
static void static void
change_allocno_in_range_list (allocno_live_range_t r, ira_allocno_t a) change_allocno_in_range_list (allocno_live_range_t r, ira_allocno_t a)
...@@ -1762,7 +1789,8 @@ remove_unnecessary_allocnos (void) ...@@ -1762,7 +1789,8 @@ remove_unnecessary_allocnos (void)
r = ALLOCNO_LIVE_RANGES (a); r = ALLOCNO_LIVE_RANGES (a);
change_allocno_in_range_list (r, parent_a); change_allocno_in_range_list (r, parent_a);
ALLOCNO_LIVE_RANGES (parent_a) ALLOCNO_LIVE_RANGES (parent_a)
= merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a)); = ira_merge_allocno_live_ranges
(r, ALLOCNO_LIVE_RANGES (parent_a));
merged_p = true; merged_p = true;
ALLOCNO_LIVE_RANGES (a) = NULL; ALLOCNO_LIVE_RANGES (a) = NULL;
IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a), IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a),
...@@ -2155,10 +2183,10 @@ copy_info_to_removed_store_destinations (int regno) ...@@ -2155,10 +2183,10 @@ copy_info_to_removed_store_destinations (int regno)
ira_print_live_range_list (ira_dump_file, ira_print_live_range_list (ira_dump_file,
ALLOCNO_LIVE_RANGES (a)); ALLOCNO_LIVE_RANGES (a));
} }
r = copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a)); r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
change_allocno_in_range_list (r, parent_a); change_allocno_in_range_list (r, parent_a);
ALLOCNO_LIVE_RANGES (parent_a) ALLOCNO_LIVE_RANGES (parent_a)
= merge_ranges (r, ALLOCNO_LIVE_RANGES (parent_a)); = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (parent_a));
IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
#ifdef STACK_REGS #ifdef STACK_REGS
...@@ -2255,8 +2283,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) ...@@ -2255,8 +2283,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
} }
change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a); change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a);
ALLOCNO_LIVE_RANGES (parent_a) ALLOCNO_LIVE_RANGES (parent_a)
= merge_ranges (ALLOCNO_LIVE_RANGES (a), = ira_merge_allocno_live_ranges
ALLOCNO_LIVE_RANGES (parent_a)); (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a));
merged_p = true; merged_p = true;
ALLOCNO_LIVE_RANGES (a) = NULL; ALLOCNO_LIVE_RANGES (a) = NULL;
ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a) ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
......
...@@ -84,6 +84,49 @@ static VEC(ira_allocno_t,heap) *removed_splay_allocno_vec; ...@@ -84,6 +84,49 @@ static VEC(ira_allocno_t,heap) *removed_splay_allocno_vec;
/* This page contains functions used to find conflicts using allocno
live ranges. */
/* Return TRUE if live ranges of allocnos A1 and A2 intersect. It is
used to find a conflict for new allocnos or allocnos with the
different cover classes. */
static bool
allocnos_have_intersected_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
{
if (a1 == a2)
return false;
if (ALLOCNO_REG (a1) != NULL && ALLOCNO_REG (a2) != NULL
&& (ORIGINAL_REGNO (ALLOCNO_REG (a1))
== ORIGINAL_REGNO (ALLOCNO_REG (a2))))
return false;
return ira_allocno_live_ranges_intersect_p (ALLOCNO_LIVE_RANGES (a1),
ALLOCNO_LIVE_RANGES (a2));
}
#ifdef ENABLE_IRA_CHECKING
/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
intersect. This should be used when there is only one region.
Currently this is used during reload. */
static bool
pseudos_have_intersected_live_ranges_p (int regno1, int regno2)
{
ira_allocno_t a1, a2;
ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
&& regno2 >= FIRST_PSEUDO_REGISTER);
/* Reg info caclulated by dataflow infrastructure can be different
from one calculated by regclass. */
if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
|| (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
return false;
return allocnos_have_intersected_live_ranges_p (a1, a2);
}
#endif
/* This page contains functions used to choose hard registers for /* This page contains functions used to choose hard registers for
allocnos. */ allocnos. */
...@@ -1489,7 +1532,8 @@ coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2, ...@@ -1489,7 +1532,8 @@ coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2,
conflict_allocno conflict_allocno
= ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_allocno)) = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_allocno))
{ {
if (ira_allocno_live_ranges_intersect_p (a, conflict_allocno)) if (allocnos_have_intersected_live_ranges_p (a,
conflict_allocno))
return true; return true;
if (conflict_allocno == a1) if (conflict_allocno == a1)
break; break;
...@@ -2319,38 +2363,37 @@ collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n, ...@@ -2319,38 +2363,37 @@ collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n,
return num; return num;
} }
/* Array of bitmaps of size IRA_MAX_POINT. Bitmap for given point /* Array of live ranges of size IRA_ALLOCNOS_NUM. Live range for
contains numbers of coalesced allocnos living at this point. */ given slot contains live ranges of coalesced allocnos assigned to
static regset_head *coalesced_allocnos_living_at_program_points; given slot. */
static allocno_live_range_t *slot_coalesced_allocnos_live_ranges;
/* Return TRUE if coalesced allocnos represented by ALLOCNO live at /* Return TRUE if coalesced allocnos represented by ALLOCNO has live
program points of coalesced allocnos with number N. */ ranges intersected with live ranges of coalesced allocnos assigned
to slot with number N. */
static bool static bool
coalesced_allocnos_live_at_points_p (ira_allocno_t allocno, int n) slot_coalesced_allocno_live_ranges_intersect_p (ira_allocno_t allocno, int n)
{ {
int i;
ira_allocno_t a; ira_allocno_t a;
allocno_live_range_t r;
for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);; for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a)) a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
{ {
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next) if (ira_allocno_live_ranges_intersect_p
for (i = r->start; i <= r->finish; i++) (slot_coalesced_allocnos_live_ranges[n], ALLOCNO_LIVE_RANGES (a)))
if (bitmap_bit_p (&coalesced_allocnos_living_at_program_points[i], n)) return true;
return true;
if (a == allocno) if (a == allocno)
break; break;
} }
return false; return false;
} }
/* Mark program points where coalesced allocnos represented by ALLOCNO /* Update live ranges of slot to which coalesced allocnos represented
live. */ by ALLOCNO were assigned. */
static void static void
set_coalesced_allocnos_live_points (ira_allocno_t allocno) setup_slot_coalesced_allocno_live_ranges (ira_allocno_t allocno)
{ {
int i, n; int n;
ira_allocno_t a; ira_allocno_t a;
allocno_live_range_t r; allocno_live_range_t r;
...@@ -2358,9 +2401,10 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno) ...@@ -2358,9 +2401,10 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);; for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a)) a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
{ {
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next) r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
for (i = r->start; i <= r->finish; i++) slot_coalesced_allocnos_live_ranges[n]
bitmap_set_bit (&coalesced_allocnos_living_at_program_points[i], n); = ira_merge_allocno_live_ranges
(slot_coalesced_allocnos_live_ranges[n], r);
if (a == allocno) if (a == allocno)
break; break;
} }
...@@ -2374,14 +2418,15 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno) ...@@ -2374,14 +2418,15 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
static bool static bool
coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num) coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
{ {
int i, j, last_coalesced_allocno_num; int i, j, n, last_coalesced_allocno_num;
ira_allocno_t allocno, a; ira_allocno_t allocno, a;
bool merged_p = false; bool merged_p = false;
coalesced_allocnos_living_at_program_points slot_coalesced_allocnos_live_ranges
= (regset_head *) ira_allocate (sizeof (regset_head) * ira_max_point); = (allocno_live_range_t *) ira_allocate (sizeof (allocno_live_range_t)
for (i = 0; i < ira_max_point; i++) * ira_allocnos_num);
INIT_REG_SET (&coalesced_allocnos_living_at_program_points[i]); memset (slot_coalesced_allocnos_live_ranges, 0,
sizeof (allocno_live_range_t) * ira_allocnos_num);
last_coalesced_allocno_num = 0; last_coalesced_allocno_num = 0;
/* Coalesce non-conflicting spilled allocnos preferring most /* Coalesce non-conflicting spilled allocnos preferring most
frequently used. */ frequently used. */
...@@ -2390,18 +2435,18 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num) ...@@ -2390,18 +2435,18 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
allocno = spilled_coalesced_allocnos[i]; allocno = spilled_coalesced_allocnos[i];
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
|| (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
&& (ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)] && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
|| ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX))) || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
continue; continue;
for (j = 0; j < i; j++) for (j = 0; j < i; j++)
{ {
a = spilled_coalesced_allocnos[j]; a = spilled_coalesced_allocnos[j];
n = ALLOCNO_TEMP (a);
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
&& (ALLOCNO_REGNO (a) >= ira_reg_equiv_len && (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
|| (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)] || (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
&& ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX)) && ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX))
&& ! coalesced_allocnos_live_at_points_p (allocno, && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
ALLOCNO_TEMP (a)))
break; break;
} }
if (j >= i) if (j >= i)
...@@ -2409,7 +2454,7 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num) ...@@ -2409,7 +2454,7 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
/* No coalescing: set up number for coalesced allocnos /* No coalescing: set up number for coalesced allocnos
represented by ALLOCNO. */ represented by ALLOCNO. */
ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++; ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++;
set_coalesced_allocnos_live_points (allocno); setup_slot_coalesced_allocno_live_ranges (allocno);
} }
else else
{ {
...@@ -2421,14 +2466,15 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num) ...@@ -2421,14 +2466,15 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno), ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
ALLOCNO_NUM (a), ALLOCNO_REGNO (a)); ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a); ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a);
set_coalesced_allocnos_live_points (allocno); setup_slot_coalesced_allocno_live_ranges (allocno);
merge_allocnos (a, allocno); merge_allocnos (a, allocno);
ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a); ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a);
} }
} }
for (i = 0; i < ira_max_point; i++) for (i = 0; i < ira_allocnos_num; i++)
CLEAR_REG_SET (&coalesced_allocnos_living_at_program_points[i]); ira_finish_allocno_live_range_list
ira_free (coalesced_allocnos_living_at_program_points); (slot_coalesced_allocnos_live_ranges[i]);
ira_free (slot_coalesced_allocnos_live_ranges);
return merged_p; return merged_p;
} }
...@@ -2499,8 +2545,8 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n, ...@@ -2499,8 +2545,8 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n,
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
|| ALLOCNO_HARD_REGNO (allocno) >= 0 || ALLOCNO_HARD_REGNO (allocno) >= 0
|| (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len || (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
&& (ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)] && (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
|| ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX))) || ira_reg_equiv_invariant_p[ALLOCNO_REGNO (allocno)])))
continue; continue;
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Slot %d (freq,size):", slot_num); fprintf (ira_dump_file, " Slot %d (freq,size):", slot_num);
...@@ -2829,8 +2875,8 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size, ...@@ -2829,8 +2875,8 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
FIRST_PSEUDO_REGISTER, i, bi) FIRST_PSEUDO_REGISTER, i, bi)
{ {
another_allocno = ira_regno_allocno_map[i]; another_allocno = ira_regno_allocno_map[i];
if (ira_allocno_live_ranges_intersect_p (allocno, if (allocnos_have_intersected_live_ranges_p (allocno,
another_allocno)) another_allocno))
goto cont; goto cont;
} }
for (cost = 0, cp = ALLOCNO_COPIES (allocno); for (cost = 0, cp = ALLOCNO_COPIES (allocno);
...@@ -2878,7 +2924,7 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size, ...@@ -2878,7 +2924,7 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs, EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
FIRST_PSEUDO_REGISTER, i, bi) FIRST_PSEUDO_REGISTER, i, bi)
{ {
ira_assert (! ira_pseudo_live_ranges_intersect_p (regno, i)); ira_assert (! pseudos_have_intersected_live_ranges_p (regno, i));
} }
SET_REGNO_REG_SET (&slot->spilled_regs, regno); SET_REGNO_REG_SET (&slot->spilled_regs, regno);
if (internal_flag_ira_verbose > 3 && ira_dump_file) if (internal_flag_ira_verbose > 3 && ira_dump_file)
......
...@@ -532,52 +532,6 @@ propagate_copies (void) ...@@ -532,52 +532,6 @@ propagate_copies (void)
} }
} }
/* Return TRUE if live ranges of allocnos A1 and A2 intersect. It is
used to find a conflict for new allocnos or allocnos with the
different cover classes. */
bool
ira_allocno_live_ranges_intersect_p (ira_allocno_t a1, ira_allocno_t a2)
{
allocno_live_range_t r1, r2;
if (a1 == a2)
return false;
if (ALLOCNO_REG (a1) != NULL && ALLOCNO_REG (a2) != NULL
&& (ORIGINAL_REGNO (ALLOCNO_REG (a1))
== ORIGINAL_REGNO (ALLOCNO_REG (a2))))
return false;
/* Remember the ranges are always kept ordered. */
for (r1 = ALLOCNO_LIVE_RANGES (a1), r2 = ALLOCNO_LIVE_RANGES (a2);
r1 != NULL && r2 != NULL;)
{
if (r1->start > r2->finish)
r1 = r1->next;
else if (r2->start > r1->finish)
r2 = r2->next;
else
return true;
}
return false;
}
/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
intersect. This should be used when there is only one region.
Currently this is used during reload. */
bool
ira_pseudo_live_ranges_intersect_p (int regno1, int regno2)
{
ira_allocno_t a1, a2;
ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
&& regno2 >= FIRST_PSEUDO_REGISTER);
/* Reg info caclulated by dataflow infrastructure can be different
from one calculated by regclass. */
if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
|| (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
return false;
return ira_allocno_live_ranges_intersect_p (a1, a2);
}
/* Array used to collect all conflict allocnos for given allocno. */ /* Array used to collect all conflict allocnos for given allocno. */
static ira_allocno_t *collected_conflict_allocnos; static ira_allocno_t *collected_conflict_allocnos;
......
...@@ -862,7 +862,14 @@ extern void ira_add_allocno_conflict (ira_allocno_t, ira_allocno_t); ...@@ -862,7 +862,14 @@ extern void ira_add_allocno_conflict (ira_allocno_t, ira_allocno_t);
extern void ira_print_expanded_allocno (ira_allocno_t); extern void ira_print_expanded_allocno (ira_allocno_t);
extern allocno_live_range_t ira_create_allocno_live_range extern allocno_live_range_t ira_create_allocno_live_range
(ira_allocno_t, int, int, allocno_live_range_t); (ira_allocno_t, int, int, allocno_live_range_t);
extern allocno_live_range_t ira_copy_allocno_live_range_list
(allocno_live_range_t);
extern allocno_live_range_t ira_merge_allocno_live_ranges
(allocno_live_range_t, allocno_live_range_t);
extern bool ira_allocno_live_ranges_intersect_p (allocno_live_range_t,
allocno_live_range_t);
extern void ira_finish_allocno_live_range (allocno_live_range_t); extern void ira_finish_allocno_live_range (allocno_live_range_t);
extern void ira_finish_allocno_live_range_list (allocno_live_range_t);
extern void ira_free_allocno_updated_costs (ira_allocno_t); extern void ira_free_allocno_updated_costs (ira_allocno_t);
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t, extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
int, bool, rtx, ira_loop_tree_node_t); int, bool, rtx, ira_loop_tree_node_t);
...@@ -898,8 +905,6 @@ extern void ira_compress_allocno_live_ranges (void); ...@@ -898,8 +905,6 @@ extern void ira_compress_allocno_live_ranges (void);
extern void ira_finish_allocno_live_ranges (void); extern void ira_finish_allocno_live_ranges (void);
/* ira-conflicts.c */ /* ira-conflicts.c */
extern bool ira_allocno_live_ranges_intersect_p (ira_allocno_t, ira_allocno_t);
extern bool ira_pseudo_live_ranges_intersect_p (int, int);
extern void ira_debug_conflicts (bool); extern void ira_debug_conflicts (bool);
extern void ira_build_conflicts (void); extern void ira_build_conflicts (void);
......
...@@ -1695,6 +1695,23 @@ expand_reg_info (int old_size) ...@@ -1695,6 +1695,23 @@ expand_reg_info (int old_size)
} }
} }
/* Return TRUE if there is too high register pressure in the function.
It is used to decide when stack slot sharing is worth to do. */
static bool
too_high_register_pressure_p (void)
{
int i;
enum reg_class cover_class;
for (i = 0; i < ira_reg_class_cover_size; i++)
{
cover_class = ira_reg_class_cover[i];
if (ira_loop_tree_root->reg_pressure[cover_class] > 10000)
return true;
}
return false;
}
/* All natural loops. */ /* All natural loops. */
...@@ -1709,6 +1726,7 @@ ira (FILE *f) ...@@ -1709,6 +1726,7 @@ ira (FILE *f)
int max_regno_before_ira, ira_max_point_before_emit; int max_regno_before_ira, ira_max_point_before_emit;
int rebuild_p; int rebuild_p;
int saved_flag_ira_algorithm; int saved_flag_ira_algorithm;
int saved_flag_ira_share_spill_slots;
basic_block bb; basic_block bb;
timevar_push (TV_IRA); timevar_push (TV_IRA);
...@@ -1792,6 +1810,13 @@ ira (FILE *f) ...@@ -1792,6 +1810,13 @@ ira (FILE *f)
loops_p = ira_build (optimize loops_p = ira_build (optimize
&& (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
|| flag_ira_algorithm == IRA_ALGORITHM_MIXED)); || flag_ira_algorithm == IRA_ALGORITHM_MIXED));
saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
if (too_high_register_pressure_p ())
/* It is just wasting compiler's time to pack spilled pseudos into
stack slots in this case -- prohibit it. */
flag_ira_share_spill_slots = FALSE;
ira_color (); ira_color ();
ira_max_point_before_emit = ira_max_point; ira_max_point_before_emit = ira_max_point;
...@@ -1902,6 +1927,8 @@ ira (FILE *f) ...@@ -1902,6 +1927,8 @@ ira (FILE *f)
fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost); fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost);
ira_destroy (); ira_destroy ();
flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
flow_loops_free (&ira_loops); flow_loops_free (&ira_loops);
free_dominance_info (CDI_DOMINATORS); free_dominance_info (CDI_DOMINATORS);
FOR_ALL_BB (bb) FOR_ALL_BB (bb)
......
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