summaryrefslogtreecommitdiff
path: root/gcc/ira-build.c
diff options
context:
space:
mode:
authorbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-22 15:48:30 +0000
committerbernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4>2010-07-22 15:48:30 +0000
commitbe18556fae23e5b53c6219b22f23aeba6ccc2b32 (patch)
treeeaa5d4c97bfefaad493c5a8a2a304340a3fe659c /gcc/ira-build.c
parent06cfa2e631e804c06cd83a0567e2262ccd752970 (diff)
downloadgcc-be18556fae23e5b53c6219b22f23aeba6ccc2b32.tar.gz
* ira-build.c (ira_create_object): New arg SUBWORD; all callers changed.
Initialize OBJECT_SUBWORD. (ira_create_allocno): Clear ALLOCNO_NUM_OBJECTS. (ira_create_allocno_objects): Renamed from ira_create_allocno_object; all callers changed. (merge_hard_reg_conflicts): Iterate over allocno subobjects. (finish_allocno): Likewise. (move_allocno_live_ranges, copy_allocno_live_ranges): Likewise. (remove_low_level_allocnos): Likewise. (update_bad_spill_attribute): Likewise. (setup_min_max_allocno_live_range_point): Likewise. (sort_conflict_id_map): Likewise. (ira_flattening): Likewise. Use ior_hard_reg_conflicts. (ior_hard_reg_conflicts): New function. (ior_allocate_object_conflicts): Renamed first argument to OBJ. (compress_conflict_vecs): Iterate over objects, not allocnos. (ira_add_live_range_to_object): New function. (object_range_compare_func): Renamed from allocno_range_compare_func. All callers changed. (setup_min_max_conflict_allocno_ids): For allocnos with multiple subobjects, widen the min/max range of the lowest-order object to potentially include all other such low-order objects. * ira.c (ira_bad_reload_regno_1): Iterate over allocno subobjects. (check_allocation): Likewise. Use more fine-grained tests for register conflicts. * ira-color.c (allocnos_have_intersected_live_ranges_p): Iterate over allocno subobjects. (assign_hard_reg): Keep multiple sets of conflicts. Make finer-grained choices about which bits to set in each set. Don't use ira_hard_reg_not_in_set_p, perform a more elaborate test for conflicts using the multiple sets we computed. (push_allocno_to_stack): Iterate over allocno subobjects. (all_conflicting_hard_regs_coalesced): New static function. (setup_allocno_available_regs_num): Use it. (setup_allocno_left_conflicts_size): Likewise. Iterate over allocno subobjects. (coalesced_allocno_conflict): Test subobject 0 in each allocno. (setup_allocno_priorities): Divide ALLOCNO_EXCESS_PRESSURE_POINTS_NUM by ALLOCNO_NUM_OBJECTS. (calculate_spill_cost): Likewise. (color_pass): Express if statement in a more normal way. (ira_reassign_conflict_allocnos): Iterate over allocno subobjects. (slot_coalesced_allocno_live_ranges_intersect_p): Likewise. (setup_slot_coalesced_allocno_live_ranges): Likewise. (allocno_reload_assign): Likewise. (ira_reassign_pseudos): Likewise. (fast_allocation): Likewise. * ira-conflicts.c (build_conflict_bit_table): Likewise. (print_allocno_conflicts): Likewise. (ira_build_conflicts): Likewise. (allocnos_conflict_for_copy_p): Renamed from allocnos_conflict_p. All callers changed. Test subword 0 of each allocno for conflicts. (build_object_conflicts): Renamed from build_allocno_conflicts. All callers changed. Iterate over allocno subobjects. * ira-emit.c (modify_move_list): Iterate over allocno subobjects. * ira-int.h (struct ira_allocno): New member. num_objects. Rename object to objects and change it into an array. (ALLOCNO_OBJECT): Add new argument N. (ALLOCNO_NUM_OBJECTS, OBJECT_SUBWORD): New macros. (ira_create_allocno_objects): Renamed from ira_create_allocno_object. (ior_hard_reg_conflicts): Declare. (ira_add_live_range_to_object): Declare. (ira_allocno_object_iterator): New. (ira_allocno_object_iter_init, ira_allocno_object_iter_cond): New. (FOR_EACH_ALLOCNO_OBJECT): New macro. * ira-lives.c (objects_live): Renamed from allocnos_live; all uses changed. (allocnos_processed): New sparseset. (make_object_born): Renamed from make_allocno_born; take an ira_object_t argument. All callers changed. (make_object_dead): Renamed from make_allocno_dead; take an ira_object t argument. All callers changed. (update_allocno_pressure_excess_length): Take an ira_obejct_t argument. All callers changed. (mark_pseudo_regno_live): Iterate over allocno subobjects. (mark_pseudo_regno_dead): Likewise. (mark_pseudo_regno_subword_live, mark_pseudo_regno_subword_dead): New functions. (mark_ref_live): Detect subword accesses and call mark_pseudo_regno_subword_live as appropriate. (mark_ref_dead): Likewise for mark_pseudo_regno_subword_dead. (process_bb_nodes_live): Deal with object-related updates first; set and test bits in allocnos_processed to avoid computing allocno statistics more than once. (create_start_finish_chains): Iterate over objects, not allocnos. (print_object_live_ranges): New function. (print_allocno_live_ranges): Use it. (ira_create_allocno_live_ranges): Allocate and free allocnos_processed and objects_live. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@162418 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira-build.c')
-rw-r--r--gcc/ira-build.c408
1 files changed, 272 insertions, 136 deletions
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 89fb7eb3726..bf9124eca59 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -422,12 +422,13 @@ initiate_allocnos (void)
/* Create and return an object corresponding to a new allocno A. */
static ira_object_t
-ira_create_object (ira_allocno_t a)
+ira_create_object (ira_allocno_t a, int subword)
{
enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
ira_object_t obj = (ira_object_t) pool_alloc (object_pool);
OBJECT_ALLOCNO (obj) = a;
+ OBJECT_SUBWORD (obj) = subword;
OBJECT_CONFLICT_ID (obj) = ira_objects_num;
OBJECT_CONFLICT_VEC_P (obj) = false;
OBJECT_CONFLICT_ARRAY (obj) = NULL;
@@ -446,6 +447,7 @@ ira_create_object (ira_allocno_t a)
ira_object_id_map
= VEC_address (ira_object_t, ira_object_id_map_vec);
ira_objects_num = VEC_length (ira_object_t, ira_object_id_map_vec);
+
return obj;
}
@@ -510,10 +512,12 @@ ira_create_allocno (int regno, bool cap_p, ira_loop_tree_node_t loop_tree_node)
ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
+ ALLOCNO_NUM_OBJECTS (a) = 0;
VEC_safe_push (ira_allocno_t, heap, allocno_vec, a);
ira_allocnos = VEC_address (ira_allocno_t, allocno_vec);
ira_allocnos_num = VEC_length (ira_allocno_t, allocno_vec);
+
return a;
}
@@ -524,14 +528,27 @@ ira_set_allocno_cover_class (ira_allocno_t a, enum reg_class cover_class)
ALLOCNO_COVER_CLASS (a) = cover_class;
}
-/* Allocate an object for allocno A and set ALLOCNO_OBJECT. */
+/* Determine the number of objects we should associate with allocno A
+ and allocate them. */
void
-ira_create_allocno_object (ira_allocno_t a)
+ira_create_allocno_objects (ira_allocno_t a)
{
- ALLOCNO_OBJECT (a) = ira_create_object (a);
+ enum machine_mode mode = ALLOCNO_MODE (a);
+ enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
+ int n = ira_reg_class_nregs[cover_class][mode];
+ int i;
+
+ if (GET_MODE_SIZE (mode) != 2 * UNITS_PER_WORD || n != 2)
+ n = 1;
+
+ ALLOCNO_NUM_OBJECTS (a) = n;
+ for (i = 0; i < n; i++)
+ ALLOCNO_OBJECT (a, i) = ira_create_object (a, i);
}
-/* For each allocno, create the corresponding ALLOCNO_OBJECT structure. */
+/* For each allocno, set ALLOCNO_NUM_OBJECTS and create the
+ ALLOCNO_OBJECT structures. This must be called after the cover
+ classes are known. */
static void
create_allocno_objects (void)
{
@@ -539,22 +556,28 @@ create_allocno_objects (void)
ira_allocno_iterator ai;
FOR_EACH_ALLOCNO (a, ai)
- ira_create_allocno_object (a);
+ ira_create_allocno_objects (a);
}
-/* Merge hard register conflicts from allocno FROM into allocno TO. If
- TOTAL_ONLY is true, we ignore ALLOCNO_CONFLICT_HARD_REGS. */
+/* Merge hard register conflict information for all objects associated with
+ allocno TO into the corresponding objects associated with FROM.
+ If TOTAL_ONLY is true, we only merge OBJECT_TOTAL_CONFLICT_HARD_REGS. */
static void
merge_hard_reg_conflicts (ira_allocno_t from, ira_allocno_t to,
bool total_only)
{
- ira_object_t from_obj = ALLOCNO_OBJECT (from);
- ira_object_t to_obj = ALLOCNO_OBJECT (to);
- if (!total_only)
- IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (to_obj),
- OBJECT_CONFLICT_HARD_REGS (from_obj));
- IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (to_obj),
- OBJECT_TOTAL_CONFLICT_HARD_REGS (from_obj));
+ int i;
+ gcc_assert (ALLOCNO_NUM_OBJECTS (to) == ALLOCNO_NUM_OBJECTS (from));
+ for (i = 0; i < ALLOCNO_NUM_OBJECTS (to); i++)
+ {
+ ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
+ ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
+ if (!total_only)
+ IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (to_obj),
+ OBJECT_CONFLICT_HARD_REGS (from_obj));
+ IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (to_obj),
+ OBJECT_TOTAL_CONFLICT_HARD_REGS (from_obj));
+ }
#ifdef STACK_REGS
if (!total_only && ALLOCNO_NO_STACK_REG_P (from))
ALLOCNO_NO_STACK_REG_P (to) = true;
@@ -563,6 +586,20 @@ merge_hard_reg_conflicts (ira_allocno_t from, ira_allocno_t to,
#endif
}
+/* Update hard register conflict information for all objects associated with
+ A to include the regs in SET. */
+void
+ior_hard_reg_conflicts (ira_allocno_t a, HARD_REG_SET *set)
+{
+ ira_allocno_object_iterator i;
+ ira_object_t obj;
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, i)
+ {
+ IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), *set);
+ IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), *set);
+ }
+}
+
/* Return TRUE if a conflict vector with NUM elements is more
profitable than a conflict bit vector for OBJ. */
bool
@@ -617,14 +654,14 @@ allocate_conflict_bit_vec (ira_object_t obj)
}
/* Allocate and initialize the conflict vector or conflict bit vector
- of A for NUM conflicting allocnos whatever is more profitable. */
+ of OBJ for NUM conflicting allocnos whatever is more profitable. */
void
-ira_allocate_object_conflicts (ira_object_t a, int num)
+ira_allocate_object_conflicts (ira_object_t obj, int num)
{
- if (ira_conflict_vector_profitable_p (a, num))
- ira_allocate_conflict_vec (a, num);
+ if (ira_conflict_vector_profitable_p (obj, num))
+ ira_allocate_conflict_vec (obj, num);
else
- allocate_conflict_bit_vec (a);
+ allocate_conflict_bit_vec (obj);
}
/* Add OBJ2 to the conflicts of OBJ1. */
@@ -772,15 +809,14 @@ compress_conflict_vec (ira_object_t obj)
static void
compress_conflict_vecs (void)
{
- ira_allocno_t a;
- ira_allocno_iterator ai;
+ ira_object_t obj;
+ ira_object_iterator oi;
conflict_check = (int *) ira_allocate (sizeof (int) * ira_objects_num);
memset (conflict_check, 0, sizeof (int) * ira_objects_num);
curr_conflict_check_tick = 0;
- FOR_EACH_ALLOCNO (a, ai)
+ FOR_EACH_OBJECT (obj, oi)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
if (OBJECT_CONFLICT_VEC_P (obj))
compress_conflict_vec (obj);
}
@@ -823,7 +859,7 @@ create_cap_allocno (ira_allocno_t a)
ALLOCNO_MODE (cap) = ALLOCNO_MODE (a);
cover_class = ALLOCNO_COVER_CLASS (a);
ira_set_allocno_cover_class (cap, cover_class);
- ira_create_allocno_object (cap);
+ ira_create_allocno_objects (cap);
ALLOCNO_AVAILABLE_REGS_NUM (cap) = ALLOCNO_AVAILABLE_REGS_NUM (a);
ALLOCNO_CAP_MEMBER (cap) = a;
ALLOCNO_CAP (a) = cap;
@@ -838,7 +874,9 @@ 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);
+
merge_hard_reg_conflicts (a, cap, false);
+
ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a);
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
{
@@ -849,7 +887,7 @@ create_cap_allocno (ira_allocno_t a)
return cap;
}
-/* Create and return allocno live range with given attributes. */
+/* Create and return a live range for OBJECT with given attributes. */
live_range_t
ira_create_live_range (ira_object_t obj, int start, int finish,
live_range_t next)
@@ -864,6 +902,17 @@ ira_create_live_range (ira_object_t obj, int start, int finish,
return p;
}
+/* Create a new live range for OBJECT and queue it at the head of its
+ live range list. */
+void
+ira_add_live_range_to_object (ira_object_t object, int start, int finish)
+{
+ live_range_t p;
+ p = ira_create_live_range (object, start, finish,
+ OBJECT_LIVE_RANGES (object));
+ OBJECT_LIVE_RANGES (object) = p;
+}
+
/* Copy allocno live range R and return the result. */
static live_range_t
copy_live_range (live_range_t r)
@@ -1032,13 +1081,17 @@ static void
finish_allocno (ira_allocno_t a)
{
enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
- ira_object_t obj = ALLOCNO_OBJECT (a);
+ ira_object_t obj;
+ ira_allocno_object_iterator oi;
- ira_finish_live_range_list (OBJECT_LIVE_RANGES (obj));
- ira_object_id_map[OBJECT_CONFLICT_ID (obj)] = NULL;
- if (OBJECT_CONFLICT_ARRAY (obj) != NULL)
- ira_free (OBJECT_CONFLICT_ARRAY (obj));
- pool_free (object_pool, obj);
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ {
+ ira_finish_live_range_list (OBJECT_LIVE_RANGES (obj));
+ ira_object_id_map[OBJECT_CONFLICT_ID (obj)] = NULL;
+ if (OBJECT_CONFLICT_ARRAY (obj) != NULL)
+ ira_free (OBJECT_CONFLICT_ARRAY (obj));
+ pool_free (object_pool, obj);
+ }
ira_allocnos[ALLOCNO_NUM (a)] = NULL;
if (ALLOCNO_HARD_REG_COSTS (a) != NULL)
@@ -1708,44 +1761,58 @@ change_object_in_range_list (live_range_t r, ira_object_t obj)
static void
move_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to)
{
- ira_object_t from_obj = ALLOCNO_OBJECT (from);
- ira_object_t to_obj = ALLOCNO_OBJECT (to);
- live_range_t lr = OBJECT_LIVE_RANGES (from_obj);
+ int i;
+ int n = ALLOCNO_NUM_OBJECTS (from);
+
+ gcc_assert (n == ALLOCNO_NUM_OBJECTS (to));
- if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+ for (i = 0; i < n; i++)
{
- 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);
+ ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
+ ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
+ live_range_t lr = OBJECT_LIVE_RANGES (from_obj);
+
+ 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_object_in_range_list (lr, to_obj);
+ OBJECT_LIVE_RANGES (to_obj)
+ = ira_merge_live_ranges (lr, OBJECT_LIVE_RANGES (to_obj));
+ OBJECT_LIVE_RANGES (from_obj) = NULL;
}
- change_object_in_range_list (lr, to_obj);
- OBJECT_LIVE_RANGES (to_obj)
- = ira_merge_live_ranges (lr, OBJECT_LIVE_RANGES (to_obj));
- OBJECT_LIVE_RANGES (from_obj) = 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)
{
- ira_object_t from_obj = ALLOCNO_OBJECT (from);
- ira_object_t to_obj = ALLOCNO_OBJECT (to);
- live_range_t lr = OBJECT_LIVE_RANGES (from_obj);
+ int i;
+ int n = ALLOCNO_NUM_OBJECTS (from);
- if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
+ gcc_assert (n == ALLOCNO_NUM_OBJECTS (to));
+
+ for (i = 0; i < n; i++)
{
- 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);
+ ira_object_t from_obj = ALLOCNO_OBJECT (from, i);
+ ira_object_t to_obj = ALLOCNO_OBJECT (to, i);
+ live_range_t lr = OBJECT_LIVE_RANGES (from_obj);
+
+ 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_live_range_list (lr);
+ change_object_in_range_list (lr, to_obj);
+ OBJECT_LIVE_RANGES (to_obj)
+ = ira_merge_live_ranges (lr, OBJECT_LIVE_RANGES (to_obj));
}
- lr = ira_copy_live_range_list (lr);
- change_object_in_range_list (lr, to_obj);
- OBJECT_LIVE_RANGES (to_obj)
- = ira_merge_live_ranges (lr, OBJECT_LIVE_RANGES (to_obj));
}
/* Return TRUE if NODE represents a loop with low register
@@ -2125,13 +2192,15 @@ remove_low_level_allocnos (void)
regno = ALLOCNO_REGNO (a);
if (ira_loop_tree_root->regno_allocno_map[regno] == a)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
+ ira_object_t obj;
+ ira_allocno_object_iterator oi;
ira_regno_allocno_map[regno] = a;
ALLOCNO_NEXT_REGNO_ALLOCNO (a) = NULL;
ALLOCNO_CAP_MEMBER (a) = NULL;
- COPY_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
- OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ COPY_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+ OBJECT_TOTAL_CONFLICT_HARD_REGS (obj));
#ifdef STACK_REGS
if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
ALLOCNO_NO_STACK_REG_P (a) = true;
@@ -2194,6 +2263,8 @@ update_bad_spill_attribute (void)
int i;
ira_allocno_t a;
ira_allocno_iterator ai;
+ ira_allocno_object_iterator aoi;
+ ira_object_t obj;
live_range_t r;
enum reg_class cover_class;
bitmap_head dead_points[N_REG_CLASSES];
@@ -2205,31 +2276,36 @@ update_bad_spill_attribute (void)
}
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
cover_class = ALLOCNO_COVER_CLASS (a);
if (cover_class == NO_REGS)
continue;
- for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
- bitmap_set_bit (&dead_points[cover_class], r->finish);
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, aoi)
+ for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+ bitmap_set_bit (&dead_points[cover_class], r->finish);
}
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
cover_class = ALLOCNO_COVER_CLASS (a);
if (cover_class == NO_REGS)
continue;
if (! ALLOCNO_BAD_SPILL_P (a))
continue;
- for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, aoi)
{
- for (i = r->start + 1; i < r->finish; i++)
- if (bitmap_bit_p (&dead_points[cover_class], i))
+ for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+ {
+ for (i = r->start + 1; i < r->finish; i++)
+ if (bitmap_bit_p (&dead_points[cover_class], i))
+ break;
+ if (i < r->finish)
+ break;
+ }
+ if (r != NULL)
+ {
+ ALLOCNO_BAD_SPILL_P (a) = false;
break;
- if (i < r->finish)
- break;
+ }
}
- if (r != NULL)
- ALLOCNO_BAD_SPILL_P (a) = false;
}
for (i = 0; i < ira_reg_class_cover_size; i++)
{
@@ -2247,57 +2323,69 @@ setup_min_max_allocno_live_range_point (void)
int i;
ira_allocno_t a, parent_a, cap;
ira_allocno_iterator ai;
+#ifdef ENABLE_IRA_CHECKING
+ ira_object_iterator oi;
+ ira_object_t obj;
+#endif
live_range_t r;
ira_loop_tree_node_t parent;
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
- r = OBJECT_LIVE_RANGES (obj);
- if (r == NULL)
- continue;
- OBJECT_MAX (obj) = r->finish;
- for (; r->next != NULL; r = r->next)
- ;
- OBJECT_MIN (obj) = r->start;
+ int n = ALLOCNO_NUM_OBJECTS (a);
+ for (i = 0; i < n; i++)
+ {
+ ira_object_t obj = ALLOCNO_OBJECT (a, i);
+ r = OBJECT_LIVE_RANGES (obj);
+ if (r == NULL)
+ continue;
+ OBJECT_MAX (obj) = r->finish;
+ for (; r->next != NULL; r = r->next)
+ ;
+ OBJECT_MIN (obj) = r->start;
+ }
}
for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
for (a = ira_regno_allocno_map[i];
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
- ira_object_t parent_obj;
-
- if (OBJECT_MAX (obj) < 0)
- continue;
- ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
- /* Accumulation of range info. */
- if (ALLOCNO_CAP (a) != NULL)
+ int j;
+ int n = ALLOCNO_NUM_OBJECTS (a);
+ for (j = 0; j < n; j++)
{
- for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap))
+ ira_object_t obj = ALLOCNO_OBJECT (a, j);
+ ira_object_t parent_obj;
+
+ if (OBJECT_MAX (obj) < 0)
+ continue;
+ ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
+ /* Accumulation of range info. */
+ if (ALLOCNO_CAP (a) != NULL)
{
- ira_object_t cap_obj = ALLOCNO_OBJECT (cap);
- if (OBJECT_MAX (cap_obj) < OBJECT_MAX (obj))
- OBJECT_MAX (cap_obj) = OBJECT_MAX (obj);
- if (OBJECT_MIN (cap_obj) > OBJECT_MIN (obj))
- OBJECT_MIN (cap_obj) = OBJECT_MIN (obj);
+ for (cap = ALLOCNO_CAP (a); cap != NULL; cap = ALLOCNO_CAP (cap))
+ {
+ ira_object_t cap_obj = ALLOCNO_OBJECT (cap, j);
+ if (OBJECT_MAX (cap_obj) < OBJECT_MAX (obj))
+ OBJECT_MAX (cap_obj) = OBJECT_MAX (obj);
+ if (OBJECT_MIN (cap_obj) > OBJECT_MIN (obj))
+ OBJECT_MIN (cap_obj) = OBJECT_MIN (obj);
+ }
+ continue;
}
- continue;
+ if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL)
+ continue;
+ parent_a = parent->regno_allocno_map[i];
+ parent_obj = ALLOCNO_OBJECT (parent_a, j);
+ if (OBJECT_MAX (parent_obj) < OBJECT_MAX (obj))
+ OBJECT_MAX (parent_obj) = OBJECT_MAX (obj);
+ if (OBJECT_MIN (parent_obj) > OBJECT_MIN (obj))
+ OBJECT_MIN (parent_obj) = OBJECT_MIN (obj);
}
- if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL)
- continue;
- parent_a = parent->regno_allocno_map[i];
- parent_obj = ALLOCNO_OBJECT (parent_a);
- if (OBJECT_MAX (parent_obj) < OBJECT_MAX (obj))
- OBJECT_MAX (parent_obj) = OBJECT_MAX (obj);
- if (OBJECT_MIN (parent_obj) > OBJECT_MIN (obj))
- OBJECT_MIN (parent_obj) = OBJECT_MIN (obj);
}
#ifdef ENABLE_IRA_CHECKING
- FOR_EACH_ALLOCNO (a, ai)
+ FOR_EACH_OBJECT (obj, oi)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
if ((0 <= OBJECT_MIN (obj) && OBJECT_MIN (obj) <= ira_max_point)
&& (0 <= OBJECT_MAX (obj) && OBJECT_MAX (obj) <= ira_max_point))
continue;
@@ -2312,7 +2400,7 @@ setup_min_max_allocno_live_range_point (void)
(min). Allocnos with the same start are ordered according their
finish (max). */
static int
-allocno_range_compare_func (const void *v1p, const void *v2p)
+object_range_compare_func (const void *v1p, const void *v2p)
{
int diff;
ira_object_t obj1 = *(const ira_object_t *) v1p;
@@ -2340,9 +2428,15 @@ sort_conflict_id_map (void)
num = 0;
FOR_EACH_ALLOCNO (a, ai)
- ira_object_id_map[num++] = ALLOCNO_OBJECT (a);
+ {
+ ira_allocno_object_iterator oi;
+ ira_object_t obj;
+
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ ira_object_id_map[num++] = obj;
+ }
qsort (ira_object_id_map, num, sizeof (ira_object_t),
- allocno_range_compare_func);
+ object_range_compare_func);
for (i = 0; i < num; i++)
{
ira_object_t obj = ira_object_id_map[i];
@@ -2361,7 +2455,9 @@ setup_min_max_conflict_allocno_ids (void)
int cover_class;
int i, j, min, max, start, finish, first_not_finished, filled_area_start;
int *live_range_min, *last_lived;
+ int word0_min, word0_max;
ira_allocno_t a;
+ ira_allocno_iterator ai;
live_range_min = (int *) ira_allocate (sizeof (int) * ira_objects_num);
cover_class = -1;
@@ -2388,10 +2484,10 @@ setup_min_max_conflict_allocno_ids (void)
/* If we skip an allocno, the allocno with smaller ids will
be also skipped because of the secondary sorting the
range finishes (see function
- allocno_range_compare_func). */
+ object_range_compare_func). */
while (first_not_finished < i
&& start > OBJECT_MAX (ira_object_id_map
- [first_not_finished]))
+ [first_not_finished]))
first_not_finished++;
min = first_not_finished;
}
@@ -2442,6 +2538,38 @@ setup_min_max_conflict_allocno_ids (void)
}
ira_free (last_lived);
ira_free (live_range_min);
+
+ /* For allocnos with more than one object, we may later record extra conflicts in
+ subobject 0 that we cannot really know about here.
+ For now, simply widen the min/max range of these subobjects. */
+
+ word0_min = INT_MAX;
+ word0_max = INT_MIN;
+
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ int n = ALLOCNO_NUM_OBJECTS (a);
+ ira_object_t obj0;
+ if (n < 2)
+ continue;
+ obj0 = ALLOCNO_OBJECT (a, 0);
+ if (OBJECT_CONFLICT_ID (obj0) < word0_min)
+ word0_min = OBJECT_CONFLICT_ID (obj0);
+ if (OBJECT_CONFLICT_ID (obj0) > word0_max)
+ word0_max = OBJECT_CONFLICT_ID (obj0);
+ }
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ int n = ALLOCNO_NUM_OBJECTS (a);
+ ira_object_t obj0;
+ if (n < 2)
+ continue;
+ obj0 = ALLOCNO_OBJECT (a, 0);
+ if (OBJECT_MIN (obj0) > word0_min)
+ OBJECT_MIN (obj0) = word0_min;
+ if (OBJECT_MAX (obj0) < word0_max)
+ OBJECT_MAX (obj0) = word0_max;
+ }
}
@@ -2529,6 +2657,7 @@ copy_info_to_removed_store_destinations (int regno)
if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))])
/* This allocno will be removed. */
continue;
+
/* Caps will be removed. */
ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
for (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent;
@@ -2541,8 +2670,10 @@ copy_info_to_removed_store_destinations (int regno)
break;
if (parent == NULL || parent_a == NULL)
continue;
+
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);
@@ -2582,14 +2713,16 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
new_pseudos_p = merged_p = false;
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
+ ira_allocno_object_iterator oi;
+ ira_object_t obj;
if (ALLOCNO_CAP_MEMBER (a) != NULL)
/* Caps are not in the regno allocno maps and they are never
will be transformed into allocnos existing after IR
flattening. */
continue;
- COPY_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
- OBJECT_CONFLICT_HARD_REGS (obj));
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ COPY_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+ OBJECT_CONFLICT_HARD_REGS (obj));
#ifdef STACK_REGS
ALLOCNO_TOTAL_NO_STACK_REG_P (a) = ALLOCNO_NO_STACK_REG_P (a);
#endif
@@ -2674,13 +2807,17 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
/* Rebuild conflicts. */
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
+ ira_allocno_object_iterator oi;
+ ira_object_t obj;
if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
- for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
- ira_assert (r->object == obj);
- clear_conflicts (obj);
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ {
+ for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+ ira_assert (r->object == obj);
+ clear_conflicts (obj);
+ }
}
objects_live = sparseset_alloc (ira_objects_num);
for (i = 0; i < ira_max_point; i++)
@@ -2692,6 +2829,7 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
+
cover_class = ALLOCNO_COVER_CLASS (a);
sparseset_set_bit (objects_live, OBJECT_CONFLICT_ID (obj));
EXECUTE_IF_SET_IN_SPARSESET (objects_live, n)
@@ -2699,7 +2837,6 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
ira_object_t live_obj = ira_object_id_map[n];
ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj);
enum reg_class live_cover = ALLOCNO_COVER_CLASS (live_a);
-
if (ira_reg_classes_intersect_p[cover_class][live_cover]
/* Don't set up conflict for the allocno with itself. */
&& live_a != a)
@@ -2931,40 +3068,39 @@ ira_build (bool loops_p)
allocno crossing calls. */
FOR_EACH_ALLOCNO (a, ai)
if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
- {
- ira_object_t obj = ALLOCNO_OBJECT (a);
- IOR_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
- call_used_reg_set);
- IOR_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
- call_used_reg_set);
- }
+ ior_hard_reg_conflicts (a, &call_used_reg_set);
}
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
print_copies (ira_dump_file);
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
{
- int n, nr;
+ int n, nr, nr_big;
ira_allocno_t a;
live_range_t r;
ira_allocno_iterator ai;
n = 0;
+ nr = 0;
+ nr_big = 0;
FOR_EACH_ALLOCNO (a, ai)
{
- ira_object_t obj = ALLOCNO_OBJECT (a);
- n += OBJECT_NUM_CONFLICTS (obj);
+ int j, nobj = ALLOCNO_NUM_OBJECTS (a);
+ if (nobj > 1)
+ nr_big++;
+ for (j = 0; j < nobj; j++)
+ {
+ ira_object_t obj = ALLOCNO_OBJECT (a, j);
+ n += OBJECT_NUM_CONFLICTS (obj);
+ for (r = OBJECT_LIVE_RANGES (obj); r != NULL; r = r->next)
+ nr++;
+ }
}
- nr = 0;
- FOR_EACH_ALLOCNO (a, ai)
- for (r = OBJECT_LIVE_RANGES (ALLOCNO_OBJECT (a)); r != NULL;
- r = r->next)
- nr++;
fprintf (ira_dump_file, " regions=%d, blocks=%d, points=%d\n",
VEC_length (loop_p, ira_loops.larray), n_basic_blocks,
ira_max_point);
fprintf (ira_dump_file,
- " allocnos=%d, copies=%d, conflicts=%d, ranges=%d\n",
- ira_allocnos_num, ira_copies_num, n, nr);
+ " allocnos=%d (big %d), copies=%d, conflicts=%d, ranges=%d\n",
+ ira_allocnos_num, nr_big, ira_copies_num, n, nr);
}
return loops_p;
}