summaryrefslogtreecommitdiff
path: root/gcc/ira-build.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/ira-build.c')
-rw-r--r--gcc/ira-build.c256
1 files changed, 132 insertions, 124 deletions
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 502b0f63442..6936cec3048 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -383,8 +383,8 @@ rebuild_regno_allocno_maps (void)
-/* Pools for allocnos and allocno live ranges. */
-static alloc_pool allocno_pool, allocno_live_range_pool;
+/* Pools for allocnos and live ranges. */
+static alloc_pool allocno_pool, live_range_pool;
/* Vec containing references to all created allocnos. It is a
container of array allocnos. */
@@ -398,9 +398,9 @@ static VEC(ira_allocno_t,heap) *ira_conflict_id_allocno_map_vec;
static void
initiate_allocnos (void)
{
- allocno_live_range_pool
- = create_alloc_pool ("allocno live ranges",
- sizeof (struct ira_allocno_live_range), 100);
+ live_range_pool
+ = create_alloc_pool ("live ranges",
+ sizeof (struct live_range), 100);
allocno_pool
= create_alloc_pool ("allocnos", sizeof (struct ira_allocno), 100);
allocno_vec = VEC_alloc (ira_allocno_t, heap, max_reg_num () * 2);
@@ -504,6 +504,25 @@ ira_set_allocno_cover_class (ira_allocno_t a, enum reg_class cover_class)
reg_class_contents[cover_class]);
}
+/* Merge hard register conflicts from allocno FROM into allocno TO. If
+ TOTAL_ONLY is true, we ignore ALLOCNO_CONFLICT_HARD_REGS. */
+static void
+merge_hard_reg_conflicts (ira_allocno_t from, ira_allocno_t to,
+ bool total_only)
+{
+ if (!total_only)
+ IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (to),
+ ALLOCNO_CONFLICT_HARD_REGS (from));
+ IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (to),
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from));
+#ifdef STACK_REGS
+ if (!total_only && ALLOCNO_NO_STACK_REG_P (from))
+ ALLOCNO_NO_STACK_REG_P (to) = true;
+ if (ALLOCNO_TOTAL_NO_STACK_REG_P (from))
+ ALLOCNO_TOTAL_NO_STACK_REG_P (to) = true;
+#endif
+}
+
/* Return TRUE if the conflict vector with NUM elements is more
profitable than conflict bit vector for A. */
bool
@@ -651,7 +670,7 @@ add_to_allocno_conflicts (ira_allocno_t a1, ira_allocno_t a2)
}
ALLOCNO_MAX (a1) = id;
}
- SET_ALLOCNO_SET_BIT (vec, id, ALLOCNO_MIN (a1), ALLOCNO_MAX (a1));
+ SET_MINMAX_SET_BIT (vec, id, ALLOCNO_MIN (a1), ALLOCNO_MAX (a1));
}
}
@@ -781,15 +800,8 @@ create_cap_allocno (ira_allocno_t a)
ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a);
ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a);
ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a);
- IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (cap),
- ALLOCNO_CONFLICT_HARD_REGS (a));
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (cap),
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ merge_hard_reg_conflicts (a, cap, false);
ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a);
-#ifdef STACK_REGS
- ALLOCNO_NO_STACK_REG_P (cap) = ALLOCNO_NO_STACK_REG_P (a);
- ALLOCNO_TOTAL_NO_STACK_REG_P (cap) = ALLOCNO_TOTAL_NO_STACK_REG_P (a);
-#endif
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Creating cap ");
@@ -800,13 +812,13 @@ create_cap_allocno (ira_allocno_t a)
}
/* Create and return allocno live range with given attributes. */
-allocno_live_range_t
+live_range_t
ira_create_allocno_live_range (ira_allocno_t a, int start, int finish,
- allocno_live_range_t next)
+ live_range_t next)
{
- allocno_live_range_t p;
+ live_range_t p;
- p = (allocno_live_range_t) pool_alloc (allocno_live_range_pool);
+ p = (live_range_t) pool_alloc (live_range_pool);
p->allocno = a;
p->start = start;
p->finish = finish;
@@ -815,22 +827,22 @@ ira_create_allocno_live_range (ira_allocno_t a, int start, int finish,
}
/* Copy allocno live range R and return the result. */
-static allocno_live_range_t
-copy_allocno_live_range (allocno_live_range_t r)
+static live_range_t
+copy_allocno_live_range (live_range_t r)
{
- allocno_live_range_t p;
+ live_range_t p;
- p = (allocno_live_range_t) pool_alloc (allocno_live_range_pool);
+ p = (live_range_t) pool_alloc (live_range_pool);
*p = *r;
return p;
}
/* Copy allocno live range list given by its head R and return the
result. */
-allocno_live_range_t
-ira_copy_allocno_live_range_list (allocno_live_range_t r)
+live_range_t
+ira_copy_allocno_live_range_list (live_range_t r)
{
- allocno_live_range_t p, first, last;
+ live_range_t p, first, last;
if (r == NULL)
return NULL;
@@ -849,11 +861,10 @@ ira_copy_allocno_live_range_list (allocno_live_range_t r)
/* 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)
+live_range_t
+ira_merge_allocno_live_ranges (live_range_t r1, live_range_t r2)
{
- allocno_live_range_t first, last, temp;
+ live_range_t first, last, temp;
if (r1 == NULL)
return r2;
@@ -927,8 +938,7 @@ ira_merge_allocno_live_ranges (allocno_live_range_t r1,
/* 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)
+ira_allocno_live_ranges_intersect_p (live_range_t r1, live_range_t r2)
{
/* Remember the live ranges are always kept ordered. */
while (r1 != NULL && r2 != NULL)
@@ -945,16 +955,16 @@ ira_allocno_live_ranges_intersect_p (allocno_live_range_t r1,
/* Free allocno live range R. */
void
-ira_finish_allocno_live_range (allocno_live_range_t r)
+ira_finish_allocno_live_range (live_range_t r)
{
- pool_free (allocno_live_range_pool, r);
+ pool_free (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)
+ira_finish_allocno_live_range_list (live_range_t r)
{
- allocno_live_range_t next_r;
+ live_range_t next_r;
for (; r != NULL; r = next_r)
{
@@ -1015,7 +1025,7 @@ finish_allocnos (void)
VEC_free (ira_allocno_t, heap, ira_conflict_id_allocno_map_vec);
VEC_free (ira_allocno_t, heap, allocno_vec);
free_alloc_pool (allocno_pool);
- free_alloc_pool (allocno_live_range_pool);
+ free_alloc_pool (live_range_pool);
}
@@ -1603,12 +1613,7 @@ propagate_allocno_info (void)
ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a);
ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a);
ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
-#ifdef STACK_REGS
- if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
- ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ merge_hard_reg_conflicts (a, parent_a, true);
ALLOCNO_CALLS_CROSSED_NUM (parent_a)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
@@ -1651,12 +1656,52 @@ create_allocnos (void)
/* 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)
+change_allocno_in_range_list (live_range_t r, ira_allocno_t a)
{
for (; r != NULL; r = r->next)
r->allocno = a;
}
+/* Move all live ranges associated with allocno FROM to allocno TO. */
+static void
+move_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to)
+{
+ live_range_t lr = ALLOCNO_LIVE_RANGES (from);
+
+ if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+ {
+ fprintf (ira_dump_file,
+ " Moving ranges of a%dr%d to a%dr%d: ",
+ ALLOCNO_NUM (from), ALLOCNO_REGNO (from),
+ ALLOCNO_NUM (to), ALLOCNO_REGNO (to));
+ ira_print_live_range_list (ira_dump_file, lr);
+ }
+ change_allocno_in_range_list (lr, to);
+ ALLOCNO_LIVE_RANGES (to)
+ = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to));
+ ALLOCNO_LIVE_RANGES (from) = NULL;
+}
+
+/* Copy all live ranges associated with allocno FROM to allocno TO. */
+static void
+copy_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to)
+{
+ live_range_t lr = ALLOCNO_LIVE_RANGES (from);
+
+ if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+ {
+ fprintf (ira_dump_file,
+ " Copying ranges of a%dr%d to a%dr%d: ",
+ ALLOCNO_NUM (from), ALLOCNO_REGNO (from),
+ ALLOCNO_NUM (to), ALLOCNO_REGNO (to));
+ ira_print_live_range_list (ira_dump_file, lr);
+ }
+ lr = ira_copy_allocno_live_range_list (lr);
+ change_allocno_in_range_list (lr, to);
+ ALLOCNO_LIVE_RANGES (to)
+ = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to));
+}
+
/* Return TRUE if NODE represents a loop with low register
pressure. */
static bool
@@ -1890,26 +1935,15 @@ propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
{
enum reg_class cover_class;
- IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
- ALLOCNO_CONFLICT_HARD_REGS (from_a));
-#ifdef STACK_REGS
- if (ALLOCNO_NO_STACK_REG_P (from_a))
- ALLOCNO_NO_STACK_REG_P (a) = true;
-#endif
+ merge_hard_reg_conflicts (from_a, a, false);
ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
ALLOCNO_FREQ (a) += ALLOCNO_FREQ (from_a);
ALLOCNO_CALL_FREQ (a) += ALLOCNO_CALL_FREQ (from_a);
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from_a));
ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
if (! ALLOCNO_BAD_SPILL_P (from_a))
ALLOCNO_BAD_SPILL_P (a) = false;
-#ifdef STACK_REGS
- if (ALLOCNO_TOTAL_NO_STACK_REG_P (from_a))
- ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true;
-#endif
cover_class = ALLOCNO_COVER_CLASS (from_a);
ira_assert (cover_class == ALLOCNO_COVER_CLASS (a));
ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
@@ -1930,7 +1964,6 @@ remove_unnecessary_allocnos (void)
bool merged_p, rebuild_p;
ira_allocno_t a, prev_a, next_a, parent_a;
ira_loop_tree_node_t a_node, parent;
- allocno_live_range_t r;
merged_p = false;
regno_allocnos = NULL;
@@ -1971,13 +2004,8 @@ remove_unnecessary_allocnos (void)
ira_regno_allocno_map[regno] = next_a;
else
ALLOCNO_NEXT_REGNO_ALLOCNO (prev_a) = next_a;
- r = ALLOCNO_LIVE_RANGES (a);
- change_allocno_in_range_list (r, parent_a);
- ALLOCNO_LIVE_RANGES (parent_a)
- = ira_merge_allocno_live_ranges
- (r, ALLOCNO_LIVE_RANGES (parent_a));
+ move_allocno_live_ranges (a, parent_a);
merged_p = true;
- ALLOCNO_LIVE_RANGES (a) = NULL;
propagate_some_info_from_allocno (parent_a, a);
/* Remove it from the corresponding regno allocno
map to avoid info propagation of subsequent
@@ -2011,7 +2039,6 @@ remove_low_level_allocnos (void)
bool merged_p, propagate_p;
ira_allocno_t a, top_a;
ira_loop_tree_node_t a_node, parent;
- allocno_live_range_t r;
ira_allocno_iterator ai;
merged_p = false;
@@ -2030,12 +2057,8 @@ remove_low_level_allocnos (void)
propagate_p = a_node->parent->regno_allocno_map[regno] == NULL;
/* Remove the allocno and update info of allocno in the upper
region. */
- r = ALLOCNO_LIVE_RANGES (a);
- change_allocno_in_range_list (r, top_a);
- ALLOCNO_LIVE_RANGES (top_a)
- = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (top_a));
+ move_allocno_live_ranges (a, top_a);
merged_p = true;
- ALLOCNO_LIVE_RANGES (a) = NULL;
if (propagate_p)
propagate_some_info_from_allocno (top_a, a);
}
@@ -2123,7 +2146,7 @@ update_bad_spill_attribute (void)
int i;
ira_allocno_t a;
ira_allocno_iterator ai;
- allocno_live_range_t r;
+ live_range_t r;
enum reg_class cover_class;
bitmap_head dead_points[N_REG_CLASSES];
@@ -2174,7 +2197,7 @@ setup_min_max_allocno_live_range_point (void)
int i;
ira_allocno_t a, parent_a, cap;
ira_allocno_iterator ai;
- allocno_live_range_t r;
+ live_range_t r;
ira_loop_tree_node_t parent;
FOR_EACH_ALLOCNO (a, ai)
@@ -2391,6 +2414,34 @@ create_caps (void)
IR with one region. */
static ira_allocno_t *regno_top_level_allocno_map;
+/* Find the allocno that corresponds to A at a level one higher up in the
+ loop tree. Returns NULL if A is a cap, or if it has no parent. */
+ira_allocno_t
+ira_parent_allocno (ira_allocno_t a)
+{
+ ira_loop_tree_node_t parent;
+
+ if (ALLOCNO_CAP (a) != NULL)
+ return NULL;
+
+ parent = ALLOCNO_LOOP_TREE_NODE (a)->parent;
+ if (parent == NULL)
+ return NULL;
+
+ return parent->regno_allocno_map[ALLOCNO_REGNO (a)];
+}
+
+/* Find the allocno that corresponds to A at a level one higher up in the
+ loop tree. If ALLOCNO_CAP is set for A, return that. */
+ira_allocno_t
+ira_parent_or_cap_allocno (ira_allocno_t a)
+{
+ if (ALLOCNO_CAP (a) != NULL)
+ return ALLOCNO_CAP (a);
+
+ return ira_parent_allocno (a);
+}
+
/* Process all allocnos originated from pseudo REGNO and copy live
ranges, hard reg conflicts, and allocno stack reg attributes from
low level allocnos to final allocnos which are destinations of
@@ -2402,7 +2453,6 @@ copy_info_to_removed_store_destinations (int regno)
ira_allocno_t a;
ira_allocno_t parent_a = NULL;
ira_loop_tree_node_t parent;
- allocno_live_range_t r;
bool merged_p;
merged_p = false;
@@ -2425,26 +2475,8 @@ copy_info_to_removed_store_destinations (int regno)
break;
if (parent == NULL || parent_a == NULL)
continue;
- if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
- {
- fprintf
- (ira_dump_file,
- " Coping ranges of a%dr%d to a%dr%d: ",
- ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)),
- ALLOCNO_NUM (parent_a), REGNO (ALLOCNO_REG (parent_a)));
- ira_print_live_range_list (ira_dump_file,
- 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)
- = 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
- if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
- ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
+ copy_allocno_live_ranges (a, parent_a);
+ merge_hard_reg_conflicts (a, parent_a, true);
ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
ALLOCNO_CALLS_CROSSED_NUM (parent_a)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
@@ -2472,8 +2504,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
enum reg_class cover_class;
ira_allocno_t a, parent_a, first, second, node_first, node_second;
ira_copy_t cp;
- ira_loop_tree_node_t parent, node;
- allocno_live_range_t r;
+ ira_loop_tree_node_t node;
+ live_range_t r;
ira_allocno_iterator ai;
ira_copy_iterator ci;
sparseset allocnos_live;
@@ -2507,10 +2539,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
if (ALLOCNO_SOMEWHERE_RENAMED_P (a))
new_pseudos_p = true;
- if (ALLOCNO_CAP (a) != NULL
- || (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL
- || ((parent_a = parent->regno_allocno_map[ALLOCNO_REGNO (a)])
- == NULL))
+ parent_a = ira_parent_allocno (a);
+ if (parent_a == NULL)
{
ALLOCNO_COPIES (a) = NULL;
regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a;
@@ -2522,28 +2552,9 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
mem_dest_p = true;
if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a)))
{
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
-#ifdef STACK_REGS
- if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
- ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
- if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
- {
- fprintf (ira_dump_file,
- " Moving ranges of a%dr%d to a%dr%d: ",
- ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)),
- ALLOCNO_NUM (parent_a),
- REGNO (ALLOCNO_REG (parent_a)));
- ira_print_live_range_list (ira_dump_file,
- ALLOCNO_LIVE_RANGES (a));
- }
- change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a);
- ALLOCNO_LIVE_RANGES (parent_a)
- = ira_merge_allocno_live_ranges
- (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a));
+ merge_hard_reg_conflicts (a, parent_a, true);
+ move_allocno_live_ranges (a, parent_a);
merged_p = true;
- ALLOCNO_LIVE_RANGES (a) = NULL;
ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
= (ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
|| ALLOCNO_MEM_OPTIMIZED_DEST_P (a));
@@ -2577,11 +2588,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
ALLOCNO_COVER_CLASS_COST (parent_a)
-= ALLOCNO_COVER_CLASS_COST (a);
ALLOCNO_MEMORY_COST (parent_a) -= ALLOCNO_MEMORY_COST (a);
- if (ALLOCNO_CAP (parent_a) != NULL
- || (parent
- = ALLOCNO_LOOP_TREE_NODE (parent_a)->parent) == NULL
- || (parent_a = (parent->regno_allocno_map
- [ALLOCNO_REGNO (parent_a)])) == NULL)
+ parent_a = ira_parent_allocno (parent_a);
+ if (parent_a == NULL)
break;
}
ALLOCNO_COPIES (a) = NULL;
@@ -2865,7 +2873,7 @@ ira_build (bool loops_p)
{
int n, nr;
ira_allocno_t a;
- allocno_live_range_t r;
+ live_range_t r;
ira_allocno_iterator ai;
n = 0;