#include "insn-config.h"
#include "recog.h"
#include "diagnostic-core.h"
-#include "toplev.h"
#include "params.h"
#include "df.h"
#include "output.h"
ira_allocate (sizeof (struct ira_loop_tree_node)
* VEC_length (loop_p, ira_loops.larray)));
max_regno = max_reg_num ();
- for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
{
if (loop != ira_loops.tree_root)
{
if (skip_p)
continue;
edges = get_loop_exit_edges (loop);
- for (j = 0; VEC_iterate (edge, edges, j, e); j++)
+ FOR_EACH_VEC_ELT (edge, edges, j, e)
if ((e->flags & EDGE_ABNORMAL) && EDGE_CRITICAL_P (e))
{
skip_p = true;
unsigned int i;
loop_p loop;
- for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
if (ira_loop_nodes[i].regno_allocno_map != NULL
&& ira_loop_tree_root != &ira_loop_nodes[i])
return true;
unsigned int i;
loop_p loop;
- for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
finish_loop_tree_node (&ira_loop_nodes[i]);
ira_free (ira_loop_nodes);
for (i = 0; i < (unsigned int) last_basic_block_before_change; i++)
/* We can not use loop/bb node access macros because of potential
checking and because the nodes are not initialized enough
yet. */
- for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
if (ira_loop_nodes[i].regno_allocno_map != NULL)
{
ira_loop_nodes[i].children = NULL;
ira_allocno_iterator ai;
max_regno = max_reg_num ();
- for (l = 0; VEC_iterate (loop_p, ira_loops.larray, l, loop); l++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, l, loop)
if (ira_loop_nodes[l].regno_allocno_map != NULL)
{
ira_free (ira_loop_nodes[l].regno_allocno_map);
= VEC_alloc (ira_object_t, heap, max_reg_num () * 2);
ira_object_id_map = NULL;
ira_regno_allocno_map
- = (ira_allocno_t *) ira_allocate (max_reg_num () * sizeof (ira_allocno_t));
+ = (ira_allocno_t *) ira_allocate (max_reg_num ()
+ * sizeof (ira_allocno_t));
memset (ira_regno_allocno_map, 0, max_reg_num () * sizeof (ira_allocno_t));
}
/* 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);
+ enum reg_class aclass = ALLOCNO_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;
COPY_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj), ira_no_alloc_regs);
COPY_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj), ira_no_alloc_regs);
IOR_COMPL_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
- reg_class_contents[cover_class]);
+ reg_class_contents[aclass]);
IOR_COMPL_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
- reg_class_contents[cover_class]);
+ reg_class_contents[aclass]);
OBJECT_MIN (obj) = INT_MAX;
OBJECT_MAX (obj) = -1;
+ OBJECT_LIVE_RANGES (obj) = NULL;
VEC_safe_push (ira_object_t, heap, ira_object_id_map_vec, obj);
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;
}
LOOP_TREE_NODE. Add the allocno to the list of allocnos with the
same regno if CAP_P is FALSE. */
ira_allocno_t
-ira_create_allocno (int regno, bool cap_p, ira_loop_tree_node_t loop_tree_node)
+ira_create_allocno (int regno, bool cap_p,
+ ira_loop_tree_node_t loop_tree_node)
{
ira_allocno_t a;
ALLOCNO_NO_STACK_REG_P (a) = false;
ALLOCNO_TOTAL_NO_STACK_REG_P (a) = false;
#endif
- ALLOCNO_MEM_OPTIMIZED_DEST (a) = NULL;
- ALLOCNO_MEM_OPTIMIZED_DEST_P (a) = false;
- ALLOCNO_SOMEWHERE_RENAMED_P (a) = false;
- ALLOCNO_CHILD_RENAMED_P (a) = false;
ALLOCNO_DONT_REASSIGN_P (a) = false;
ALLOCNO_BAD_SPILL_P (a) = false;
- ALLOCNO_IN_GRAPH_P (a) = false;
ALLOCNO_ASSIGNED_P (a) = false;
- ALLOCNO_MAY_BE_SPILLED_P (a) = false;
- ALLOCNO_SPLAY_REMOVED_P (a) = false;
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
ALLOCNO_COPIES (a) = NULL;
ALLOCNO_HARD_REG_COSTS (a) = NULL;
ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
ALLOCNO_UPDATED_HARD_REG_COSTS (a) = NULL;
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
- ALLOCNO_LEFT_CONFLICTS_SIZE (a) = -1;
- ALLOCNO_COVER_CLASS (a) = NO_REGS;
- ALLOCNO_UPDATED_COVER_CLASS_COST (a) = 0;
- ALLOCNO_COVER_CLASS_COST (a) = 0;
+ ALLOCNO_CLASS (a) = NO_REGS;
+ ALLOCNO_UPDATED_CLASS_COST (a) = 0;
+ ALLOCNO_CLASS_COST (a) = 0;
ALLOCNO_MEMORY_COST (a) = 0;
ALLOCNO_UPDATED_MEMORY_COST (a) = 0;
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) = 0;
- ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = NULL;
- ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
- ALLOCNO_LIVE_RANGES (a) = NULL;
+ ALLOCNO_NUM_OBJECTS (a) = 0;
+ ALLOCNO_ADD_DATA (a) = NULL;
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;
}
-/* Set up cover class for A and update its conflict hard registers. */
+/* Set up register class for A and update its conflict hard
+ registers. */
void
-ira_set_allocno_cover_class (ira_allocno_t a, enum reg_class cover_class)
+ira_set_allocno_class (ira_allocno_t a, enum reg_class aclass)
{
- ALLOCNO_COVER_CLASS (a) = cover_class;
+ ira_allocno_object_iterator oi;
+ ira_object_t obj;
+
+ ALLOCNO_CLASS (a) = aclass;
+ FOR_EACH_ALLOCNO_OBJECT (a, obj, oi)
+ {
+ IOR_COMPL_HARD_REG_SET (OBJECT_CONFLICT_HARD_REGS (obj),
+ reg_class_contents[aclass]);
+ IOR_COMPL_HARD_REG_SET (OBJECT_TOTAL_CONFLICT_HARD_REGS (obj),
+ reg_class_contents[aclass]);
+ }
}
-/* 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 aclass = ALLOCNO_CLASS (a);
+ int n = ira_reg_class_max_nregs[aclass][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 allocno
+ classes are known. */
static void
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;
#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
}
/* 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. */
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);
}
{
ira_allocno_t cap;
ira_loop_tree_node_t parent;
- enum reg_class cover_class;
+ enum reg_class aclass;
- ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
- && ALLOCNO_NEXT_COALESCED_ALLOCNO (a) == a);
parent = ALLOCNO_LOOP_TREE_NODE (a)->parent;
cap = ira_create_allocno (ALLOCNO_REGNO (a), true, parent);
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);
- ALLOCNO_AVAILABLE_REGS_NUM (cap) = ALLOCNO_AVAILABLE_REGS_NUM (a);
+ aclass = ALLOCNO_CLASS (a);
+ ira_set_allocno_class (cap, aclass);
+ ira_create_allocno_objects (cap);
ALLOCNO_CAP_MEMBER (cap) = a;
ALLOCNO_CAP (a) = cap;
- ALLOCNO_COVER_CLASS_COST (cap) = ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (cap) = ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (cap) = ALLOCNO_MEMORY_COST (a);
ira_allocate_and_copy_costs
- (&ALLOCNO_HARD_REG_COSTS (cap), cover_class, ALLOCNO_HARD_REG_COSTS (a));
+ (&ALLOCNO_HARD_REG_COSTS (cap), aclass, ALLOCNO_HARD_REG_COSTS (a));
ira_allocate_and_copy_costs
- (&ALLOCNO_CONFLICT_HARD_REG_COSTS (cap), cover_class,
+ (&ALLOCNO_CONFLICT_HARD_REG_COSTS (cap), aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
ALLOCNO_BAD_SPILL_P (cap) = ALLOCNO_BAD_SPILL_P (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)
{
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_allocno_live_range (ira_allocno_t a, int start, int finish,
- live_range_t next)
+ira_create_live_range (ira_object_t obj, int start, int finish,
+ live_range_t next)
{
live_range_t p;
p = (live_range_t) pool_alloc (live_range_pool);
- p->allocno = a;
+ p->object = obj;
p->start = start;
p->finish = finish;
p->next = next;
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_allocno_live_range (live_range_t r)
+copy_live_range (live_range_t r)
{
live_range_t p;
/* Copy allocno live range list given by its head R and return the
result. */
live_range_t
-ira_copy_allocno_live_range_list (live_range_t r)
+ira_copy_live_range_list (live_range_t r)
{
live_range_t p, first, last;
return NULL;
for (first = last = NULL; r != NULL; r = r->next)
{
- p = copy_allocno_live_range (r);
+ p = copy_live_range (r);
if (first == NULL)
first = p;
else
maintains the order of ranges and tries to minimize number of the
result ranges. */
live_range_t
-ira_merge_allocno_live_ranges (live_range_t r1, live_range_t r2)
+ira_merge_live_ranges (live_range_t r1, live_range_t r2)
{
live_range_t first, last, temp;
r1->finish = r2->finish;
temp = r2;
r2 = r2->next;
- ira_finish_allocno_live_range (temp);
+ ira_finish_live_range (temp);
if (r2 == NULL)
{
/* To try to merge with subsequent ranges in r1. */
/* Return TRUE if live ranges R1 and R2 intersect. */
bool
-ira_allocno_live_ranges_intersect_p (live_range_t r1, live_range_t r2)
+ira_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)
/* Free allocno live range R. */
void
-ira_finish_allocno_live_range (live_range_t r)
+ira_finish_live_range (live_range_t r)
{
pool_free (live_range_pool, r);
}
/* Free list of allocno live ranges starting with R. */
void
-ira_finish_allocno_live_range_list (live_range_t r)
+ira_finish_live_range_list (live_range_t r)
{
live_range_t next_r;
for (; r != NULL; r = next_r)
{
next_r = r->next;
- ira_finish_allocno_live_range (r);
+ ira_finish_live_range (r);
}
}
void
ira_free_allocno_updated_costs (ira_allocno_t a)
{
- enum reg_class cover_class;
+ enum reg_class aclass;
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass);
ALLOCNO_UPDATED_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),
- cover_class);
+ aclass);
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
}
-/* Free the memory allocated for allocno A. */
+/* Free and nullify all cost vectors allocated earlier for allocno
+ A. */
static void
-finish_allocno (ira_allocno_t a)
+ira_free_allocno_costs (ira_allocno_t a)
{
- enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
- ira_object_t obj = ALLOCNO_OBJECT (a);
+ enum reg_class aclass = ALLOCNO_CLASS (a);
+ ira_object_t obj;
+ ira_allocno_object_iterator oi;
+
+ 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)
- ira_free_cost_vector (ALLOCNO_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_CONFLICT_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
- cover_class);
- ira_finish_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
- pool_free (allocno_pool, a);
+ aclass);
+ ALLOCNO_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_UPDATED_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
+}
- 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);
+/* Free the memory allocated for allocno A. */
+static void
+finish_allocno (ira_allocno_t a)
+{
+ ira_free_allocno_costs (a);
+ pool_free (allocno_pool, a);
}
/* Free the memory allocated for all allocnos. */
ALLOCNO_COPIES (second) = cp;
}
-/* Detach a copy CP from allocnos involved into the copy. */
-void
-ira_remove_allocno_copy_from_list (ira_copy_t cp)
-{
- ira_allocno_t first = cp->first, second = cp->second;
- ira_copy_t prev, next;
-
- next = cp->next_first_allocno_copy;
- prev = cp->prev_first_allocno_copy;
- if (prev == NULL)
- ALLOCNO_COPIES (first) = next;
- else if (prev->first == first)
- prev->next_first_allocno_copy = next;
- else
- prev->next_second_allocno_copy = next;
- if (next != NULL)
- {
- if (next->first == first)
- next->prev_first_allocno_copy = prev;
- else
- next->prev_second_allocno_copy = prev;
- }
- cp->prev_first_allocno_copy = cp->next_first_allocno_copy = NULL;
-
- next = cp->next_second_allocno_copy;
- prev = cp->prev_second_allocno_copy;
- if (prev == NULL)
- ALLOCNO_COPIES (second) = next;
- else if (prev->second == second)
- prev->next_second_allocno_copy = next;
- else
- prev->next_first_allocno_copy = next;
- if (next != NULL)
- {
- if (next->second == second)
- next->prev_second_allocno_copy = prev;
- else
- next->prev_first_allocno_copy = prev;
- }
- cp->prev_second_allocno_copy = cp->next_second_allocno_copy = NULL;
-}
-
/* Make a copy CP a canonical copy where number of the
first allocno is less than the second one. */
void
\f
-/* Pools for cost vectors. It is defined only for cover classes. */
+/* Pools for cost vectors. It is defined only for allocno classes. */
static alloc_pool cost_vector_pool[N_REG_CLASSES];
/* The function initiates work with hard register cost vectors. It
- creates allocation pool for each cover class. */
+ creates allocation pool for each allocno class. */
static void
initiate_cost_vectors (void)
{
int i;
- enum reg_class cover_class;
+ enum reg_class aclass;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- cost_vector_pool[cover_class]
+ aclass = ira_allocno_classes[i];
+ cost_vector_pool[aclass]
= create_alloc_pool ("cost vectors",
- sizeof (int)
- * ira_class_hard_regs_num[cover_class],
+ sizeof (int) * ira_class_hard_regs_num[aclass],
100);
}
}
-/* Allocate and return a cost vector VEC for COVER_CLASS. */
+/* Allocate and return a cost vector VEC for ACLASS. */
int *
-ira_allocate_cost_vector (enum reg_class cover_class)
+ira_allocate_cost_vector (reg_class_t aclass)
{
- return (int *) pool_alloc (cost_vector_pool[cover_class]);
+ return (int *) pool_alloc (cost_vector_pool[(int) aclass]);
}
-/* Free a cost vector VEC for COVER_CLASS. */
+/* Free a cost vector VEC for ACLASS. */
void
-ira_free_cost_vector (int *vec, enum reg_class cover_class)
+ira_free_cost_vector (int *vec, reg_class_t aclass)
{
ira_assert (vec != NULL);
- pool_free (cost_vector_pool[cover_class], vec);
+ pool_free (cost_vector_pool[(int) aclass], vec);
}
/* Finish work with hard register cost vectors. Release allocation
- pool for each cover class. */
+ pool for each allocno class. */
static void
finish_cost_vectors (void)
{
int i;
- enum reg_class cover_class;
+ enum reg_class aclass;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- free_alloc_pool (cost_vector_pool[cover_class]);
+ aclass = ira_allocno_classes[i];
+ free_alloc_pool (cost_vector_pool[aclass]);
}
}
create_loop_allocnos (e);
edges = get_loop_exit_edges (loop_node->loop);
- for (i = 0; VEC_iterate (edge, edges, i, e); i++)
+ FOR_EACH_VEC_ELT (edge, edges, i, e)
create_loop_allocnos (e);
VEC_free (edge, heap, edges);
}
int i;
ira_allocno_t a, parent_a;
ira_loop_tree_node_t parent;
- enum reg_class cover_class;
+ enum reg_class aclass;
if (flag_ira_region != IRA_REGION_ALL
&& flag_ira_region != IRA_REGION_MIXED)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
- ira_assert (cover_class == ALLOCNO_COVER_CLASS (parent_a));
+ aclass = ALLOCNO_CLASS (a);
+ ira_assert (aclass == ALLOCNO_CLASS (parent_a));
ira_allocate_and_accumulate_costs
- (&ALLOCNO_HARD_REG_COSTS (parent_a), cover_class,
+ (&ALLOCNO_HARD_REG_COSTS (parent_a), aclass,
ALLOCNO_HARD_REG_COSTS (a));
ira_allocate_and_accumulate_costs
(&ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a),
- cover_class,
+ aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
- ALLOCNO_COVER_CLASS_COST (parent_a)
- += ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (parent_a)
+ += ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a);
}
}
will hardly improve the result. As a result we speed up regional
register allocation. */
-/* The function changes allocno in range list given by R onto A. */
+/* The function changes the object in range list given by R to OBJ. */
static void
-change_allocno_in_range_list (live_range_t r, ira_allocno_t a)
+change_object_in_range_list (live_range_t r, ira_object_t obj)
{
for (; r != NULL; r = r->next)
- r->allocno = a;
+ r->object = obj;
}
/* 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);
+ 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,
- " 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_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);
+ 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_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
low_pressure_loop_node_p (ira_loop_tree_node_t node)
{
int i;
- enum reg_class cover_class;
+ enum reg_class pclass;
if (node->bb != NULL)
return false;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- if (node->reg_pressure[cover_class]
- > ira_available_class_regs[cover_class])
+ pclass = ira_pressure_classes[i];
+ if (node->reg_pressure[pclass] > ira_available_class_regs[pclass]
+ && ira_available_class_regs[pclass] > 1)
return false;
}
return true;
}
+#ifdef STACK_REGS
+/* Return TRUE if LOOP has a complex enter or exit edge. We don't
+ form a region from such loop if the target use stack register
+ because reg-stack.c can not deal with such edges. */
+static bool
+loop_with_complex_edge_p (struct loop *loop)
+{
+ int i;
+ edge_iterator ei;
+ edge e;
+ VEC (edge, heap) *edges;
+
+ FOR_EACH_EDGE (e, ei, loop->header->preds)
+ if (e->flags & EDGE_EH)
+ return true;
+ edges = get_loop_exit_edges (loop);
+ FOR_EACH_VEC_ELT (edge, edges, i, e)
+ if (e->flags & EDGE_COMPLEX)
+ return true;
+ return false;
+}
+#endif
+
/* Sort loops for marking them for removal. We put already marked
loops first, then less frequent loops next, and then outer loops
next. */
return l1->loop->num - l2->loop->num;
}
-
/* Mark loops which should be removed from regional allocation. We
remove a loop with low register pressure inside another loop with
register pressure. In this case a separate allocation of the loop
hardly helps (for irregular register file architecture it could
help by choosing a better hard register in the loop but we prefer
faster allocation even in this case). We also remove cheap loops
- if there are more than IRA_MAX_LOOPS_NUM of them. */
+ if there are more than IRA_MAX_LOOPS_NUM of them. Loop with EH
+ exit or enter edges are removed too because the allocation might
+ require put pseudo moves on the EH edges (we could still do this
+ for pseudos with caller saved hard registers in some cases but it
+ is impossible to say here or during top-down allocation pass what
+ hard register the pseudos get finally). */
static void
mark_loops_for_removal (void)
{
}
sorted_loops[n++] = &ira_loop_nodes[i];
ira_loop_nodes[i].to_remove_p
- = (low_pressure_loop_node_p (ira_loop_nodes[i].parent)
- && low_pressure_loop_node_p (&ira_loop_nodes[i]));
+ = ((low_pressure_loop_node_p (ira_loop_nodes[i].parent)
+ && low_pressure_loop_node_p (&ira_loop_nodes[i]))
+#ifdef STACK_REGS
+ || loop_with_complex_edge_p (ira_loop_nodes[i].loop)
+#endif
+ );
}
qsort (sorted_loops, n, sizeof (ira_loop_tree_node_t), loop_compare_func);
for (i = 0; n - i + 1 > IRA_MAX_LOOPS_NUM; i++)
int i;
loop_p loop;
- for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ FOR_EACH_VEC_ELT (loop_p, ira_loops.larray, i, loop)
if (ira_loop_nodes[i].regno_allocno_map != NULL)
{
if (ira_loop_nodes[i].parent == NULL)
static void
propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
{
- enum reg_class cover_class;
+ enum reg_class aclass;
merge_hard_reg_conflicts (from_a, a, false);
ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
if (! ALLOCNO_BAD_SPILL_P (from_a))
ALLOCNO_BAD_SPILL_P (a) = false;
- 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,
+ aclass = ALLOCNO_CLASS (from_a);
+ ira_assert (aclass == ALLOCNO_CLASS (a));
+ ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), aclass,
ALLOCNO_HARD_REG_COSTS (from_a));
ira_allocate_and_accumulate_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
- cover_class,
+ aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (from_a));
- ALLOCNO_COVER_CLASS_COST (a) += ALLOCNO_COVER_CLASS_COST (from_a);
+ ALLOCNO_CLASS_COST (a) += ALLOCNO_CLASS_COST (from_a);
ALLOCNO_MEMORY_COST (a) += ALLOCNO_MEMORY_COST (from_a);
}
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;
/* Remove loops from consideration. We remove all loops except for
root if ALL_P or loops for which a separate allocation will not
improve the result. We have to do this after allocno creation and
- their costs and cover class evaluation because only after that the
- register pressure can be known and is calculated. */
+ their costs and allocno class evaluation because only after that
+ the register pressure can be known and is calculated. */
static void
remove_unnecessary_regions (bool all_p)
{
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;
+ enum reg_class aclass;
bitmap_head dead_points[N_REG_CLASSES];
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- bitmap_initialize (&dead_points[cover_class], ®_obstack);
+ aclass = ira_allocno_classes[i];
+ bitmap_initialize (&dead_points[aclass], ®_obstack);
}
FOR_EACH_ALLOCNO (a, ai)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
continue;
- for (r = ALLOCNO_LIVE_RANGES (a); 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[aclass], r->finish);
}
FOR_EACH_ALLOCNO (a, ai)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
continue;
if (! ALLOCNO_BAD_SPILL_P (a))
continue;
- for (r = ALLOCNO_LIVE_RANGES (a); 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[aclass], 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++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- bitmap_clear (&dead_points[cover_class]);
+ aclass = ira_allocno_classes[i];
+ bitmap_clear (&dead_points[aclass]);
}
}
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 = ALLOCNO_LIVE_RANGES (a);
- 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;
+ int j;
+ int n = ALLOCNO_NUM_OBJECTS (a);
- if (OBJECT_MAX (obj) < 0)
- continue;
- ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
- /* Accumulation of range info. */
- if (ALLOCNO_CAP (a) != NULL)
+ 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;
}
/* Sort allocnos according to their live ranges. Allocnos with
- smaller cover class are put first unless we use priority coloring.
- Allocnos with the same cover class are ordered according their start
- (min). Allocnos with the same start are ordered according their
- finish (max). */
+ smaller allocno class are put first unless we use priority
+ coloring. Allocnos with the same class are ordered according
+ their start (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;
ira_allocno_t a1 = OBJECT_ALLOCNO (obj1);
ira_allocno_t a2 = OBJECT_ALLOCNO (obj2);
- if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && (diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0)
- return diff;
if ((diff = OBJECT_MIN (obj1) - OBJECT_MIN (obj2)) != 0)
return diff;
if ((diff = OBJECT_MAX (obj1) - OBJECT_MAX (obj2)) != 0)
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];
+
gcc_assert (obj != NULL);
OBJECT_CONFLICT_ID (obj) = i;
}
static void
setup_min_max_conflict_allocno_ids (void)
{
- int cover_class;
+ int aclass;
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;
+ aclass = -1;
first_not_finished = -1;
for (i = 0; i < ira_objects_num; i++)
{
ira_object_t obj = ira_object_id_map[i];
+
if (obj == NULL)
continue;
a = OBJECT_ALLOCNO (obj);
- if (cover_class < 0
- || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
+ if (aclass < 0)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
min = i;
first_not_finished = i;
}
/* 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;
}
OBJECT_MIN (obj) = min;
}
last_lived = (int *) ira_allocate (sizeof (int) * ira_max_point);
- cover_class = -1;
+ aclass = -1;
filled_area_start = -1;
for (i = ira_objects_num - 1; i >= 0; i--)
{
ira_object_t obj = ira_object_id_map[i];
+
if (obj == NULL)
continue;
a = OBJECT_ALLOCNO (obj);
- if (cover_class < 0
- || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
+ if (aclass < 0)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
for (j = 0; j < ira_max_point; j++)
last_lived[j] = -1;
filled_area_start = ira_max_point;
}
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;
+ }
}
\f
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
- if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))])
+ if (a != regno_top_level_allocno_map[REGNO (allocno_emit_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;
parent != NULL;
parent = parent->parent)
if ((parent_a = parent->regno_allocno_map[regno]) == NULL
- || (parent_a == regno_top_level_allocno_map[REGNO (ALLOCNO_REG
- (parent_a))]
- && ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)))
+ || (parent_a
+ == regno_top_level_allocno_map[REGNO
+ (allocno_emit_reg (parent_a))]
+ && ALLOCNO_EMIT_DATA (parent_a)->mem_optimized_dest_p))
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);
void
ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit)
{
- int i, j, num;
+ int i, j;
bool keep_p;
int hard_regs_num;
bool new_pseudos_p, merged_p, mem_dest_p;
unsigned int n;
- enum reg_class cover_class;
+ enum reg_class aclass;
ira_allocno_t a, parent_a, first, second, node_first, node_second;
ira_copy_t cp;
ira_loop_tree_node_t node;
live_range_t r;
ira_allocno_iterator ai;
ira_copy_iterator ci;
- sparseset allocnos_live;
regno_top_level_allocno_map
- = (ira_allocno_t *) ira_allocate (max_reg_num () * sizeof (ira_allocno_t));
+ = (ira_allocno_t *) ira_allocate (max_reg_num ()
+ * sizeof (ira_allocno_t));
memset (regno_top_level_allocno_map, 0,
max_reg_num () * sizeof (ira_allocno_t));
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
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
+ ira_emit_data_t parent_data, data = ALLOCNO_EMIT_DATA (a);
+
ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
- if (ALLOCNO_SOMEWHERE_RENAMED_P (a))
+ if (data->somewhere_renamed_p)
new_pseudos_p = true;
parent_a = ira_parent_allocno (a);
if (parent_a == NULL)
{
ALLOCNO_COPIES (a) = NULL;
- regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a;
+ regno_top_level_allocno_map[REGNO (data->reg)] = a;
continue;
}
ira_assert (ALLOCNO_CAP_MEMBER (parent_a) == NULL);
- if (ALLOCNO_MEM_OPTIMIZED_DEST (a) != NULL)
+ if (data->mem_optimized_dest != NULL)
mem_dest_p = true;
- if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a)))
+ parent_data = ALLOCNO_EMIT_DATA (parent_a);
+ if (REGNO (data->reg) == REGNO (parent_data->reg))
{
merge_hard_reg_conflicts (a, parent_a, true);
move_allocno_live_ranges (a, parent_a);
merged_p = true;
- ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
- = (ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a)
- || ALLOCNO_MEM_OPTIMIZED_DEST_P (a));
+ parent_data->mem_optimized_dest_p
+ = (parent_data->mem_optimized_dest_p
+ || data->mem_optimized_dest_p);
continue;
}
new_pseudos_p = true;
ira_assert (ALLOCNO_CALLS_CROSSED_NUM (parent_a) >= 0
&& ALLOCNO_NREFS (parent_a) >= 0
&& ALLOCNO_FREQ (parent_a) >= 0);
- cover_class = ALLOCNO_COVER_CLASS (parent_a);
- hard_regs_num = ira_class_hard_regs_num[cover_class];
+ aclass = ALLOCNO_CLASS (parent_a);
+ hard_regs_num = ira_class_hard_regs_num[aclass];
if (ALLOCNO_HARD_REG_COSTS (a) != NULL
&& ALLOCNO_HARD_REG_COSTS (parent_a) != NULL)
for (j = 0; j < hard_regs_num; j++)
for (j = 0; j < hard_regs_num; j++)
ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a)[j]
-= ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[j];
- ALLOCNO_COVER_CLASS_COST (parent_a)
- -= ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (parent_a)
+ -= ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (parent_a) -= ALLOCNO_MEMORY_COST (a);
parent_a = ira_parent_allocno (parent_a);
if (parent_a == NULL)
break;
}
ALLOCNO_COPIES (a) = NULL;
- regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))] = a;
+ regno_top_level_allocno_map[REGNO (data->reg)] = a;
}
if (mem_dest_p && copy_info_to_removed_store_destinations (i))
merged_p = true;
ira_rebuild_start_finish_chains ();
if (new_pseudos_p)
{
+ sparseset objects_live;
+
/* Rebuild conflicts. */
FOR_EACH_ALLOCNO (a, ai)
{
- if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+ ira_allocno_object_iterator oi;
+ ira_object_t obj;
+
+ if (a != regno_top_level_allocno_map[REGNO (allocno_emit_reg (a))]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
- for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
- ira_assert (r->allocno == a);
- clear_conflicts (ALLOCNO_OBJECT (a));
+ 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);
+ }
}
- allocnos_live = sparseset_alloc (ira_allocnos_num);
+ objects_live = sparseset_alloc (ira_objects_num);
for (i = 0; i < ira_max_point; i++)
{
for (r = ira_start_point_ranges[i]; r != NULL; r = r->start_next)
{
- a = r->allocno;
- if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+ ira_object_t obj = r->object;
+
+ a = OBJECT_ALLOCNO (obj);
+ if (a != regno_top_level_allocno_map[REGNO (allocno_emit_reg (a))]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
- num = ALLOCNO_NUM (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
- sparseset_set_bit (allocnos_live, num);
- EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, n)
+
+ aclass = ALLOCNO_CLASS (a);
+ sparseset_set_bit (objects_live, OBJECT_CONFLICT_ID (obj));
+ EXECUTE_IF_SET_IN_SPARSESET (objects_live, n)
{
- ira_allocno_t live_a = ira_allocnos[n];
+ ira_object_t live_obj = ira_object_id_map[n];
+ ira_allocno_t live_a = OBJECT_ALLOCNO (live_obj);
+ enum reg_class live_aclass = ALLOCNO_CLASS (live_a);
- if (ira_reg_classes_intersect_p
- [cover_class][ALLOCNO_COVER_CLASS (live_a)]
+ if (ira_reg_classes_intersect_p[aclass][live_aclass]
/* Don't set up conflict for the allocno with itself. */
- && num != (int) n)
- {
- ira_object_t obj = ALLOCNO_OBJECT (a);
- ira_object_t live_obj = ALLOCNO_OBJECT (live_a);
- ira_add_conflict (obj, live_obj);
- }
+ && live_a != a)
+ ira_add_conflict (obj, live_obj);
}
}
for (r = ira_finish_point_ranges[i]; r != NULL; r = r->finish_next)
- sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (r->allocno));
+ sparseset_clear_bit (objects_live, OBJECT_CONFLICT_ID (r->object));
}
- sparseset_free (allocnos_live);
+ sparseset_free (objects_live);
compress_conflict_vecs ();
}
/* Mark some copies for removing and change allocnos in the rest
fprintf
(ira_dump_file, " Remove cp%d:%c%dr%d-%c%dr%d\n",
cp->num, ALLOCNO_CAP_MEMBER (cp->first) != NULL ? 'c' : 'a',
- ALLOCNO_NUM (cp->first), REGNO (ALLOCNO_REG (cp->first)),
+ ALLOCNO_NUM (cp->first),
+ REGNO (allocno_emit_reg (cp->first)),
ALLOCNO_CAP_MEMBER (cp->second) != NULL ? 'c' : 'a',
- ALLOCNO_NUM (cp->second), REGNO (ALLOCNO_REG (cp->second)));
+ ALLOCNO_NUM (cp->second),
+ REGNO (allocno_emit_reg (cp->second)));
cp->loop_tree_node = NULL;
continue;
}
- first = regno_top_level_allocno_map[REGNO (ALLOCNO_REG (cp->first))];
- second = regno_top_level_allocno_map[REGNO (ALLOCNO_REG (cp->second))];
+ first
+ = regno_top_level_allocno_map[REGNO (allocno_emit_reg (cp->first))];
+ second
+ = regno_top_level_allocno_map[REGNO (allocno_emit_reg (cp->second))];
node = cp->loop_tree_node;
if (node == NULL)
keep_p = true; /* It copy generated in ira-emit.c. */
which we will have different pseudos. */
node_first = node->regno_allocno_map[ALLOCNO_REGNO (cp->first)];
node_second = node->regno_allocno_map[ALLOCNO_REGNO (cp->second)];
- keep_p = ((REGNO (ALLOCNO_REG (first))
- == REGNO (ALLOCNO_REG (node_first)))
- && (REGNO (ALLOCNO_REG (second))
- == REGNO (ALLOCNO_REG (node_second))));
+ keep_p = ((REGNO (allocno_emit_reg (first))
+ == REGNO (allocno_emit_reg (node_first)))
+ && (REGNO (allocno_emit_reg (second))
+ == REGNO (allocno_emit_reg (node_second))));
}
if (keep_p)
{
if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Remove cp%d:a%dr%d-a%dr%d\n",
cp->num, ALLOCNO_NUM (cp->first),
- REGNO (ALLOCNO_REG (cp->first)), ALLOCNO_NUM (cp->second),
- REGNO (ALLOCNO_REG (cp->second)));
+ REGNO (allocno_emit_reg (cp->first)),
+ ALLOCNO_NUM (cp->second),
+ REGNO (allocno_emit_reg (cp->second)));
}
}
/* Remove unnecessary allocnos on lower levels of the loop tree. */
FOR_EACH_ALLOCNO (a, ai)
{
- if (a != regno_top_level_allocno_map[REGNO (ALLOCNO_REG (a))]
+ if (a != regno_top_level_allocno_map[REGNO (allocno_emit_reg (a))]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
{
if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Remove a%dr%d\n",
- ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)));
+ ALLOCNO_NUM (a), REGNO (allocno_emit_reg (a)));
finish_allocno (a);
continue;
}
ALLOCNO_LOOP_TREE_NODE (a) = ira_loop_tree_root;
- ALLOCNO_REGNO (a) = REGNO (ALLOCNO_REG (a));
+ ALLOCNO_REGNO (a) = REGNO (allocno_emit_reg (a));
ALLOCNO_CAP (a) = NULL;
/* Restore updated costs for assignments from reload. */
ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
- ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_UPDATED_CLASS_COST (a) = ALLOCNO_CLASS_COST (a);
if (! ALLOCNO_ASSIGNED_P (a))
ira_free_allocno_updated_costs (a);
ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
FOR_EACH_ALLOCNO (a, ai)
{
- enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
- enum reg_class pref = reg_preferred_class (ALLOCNO_REGNO (a));
+ reg_class_t aclass = ALLOCNO_CLASS (a);
+ reg_class_t pref = reg_preferred_class (ALLOCNO_REGNO (a));
- if (reg_class_size[pref] != 1)
+ if (reg_class_size[(int) pref] != 1)
continue;
- index = (ira_class_hard_reg_index[cover_class]
- [ira_class_hard_regs[pref][0]]);
+ index = ira_class_hard_reg_index[(int) aclass]
+ [ira_class_hard_regs[(int) pref][0]];
if (index < 0)
continue;
if (ALLOCNO_CONFLICT_HARD_REG_COSTS (a) == NULL
|| ALLOCNO_HARD_REG_COSTS (a) == NULL)
continue;
min = INT_MAX;
- for (i = ira_class_hard_regs_num[cover_class] - 1; i >= 0; i--)
- if (ALLOCNO_HARD_REG_COSTS (a)[i] > ALLOCNO_COVER_CLASS_COST (a)
+ for (i = ira_class_hard_regs_num[(int) aclass] - 1; i >= 0; i--)
+ if (ALLOCNO_HARD_REG_COSTS (a)[i] > ALLOCNO_CLASS_COST (a)
&& min > ALLOCNO_HARD_REG_COSTS (a)[i])
min = ALLOCNO_HARD_REG_COSTS (a)[i];
if (min == INT_MAX)
continue;
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
- cover_class, 0);
+ aclass, 0);
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index]
- -= min - ALLOCNO_COVER_CLASS_COST (a);
+ -= min - ALLOCNO_CLASS_COST (a);
}
}
propagate_allocno_info ();
create_caps ();
}
- ira_tune_allocno_costs_and_cover_classes ();
+ ira_tune_allocno_costs ();
#ifdef ENABLE_IRA_CHECKING
check_allocno_creation ();
#endif
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 = ALLOCNO_LIVE_RANGES (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;
}