summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-19 21:20:44 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2008-11-19 21:20:44 +0000
commit69f8e08094a3f6e518c08f323bc2687ffe696c9e (patch)
tree5b79c7c3d997c7b687af33f6229b6111cc84177b /gcc
parentd046014d4feb3098f10fd9f83d0288772628c3aa (diff)
downloadgcc-69f8e08094a3f6e518c08f323bc2687ffe696c9e.tar.gz
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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@142017 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog49
-rw-r--r--gcc/global.c3
-rw-r--r--gcc/ira-build.c210
-rw-r--r--gcc/ira-color.c124
-rw-r--r--gcc/ira-conflicts.c46
-rw-r--r--gcc/ira-int.h9
-rw-r--r--gcc/ira.c27
7 files changed, 289 insertions, 179 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 6b972eec096..eacb5e0e588 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,52 @@
+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>
* tree.c (build2_stat): Allow non-POINTER_PLUS_EXPRs with
diff --git a/gcc/global.c b/gcc/global.c
index edc2a42c590..824fcf0f702 100644
--- a/gcc/global.c
+++ b/gcc/global.c
@@ -1393,7 +1393,8 @@ pseudo_for_reload_consideration_p (int regno)
{
/* Consider spilled pseudos too for IRA because they still have a
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,
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 110da639a9c..af1d1747a5b 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -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
result. */
-static allocno_live_range_t
-copy_allocno_live_range_list (allocno_live_range_t r)
+allocno_live_range_t
+ira_copy_allocno_live_range_list (allocno_live_range_t r)
{
allocno_live_range_t p, first, last;
@@ -845,6 +845,103 @@ copy_allocno_live_range_list (allocno_live_range_t r)
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. */
void
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);
}
+/* 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. */
void
ira_free_allocno_updated_costs (ira_allocno_t a)
@@ -872,7 +982,6 @@ ira_free_allocno_updated_costs (ira_allocno_t a)
static void
finish_allocno (ira_allocno_t a)
{
- allocno_live_range_t r, next_r;
enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
ira_allocnos[ALLOCNO_NUM (a)] = NULL;
@@ -888,11 +997,7 @@ finish_allocno (ira_allocno_t a)
if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
cover_class);
- for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = next_r)
- {
- next_r = r->next;
- ira_finish_allocno_live_range (r);
- }
+ ira_finish_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
pool_free (allocno_pool, a);
}
@@ -1543,84 +1648,6 @@ create_allocnos (void)
will hardly improve the result. As a result we speed up regional
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. */
static void
change_allocno_in_range_list (allocno_live_range_t r, ira_allocno_t a)
@@ -1762,7 +1789,8 @@ remove_unnecessary_allocnos (void)
r = ALLOCNO_LIVE_RANGES (a);
change_allocno_in_range_list (r, 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;
ALLOCNO_LIVE_RANGES (a) = NULL;
IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a),
@@ -2155,10 +2183,10 @@ copy_info_to_removed_store_destinations (int regno)
ira_print_live_range_list (ira_dump_file,
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);
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),
ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
#ifdef STACK_REGS
@@ -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);
ALLOCNO_LIVE_RANGES (parent_a)
- = merge_ranges (ALLOCNO_LIVE_RANGES (a),
- ALLOCNO_LIVE_RANGES (parent_a));
+ = ira_merge_allocno_live_ranges
+ (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a));
merged_p = true;
ALLOCNO_LIVE_RANGES (a) = NULL;
ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
diff --git a/gcc/ira-color.c b/gcc/ira-color.c
index eea3b2c6714..7343e0c8078 100644
--- a/gcc/ira-color.c
+++ b/gcc/ira-color.c
@@ -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
allocnos. */
@@ -1489,7 +1532,8 @@ coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2,
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;
if (conflict_allocno == a1)
break;
@@ -2319,38 +2363,37 @@ collect_spilled_coalesced_allocnos (int *pseudo_regnos, int n,
return num;
}
-/* Array of bitmaps of size IRA_MAX_POINT. Bitmap for given point
- contains numbers of coalesced allocnos living at this point. */
-static regset_head *coalesced_allocnos_living_at_program_points;
+/* Array of live ranges of size IRA_ALLOCNOS_NUM. Live range for
+ given slot contains live ranges of coalesced allocnos assigned to
+ given slot. */
+static allocno_live_range_t *slot_coalesced_allocnos_live_ranges;
-/* Return TRUE if coalesced allocnos represented by ALLOCNO live at
- program points of coalesced allocnos with number N. */
+/* Return TRUE if coalesced allocnos represented by ALLOCNO has live
+ ranges intersected with live ranges of coalesced allocnos assigned
+ to slot with number N. */
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;
- allocno_live_range_t r;
for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
{
- for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
- for (i = r->start; i <= r->finish; i++)
- if (bitmap_bit_p (&coalesced_allocnos_living_at_program_points[i], n))
- return true;
+ if (ira_allocno_live_ranges_intersect_p
+ (slot_coalesced_allocnos_live_ranges[n], ALLOCNO_LIVE_RANGES (a)))
+ return true;
if (a == allocno)
break;
}
return false;
}
-/* Mark program points where coalesced allocnos represented by ALLOCNO
- live. */
+/* Update live ranges of slot to which coalesced allocnos represented
+ by ALLOCNO were assigned. */
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;
allocno_live_range_t r;
@@ -2358,9 +2401,10 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
{
- for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
- for (i = r->start; i <= r->finish; i++)
- bitmap_set_bit (&coalesced_allocnos_living_at_program_points[i], n);
+ r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
+ slot_coalesced_allocnos_live_ranges[n]
+ = ira_merge_allocno_live_ranges
+ (slot_coalesced_allocnos_live_ranges[n], r);
if (a == allocno)
break;
}
@@ -2374,14 +2418,15 @@ set_coalesced_allocnos_live_points (ira_allocno_t allocno)
static bool
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;
bool merged_p = false;
- coalesced_allocnos_living_at_program_points
- = (regset_head *) ira_allocate (sizeof (regset_head) * ira_max_point);
- for (i = 0; i < ira_max_point; i++)
- INIT_REG_SET (&coalesced_allocnos_living_at_program_points[i]);
+ slot_coalesced_allocnos_live_ranges
+ = (allocno_live_range_t *) ira_allocate (sizeof (allocno_live_range_t)
+ * ira_allocnos_num);
+ memset (slot_coalesced_allocnos_live_ranges, 0,
+ sizeof (allocno_live_range_t) * ira_allocnos_num);
last_coalesced_allocno_num = 0;
/* Coalesce non-conflicting spilled allocnos preferring most
frequently used. */
@@ -2390,18 +2435,18 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
allocno = spilled_coalesced_allocnos[i];
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
|| (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;
for (j = 0; j < i; j++)
{
a = spilled_coalesced_allocnos[j];
+ n = ALLOCNO_TEMP (a);
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
&& (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
|| (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
&& ira_reg_equiv_const[ALLOCNO_REGNO (a)] == NULL_RTX))
- && ! coalesced_allocnos_live_at_points_p (allocno,
- ALLOCNO_TEMP (a)))
+ && ! slot_coalesced_allocno_live_ranges_intersect_p (allocno, n))
break;
}
if (j >= i)
@@ -2409,7 +2454,7 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
/* No coalescing: set up number for coalesced allocnos
represented by ALLOCNO. */
ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++;
- set_coalesced_allocnos_live_points (allocno);
+ setup_slot_coalesced_allocno_live_ranges (allocno);
}
else
{
@@ -2421,14 +2466,15 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num)
ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a);
- set_coalesced_allocnos_live_points (allocno);
+ setup_slot_coalesced_allocno_live_ranges (allocno);
merge_allocnos (a, allocno);
ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a);
}
}
- for (i = 0; i < ira_max_point; i++)
- CLEAR_REG_SET (&coalesced_allocnos_living_at_program_points[i]);
- ira_free (coalesced_allocnos_living_at_program_points);
+ for (i = 0; i < ira_allocnos_num; i++)
+ ira_finish_allocno_live_range_list
+ (slot_coalesced_allocnos_live_ranges[i]);
+ ira_free (slot_coalesced_allocnos_live_ranges);
return merged_p;
}
@@ -2499,8 +2545,8 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n,
if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
|| ALLOCNO_HARD_REGNO (allocno) >= 0
|| (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;
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Slot %d (freq,size):", slot_num);
@@ -2829,8 +2875,8 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
FIRST_PSEUDO_REGISTER, i, bi)
{
another_allocno = ira_regno_allocno_map[i];
- if (ira_allocno_live_ranges_intersect_p (allocno,
- another_allocno))
+ if (allocnos_have_intersected_live_ranges_p (allocno,
+ another_allocno))
goto cont;
}
for (cost = 0, cp = ALLOCNO_COPIES (allocno);
@@ -2878,7 +2924,7 @@ ira_reuse_stack_slot (int regno, unsigned int inherent_size,
EXECUTE_IF_SET_IN_BITMAP (&slot->spilled_regs,
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);
if (internal_flag_ira_verbose > 3 && ira_dump_file)
diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c
index 66376b63a5c..6e7d7692b67 100644
--- a/gcc/ira-conflicts.c
+++ b/gcc/ira-conflicts.c
@@ -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. */
static ira_allocno_t *collected_conflict_allocnos;
diff --git a/gcc/ira-int.h b/gcc/ira-int.h
index 0b2e9280388..7f5479b7b57 100644
--- a/gcc/ira-int.h
+++ b/gcc/ira-int.h
@@ -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 allocno_live_range_t ira_create_allocno_live_range
(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_list (allocno_live_range_t);
extern void ira_free_allocno_updated_costs (ira_allocno_t);
extern ira_copy_t ira_create_copy (ira_allocno_t, ira_allocno_t,
int, bool, rtx, ira_loop_tree_node_t);
@@ -898,8 +905,6 @@ extern void ira_compress_allocno_live_ranges (void);
extern void ira_finish_allocno_live_ranges (void);
/* 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_build_conflicts (void);
diff --git a/gcc/ira.c b/gcc/ira.c
index d0232f75a1e..d7f4e3d0dab 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -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. */
@@ -1709,6 +1726,7 @@ ira (FILE *f)
int max_regno_before_ira, ira_max_point_before_emit;
int rebuild_p;
int saved_flag_ira_algorithm;
+ int saved_flag_ira_share_spill_slots;
basic_block bb;
timevar_push (TV_IRA);
@@ -1792,6 +1810,13 @@ ira (FILE *f)
loops_p = ira_build (optimize
&& (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL
|| 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_max_point_before_emit = ira_max_point;
@@ -1902,6 +1927,8 @@ ira (FILE *f)
fprintf (ira_dump_file, "+++Overall after reload %d\n", ira_overall_cost);
ira_destroy ();
+ flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
+
flow_loops_free (&ira_loops);
free_dominance_info (CDI_DOMINATORS);
FOR_ALL_BB (bb)