@@ -454,17 +454,10 @@ ira_create_allocno (int regno, bool cap_
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_CONFLICT_VEC_P (a) = false;
- ALLOCNO_COLORABLE_P (a) = false;
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
ALLOCNO_COPIES (a) = NULL;
ALLOCNO_HARD_REG_COSTS (a) = NULL;
@@ -477,18 +470,11 @@ ira_create_allocno (int regno, bool cap_
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_MIN (a) = INT_MAX;
ALLOCNO_MAX (a) = -1;
ALLOCNO_CONFLICT_ID (a) = ira_allocnos_num;
- CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
- ALLOCNO_HARD_REGS_NODE (a) = NULL;
- ALLOCNO_HARD_REGS_SUBNODES_START (a) = 0;
- ALLOCNO_HARD_REGS_SUBNODES_NUM (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);
@@ -2425,7 +2411,7 @@ copy_info_to_removed_store_destinations
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_DATA (a)->reg)])
/* This allocno will be removed. */
continue;
/* Caps will be removed. */
@@ -2434,9 +2420,10 @@ copy_info_to_removed_store_destinations
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_DATA
+ (parent_a)->reg)]
+ && ALLOCNO_EMIT_DATA (parent_a)->mem_optimized_dest_p))
break;
if (parent == NULL || parent_a == NULL)
continue;
@@ -2502,28 +2489,31 @@ ira_flattening (int max_regno_before_emi
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;
@@ -2559,7 +2549,7 @@ ira_flattening (int max_regno_before_emi
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;
@@ -2572,7 +2562,8 @@ ira_flattening (int max_regno_before_emi
/* Rebuild conflicts. */
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_DATA (a)->reg)]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
@@ -2585,7 +2576,8 @@ ira_flattening (int max_regno_before_emi
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))]
+ if (a != regno_top_level_allocno_map[REGNO
+ (ALLOCNO_EMIT_DATA (a)->reg)]
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
num = ALLOCNO_NUM (a);
@@ -2620,14 +2612,18 @@ ira_flattening (int max_regno_before_emi
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_DATA (cp->first)->reg),
ALLOCNO_CAP_MEMBER (cp->second) != NULL ? 'c' : 'a',
- ALLOCNO_NUM (cp->second), REGNO (ALLOCNO_REG (cp->second)));
+ ALLOCNO_NUM (cp->second),
+ REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
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_DATA
+ (cp->first)->reg)];
+ second = regno_top_level_allocno_map[REGNO (ALLOCNO_EMIT_DATA
+ (cp->second)->reg)];
node = cp->loop_tree_node;
if (node == NULL)
keep_p = true; /* It copy generated in ira-emit.c. */
@@ -2637,10 +2633,10 @@ ira_flattening (int max_regno_before_emi
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_DATA (first)->reg)
+ == REGNO (ALLOCNO_EMIT_DATA (node_first)->reg))
+ && (REGNO (ALLOCNO_EMIT_DATA (second)->reg)
+ == REGNO (ALLOCNO_EMIT_DATA (node_second)->reg)));
}
if (keep_p)
{
@@ -2654,24 +2650,25 @@ ira_flattening (int max_regno_before_emi
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_DATA (cp->first)->reg),
+ ALLOCNO_NUM (cp->second),
+ REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
}
}
/* 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_DATA (a)->reg)]
|| 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_DATA (a)->reg));
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_DATA (a)->reg);
ALLOCNO_CAP (a) = NULL;
/* Restore updated costs for assignments from reload. */
ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
@@ -697,20 +697,6 @@ ira_allocate (size_t len)
return res;
}
-/* Reallocate memory PTR of size LEN for IRA data. */
-void *
-ira_reallocate (void *ptr, size_t len)
-{
- void *res;
-
-#ifndef IRA_NO_OBSTACK
- res = obstack_alloc (&ira_obstack, len);
-#else
- res = xrealloc (ptr, len);
-#endif
- return res;
-}
-
/* Free memory ADDR allocated for IRA data. */
void
ira_free (void *addr ATTRIBUTE_UNUSED)
@@ -880,9 +866,8 @@ setup_pressure_classes (void)
ira_prohibited_class_mode_regs[cl][m]);
if (hard_reg_set_empty_p (temp_hard_regset))
continue;
- cost = ira_get_register_move_cost ((enum machine_mode) m,
- (enum reg_class) cl,
- (enum reg_class) cl);
+ ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
+ cost = ira_register_move_cost[m][cl][cl];
if (cost <= ira_max_memory_move_cost[m][cl][1]
|| cost <= ira_max_memory_move_cost[m][cl][0])
break;
@@ -1984,7 +1969,7 @@ setup_allocno_assignment_flags (void)
allocnos because the cost info and info about intersected
calls are incorrect for them. */
ALLOCNO_ASSIGNED_P (a) = (hard_regno >= 0
- || ALLOCNO_MEM_OPTIMIZED_DEST_P (a)
+ || ALLOCNO_EMIT_DATA (a)->mem_optimized_dest_p
|| (ALLOCNO_MEMORY_COST (a)
- ALLOCNO_CLASS_COST (a)) < 0);
ira_assert (hard_regno < 0
@@ -3519,7 +3504,7 @@ ira (FILE *f)
df_clear_flags (DF_NO_INSN_RESCAN);
regstat_init_n_sets_and_refs ();
regstat_compute_ri ();
-
+
/* If we are not optimizing, then this is the only place before
register allocation where dataflow is done. And that is needed
to generate these warnings. */
@@ -3591,6 +3576,8 @@ ira (FILE *f)
ira_max_point_before_emit = ira_max_point;
+ ira_initiate_emit_data ();
+
ira_emit (loops_p);
if (ira_conflicts_p)
@@ -3623,6 +3610,8 @@ ira (FILE *f)
}
}
+ ira_finish_emit_data ();
+
setup_reg_renumber ();
calculate_allocation_cost ();
@@ -39,6 +39,104 @@ along with GCC; see the file COPYING3.
#include "df.h"
#include "ira-int.h"
+/* See below. */
+typedef struct allocno_hard_regs *allocno_hard_regs_t;
+
+/* The structure contains information about hard registers can be
+ assigned to allocnos. Usually it is allocno profitable hard
+ registers but in some cases this set can be a bit different. Major
+ reason of the difference is a requirement to use hard register sets
+ that form a tree or a forest (set of trees), i.e. hard register set
+ of a node should contain hard register sets of its subnodes. */
+struct allocno_hard_regs
+{
+ /* Hard registers can be assigned to an allocno. */
+ HARD_REG_SET set;
+ /* Overall (spilling) cost of all allocnos with given register
+ set. */
+ long long int cost;
+};
+
+/* See below. */
+typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
+
+/* A node representing allocno hard registers. Such nodes form a
+ forest (set of trees). Each subnode of given node in the forest
+ refers for hard register set (usually allocno profitable hard
+ register set) which is a subset of one referred from given
+ node. */
+struct allocno_hard_regs_node
+{
+ /* Set up number of the node in preorder traversing of the forest. */
+ int preorder_num;
+ /* Used for different calculation like finding conflict size of an
+ allocno. */
+ int check;
+ /* Used for calculation of conflict size of an allocno. The
+ conflict size of the allocno is maximal number of given allocno
+ hard registers needed for allocation of the conflicting allocnos.
+ Given allocno is trivially colored if this number plus the number
+ of hard registers needed for given allocno is not greater than
+ the number of given allocno hard register set. */
+ int conflict_size;
+ /* The number of hard registers given by member hard_regs. */
+ int hard_regs_num;
+ /* The following member is used to form the final forest. */
+ bool used_p;
+ /* Pointer to the corresponding profitable hard registers. */
+ allocno_hard_regs_t hard_regs;
+ /* Parent, first subnode, previous and next node with the same
+ parent in the forest. */
+ allocno_hard_regs_node_t parent, first, prev, next;
+};
+
+/* To decrease footprint of ira_allocno structure we store all data
+ needed only for coloring in the following structure. */
+struct color_data
+{
+ /* TRUE value means that the allocno was not removed yet from the
+ conflicting graph during colouring. */
+ unsigned int in_graph_p : 1;
+ /* TRUE if it is put on the stack to make other allocnos
+ colorable. */
+ unsigned int may_be_spilled_p : 1;
+ /* TRUE if the allocno is trivially colorable. */
+ unsigned int colorable_p : 1;
+ /* Number of hard registers of the allocno class really
+ available for the allocno allocation. It is number of the
+ profitable hard regs. */
+ int available_regs_num;
+ /* Allocnos in a bucket (used in coloring) chained by the following
+ two members. */
+ ira_allocno_t next_bucket_allocno;
+ ira_allocno_t prev_bucket_allocno;
+ /* Used for temporary purposes. */
+ int temp;
+ /* Profitable hard regs available for this pseudo allocation. It
+ means that the set excludes unavailable hard regs and hard regs
+ conflicting with given pseudo. They should be of the allocno
+ class. */
+ HARD_REG_SET profitable_hard_regs;
+ /* The allocno hard registers node. */
+ allocno_hard_regs_node_t hard_regs_node;
+ /* Array of structures allocno_hard_regs_subnode representing
+ given allocno hard registers node (the 1st element in the array)
+ and all its subnodes in the tree (forest) of allocno hard
+ register nodes (see comments above). */
+ int hard_regs_subnodes_start;
+ /* The length of the previous array. */
+ int hard_regs_subnodes_num;
+};
+
+/* See above. */
+typedef struct color_data *color_data_t;
+
+/* Container for storing allocno data concerning coloring. */
+static color_data_t allocno_color_data;
+
+/* Macro to access the data concerning coloring. */
+#define ALLOCNO_COLOR_DATA(a) ((color_data_t) ALLOCNO_ADD_DATA (a))
+
/* This file contains code for regional graph coloring, spill/restore
code placement optimization, and code helping the reload pass to do
a better job. */
@@ -554,6 +652,7 @@ form_allocno_hard_regs_nodes_forest (voi
bitmap_iterator bi;
HARD_REG_SET temp;
allocno_hard_regs_node_t node, allocno_hard_regs_node;
+ color_data_t data;
node_check_tick = 0;
init_allocno_hard_regs ();
@@ -572,10 +671,10 @@ form_allocno_hard_regs_nodes_forest (voi
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ if (hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs))
continue;
hv = (add_allocno_hard_regs
- (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
}
SET_HARD_REG_SET (temp);
@@ -598,11 +697,12 @@ form_allocno_hard_regs_nodes_forest (voi
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ data = ALLOCNO_COLOR_DATA (a);
+ if (hard_reg_set_empty_p (data->profitable_hard_regs))
continue;
VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, 0);
collect_allocno_hard_regs_cover (hard_regs_roots,
- ALLOCNO_PROFITABLE_HARD_REGS (a));
+ data->profitable_hard_regs);
allocno_hard_regs_node = NULL;
for (j = 0;
VEC_iterate (allocno_hard_regs_node_t, hard_regs_node_vec,
@@ -614,7 +714,7 @@ form_allocno_hard_regs_nodes_forest (voi
: first_common_ancestor_node (node, allocno_hard_regs_node));
/* That is a temporary storage. */
allocno_hard_regs_node->used_p = true;
- ALLOCNO_HARD_REGS_NODE (a) = allocno_hard_regs_node;
+ data->hard_regs_node = allocno_hard_regs_node;
}
ira_assert (hard_regs_roots->next == NULL);
hard_regs_roots->used_p = true;
@@ -635,11 +735,12 @@ form_allocno_hard_regs_nodes_forest (voi
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ data = ALLOCNO_COLOR_DATA (a);
+ if (hard_reg_set_empty_p (data->profitable_hard_regs))
continue;
- len = get_allocno_hard_regs_subnodes_num (ALLOCNO_HARD_REGS_NODE (a));
- ALLOCNO_HARD_REGS_SUBNODES_START (a) = start;
- ALLOCNO_HARD_REGS_SUBNODES_NUM (a) = len;
+ len = get_allocno_hard_regs_subnodes_num (data->hard_regs_node);
+ data->hard_regs_subnodes_start = start;
+ data->hard_regs_subnodes_num = len;
start += len;
}
allocno_hard_regs_subnodes
@@ -693,20 +794,23 @@ setup_left_conflict_sizes_p (ira_allocno
allocno_hard_regs_subnode_t subnodes;
allocno_hard_regs_node_t node, conflict_node, temp_node, parent;
HARD_REG_SET node_set, conflict_node_set;
+ color_data_t data, conflict_data;
node_check_tick++;
- subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
- COPY_HARD_REG_SET (profitable_hard_regs, ALLOCNO_PROFITABLE_HARD_REGS (a));
- node = ALLOCNO_HARD_REGS_NODE (a);
+ data = ALLOCNO_COLOR_DATA (a);
+ subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
+ COPY_HARD_REG_SET (profitable_hard_regs, data->profitable_hard_regs);
+ node = data->hard_regs_node;
node_preorder_num = node->preorder_num;
COPY_HARD_REG_SET (node_set, node->hard_regs->set);
FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
{
- if (! ALLOCNO_IN_GRAPH_P (conflict_a)
+ conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
+ if (! conflict_data->in_graph_p
|| ! hard_reg_set_intersect_p (profitable_hard_regs,
- ALLOCNO_PROFITABLE_HARD_REGS (conflict_a)))
+ conflict_data->profitable_hard_regs))
continue;
- conflict_node = ALLOCNO_HARD_REGS_NODE (conflict_a);
+ conflict_node = conflict_data->hard_regs_node;
COPY_HARD_REG_SET (conflict_node_set, conflict_node->hard_regs->set);
if (hard_reg_set_subset_p (node_set, conflict_node_set))
temp_node = node;
@@ -724,7 +828,7 @@ setup_left_conflict_sizes_p (ira_allocno
+= (ira_reg_class_max_nregs
[ALLOCNO_CLASS (conflict_a)][ALLOCNO_MODE (conflict_a)]);
}
- for (i = 0; i < ALLOCNO_HARD_REGS_SUBNODES_NUM (a); i++)
+ for (i = 0; i < data->hard_regs_subnodes_num; i++)
{
temp_node = allocno_hard_regs_nodes[i + node_preorder_num];
ira_assert (temp_node->preorder_num == i + node_preorder_num);
@@ -750,7 +854,7 @@ setup_left_conflict_sizes_p (ira_allocno
subnodes[i].left_conflict_subnodes_size = 0;
}
start = node_preorder_num * allocno_hard_regs_nodes_num;
- for (i = ALLOCNO_HARD_REGS_SUBNODES_NUM (a) - 1; i >= 0; i--)
+ for (i = data->hard_regs_subnodes_num - 1; i >= 0; i--)
{
size = (subnodes[i].left_conflict_subnodes_size
+ MIN (subnodes[i].max_node_impact
@@ -772,8 +876,8 @@ setup_left_conflict_sizes_p (ira_allocno
subnodes[0].left_conflict_size));
conflict_size
+= ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
- ALLOCNO_COLORABLE_P (a) = conflict_size <= ALLOCNO_AVAILABLE_REGS_NUM (a);
- return ALLOCNO_COLORABLE_P (a);
+ data->colorable_p = conflict_size <= data->available_regs_num;
+ return data->colorable_p;
}
/* Update left conflict sizes of hard registers subnodes of allocno A
@@ -786,10 +890,12 @@ update_left_conflict_sizes_p (ira_allocn
int node_preorder_num, parent_i;
allocno_hard_regs_node_t node, removed_node, parent;
allocno_hard_regs_subnode_t subnodes;
+ color_data_t data;
- node = ALLOCNO_HARD_REGS_NODE (a);
+ data = ALLOCNO_COLOR_DATA (a);
+ node = data->hard_regs_node;
node_preorder_num = node->preorder_num;
- removed_node = ALLOCNO_HARD_REGS_NODE (removed_a);
+ removed_node = ALLOCNO_COLOR_DATA (removed_a)->hard_regs_node;
ira_assert (hard_reg_set_subset_p (removed_node->hard_regs->set,
node->hard_regs->set)
|| hard_reg_set_subset_p (node->hard_regs->set,
@@ -798,7 +904,7 @@ update_left_conflict_sizes_p (ira_allocn
i = allocno_hard_regs_subnode_index[start + removed_node->preorder_num];
if (i < 0)
i = 0;
- subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
+ subnodes = allocno_hard_regs_subnodes + data->hard_regs_subnodes_start;
before_conflict_size
= (subnodes[i].left_conflict_subnodes_size
+ MIN (subnodes[i].max_node_impact
@@ -835,12 +941,12 @@ update_left_conflict_sizes_p (ira_allocn
if (i == 0
&& (conflict_size
+ ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
- <= ALLOCNO_AVAILABLE_REGS_NUM (a)))
+ <= data->available_regs_num))
{
- ALLOCNO_COLORABLE_P (a) = true;
+ data->colorable_p = true;
return true;
}
- ira_assert (! ALLOCNO_COLORABLE_P (a));
+ ira_assert (! data->colorable_p);
return false;
}
@@ -856,26 +962,28 @@ setup_profitable_hard_regs (void)
bitmap_iterator bi;
enum reg_class aclass;
enum machine_mode mode;
+ color_data_t data;
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS)
continue;
+ data = ALLOCNO_COLOR_DATA (a);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
&& ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
- CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+ CLEAR_HARD_REG_SET (data->profitable_hard_regs);
else
{
mode = ALLOCNO_MODE (a);
- COPY_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ COPY_HARD_REG_SET (data->profitable_hard_regs,
reg_class_contents[aclass]);
AND_COMPL_HARD_REG_SET
- (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ (data->profitable_hard_regs,
ira_prohibited_class_mode_regs[aclass][mode]);
- AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
ira_no_alloc_regs);
- AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ AND_COMPL_HARD_REG_SET (data->profitable_hard_regs,
ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
}
}
@@ -888,7 +996,7 @@ setup_profitable_hard_regs (void)
continue;
FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
AND_COMPL_HARD_REG_SET
- (ALLOCNO_PROFITABLE_HARD_REGS (conflict_a),
+ (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs,
ira_reg_mode_hard_regset[hard_regno][ALLOCNO_MODE (a)]);
}
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
@@ -897,8 +1005,9 @@ setup_profitable_hard_regs (void)
int *costs;
a = ira_allocnos[i];
+ data = ALLOCNO_COLOR_DATA (a);
if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
- || hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ || hard_reg_set_empty_p (data->profitable_hard_regs))
continue;
if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
|| (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
@@ -908,11 +1017,11 @@ setup_profitable_hard_regs (void)
for (j = 0; j < class_size; j++)
{
hard_regno = ira_class_hard_regs[aclass][j];
- if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ if (! TEST_HARD_REG_BIT (data->profitable_hard_regs,
hard_regno))
continue;
if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
- CLEAR_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ CLEAR_HARD_REG_BIT (data->profitable_hard_regs,
hard_regno);
else if (min_cost > costs[j])
min_cost = costs[j];
@@ -920,7 +1029,7 @@ setup_profitable_hard_regs (void)
}
else if (ALLOCNO_UPDATED_MEMORY_COST (a)
< ALLOCNO_UPDATED_CLASS_COST (a))
- CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+ CLEAR_HARD_REG_SET (data->profitable_hard_regs);
if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
}
@@ -1000,8 +1109,8 @@ start_update_cost (void)
update_cost_queue = NULL;
}
-/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue,
- unless ALLOCNO is already in the queue, or has NO_REGS class. */
+/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue, unless
+ ALLOCNO is already in the queue, or has NO_REGS class. */
static inline void
queue_update_cost (ira_allocno_t allocno, int divisor)
{
@@ -1066,6 +1175,7 @@ update_copy_costs (ira_allocno_t allocno
do
{
mode = ALLOCNO_MODE (allocno);
+ ira_init_register_move_cost_if_necessary (mode);
for (cp = ALLOCNO_COPIES (allocno); cp != NULL; cp = next_cp)
{
if (cp->first == allocno)
@@ -1087,8 +1197,8 @@ update_copy_costs (ira_allocno_t allocno
continue;
cost = (cp->second == allocno
- ? ira_get_register_move_cost (mode, rclass, aclass)
- : ira_get_register_move_cost (mode, aclass, rclass));
+ ? ira_register_move_cost[mode][rclass][aclass]
+ : ira_register_move_cost[mode][aclass][rclass]);
if (decr_p)
cost = -cost;
@@ -1150,8 +1260,7 @@ update_conflict_hard_regno_costs (int *c
another_aclass = ALLOCNO_CLASS (another_allocno);
if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|| ALLOCNO_ASSIGNED_P (another_allocno)
- || ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
- (another_allocno)))
+ || ALLOCNO_COLOR_DATA (another_allocno)->may_be_spilled_p)
continue;
class_size = ira_class_hard_regs_num[another_aclass];
ira_allocate_and_copy_costs
@@ -1245,7 +1354,7 @@ assign_hard_reg (ira_allocno_t a, bool r
reg_class_contents[aclass]);
else
COPY_HARD_REG_SET (profitable_hard_regs,
- ALLOCNO_PROFITABLE_HARD_REGS (a));
+ ALLOCNO_COLOR_DATA (a)->profitable_hard_regs);
class_size = ira_class_hard_regs_num[aclass];
mode = ALLOCNO_MODE (a);
CLEAR_HARD_REG_SET (conflicting_regs);
@@ -1291,7 +1400,7 @@ assign_hard_reg (ira_allocno_t a, bool r
&& ALLOCNO_HARD_REGNO (conflict_a) >= 0)
|| (hard_reg_set_intersect_p
(profitable_hard_regs,
- ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))))
+ ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs)))))
{
conflict_aclass = ALLOCNO_CLASS (conflict_a);
ira_assert (ira_reg_classes_intersect_p[aclass][conflict_aclass]);
@@ -1310,7 +1419,7 @@ assign_hard_reg (ira_allocno_t a, bool r
}
}
else if (! retry_p
- && ! ALLOCNO_MAY_BE_SPILLED_P (conflict_a))
+ && ! ALLOCNO_COLOR_DATA (conflict_a)->may_be_spilled_p)
{
ira_allocate_and_copy_costs
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a),
@@ -1331,13 +1440,14 @@ assign_hard_reg (ira_allocno_t a, bool r
}
}
if (! retry_p)
+ /* Take into account preferences of allocnos connected by copies to
+ the conflict allocnos. */
+ update_conflict_hard_regno_costs (full_costs, aclass, true);
+
+ /* Take preferences of allocnos connected by copies into
+ account. */
+ if (! retry_p)
{
- /* Take into account preferences of allocnos connected by copies
- to the conflict allocnos. */
- update_conflict_hard_regno_costs (full_costs, aclass, true);
-
- /* Take preferences of allocnos connected by copies into
- account. */
start_update_cost ();
queue_update_cost (a, COST_HOP_DIVISOR);
update_conflict_hard_regno_costs (full_costs, aclass, false);
@@ -1420,21 +1530,24 @@ static int uncolorable_allocnos_num;
/* Return the current spill priority of allocno A. The less the
number, the more preferable the allocno for spilling. */
-static int
+static inline int
allocno_spill_priority (ira_allocno_t a)
{
- return (ALLOCNO_TEMP (a)
+ color_data_t data = ALLOCNO_COLOR_DATA (a);
+
+ return (data->temp
/ (ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
* ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
+ 1));
}
-/* Add A to bucket *BUCKET_PTR. A should be not in a bucket
+/* Add allocno A to bucket *BUCKET_PTR. A should be not in a bucket
before the call. */
static void
add_allocno_to_bucket (ira_allocno_t a, ira_allocno_t *bucket_ptr)
{
ira_allocno_t first_a;
+ color_data_t data;
if (bucket_ptr == &uncolorable_allocno_bucket
&& ALLOCNO_CLASS (a) != NO_REGS)
@@ -1443,10 +1556,11 @@ add_allocno_to_bucket (ira_allocno_t a,
ira_assert (uncolorable_allocnos_num > 0);
}
first_a = *bucket_ptr;
- ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = first_a;
- ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
+ data = ALLOCNO_COLOR_DATA (a);
+ data->next_bucket_allocno = first_a;
+ data->prev_bucket_allocno = NULL;
if (first_a != NULL)
- ALLOCNO_PREV_BUCKET_ALLOCNO (first_a) = a;
+ ALLOCNO_COLOR_DATA (first_a)->prev_bucket_allocno = a;
*bucket_ptr = a;
}
@@ -1467,9 +1581,9 @@ bucket_allocno_compare_func (const void
if ((diff = (int) ALLOCNO_CLASS (a2) - ALLOCNO_CLASS (a1)) != 0)
return diff;
a1_freq = ALLOCNO_FREQ (a1);
- a1_num = ALLOCNO_AVAILABLE_REGS_NUM (a1);
+ a1_num = ALLOCNO_COLOR_DATA (a1)->available_regs_num;
a2_freq = ALLOCNO_FREQ (a2);
- a2_num = ALLOCNO_AVAILABLE_REGS_NUM (a2);
+ a2_num = ALLOCNO_COLOR_DATA (a2)->available_regs_num;
if ((diff = a2_num - a1_num) != 0)
return diff;
else if ((diff = a1_freq - a2_freq) != 0)
@@ -1486,7 +1600,9 @@ sort_bucket (ira_allocno_t *bucket_ptr,
ira_allocno_t a, head;
int n;
- for (n = 0, a = *bucket_ptr; a != NULL; a = ALLOCNO_NEXT_BUCKET_ALLOCNO (a))
+ for (n = 0, a = *bucket_ptr;
+ a != NULL;
+ a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
sorted_allocnos[n++] = a;
if (n <= 1)
return;
@@ -1495,10 +1611,10 @@ sort_bucket (ira_allocno_t *bucket_ptr,
for (n--; n >= 0; n--)
{
a = sorted_allocnos[n];
- ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = head;
- ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
+ ALLOCNO_COLOR_DATA (a)->next_bucket_allocno = head;
+ ALLOCNO_COLOR_DATA (a)->prev_bucket_allocno = NULL;
if (head != NULL)
- ALLOCNO_PREV_BUCKET_ALLOCNO (head) = a;
+ ALLOCNO_COLOR_DATA (head)->prev_bucket_allocno = a;
head = a;
}
*bucket_ptr = head;
@@ -1521,17 +1637,18 @@ add_allocno_to_ordered_bucket (ira_alloc
}
for (before = *bucket_ptr, after = NULL;
before != NULL;
- after = before, before = ALLOCNO_NEXT_BUCKET_ALLOCNO (before))
+ after = before,
+ before = ALLOCNO_COLOR_DATA (before)->next_bucket_allocno)
if (bucket_allocno_compare_func (&allocno, &before) < 0)
break;
- ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno) = before;
- ALLOCNO_PREV_BUCKET_ALLOCNO (allocno) = after;
+ ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno = before;
+ ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno = after;
if (after == NULL)
*bucket_ptr = allocno;
else
- ALLOCNO_NEXT_BUCKET_ALLOCNO (after) = allocno;
+ ALLOCNO_COLOR_DATA (after)->next_bucket_allocno = allocno;
if (before != NULL)
- ALLOCNO_PREV_BUCKET_ALLOCNO (before) = allocno;
+ ALLOCNO_COLOR_DATA (before)->prev_bucket_allocno = allocno;
}
/* Delete ALLOCNO from bucket *BUCKET_PTR. It should be there before
@@ -1547,20 +1664,20 @@ delete_allocno_from_bucket (ira_allocno_
uncolorable_allocnos_num--;
ira_assert (uncolorable_allocnos_num >= 0);
}
- prev_allocno = ALLOCNO_PREV_BUCKET_ALLOCNO (allocno);
- next_allocno = ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno);
+ prev_allocno = ALLOCNO_COLOR_DATA (allocno)->prev_bucket_allocno;
+ next_allocno = ALLOCNO_COLOR_DATA (allocno)->next_bucket_allocno;
if (prev_allocno != NULL)
- ALLOCNO_NEXT_BUCKET_ALLOCNO (prev_allocno) = next_allocno;
+ ALLOCNO_COLOR_DATA (prev_allocno)->next_bucket_allocno = next_allocno;
else
{
ira_assert (*bucket_ptr == allocno);
*bucket_ptr = next_allocno;
}
if (next_allocno != NULL)
- ALLOCNO_PREV_BUCKET_ALLOCNO (next_allocno) = prev_allocno;
+ ALLOCNO_COLOR_DATA (next_allocno)->prev_bucket_allocno = prev_allocno;
}
-/* Put A onto the coloring stack without removing it from its
+/* Put allocno A onto the coloring stack without removing it from its
bucket. Pushing allocno to the coloring stack can result in moving
conflicting allocnos from the uncolorable bucket to the colorable
one. */
@@ -1570,20 +1687,23 @@ push_allocno_to_stack (ira_allocno_t a)
ira_allocno_t conflict_a;
enum reg_class aclass;
ira_allocno_conflict_iterator aci;
+ color_data_t data, conflict_data;
- ALLOCNO_IN_GRAPH_P (a) = false;
+ data = ALLOCNO_COLOR_DATA (a);
+ data->in_graph_p = false;
VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, a);
aclass = ALLOCNO_CLASS (a);
if (aclass == NO_REGS)
return;
FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
{
- if (! ALLOCNO_COLORABLE_P (conflict_a)
- && ALLOCNO_IN_GRAPH_P (conflict_a)
+ conflict_data = ALLOCNO_COLOR_DATA (conflict_a);
+ if (! conflict_data->colorable_p
+ && conflict_data->in_graph_p
&& ! ALLOCNO_ASSIGNED_P (conflict_a)
&& (hard_reg_set_intersect_p
- (ALLOCNO_PROFITABLE_HARD_REGS (a),
- ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))
+ (data->profitable_hard_regs,
+ conflict_data->profitable_hard_regs)))
{
ira_assert (bitmap_bit_p (coloring_allocno_bitmap,
ALLOCNO_NUM (conflict_a)));
@@ -1612,14 +1732,16 @@ remove_allocno_from_bucket_and_push (ira
fprintf (ira_dump_file, " Pushing");
ira_print_expanded_allocno (allocno);
if (colorable_p)
- fprintf (ira_dump_file, "(cost %d)\n", ALLOCNO_TEMP (allocno));
+ fprintf (ira_dump_file, "(cost %d)\n",
+ ALLOCNO_COLOR_DATA (allocno)->temp);
else
fprintf (ira_dump_file, "(potential spill: %spri=%d, cost=%d)\n",
ALLOCNO_BAD_SPILL_P (allocno) ? "bad spill, " : "",
- allocno_spill_priority (allocno), ALLOCNO_TEMP (allocno));
+ allocno_spill_priority (allocno),
+ ALLOCNO_COLOR_DATA (allocno)->temp);
}
if (! colorable_p)
- ALLOCNO_MAY_BE_SPILLED_P (allocno) = true;
+ ALLOCNO_COLOR_DATA (allocno)->may_be_spilled_p = true;
push_allocno_to_stack (allocno);
}
@@ -1695,13 +1817,16 @@ calculate_allocno_spill_cost (ira_allocn
+ ira_memory_move_cost[mode][rclass][1]
* ira_loop_edge_freq (loop_node, regno, false));
else
- cost += ((ira_memory_move_cost[mode][rclass][1]
- * ira_loop_edge_freq (loop_node, regno, true)
- + ira_memory_move_cost[mode][rclass][0]
- * ira_loop_edge_freq (loop_node, regno, false))
- - (ira_get_register_move_cost (mode, rclass, rclass)
- * (ira_loop_edge_freq (loop_node, regno, false)
- + ira_loop_edge_freq (loop_node, regno, true))));
+ {
+ ira_init_register_move_cost_if_necessary (mode);
+ cost += ((ira_memory_move_cost[mode][rclass][1]
+ * ira_loop_edge_freq (loop_node, regno, true)
+ + ira_memory_move_cost[mode][rclass][0]
+ * ira_loop_edge_freq (loop_node, regno, false))
+ - (ira_register_move_cost[mode][rclass][rclass]
+ * (ira_loop_edge_freq (loop_node, regno, false)
+ + ira_loop_edge_freq (loop_node, regno, true))));
+ }
return cost;
}
@@ -1719,7 +1844,8 @@ allocno_spill_priority_compare (ira_allo
pri2 = allocno_spill_priority (a2);
if ((diff = pri1 - pri2) != 0)
return diff;
- if ((diff = ALLOCNO_TEMP (a1) - ALLOCNO_TEMP (a2)) != 0)
+ if ((diff
+ = ALLOCNO_COLOR_DATA (a1)->temp - ALLOCNO_COLOR_DATA (a2)->temp) != 0)
return diff;
return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
}
@@ -1745,13 +1871,13 @@ push_allocnos_to_stack (void)
/* Calculate uncolorable allocno spill costs. */
for (a = uncolorable_allocno_bucket;
a != NULL;
- a = ALLOCNO_NEXT_BUCKET_ALLOCNO (a))
+ a = ALLOCNO_COLOR_DATA (a)->next_bucket_allocno)
if (ALLOCNO_CLASS (a) != NO_REGS)
{
cost = calculate_allocno_spill_cost (a);
/* ??? Remove cost of copies between the coalesced
allocnos. */
- ALLOCNO_TEMP (a) = cost;
+ ALLOCNO_COLOR_DATA (a)->temp = cost;
}
sort_bucket (&uncolorable_allocno_bucket, allocno_spill_sort_compare);
for (;;)
@@ -1806,21 +1932,23 @@ pop_allocnos_from_stack (void)
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, "spill\n");
}
- ALLOCNO_IN_GRAPH_P (allocno) = true;
+ ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
}
}
-/* Set up number of available hard registers for A. */
+/* Set up number of available hard registers for allocno A. */
static void
setup_allocno_available_regs_num (ira_allocno_t a)
{
int i, n, hard_regno, hard_regs_num;
- enum machine_mode mode;
enum reg_class aclass;
HARD_REG_SET temp_set;
+ enum machine_mode mode;
+ color_data_t data;
aclass = ALLOCNO_CLASS (a);
- ALLOCNO_AVAILABLE_REGS_NUM (a) = 0;
+ data = ALLOCNO_COLOR_DATA (a);
+ data->available_regs_num = 0;
if (aclass == NO_REGS)
return;
COPY_HARD_REG_SET (temp_set, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
@@ -1830,10 +1958,10 @@ setup_allocno_available_regs_num (ira_al
{
hard_regno = ira_class_hard_regs[aclass][i];
if (! ira_hard_reg_set_intersection_p (hard_regno, mode, temp_set)
- && TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a), hard_regno))
+ && TEST_HARD_REG_BIT (data->profitable_hard_regs, hard_regno))
n++;
}
- ALLOCNO_AVAILABLE_REGS_NUM (a) = n;
+ data->available_regs_num = n;
if (internal_flag_ira_verbose <= 2 || ira_dump_file == NULL)
return;
fprintf
@@ -1841,15 +1969,15 @@ setup_allocno_available_regs_num (ira_al
" Allocno a%dr%d of %s(%d) has %d avail. regs (confl. regs): ",
ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
- print_hard_reg_set (ira_dump_file, ALLOCNO_PROFITABLE_HARD_REGS (a), false);
+ print_hard_reg_set (ira_dump_file, data->profitable_hard_regs, false);
fprintf (ira_dump_file, " (");
print_hard_reg_set (ira_dump_file, temp_set, false);
fprintf (ira_dump_file, " ) %snode: ",
- hard_reg_set_equal_p (ALLOCNO_PROFITABLE_HARD_REGS (a),
- ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set)
+ hard_reg_set_equal_p (data->profitable_hard_regs,
+ data->hard_regs_node->hard_regs->set)
? "" : "^");
print_hard_reg_set (ira_dump_file,
- ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set, false);
+ data->hard_regs_node->hard_regs->set, false);
fprintf (ira_dump_file, "\n");
}
@@ -1858,7 +1986,7 @@ setup_allocno_available_regs_num (ira_al
static void
put_allocno_into_bucket (ira_allocno_t allocno)
{
- ALLOCNO_IN_GRAPH_P (allocno) = true;
+ ALLOCNO_COLOR_DATA (allocno)->in_graph_p = true;
setup_allocno_available_regs_num (allocno);
if (setup_left_conflict_sizes_p (allocno))
add_allocno_to_bucket (allocno, &colorable_allocno_bucket);
@@ -1930,7 +2058,7 @@ improve_allocation (void)
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ if (hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs))
continue;
aclass = ALLOCNO_CLASS (a);
allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
@@ -1945,13 +2073,13 @@ improve_allocation (void)
= allocno_costs[ira_class_hard_reg_index[aclass][hard_regno]];
try_p = false;
ira_assert (hard_reg_set_subset_p
- (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
reg_class_contents[aclass]));
class_size = ira_class_hard_regs_num[aclass];
for (j = 0; j < class_size; j++)
{
hard_regno = ira_class_hard_regs[aclass][j];
- if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ if (! TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
hard_regno))
continue;
ira_assert (ira_class_hard_reg_index[aclass][hard_regno] == j);
@@ -1990,14 +2118,14 @@ improve_allocation (void)
r >= 0 && r + hard_regno_nregs[r][mode] > conflict_hard_regno;
r--)
if (TEST_HARD_REG_BIT
- (ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+ (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs, r)
&& ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
costs[r] += spill_cost;
for (r = conflict_hard_regno + 1;
r < conflict_hard_regno + conflict_nregs;
r++)
if (TEST_HARD_REG_BIT
- (ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+ (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs, r)
&& ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
costs[r] += spill_cost;
}
@@ -2006,7 +2134,7 @@ improve_allocation (void)
for (j = 0; j < class_size; j++)
{
hard_regno = ira_class_hard_regs[aclass][j];
- if (TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ if (TEST_HARD_REG_BIT (ALLOCNO_COLOR_DATA (a)->profitable_hard_regs,
hard_regno)
&& (ira_hard_reg_not_in_set_p
(hard_regno, ALLOCNO_MODE (a),
@@ -2158,8 +2286,9 @@ color_allocnos (void)
{
a = ira_allocnos[i];
if (ALLOCNO_CLASS (a) != NO_REGS
- && ! hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
- ALLOCNO_IN_GRAPH_P (a) = true;
+ && ! hard_reg_set_empty_p (ALLOCNO_COLOR_DATA (a)
+ ->profitable_hard_regs))
+ ALLOCNO_COLOR_DATA (a)->in_graph_p = true;
else
{
ALLOCNO_HARD_REGNO (a) = -1;
@@ -2180,7 +2309,7 @@ color_allocnos (void)
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (ALLOCNO_IN_GRAPH_P (a))
+ if (ALLOCNO_COLOR_DATA (a)->in_graph_p)
put_allocno_into_bucket (a);
}
push_allocnos_to_stack ();
@@ -2253,7 +2382,7 @@ print_loop_title (ira_loop_tree_node_t l
static void
color_pass (ira_loop_tree_node_t loop_tree_node)
{
- int regno, hard_regno, index = -1;
+ int regno, hard_regno, index = -1, n;
int cost, exit_freq, enter_freq;
unsigned int j;
bitmap_iterator bi;
@@ -2268,13 +2397,25 @@ color_pass (ira_loop_tree_node_t loop_tr
bitmap_copy (coloring_allocno_bitmap, loop_tree_node->all_allocnos);
bitmap_copy (consideration_allocno_bitmap, coloring_allocno_bitmap);
+ n = 0;
EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
{
a = ira_allocnos[j];
+ n++;
if (! ALLOCNO_ASSIGNED_P (a))
continue;
bitmap_clear_bit (coloring_allocno_bitmap, ALLOCNO_NUM (a));
}
+ allocno_color_data
+ = (color_data_t) ira_allocate (sizeof (struct color_data) * n);
+ memset (allocno_color_data, 0, sizeof (struct color_data) * n);
+ n = 0;
+ EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, j, bi)
+ {
+ a = ira_allocnos[j];
+ ALLOCNO_ADD_DATA (a) = allocno_color_data + n;
+ n++;
+ }
/* Color all mentioned allocnos including transparent ones. */
color_allocnos ();
/* Process caps. They are processed just once. */
@@ -2382,7 +2523,8 @@ color_pass (ira_loop_tree_node_t loop_tr
else
{
aclass = ALLOCNO_CLASS (subloop_allocno);
- cost = (ira_get_register_move_cost (mode, rclass, rclass)
+ ira_init_register_move_cost_if_necessary (mode);
+ cost = (ira_register_move_cost[mode][rclass][rclass]
* (exit_freq + enter_freq));
ira_allocate_and_set_or_copy_costs
(&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), aclass,
@@ -2404,6 +2546,12 @@ color_pass (ira_loop_tree_node_t loop_tr
}
}
}
+ ira_free (allocno_color_data);
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
+ {
+ a = ira_allocnos[j];
+ ALLOCNO_ADD_DATA (a) = NULL;
+ }
}
/* Initialize the common data for coloring and calls functions to do
@@ -2471,6 +2619,7 @@ move_spill_restore (void)
- (ALLOCNO_HARD_REG_COSTS (a) == NULL
? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)[index]));
+ ira_init_register_move_cost_if_necessary (mode);
for (subloop_node = loop_node->subloops;
subloop_node != NULL;
subloop_node = subloop_node->subloop_next)
@@ -2498,7 +2647,7 @@ move_spill_restore (void)
+= (ira_memory_move_cost[mode][rclass][0] * exit_freq
+ ira_memory_move_cost[mode][rclass][1] * enter_freq);
if (hard_regno2 != hard_regno)
- cost -= (ira_get_register_move_cost (mode, rclass, rclass)
+ cost -= (ira_register_move_cost[mode][rclass][rclass]
* (exit_freq + enter_freq));
}
}
@@ -2517,7 +2666,7 @@ move_spill_restore (void)
+= (ira_memory_move_cost[mode][rclass][1] * exit_freq
+ ira_memory_move_cost[mode][rclass][0] * enter_freq);
if (hard_regno2 != hard_regno)
- cost -= (ira_get_register_move_cost (mode, rclass, rclass)
+ cost -= (ira_register_move_cost[mode][rclass][rclass]
* (exit_freq + enter_freq));
}
}
@@ -2560,6 +2709,7 @@ update_curr_costs (ira_allocno_t a)
if (aclass == NO_REGS)
return;
mode = ALLOCNO_MODE (a);
+ ira_init_register_move_cost_if_necessary (mode);
for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
{
if (cp->first == a)
@@ -2583,8 +2733,8 @@ update_curr_costs (ira_allocno_t a)
if (i < 0)
continue;
cost = (cp->first == a
- ? ira_get_register_move_cost (mode, rclass, aclass)
- : ira_get_register_move_cost (mode, aclass, rclass));
+ ? ira_register_move_cost[mode][rclass][aclass]
+ : ira_register_move_cost[mode][aclass][rclass]);
ira_allocate_and_set_or_copy_costs
(&ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a),
ALLOCNO_HARD_REG_COSTS (a));
@@ -2734,6 +2884,27 @@ static bool allocno_coalesced_p;
coalescing. */
static bitmap processed_coalesced_allocno_bitmap;
+/* See below. */
+typedef struct coalesce_data *coalesce_data_t;
+
+/* To decrease footprint of ira_allocno structure we store all data
+ needed only for coalescing in the following structure. */
+struct coalesce_data
+{
+ /* Coalesced allocnos form a cyclic list. One allocno given by
+ FIRST represents all coalesced allocnos. The
+ list is chained by NEXT. */
+ ira_allocno_t first;
+ ira_allocno_t next;
+ int temp;
+};
+
+/* Container for storing allocno data concerning coalescing. */
+static coalesce_data_t allocno_coalesce_data;
+
+/* Macro to access the data concerning coalescing. */
+#define ALLOCNO_COALESCE_DATA(a) ((coalesce_data_t) ALLOCNO_ADD_DATA (a))
+
/* The function is used to sort allocnos according to their execution
frequencies. */
static int
@@ -2760,21 +2931,21 @@ merge_allocnos (ira_allocno_t a1, ira_al
{
ira_allocno_t a, first, last, next;
- first = ALLOCNO_FIRST_COALESCED_ALLOCNO (a1);
- a = ALLOCNO_FIRST_COALESCED_ALLOCNO (a2);
+ first = ALLOCNO_COALESCE_DATA (a1)->first;
+ a = ALLOCNO_COALESCE_DATA (a2)->first;
if (first == a)
return;
- for (last = a2, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (last = a2, a = ALLOCNO_COALESCE_DATA (a2)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = first;
+ ALLOCNO_COALESCE_DATA (a)->first = first;
if (a == a2)
break;
last = a;
}
- next = ALLOCNO_NEXT_COALESCED_ALLOCNO (first);
- ALLOCNO_NEXT_COALESCED_ALLOCNO (first) = a2;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (last) = next;
+ next = allocno_coalesce_data[ALLOCNO_NUM (first)].next;
+ allocno_coalesce_data[ALLOCNO_NUM (first)].next = a2;
+ allocno_coalesce_data[ALLOCNO_NUM (last)].next = next;
}
/* Return TRUE if there are conflicting allocnos from two sets of
@@ -2790,19 +2961,19 @@ coalesced_allocno_conflict_p (ira_allocn
if (allocno_coalesced_p)
{
bitmap_clear (processed_coalesced_allocno_bitmap);
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (a = ALLOCNO_COALESCE_DATA (a1)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
if (a == a1)
break;
}
}
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (a = ALLOCNO_COALESCE_DATA (a2)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
- for (conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
- conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_a))
+ for (conflict_a = ALLOCNO_COALESCE_DATA (a1)->next;;
+ conflict_a = ALLOCNO_COALESCE_DATA (conflict_a)->next)
{
if (allocnos_have_intersected_live_ranges_p (a, conflict_a))
return true;
@@ -2890,8 +3061,8 @@ coalesce_allocnos (void)
for (n = 0; i < cp_num; i++)
{
cp = sorted_copies[i];
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->first)
- != ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->second))
+ if (allocno_coalesce_data[ALLOCNO_NUM (cp->first)].first
+ != allocno_coalesce_data[ALLOCNO_NUM (cp->second)].first)
sorted_copies[n++] = cp;
}
cp_num = n;
@@ -2989,18 +3160,18 @@ setup_coalesced_allocno_costs_and_nums (
regno_coalesced_allocno_num[regno] = ++num;
continue;
}
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno)
+ if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
continue;
num++;
- for (cost = 0, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (cost = 0, a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
cost += ALLOCNO_FREQ (a);
if (a == allocno)
break;
}
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
regno_coalesced_allocno_num[ALLOCNO_REGNO (a)] = num;
regno_coalesced_allocno_cost[ALLOCNO_REGNO (a)] = cost;
@@ -3027,7 +3198,7 @@ collect_spilled_coalesced_allocnos (int
regno = pseudo_regnos[i];
allocno = ira_regno_allocno_map[regno];
if (allocno == NULL || ALLOCNO_HARD_REGNO (allocno) >= 0
- || ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno)
+ || ALLOCNO_COALESCE_DATA (allocno)->first != allocno)
continue;
spilled_coalesced_allocnos[num++] = allocno;
}
@@ -3047,8 +3218,8 @@ slot_coalesced_allocno_live_ranges_inter
{
ira_allocno_t a;
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
if (ira_allocno_live_ranges_intersect_p
(slot_coalesced_allocnos_live_ranges[n], ALLOCNO_LIVE_RANGES (a)))
@@ -3068,9 +3239,9 @@ setup_slot_coalesced_allocno_live_ranges
ira_allocno_t a;
live_range_t r;
- n = ALLOCNO_TEMP (allocno);
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ n = ALLOCNO_COALESCE_DATA (allocno)->temp;
+ for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
slot_coalesced_allocnos_live_ranges[n]
@@ -3104,7 +3275,7 @@ coalesce_spill_slots (ira_allocno_t *spi
for (i = 0; i < num; i++)
{
allocno = spilled_coalesced_allocnos[i];
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
+ if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
|| bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (allocno))
|| (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
&& (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
@@ -3113,8 +3284,8 @@ coalesce_spill_slots (ira_allocno_t *spi
for (j = 0; j < i; j++)
{
a = spilled_coalesced_allocnos[j];
- n = ALLOCNO_TEMP (a);
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
+ n = ALLOCNO_COALESCE_DATA (a)->temp;
+ if (ALLOCNO_COALESCE_DATA (a)->first == a
&& ! bitmap_bit_p (set_jump_crosses, ALLOCNO_REGNO (a))
&& (ALLOCNO_REGNO (a) >= ira_reg_equiv_len
|| (! ira_reg_equiv_invariant_p[ALLOCNO_REGNO (a)]
@@ -3126,7 +3297,7 @@ coalesce_spill_slots (ira_allocno_t *spi
{
/* No coalescing: set up number for coalesced allocnos
represented by ALLOCNO. */
- ALLOCNO_TEMP (allocno) = last_coalesced_allocno_num++;
+ ALLOCNO_COALESCE_DATA (allocno)->temp = last_coalesced_allocno_num++;
setup_slot_coalesced_allocno_live_ranges (allocno);
}
else
@@ -3138,10 +3309,11 @@ coalesce_spill_slots (ira_allocno_t *spi
" Coalescing spilled allocnos a%dr%d->a%dr%d\n",
ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno),
ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
- ALLOCNO_TEMP (allocno) = ALLOCNO_TEMP (a);
+ ALLOCNO_COALESCE_DATA (allocno)->temp
+ = ALLOCNO_COALESCE_DATA (a)->temp;
setup_slot_coalesced_allocno_live_ranges (allocno);
merge_allocnos (a, allocno);
- ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a);
+ ira_assert (ALLOCNO_COALESCE_DATA (a)->first == a);
}
}
for (i = 0; i < ira_allocnos_num; i++)
@@ -3163,6 +3335,7 @@ ira_sort_regnos_for_alter_reg (int *pseu
int max_regno = max_reg_num ();
int i, regno, num, slot_num;
ira_allocno_t allocno, a;
+ ira_allocno_iterator ai;
ira_allocno_t *spilled_coalesced_allocnos;
/* Set up allocnos can be coalesced. */
@@ -3176,6 +3349,16 @@ ira_sort_regnos_for_alter_reg (int *pseu
}
allocno_coalesced_p = false;
processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
+ allocno_coalesce_data
+ = (coalesce_data_t) ira_allocate (sizeof (struct coalesce_data)
+ * ira_allocnos_num);
+ /* Initialize coalesce data for allocnos. */
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ ALLOCNO_ADD_DATA (a) = allocno_coalesce_data + ALLOCNO_NUM (a);
+ ALLOCNO_COALESCE_DATA (a)->first = a;
+ ALLOCNO_COALESCE_DATA (a)->next = a;
+ }
coalesce_allocnos ();
ira_free_bitmap (coloring_allocno_bitmap);
regno_coalesced_allocno_cost
@@ -3213,7 +3396,7 @@ ira_sort_regnos_for_alter_reg (int *pseu
for (i = 0; i < num; i++)
{
allocno = spilled_coalesced_allocnos[i];
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno
+ if (ALLOCNO_COALESCE_DATA (allocno)->first != allocno
|| ALLOCNO_HARD_REGNO (allocno) >= 0
|| (ALLOCNO_REGNO (allocno) < ira_reg_equiv_len
&& (ira_reg_equiv_const[ALLOCNO_REGNO (allocno)] != NULL_RTX
@@ -3222,8 +3405,8 @@ ira_sort_regnos_for_alter_reg (int *pseu
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Slot %d (freq,size):", slot_num);
slot_num++;
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ for (a = ALLOCNO_COALESCE_DATA (allocno)->next;;
+ a = ALLOCNO_COALESCE_DATA (a)->next)
{
ira_assert (ALLOCNO_HARD_REGNO (a) < 0);
ALLOCNO_HARD_REGNO (a) = -slot_num;
@@ -3244,6 +3427,9 @@ ira_sort_regnos_for_alter_reg (int *pseu
/* Sort regnos according the slot numbers. */
regno_max_ref_width = reg_max_ref_width;
qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare);
+ FOR_EACH_ALLOCNO (a, ai)
+ ALLOCNO_ADD_DATA (a) = NULL;
+ ira_free (allocno_coalesce_data);
ira_free (regno_coalesced_allocno_num);
ira_free (regno_coalesced_allocno_cost);
}
@@ -68,6 +68,7 @@ static bool
build_conflict_bit_table (void)
{
int i, num, id, allocated_words_num, conflict_bit_vec_words_num;
+ int a_min, a_max;
unsigned int j;
enum reg_class aclass;
ira_allocno_t allocno, live_a;
@@ -75,6 +76,7 @@ build_conflict_bit_table (void)
ira_allocno_iterator ai;
sparseset allocnos_live;
int allocno_set_words;
+ IRA_INT_TYPE *a_conflicts;
allocno_set_words = (ira_allocnos_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
allocated_words_num = 0;
@@ -132,6 +134,9 @@ build_conflict_bit_table (void)
allocno = r->allocno;
num = ALLOCNO_NUM (allocno);
id = ALLOCNO_CONFLICT_ID (allocno);
+ a_min = ALLOCNO_MIN (allocno);
+ a_max = ALLOCNO_MAX (allocno);
+ a_conflicts = conflicts[num];
aclass = ALLOCNO_CLASS (allocno);
sparseset_set_bit (allocnos_live, num);
EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
@@ -142,10 +147,9 @@ build_conflict_bit_table (void)
/* Don't set up conflict for the allocno with itself. */
&& num != (int) j)
{
- SET_MINMAX_SET_BIT (conflicts[num],
+ SET_MINMAX_SET_BIT (a_conflicts,
ALLOCNO_CONFLICT_ID (live_a),
- ALLOCNO_MIN (allocno),
- ALLOCNO_MAX (allocno));
+ a_min, a_max);
SET_MINMAX_SET_BIT (conflicts[j], id,
ALLOCNO_MIN (live_a),
ALLOCNO_MAX (live_a));
@@ -378,7 +382,8 @@ process_regs_for_copy (rtx reg1, rtx reg
}
else
return false;
- if (! IN_RANGE (allocno_preferenced_hard_regno, 0, FIRST_PSEUDO_REGISTER - 1))
+ if (! IN_RANGE (allocno_preferenced_hard_regno,
+ 0, FIRST_PSEUDO_REGISTER - 1))
/* Can not be tied. */
return false;
rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
@@ -392,10 +397,11 @@ process_regs_for_copy (rtx reg1, rtx reg
if (index < 0)
/* Can not be tied. It is not in the allocno class. */
return false;
+ ira_init_register_move_cost_if_necessary (mode);
if (HARD_REGISTER_P (reg1))
- cost = ira_get_register_move_cost (mode, aclass, rclass) * freq;
+ cost = ira_register_move_cost[mode][aclass][rclass] * freq;
else
- cost = ira_get_register_move_cost (mode, rclass, aclass) * freq;
+ cost = ira_register_move_cost[mode][rclass][aclass] * freq;
do
{
ira_allocate_and_set_costs
@@ -459,7 +465,8 @@ add_insn_allocno_copies (rtx insn)
? SET_SRC (set)
: SUBREG_REG (SET_SRC (set))) != NULL_RTX)
{
- process_regs_for_copy (SET_DEST (set), SET_SRC (set), false, insn, freq);
+ process_regs_for_copy (SET_DEST (set), SET_SRC (set),
+ false, insn, freq);
return;
}
/* Fast check of possibility of constraint or shuffle copies. If
@@ -555,12 +562,13 @@ static ira_allocno_t *collected_conflict
static void
build_allocno_conflicts (ira_allocno_t a)
{
- int i, px, parent_num;
+ int i, px;
int conflict_bit_vec_words_num;
ira_allocno_t parent_a, another_a, another_parent_a;
ira_allocno_t *vec;
- IRA_INT_TYPE *allocno_conflicts;
+ IRA_INT_TYPE *allocno_conflicts, *parent_conflicts;
minmax_set_iterator asi;
+ int parent_min, parent_max;
allocno_conflicts = conflicts[ALLOCNO_NUM (a)];
px = 0;
@@ -596,7 +604,9 @@ build_allocno_conflicts (ira_allocno_t a
if (parent_a == NULL)
return;
ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a));
- parent_num = ALLOCNO_NUM (parent_a);
+ parent_conflicts = conflicts[ALLOCNO_NUM (parent_a)];
+ parent_min = ALLOCNO_MIN (parent_a);
+ parent_max = ALLOCNO_MAX (parent_a);
FOR_EACH_BIT_IN_MINMAX_SET (allocno_conflicts,
ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi)
{
@@ -609,10 +619,9 @@ build_allocno_conflicts (ira_allocno_t a
ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
ira_assert (ALLOCNO_CLASS (another_a)
== ALLOCNO_CLASS (another_parent_a));
- SET_MINMAX_SET_BIT (conflicts[parent_num],
+ SET_MINMAX_SET_BIT (parent_conflicts,
ALLOCNO_CONFLICT_ID (another_parent_a),
- ALLOCNO_MIN (parent_a),
- ALLOCNO_MAX (parent_a));
+ parent_min, parent_max);
}
}
@@ -492,30 +492,56 @@ record_reg_classes (int n_alts, int n_op
Moreover, if we cannot tie them, this alternative
needs to do a copy, which is one insn. */
struct costs *pp = this_op_costs[i];
+ int *pp_costs = pp->cost;
cost_classes_t cost_classes_ptr = regno_cost_classes[REGNO (op)];
enum reg_class *cost_classes = cost_classes_ptr->classes;
+ bool in_p = recog_data.operand_type[i] != OP_OUT;
+ bool out_p = recog_data.operand_type[i] != OP_IN;
+ enum reg_class op_class = classes[i];
+ move_table *move_in_cost, *move_out_cost;
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ ira_init_register_move_cost_if_necessary (mode);
+ if (! in_p)
{
- rclass = cost_classes[k];
- pp->cost[k]
- = (((recog_data.operand_type[i] != OP_OUT
- ? ira_get_may_move_cost (mode, rclass,
- classes[i], true) : 0)
- + (recog_data.operand_type[i] != OP_IN
- ? ira_get_may_move_cost (mode, rclass,
- classes[i], false) : 0))
- * frequency);
+ ira_assert (out_p);
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_out_cost[op_class][rclass] * frequency;
+ }
+ }
+ else if (! out_p)
+ {
+ ira_assert (in_p);
+ move_in_cost = ira_may_move_in_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_in_cost[rclass][op_class] * frequency;
+ }
+ }
+ else
+ {
+ move_in_cost = ira_may_move_in_cost[mode];
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((move_in_cost[rclass][op_class]
+ + move_out_cost[op_class][rclass])
+ * frequency);
+ }
}
/* If the alternative actually allows memory, make
things a bit cheaper since we won't need an extra
insn to load it. */
pp->mem_cost
- = ((recog_data.operand_type[i] != OP_IN
- ? ira_memory_move_cost[mode][classes[i]][0] : 0)
- + (recog_data.operand_type[i] != OP_OUT
- ? ira_memory_move_cost[mode][classes[i]][1] : 0)
+ = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
+ + (in_p ? ira_memory_move_cost[mode][op_class][1] : 0)
- allows_mem[i]) * frequency;
/* If we have assigned a class to this allocno in
@@ -528,17 +554,15 @@ record_reg_classes (int n_alts, int n_op
if (pref_class == NO_REGS)
alt_cost
- += ((recog_data.operand_type[i] != OP_IN
- ? ira_memory_move_cost[mode][classes[i]][0]
- : 0)
- + (recog_data.operand_type[i] != OP_OUT
- ? ira_memory_move_cost[mode][classes[i]][1]
+ += ((out_p
+ ? ira_memory_move_cost[mode][op_class][0] : 0)
+ + (in_p
+ ? ira_memory_move_cost[mode][op_class][1]
: 0));
else if (ira_reg_class_intersect
- [pref_class][classes[i]] == NO_REGS)
- alt_cost += ira_get_register_move_cost (mode,
- pref_class,
- classes[i]);
+ [pref_class][op_class] == NO_REGS)
+ alt_cost
+ += ira_register_move_cost[mode][pref_class][op_class];
}
if (REGNO (ops[i]) != REGNO (ops[j])
&& ! find_reg_note (insn, REG_DEAD, op))
@@ -734,30 +758,56 @@ record_reg_classes (int n_alts, int n_op
else
{
struct costs *pp = this_op_costs[i];
+ int *pp_costs = pp->cost;
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
enum reg_class *cost_classes = cost_classes_ptr->classes;
+ bool in_p = recog_data.operand_type[i] != OP_OUT;
+ bool out_p = recog_data.operand_type[i] != OP_IN;
+ enum reg_class op_class = classes[i];
+ move_table *move_in_cost, *move_out_cost;
- for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ ira_init_register_move_cost_if_necessary (mode);
+ if (! in_p)
{
- rclass = cost_classes[k];
- pp->cost[k]
- = (((recog_data.operand_type[i] != OP_OUT
- ? ira_get_may_move_cost (mode, rclass,
- classes[i], true) : 0)
- + (recog_data.operand_type[i] != OP_IN
- ? ira_get_may_move_cost (mode, classes[i],
- rclass, false) : 0))
- * frequency);
+ ira_assert (out_p);
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_out_cost[op_class][rclass] * frequency;
+ }
+ }
+ else if (! out_p)
+ {
+ ira_assert (in_p);
+ move_in_cost = ira_may_move_in_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k]
+ = move_in_cost[rclass][op_class] * frequency;
+ }
+ }
+ else
+ {
+ move_in_cost = ira_may_move_in_cost[mode];
+ move_out_cost = ira_may_move_out_cost[mode];
+ for (k = cost_classes_ptr->num - 1; k >= 0; k--)
+ {
+ rclass = cost_classes[k];
+ pp_costs[k] = ((move_in_cost[rclass][op_class]
+ + move_out_cost[op_class][rclass])
+ * frequency);
+ }
}
/* If the alternative actually allows memory, make
things a bit cheaper since we won't need an extra
insn to load it. */
pp->mem_cost
- = ((recog_data.operand_type[i] != OP_IN
- ? ira_memory_move_cost[mode][classes[i]][0] : 0)
- + (recog_data.operand_type[i] != OP_OUT
- ? ira_memory_move_cost[mode][classes[i]][1] : 0)
+ = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0)
+ + (in_p ? ira_memory_move_cost[mode][op_class][1] : 0)
- allows_mem[i]) * frequency;
/* If we have assigned a class to this allocno in
our first pass, add a cost to this alternative
@@ -769,17 +819,14 @@ record_reg_classes (int n_alts, int n_op
if (pref_class == NO_REGS)
alt_cost
- += ((recog_data.operand_type[i] != OP_IN
- ? ira_memory_move_cost[mode][classes[i]][0]
- : 0)
- + (recog_data.operand_type[i] != OP_OUT
- ? ira_memory_move_cost[mode][classes[i]][1]
+ += ((out_p
+ ? ira_memory_move_cost[mode][op_class][0] : 0)
+ + (in_p
+ ? ira_memory_move_cost[mode][op_class][1]
: 0));
- else if (ira_reg_class_intersect[pref_class][classes[i]]
+ else if (ira_reg_class_intersect[pref_class][op_class]
== NO_REGS)
- alt_cost += ira_get_register_move_cost (mode,
- pref_class,
- classes[i]);
+ alt_cost += ira_register_move_cost[mode][pref_class][op_class];
}
}
}
@@ -822,6 +869,7 @@ record_reg_classes (int n_alts, int n_op
if (REG_P (ops[i]) && (regno = REGNO (ops[i])) >= FIRST_PSEUDO_REGISTER)
{
struct costs *pp = op_costs[i], *qq = this_op_costs[i];
+ int *pp_costs = pp->cost, *qq_costs = qq->cost;
int scale = 1 + (recog_data.operand_type[i] == OP_INOUT);
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
@@ -829,8 +877,8 @@ record_reg_classes (int n_alts, int n_op
(qq->mem_cost + op_cost_add) * scale);
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
- pp->cost[k]
- = MIN (pp->cost[k], (qq->cost[k] + op_cost_add) * scale);
+ pp_costs[k]
+ = MIN (pp_costs[k], (qq_costs[k] + op_cost_add) * scale);
}
}
@@ -1084,10 +1132,12 @@ record_address_regs (enum machine_mode m
case REG:
{
struct costs *pp;
+ int *pp_costs;
enum reg_class i;
int k, regno, add_cost;
cost_classes_t cost_classes_ptr;
enum reg_class *cost_classes;
+ move_table *move_in_cost;
if ((regno = REGNO (x)) < FIRST_PSEUDO_REGISTER)
break;
@@ -1102,14 +1152,17 @@ record_address_regs (enum machine_mode m
pp->mem_cost += add_cost;
cost_classes_ptr = regno_cost_classes[regno];
cost_classes = cost_classes_ptr->classes;
+ pp_costs = pp->cost;
+ ira_init_register_move_cost_if_necessary (Pmode);
+ move_in_cost = ira_may_move_in_cost[Pmode];
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
{
i = cost_classes[k];
- add_cost = (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2;
- if (INT_MAX - add_cost < pp->cost[k])
- pp->cost[k] = INT_MAX;
+ add_cost = (move_in_cost[i][rclass] * scale) / 2;
+ if (INT_MAX - add_cost < pp_costs[k])
+ pp_costs[k] = INT_MAX;
else
- pp->cost[k] += add_cost;
+ pp_costs[k] += add_cost;
}
}
break;
@@ -1240,6 +1293,7 @@ scan_one_insn (rtx insn)
{
struct costs *p = COSTS (costs, COST_INDEX (regno));
struct costs *q = op_costs[i];
+ int *p_costs = p->cost, *q_costs = q->cost;
cost_classes_t cost_classes_ptr = regno_cost_classes[regno];
int add_cost;
@@ -1250,11 +1304,11 @@ scan_one_insn (rtx insn)
p->mem_cost += add_cost;
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
{
- add_cost = q->cost[k];
- if (add_cost > 0 && INT_MAX - add_cost < p->cost[k])
- p->cost[k] = INT_MAX;
+ add_cost = q_costs[k];
+ if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
+ p_costs[k] = INT_MAX;
else
- p->cost[k] += add_cost;
+ p_costs[k] += add_cost;
}
}
@@ -1497,6 +1551,8 @@ find_costs_and_classes (FILE *dump_file)
#endif
cost_classes_t cost_classes_ptr = regno_cost_classes[i];
enum reg_class *cost_classes = cost_classes_ptr->classes;
+ int *i_costs = temp_costs->cost;
+ int i_mem_cost;
int equiv_savings = regno_equiv_gains[i];
if (! allocno_p)
@@ -1507,17 +1563,21 @@ find_costs_and_classes (FILE *dump_file)
inc_dec_p = in_inc_dec[i];
#endif
memcpy (temp_costs, COSTS (costs, i), struct_costs_size);
+ i_mem_cost = temp_costs->mem_cost;
}
else
{
if (ira_regno_allocno_map[i] == NULL)
continue;
memset (temp_costs, 0, struct_costs_size);
+ i_mem_cost = 0;
/* Find cost of all allocnos with the same regno. */
for (a = ira_regno_allocno_map[i];
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
+ int *a_costs, *p_costs;
+
a_num = ALLOCNO_NUM (a);
if ((flag_ira_region == IRA_REGION_ALL
|| flag_ira_region == IRA_REGION_MIXED)
@@ -1531,14 +1591,15 @@ find_costs_and_classes (FILE *dump_file)
/* Propagate costs to upper levels in the region
tree. */
parent_a_num = ALLOCNO_NUM (parent_a);
+ a_costs = COSTS (total_allocno_costs, a_num)->cost;
+ p_costs = COSTS (total_allocno_costs, parent_a_num)->cost;
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
{
- add_cost = COSTS (total_allocno_costs, a_num)->cost[k];
- if (add_cost > 0 && INT_MAX - add_cost
- < COSTS (total_allocno_costs, parent_a_num)->cost[k])
- COSTS (total_allocno_costs, parent_a_num)->cost[k] = INT_MAX;
+ add_cost = a_costs[k];
+ if (add_cost > 0 && INT_MAX - add_cost < p_costs[k])
+ p_costs[k] = INT_MAX;
else
- COSTS (total_allocno_costs, parent_a_num)->cost[k] += add_cost;
+ p_costs[k] += add_cost;
}
add_cost = COSTS (total_allocno_costs, a_num)->mem_cost;
if (add_cost > 0
@@ -1552,19 +1613,20 @@ find_costs_and_classes (FILE *dump_file)
+= add_cost;
}
+ a_costs = COSTS (costs, a_num)->cost;
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
{
- add_cost = COSTS (total_allocno_costs, a_num)->cost[k];
- if (add_cost > 0 && INT_MAX - add_cost < temp_costs->cost[k])
- temp_costs->cost[k] = INT_MAX;
+ add_cost = a_costs[k];
+ if (add_cost > 0 && INT_MAX - add_cost < i_costs[k])
+ i_costs[k] = INT_MAX;
else
- temp_costs->cost[k] += add_cost;
+ i_costs[k] += add_cost;
}
add_cost = COSTS (costs, a_num)->mem_cost;
- if (add_cost && INT_MAX - add_cost < temp_costs->mem_cost)
- temp_costs->mem_cost = INT_MAX;
+ if (add_cost && INT_MAX - add_cost < i_mem_cost)
+ i_mem_cost = INT_MAX;
else
- temp_costs->mem_cost += add_cost;
+ i_mem_cost += add_cost;
#ifdef FORBIDDEN_INC_DEC_CLASSES
if (in_inc_dec[a_num])
inc_dec_p = true;
@@ -1577,7 +1639,7 @@ find_costs_and_classes (FILE *dump_file)
{
temp_costs->mem_cost = 0;
for (k = cost_classes_ptr->num - 1; k >= 0; k--)
- temp_costs->cost[k] += equiv_savings;
+ i_costs[k] += equiv_savings;
}
best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
@@ -1600,21 +1662,21 @@ find_costs_and_classes (FILE *dump_file)
#endif
)
continue;
- if (temp_costs->cost[k] < best_cost)
+ if (i_costs[k] < best_cost)
{
- best_cost = temp_costs->cost[k];
+ best_cost = i_costs[k];
best = (enum reg_class) rclass;
}
- else if (temp_costs->cost[k] == best_cost)
+ else if (i_costs[k] == best_cost)
best = ira_reg_class_subunion[best][rclass];
if (pass == flag_expensive_optimizations
- && temp_costs->cost[k] < temp_costs->mem_cost
+ && i_costs[k] < i_mem_cost
&& (reg_class_size[reg_class_subunion[alt_class][rclass]]
> reg_class_size[alt_class]))
alt_class = reg_class_subunion[alt_class][rclass];
}
alt_class = ira_allocno_class_translate[alt_class];
- if (best_cost > temp_costs->mem_cost)
+ if (best_cost > i_mem_cost)
regno_aclass[i] = NO_REGS;
else
{
@@ -1627,7 +1689,7 @@ find_costs_and_classes (FILE *dump_file)
}
if (pass == flag_expensive_optimizations)
{
- if (best_cost > temp_costs->mem_cost)
+ if (best_cost > i_mem_cost)
best = alt_class = NO_REGS;
else if (best == alt_class)
alt_class = NO_REGS;
@@ -1642,7 +1704,7 @@ find_costs_and_classes (FILE *dump_file)
regno_best_class[i] = best;
if (! allocno_p)
{
- pref[i] = best_cost > temp_costs->mem_cost ? NO_REGS : best;
+ pref[i] = best_cost > i_mem_cost ? NO_REGS : best;
continue;
}
for (a = ira_regno_allocno_map[i];
@@ -1654,6 +1716,9 @@ find_costs_and_classes (FILE *dump_file)
best = NO_REGS;
else
{
+ int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost;
+ int *a_costs = COSTS (costs, a_num)->cost;
+
/* Finding best class which is subset of the common
class. */
best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1;
@@ -1677,16 +1742,16 @@ find_costs_and_classes (FILE *dump_file)
#endif
)
;
- else if (COSTS (total_allocno_costs, a_num)->cost[k] < best_cost)
+ else if (total_a_costs[k] < best_cost)
{
- best_cost = COSTS (total_allocno_costs, a_num)->cost[k];
- allocno_cost = COSTS (costs, a_num)->cost[k];
+ best_cost = total_a_costs[k];
+ allocno_cost = a_costs[k];
best = (enum reg_class) rclass;
}
- else if (COSTS (total_allocno_costs, a_num)->cost[k] == best_cost)
+ else if (total_a_costs[k] == best_cost)
{
best = ira_reg_class_subunion[best][rclass];
- allocno_cost = MAX (allocno_cost, COSTS (costs, a_num)->cost[k]);
+ allocno_cost = MAX (allocno_cost, a_costs[k]);
}
}
ALLOCNO_CLASS_COST (a) = allocno_cost;
@@ -1784,9 +1849,10 @@ process_bb_node_for_hard_reg_moves (ira_
continue;
mode = ALLOCNO_MODE (a);
hard_reg_class = REGNO_REG_CLASS (hard_regno);
+ ira_init_register_move_cost_if_necessary (mode);
cost
- = (to_p ? ira_get_register_move_cost (mode, hard_reg_class, rclass)
- : ira_get_register_move_cost (mode, rclass, hard_reg_class)) * freq;
+ = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass]
+ : ira_register_move_cost[mode][rclass][hard_reg_class]) * freq;
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
ALLOCNO_CLASS_COST (a));
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
@@ -44,6 +44,73 @@ along with GCC; see the file COPYING3.
#include "ira-int.h"
+/* Data used to emit live range split insns and to flattening IR. */
+ira_emit_data_t ira_allocno_emit_data;
+
+/* Definitions for vectors of pointers. */
+typedef void *void_p;
+DEF_VEC_P (void_p);
+DEF_VEC_ALLOC_P (void_p,heap);
+
+/* Pointers to data allocated for allocnos being created during
+ emitting. Usually there are quite few such allocnos because they
+ are created only for resolving loop in register shuffling. */
+static VEC(void_p, heap) *new_allocno_emit_data_vec;
+
+/* Allocate and initiate the emit data. */
+void
+ira_initiate_emit_data (void)
+{
+ ira_allocno_t a;
+ ira_allocno_iterator ai;
+
+ ira_allocno_emit_data
+ = (ira_emit_data_t) ira_allocate (ira_allocnos_num
+ * sizeof (struct ira_emit_data));
+ memset (ira_allocno_emit_data, 0,
+ ira_allocnos_num * sizeof (struct ira_emit_data));
+ FOR_EACH_ALLOCNO (a, ai)
+ ALLOCNO_ADD_DATA (a) = ira_allocno_emit_data + ALLOCNO_NUM (a);
+ new_allocno_emit_data_vec = VEC_alloc (void_p, heap, 50);
+
+}
+
+/* Free the emit data. */
+void
+ira_finish_emit_data (void)
+{
+ void_p p;
+ ira_allocno_t a;
+ ira_allocno_iterator ai;
+
+ ira_free (ira_allocno_emit_data);
+ FOR_EACH_ALLOCNO (a, ai)
+ ALLOCNO_ADD_DATA (a) = NULL;
+ for (;VEC_length (void_p, new_allocno_emit_data_vec) != 0;)
+ {
+ p = VEC_pop (void_p, new_allocno_emit_data_vec);
+ ira_free (p);
+ }
+ VEC_free (void_p, heap, new_allocno_emit_data_vec);
+}
+
+/* Create and return a new allocno with given REGNO and
+ LOOP_TREE_NODE. Allocate emit data for it. */
+static ira_allocno_t
+create_new_allocno (int regno, ira_loop_tree_node_t loop_tree_node)
+{
+ ira_allocno_t a;
+
+ a = ira_create_allocno (regno, false, loop_tree_node);
+ ALLOCNO_ADD_DATA (a) = ira_allocate (sizeof (struct ira_emit_data));
+ memset (ALLOCNO_ADD_DATA (a), 0, sizeof (struct ira_emit_data));
+ VEC_safe_push (void_p, heap, new_allocno_emit_data_vec, ALLOCNO_ADD_DATA (a));
+ return a;
+}
+
+
+
+/* See comments below. */
typedef struct move *move_t;
/* The structure represents an allocno move. Both allocnos have the
@@ -171,7 +238,7 @@ change_regs (rtx *loc)
return false;
if (ira_curr_regno_allocno_map[regno] == NULL)
return false;
- reg = ALLOCNO_REG (ira_curr_regno_allocno_map[regno]);
+ reg = ALLOCNO_EMIT_DATA (ira_curr_regno_allocno_map[regno])->reg;
if (reg == *loc)
return false;
*loc = reg;
@@ -258,9 +325,9 @@ set_allocno_reg (ira_allocno_t allocno,
a != NULL;
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
if (subloop_tree_node_p (ALLOCNO_LOOP_TREE_NODE (a), node))
- ALLOCNO_REG (a) = reg;
+ ALLOCNO_EMIT_DATA (a)->reg = reg;
for (a = ALLOCNO_CAP (allocno); a != NULL; a = ALLOCNO_CAP (a))
- ALLOCNO_REG (a) = reg;
+ ALLOCNO_EMIT_DATA (a)->reg = reg;
regno = ALLOCNO_REGNO (allocno);
for (a = allocno;;)
{
@@ -273,9 +340,9 @@ set_allocno_reg (ira_allocno_t allocno,
}
if (a == NULL)
continue;
- if (ALLOCNO_CHILD_RENAMED_P (a))
+ if (ALLOCNO_EMIT_DATA (a)->child_renamed_p)
break;
- ALLOCNO_CHILD_RENAMED_P (a) = true;
+ ALLOCNO_EMIT_DATA (a)->child_renamed_p = true;
}
}
@@ -346,14 +413,14 @@ store_can_be_removed_p (ira_allocno_t sr
ira_assert (ALLOCNO_CAP_MEMBER (src_allocno) == NULL
&& ALLOCNO_CAP_MEMBER (dest_allocno) == NULL);
orig_regno = ALLOCNO_REGNO (src_allocno);
- regno = REGNO (ALLOCNO_REG (dest_allocno));
+ regno = REGNO (ALLOCNO_EMIT_DATA (dest_allocno)->reg);
for (node = ALLOCNO_LOOP_TREE_NODE (src_allocno);
node != NULL;
node = node->parent)
{
a = node->regno_allocno_map[orig_regno];
ira_assert (a != NULL);
- if (REGNO (ALLOCNO_REG (a)) == (unsigned) regno)
+ if (REGNO (ALLOCNO_EMIT_DATA (a)->reg) == (unsigned) regno)
/* We achieved the destination and everything is ok. */
return true;
else if (bitmap_bit_p (node->modified_regnos, orig_regno))
@@ -397,8 +464,8 @@ generate_edge_moves (edge e)
{
src_allocno = src_map[regno];
dest_allocno = dest_map[regno];
- if (REGNO (ALLOCNO_REG (src_allocno))
- == REGNO (ALLOCNO_REG (dest_allocno)))
+ if (REGNO (ALLOCNO_EMIT_DATA (src_allocno)->reg)
+ == REGNO (ALLOCNO_EMIT_DATA (dest_allocno)->reg))
continue;
/* Remove unnecessary stores at the region exit. We should do
this for readonly memory for sure and this is guaranteed by
@@ -409,8 +476,8 @@ generate_edge_moves (edge e)
&& ALLOCNO_HARD_REGNO (src_allocno) >= 0
&& store_can_be_removed_p (src_allocno, dest_allocno))
{
- ALLOCNO_MEM_OPTIMIZED_DEST (src_allocno) = dest_allocno;
- ALLOCNO_MEM_OPTIMIZED_DEST_P (dest_allocno) = true;
+ ALLOCNO_EMIT_DATA (src_allocno)->mem_optimized_dest = dest_allocno;
+ ALLOCNO_EMIT_DATA (dest_allocno)->mem_optimized_dest_p = true;
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Remove r%d:a%d->a%d(mem)\n",
regno, ALLOCNO_NUM (src_allocno),
@@ -500,9 +567,10 @@ change_loop (ira_loop_tree_node_t node)
|| ira_reg_equiv_invariant_p[regno]
|| ira_reg_equiv_const[regno] != NULL_RTX))
continue;
- original_reg = ALLOCNO_REG (allocno);
+ original_reg = ALLOCNO_EMIT_DATA (allocno)->reg;
if (parent_allocno == NULL
- || REGNO (ALLOCNO_REG (parent_allocno)) == REGNO (original_reg))
+ || (REGNO (ALLOCNO_EMIT_DATA (parent_allocno)->reg)
+ == REGNO (original_reg)))
{
if (internal_flag_ira_verbose > 3 && ira_dump_file)
fprintf (ira_dump_file, " %i vs parent %i:",
@@ -526,11 +594,12 @@ change_loop (ira_loop_tree_node_t node)
continue;
used_p = bitmap_bit_p (used_regno_bitmap, regno);
bitmap_set_bit (used_regno_bitmap, regno);
- ALLOCNO_SOMEWHERE_RENAMED_P (allocno) = true;
+ ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
if (! used_p)
continue;
bitmap_set_bit (renamed_regno_bitmap, regno);
- set_allocno_reg (allocno, create_new_reg (ALLOCNO_REG (allocno)));
+ set_allocno_reg (allocno,
+ create_new_reg (ALLOCNO_EMIT_DATA (allocno)->reg));
}
}
@@ -546,8 +615,8 @@ set_allocno_somewhere_renamed_p (void)
{
regno = ALLOCNO_REGNO (allocno);
if (bitmap_bit_p (renamed_regno_bitmap, regno)
- && REGNO (ALLOCNO_REG (allocno)) == regno)
- ALLOCNO_SOMEWHERE_RENAMED_P (allocno) = true;
+ && REGNO (ALLOCNO_EMIT_DATA (allocno)->reg) == regno)
+ ALLOCNO_EMIT_DATA (allocno)->somewhere_renamed_p = true;
}
}
@@ -724,15 +793,15 @@ modify_move_list (move_t list)
subsequent IRA internal representation
flattening. */
new_allocno
- = ira_create_allocno (ALLOCNO_REGNO (set_move->to), false,
+ = create_new_allocno (ALLOCNO_REGNO (set_move->to),
ALLOCNO_LOOP_TREE_NODE (set_move->to));
ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
- ira_set_allocno_class
- (new_allocno, ALLOCNO_CLASS (set_move->to));
+ ira_set_allocno_class (new_allocno,
+ ALLOCNO_CLASS (set_move->to));
ALLOCNO_ASSIGNED_P (new_allocno) = true;
ALLOCNO_HARD_REGNO (new_allocno) = -1;
- ALLOCNO_REG (new_allocno)
- = create_new_reg (ALLOCNO_REG (set_move->to));
+ ALLOCNO_EMIT_DATA (new_allocno)->reg
+ = create_new_reg (ALLOCNO_EMIT_DATA (set_move->to)->reg);
ALLOCNO_CONFLICT_ID (new_allocno) = ALLOCNO_NUM (new_allocno);
/* Make it possibly conflicting with all earlier
created allocnos. Cases where temporary allocnos
@@ -747,7 +816,7 @@ modify_move_list (move_t list)
fprintf (ira_dump_file,
" Creating temporary allocno a%dr%d\n",
ALLOCNO_NUM (new_allocno),
- REGNO (ALLOCNO_REG (new_allocno)));
+ REGNO (ALLOCNO_EMIT_DATA (new_allocno)->reg));
}
}
if ((hard_regno = ALLOCNO_HARD_REGNO (to)) < 0)
@@ -783,7 +852,8 @@ emit_move_list (move_t list, int freq)
for (; list != NULL; list = list->next)
{
start_sequence ();
- emit_move_insn (ALLOCNO_REG (list->to), ALLOCNO_REG (list->from));
+ emit_move_insn (ALLOCNO_EMIT_DATA (list->to)->reg,
+ ALLOCNO_EMIT_DATA (list->from)->reg);
list->insn = get_insns ();
end_sequence ();
/* The reload needs to have set up insn codes. If the reload
@@ -814,8 +884,8 @@ emit_move_list (move_t list, int freq)
}
else
{
- cost = (ira_get_register_move_cost (mode, aclass, aclass)
- * freq);
+ ira_init_register_move_cost_if_necessary (mode);
+ cost = ira_register_move_cost[mode][aclass][aclass] * freq;
ira_shuffle_cost += cost;
}
ira_overall_cost += cost;
@@ -938,7 +1008,7 @@ add_range_and_copies_from_move_list (mov
{
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Allocate conflicts for a%dr%d\n",
- ALLOCNO_NUM (to), REGNO (ALLOCNO_REG (to)));
+ ALLOCNO_NUM (to), REGNO (ALLOCNO_EMIT_DATA (to)->reg));
ira_allocate_allocno_conflicts (to, n);
}
bitmap_clear_bit (live_through, ALLOCNO_REGNO (from));
@@ -955,8 +1025,9 @@ add_range_and_copies_from_move_list (mov
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
fprintf (ira_dump_file, " Adding 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_DATA (cp->first)->reg),
+ ALLOCNO_NUM (cp->second),
+ REGNO (ALLOCNO_EMIT_DATA (cp->second)->reg));
r = ALLOCNO_LIVE_RANGES (from);
if (r == NULL || r->finish >= 0)
{
@@ -966,7 +1037,7 @@ add_range_and_copies_from_move_list (mov
fprintf (ira_dump_file,
" Adding range [%d..%d] to allocno a%dr%d\n",
start, ira_max_point, ALLOCNO_NUM (from),
- REGNO (ALLOCNO_REG (from)));
+ REGNO (ALLOCNO_EMIT_DATA (from)->reg));
}
else
{
@@ -975,7 +1046,7 @@ add_range_and_copies_from_move_list (mov
fprintf (ira_dump_file,
" Adding range [%d..%d] to allocno a%dr%d\n",
r->start, ira_max_point, ALLOCNO_NUM (from),
- REGNO (ALLOCNO_REG (from)));
+ REGNO (ALLOCNO_EMIT_DATA (from)->reg));
}
ira_max_point++;
ALLOCNO_LIVE_RANGES (to)
@@ -993,13 +1064,13 @@ add_range_and_copies_from_move_list (mov
fprintf (ira_dump_file,
" Adding range [%d..%d] to allocno a%dr%d\n",
r->start, r->finish, ALLOCNO_NUM (move->to),
- REGNO (ALLOCNO_REG (move->to)));
+ REGNO (ALLOCNO_EMIT_DATA (move->to)->reg));
}
}
EXECUTE_IF_SET_IN_BITMAP (live_through, FIRST_PSEUDO_REGISTER, regno, bi)
{
a = node->regno_allocno_map[regno];
- if ((to = ALLOCNO_MEM_OPTIMIZED_DEST (a)) != NULL)
+ if ((to = ALLOCNO_EMIT_DATA (a)->mem_optimized_dest) != NULL)
a = to;
ALLOCNO_LIVE_RANGES (a)
= ira_create_allocno_live_range (a, start, ira_max_point - 1,
@@ -1010,7 +1081,7 @@ add_range_and_copies_from_move_list (mov
" Adding range [%d..%d] to live through %s allocno a%dr%d\n",
start, ira_max_point - 1,
to != NULL ? "upper level" : "",
- ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)));
+ ALLOCNO_NUM (a), REGNO (ALLOCNO_EMIT_DATA (a)->reg));
}
}
@@ -1063,7 +1134,7 @@ ira_emit (bool loops_p)
ira_allocno_iterator ai;
FOR_EACH_ALLOCNO (a, ai)
- ALLOCNO_REG (a) = regno_reg_rtx[ALLOCNO_REGNO (a)];
+ ALLOCNO_EMIT_DATA (a)->reg = regno_reg_rtx[ALLOCNO_REGNO (a)];
if (! loops_p)
return;
at_bb_start = (move_t *) ira_allocate (sizeof (move_t) * last_basic_block);
@@ -43,9 +43,9 @@ along with GCC; see the file COPYING3.
profile driven feedback is available and the function is never
executed, frequency is always equivalent. Otherwise rescale the
edge frequency. */
-#define REG_FREQ_FROM_EDGE_FREQ(freq) \
- (optimize_size || (flag_branch_probabilities && !ENTRY_BLOCK_PTR->count) \
- ? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX) \
+#define REG_FREQ_FROM_EDGE_FREQ(freq) \
+ (optimize_size || (flag_branch_probabilities && !ENTRY_BLOCK_PTR->count) \
+ ? REG_FREQ_MAX : (freq * REG_FREQ_MAX / BB_FREQ_MAX) \
? (freq * REG_FREQ_MAX / BB_FREQ_MAX) : 1)
/* All natural loops. */
@@ -219,57 +219,6 @@ extern int ira_max_point;
live ranges with given start/finish point. */
extern live_range_t *ira_start_point_ranges, *ira_finish_point_ranges;
-/* See below. */
-typedef struct allocno_hard_regs *allocno_hard_regs_t;
-
-/* The structure contains information about hard registers can be
- assigned to allocnos. Usually it is allocno profitable hard
- registers but in some cases this set can be a bit different. Major
- reason of the difference is a requirement to use hard register sets
- that form a tree or a forest (set of trees), i.e. hard register set
- of a node should contain hard register sets of its subnodes. */
-struct allocno_hard_regs
-{
- /* Hard registers can be assigned to an allocno. */
- HARD_REG_SET set;
- /* Overall (spilling) cost of all allocnos with given register
- set. */
- long long int cost;
-};
-
-/* See below. */
-typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
-
-/* A node representing allocno hard registers. Such nodes form a
- forest (set of trees). Each subnode of given node in the forest
- refers for hard register set (usually allocno profitable hard
- register set) which is a subset of one referred from given
- node. */
-struct allocno_hard_regs_node
-{
- /* Set up number of the node in preorder traversing of the forest. */
- int preorder_num;
- /* Used for different calculation like finding conflict size of an
- allocno. */
- int check;
- /* Used for calculation of conflict size of an allocno. The
- conflict size of the allocno is maximal number of given allocno
- hard registers needed for allocation of the conflicting allocnos.
- Given allocno is trivially colored if this number plus the number
- of hard registers needed for given allocno is not greater than
- the number of given allocno hard register set. */
- int conflict_size;
- /* The number of hard registers given by member hard_regs. */
- int hard_regs_num;
- /* The following member is used to form the final forest. */
- bool used_p;
- /* Pointer to the corresponding profitable hard registers. */
- allocno_hard_regs_t hard_regs;
- /* Parent, first subnode, previous and next node with the same
- parent in the forest. */
- allocno_hard_regs_node_t parent, first, prev, next;
-};
-
/* A structure representing an allocno (allocation entity). Allocno
represents a pseudo-register in an allocation region. If
pseudo-register does not live in a region but it lives in the
@@ -287,16 +236,40 @@ struct ira_allocno
int regno;
/* Mode of the allocno which is the mode of the corresponding
pseudo-register. */
- enum machine_mode mode;
+ ENUM_BITFIELD (machine_mode) mode : 8;
+ /* Register class which should be used for allocation for given
+ allocno. NO_REGS means that we should use memory. */
+ ENUM_BITFIELD (reg_class) aclass : 16;
+ /* During the reload, value TRUE means that we should not reassign a
+ hard register to the allocno got memory earlier. It is set up
+ when we removed memory-memory move insn before each iteration of
+ the reload. */
+ unsigned int dont_reassign_p : 1;
+#ifdef STACK_REGS
+ /* Set to TRUE if allocno can't be assigned to the stack hard
+ register correspondingly in this region and area including the
+ region and all its subregions recursively. */
+ unsigned int no_stack_reg_p : 1, total_no_stack_reg_p : 1;
+#endif
+ /* TRUE value means that there is no sense to spill the allocno
+ during coloring because the spill will result in additional
+ reloads in reload pass. */
+ unsigned int bad_spill_p : 1;
+ /* TRUE if a hard register or memory has been assigned to the
+ allocno. */
+ unsigned int assigned_p : 1;
+ /* TRUE if conflicts for given allocno are represented by vector of
+ pointers to the conflicting allocnos. Otherwise, we use a bit
+ vector where a bit with given index represents allocno with the
+ same number. */
+ unsigned int conflict_vec_p : 1;
/* Hard register assigned to given allocno. Negative value means
that memory was allocated to the allocno. During the reload,
spilled allocno has value equal to the corresponding stack slot
number (0, ...) - 2. Value -1 is used for allocnos spilled by the
reload (at this point pseudo-register has only one allocno) which
did not get stack slot yet. */
- int hard_regno;
- /* Final rtx representation of the allocno. */
- rtx reg;
+ short int hard_regno;
/* Allocnos with the same regno are linked by the following member.
Allocnos corresponding to inner loops are first in the list (it
corresponds to depth-first traverse of the loops). */
@@ -314,9 +287,6 @@ struct ira_allocno
int nrefs;
/* Accumulated frequency of usage of the allocno. */
int freq;
- /* Register class which should be used for allocation for given
- allocno. NO_REGS means that we should use memory. */
- enum reg_class aclass;
/* Minimal accumulated and updated costs of usage register of the
allocno class. */
int class_cost, updated_class_cost;
@@ -344,11 +314,6 @@ struct ira_allocno
/* It is a link to allocno (cap) on lower loop level represented by
given cap. Null if given allocno is not a cap. */
ira_allocno_t cap_member;
- /* Coalesced allocnos form a cyclic list. One allocno given by
- FIRST_COALESCED_ALLOCNO represents all coalesced allocnos. The
- list is chained by NEXT_COALESCED_ALLOCNO. */
- ira_allocno_t first_coalesced_allocno;
- ira_allocno_t next_coalesced_allocno;
/* Pointer to structures describing at what program point the
allocno lives. We always maintain the list in such way that *the
ranges in the list are not intersected and ordered by decreasing
@@ -381,53 +346,6 @@ struct ira_allocno
int call_freq;
/* Accumulated number of the intersected calls. */
int calls_crossed_num;
- /* TRUE if the allocno assigned to memory was a destination of
- removed move (see ira-emit.c) at loop exit because the value of
- the corresponding pseudo-register is not changed inside the
- loop. */
- unsigned int mem_optimized_dest_p : 1;
- /* TRUE if the corresponding pseudo-register has disjoint live
- ranges and the other allocnos of the pseudo-register except this
- one changed REG. */
- unsigned int somewhere_renamed_p : 1;
- /* TRUE if allocno with the same REGNO in a subregion has been
- renamed, in other words, got a new pseudo-register. */
- unsigned int child_renamed_p : 1;
- /* During the reload, value TRUE means that we should not reassign a
- hard register to the allocno got memory earlier. It is set up
- when we removed memory-memory move insn before each iteration of
- the reload. */
- unsigned int dont_reassign_p : 1;
-#ifdef STACK_REGS
- /* Set to TRUE if allocno can't be assigned to the stack hard
- register correspondingly in this region and area including the
- region and all its subregions recursively. */
- unsigned int no_stack_reg_p : 1, total_no_stack_reg_p : 1;
-#endif
- /* TRUE value means that there is no sense to spill the allocno
- during coloring because the spill will result in additional
- reloads in reload pass. */
- unsigned int bad_spill_p : 1;
- /* TRUE value means that the allocno was not removed yet from the
- conflicting graph during colouring. */
- unsigned int in_graph_p : 1;
- /* TRUE if a hard register or memory has been assigned to the
- allocno. */
- unsigned int assigned_p : 1;
- /* TRUE if it is put on the stack to make other allocnos
- colorable. */
- unsigned int may_be_spilled_p : 1;
- /* TRUE if conflicts for given allocno are represented by vector of
- pointers to the conflicting allocnos. Otherwise, we use a bit
- vector where a bit with given index represents allocno with the
- same number. */
- unsigned int conflict_vec_p : 1;
- /* TRUE if the allocno is trivially colorable. */
- unsigned int colorable_p : 1;
- /* Non NULL if we remove restoring value from given allocno to
- MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
- allocno value is not changed inside the loop. */
- ira_allocno_t mem_optimized_dest;
/* Array of usage costs (accumulated and the one updated during
coloring) for each hard register of the allocno class. The
member value can be NULL if all costs are the same and equal to
@@ -450,32 +368,12 @@ struct ira_allocno
of other allocnos not assigned yet during assigning to given
allocno. */
int *conflict_hard_reg_costs, *updated_conflict_hard_reg_costs;
- /* Number of hard registers of the allocno class really
- available for the allocno allocation. It is number of the
- profitable hard regs. */
- int available_regs_num;
- /* Allocnos in a bucket (used in coloring) chained by the following
- two members. */
- ira_allocno_t next_bucket_allocno;
- ira_allocno_t prev_bucket_allocno;
- /* Used for temporary purposes. */
- int temp;
- /* Profitable hard regs available for this pseudo allocation. It
- means that the set excludes unavailable hard regs and hard regs
- conflicting with given pseudo. They should be of the allocno
- class. */
- HARD_REG_SET profitable_hard_regs;
- /* The allocno hard registers node. */
- allocno_hard_regs_node_t hard_regs_node;
- /* Array of structures allocno_hard_regs_subnode representing
- given allocno hard registers node (the 1st element in the array)
- and all its subnodes in the tree (forest) of allocno hard
- register nodes (see comments above). */
- int hard_regs_subnodes_start;
- /* The length of the previous array. */
- int hard_regs_subnodes_num;
+ /* Different additional data. It is used to decrease size of
+ allocno data footprint. */
+ void *add_data;
};
+
/* All members of the allocno structures should be accessed only
through the following macros. */
#define ALLOCNO_NUM(A) ((A)->num)
@@ -507,11 +405,8 @@ struct ira_allocno
#define ALLOCNO_TOTAL_NO_STACK_REG_P(A) ((A)->total_no_stack_reg_p)
#endif
#define ALLOCNO_BAD_SPILL_P(A) ((A)->bad_spill_p)
-#define ALLOCNO_IN_GRAPH_P(A) ((A)->in_graph_p)
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
-#define ALLOCNO_MAY_BE_SPILLED_P(A) ((A)->may_be_spilled_p)
#define ALLOCNO_CONFLICT_VEC_P(A) ((A)->conflict_vec_p)
-#define ALLOCNO_COLORABLE_P(A) ((A)->colorable_p)
#define ALLOCNO_MODE(A) ((A)->mode)
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
@@ -525,21 +420,45 @@ struct ira_allocno
#define ALLOCNO_UPDATED_CLASS_COST(A) ((A)->updated_class_cost)
#define ALLOCNO_MEMORY_COST(A) ((A)->memory_cost)
#define ALLOCNO_UPDATED_MEMORY_COST(A) ((A)->updated_memory_cost)
-#define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) ((A)->excess_pressure_points_num)
-#define ALLOCNO_AVAILABLE_REGS_NUM(A) ((A)->available_regs_num)
-#define ALLOCNO_NEXT_BUCKET_ALLOCNO(A) ((A)->next_bucket_allocno)
-#define ALLOCNO_PREV_BUCKET_ALLOCNO(A) ((A)->prev_bucket_allocno)
-#define ALLOCNO_TEMP(A) ((A)->temp)
-#define ALLOCNO_FIRST_COALESCED_ALLOCNO(A) ((A)->first_coalesced_allocno)
-#define ALLOCNO_NEXT_COALESCED_ALLOCNO(A) ((A)->next_coalesced_allocno)
+#define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) \
+ ((A)->excess_pressure_points_num)
#define ALLOCNO_LIVE_RANGES(A) ((A)->live_ranges)
#define ALLOCNO_MIN(A) ((A)->min)
#define ALLOCNO_MAX(A) ((A)->max)
#define ALLOCNO_CONFLICT_ID(A) ((A)->conflict_id)
-#define ALLOCNO_PROFITABLE_HARD_REGS(A) ((A)->profitable_hard_regs)
-#define ALLOCNO_HARD_REGS_NODE(A) ((A)->hard_regs_node)
-#define ALLOCNO_HARD_REGS_SUBNODES_START(A) ((A)->hard_regs_subnodes_start)
-#define ALLOCNO_HARD_REGS_SUBNODES_NUM(A) ((A)->hard_regs_subnodes_num)
+#define ALLOCNO_ADD_DATA(A) ((A)->add_data)
+
+/* Typedef for pointer to the subsequent structure. */
+typedef struct ira_emit_data *ira_emit_data_t;
+
+/* Allocno bound data used for emit pseudo live range split insns and
+ to flattening IR. */
+struct ira_emit_data
+{
+ /* TRUE if the allocno assigned to memory was a destination of
+ removed move (see ira-emit.c) at loop exit because the value of
+ the corresponding pseudo-register is not changed inside the
+ loop. */
+ unsigned int mem_optimized_dest_p : 1;
+ /* TRUE if the corresponding pseudo-register has disjoint live
+ ranges and the other allocnos of the pseudo-register except this
+ one changed REG. */
+ unsigned int somewhere_renamed_p : 1;
+ /* TRUE if allocno with the same REGNO in a subregion has been
+ renamed, in other words, got a new pseudo-register. */
+ unsigned int child_renamed_p : 1;
+ /* Final rtx representation of the allocno. */
+ rtx reg;
+ /* Non NULL if we remove restoring value from given allocno to
+ MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
+ allocno value is not changed inside the loop. */
+ ira_allocno_t mem_optimized_dest;
+};
+
+#define ALLOCNO_EMIT_DATA(a) ((ira_emit_data_t) ALLOCNO_ADD_DATA (a))
+
+/* Data used to emit live range split insns and to flattening IR. */
+extern ira_emit_data_t ira_allocno_emit_data;
/* Map regno -> allocnos with given regno (see comments for
allocno member `next_regno_allocno'). */
@@ -781,23 +700,22 @@ minmax_set_iter_next (minmax_set_iterato
extern HARD_REG_SET ira_reg_mode_hard_regset
[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
-/* Array based on TARGET_REGISTER_MOVE_COST. Don't use
- ira_register_move_cost directly. Use function of
- ira_get_may_move_cost instead. */
+/* Array based on TARGET_REGISTER_MOVE_COST. The element is
+ initialized by ira_init_register_move_cost_if_necessary. */
extern move_table *ira_register_move_cost[MAX_MACHINE_MODE];
/* Similar to may_move_in_cost but it is calculated in IRA instead of
regclass. Another difference we take only available hard registers
into account to figure out that one register class is a subset of
- the another one. Don't use it directly. Use function of
- ira_get_may_move_cost instead. */
+ the another one. The element is initialized by
+ ira_init_register_move_cost_if_necessary. */
extern move_table *ira_may_move_in_cost[MAX_MACHINE_MODE];
/* Similar to may_move_out_cost but it is calculated in IRA instead of
regclass. Another difference we take only available hard registers
into account to figure out that one register class is a subset of
- the another one. Don't use it directly. Use function of
- ira_get_may_move_cost instead. */
+ the another one. The element is initialized by
+ ira_init_register_move_cost_if_necessary. */
extern move_table *ira_may_move_out_cost[MAX_MACHINE_MODE];
/* Register class subset relation: TRUE if the first class is a subset
@@ -876,7 +794,6 @@ extern enum reg_class ira_reg_class_subu
extern enum reg_class ira_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
extern void *ira_allocate (size_t);
-extern void *ira_reallocate (void *, size_t);
extern void ira_free (void *addr);
extern bitmap ira_allocate_bitmap (void);
extern void ira_free_bitmap (bitmap);
@@ -930,7 +847,6 @@ extern ira_copy_t ira_create_copy (ira_a
int, bool, rtx, ira_loop_tree_node_t);
extern void ira_add_allocno_copy_to_list (ira_copy_t);
extern void ira_swap_allocno_copy_ends_if_necessary (ira_copy_t);
-extern void ira_remove_allocno_copy_from_list (ira_copy_t);
extern ira_copy_t ira_add_allocno_copy (ira_allocno_t, ira_allocno_t, int,
bool, rtx, ira_loop_tree_node_t);
@@ -972,34 +888,18 @@ extern void ira_finish_assign (void);
extern void ira_color (void);
/* ira-emit.c */
+extern void ira_initiate_emit_data (void);
+extern void ira_finish_emit_data (void);
extern void ira_emit (bool);
-/* Return cost of moving value of MODE from register of class FROM to
- register of class TO. */
-static inline int
-ira_get_register_move_cost (enum machine_mode mode,
- enum reg_class from, enum reg_class to)
-{
- if (ira_register_move_cost[mode] == NULL)
- ira_init_register_move_cost (mode);
- return ira_register_move_cost[mode][from][to];
-}
-
-/* Return cost of moving value of MODE from register of class FROM to
- register of class TO. Return zero if IN_P is true and FROM is
- subset of TO or if IN_P is false and FROM is superset of TO. */
-static inline int
-ira_get_may_move_cost (enum machine_mode mode,
- enum reg_class from, enum reg_class to,
- bool in_p)
+/* Initialize register costs for MODE if necessary. */
+static inline void
+ira_init_register_move_cost_if_necessary (enum machine_mode mode)
{
if (ira_register_move_cost[mode] == NULL)
ira_init_register_move_cost (mode);
- return (in_p
- ? ira_may_move_in_cost[mode][from][to]
- : ira_may_move_out_cost[mode][from][to]);
}
@@ -1150,7 +1050,7 @@ ira_allocno_conflict_iter_cond (ira_allo
if (i->allocno_conflict_vec_p)
{
- conflict_allocno = ((ira_allocno_t *) i->vec)[i->word_num];
+ conflict_allocno = ((ira_allocno_t *) i->vec)[i->word_num++];
if (conflict_allocno == NULL)
return false;
*a = conflict_allocno;
@@ -1158,8 +1058,11 @@ ira_allocno_conflict_iter_cond (ira_allo
}
else
{
+ unsigned IRA_INT_TYPE word = i->word;
+ unsigned int bit_num = i->bit_num;
+
/* Skip words that are zeros. */
- for (; i->word == 0; i->word = ((IRA_INT_TYPE *) i->vec)[i->word_num])
+ for (; word == 0; word = ((IRA_INT_TYPE *) i->vec)[i->word_num])
{
i->word_num++;
@@ -1167,40 +1070,28 @@ ira_allocno_conflict_iter_cond (ira_allo
if (i->word_num * sizeof (IRA_INT_TYPE) >= i->size)
return false;
- i->bit_num = i->word_num * IRA_INT_BITS;
+ bit_num = i->word_num * IRA_INT_BITS;
}
/* Skip bits that are zero. */
- for (; (i->word & 1) == 0; i->word >>= 1)
- i->bit_num++;
+ for (; (word & 1) == 0; word >>= 1)
+ bit_num++;
- *a = ira_conflict_id_allocno_map[i->bit_num + i->base_conflict_id];
+ *a = ira_conflict_id_allocno_map[bit_num + i->base_conflict_id];
+ i->bit_num = bit_num + 1;
+ i->word = word >> 1;
return true;
}
}
-/* Advance to the next conflicting allocno. */
-static inline void
-ira_allocno_conflict_iter_next (ira_allocno_conflict_iterator *i)
-{
- if (i->allocno_conflict_vec_p)
- i->word_num++;
- else
- {
- i->word >>= 1;
- i->bit_num++;
- }
-}
-
/* Loop over all allocnos conflicting with ALLOCNO. In each
iteration, A is set to the next conflicting allocno. ITER is an
instance of ira_allocno_conflict_iterator used to iterate the
conflicts. */
#define FOR_EACH_ALLOCNO_CONFLICT(ALLOCNO, A, ITER) \
for (ira_allocno_conflict_iter_init (&(ITER), (ALLOCNO)); \
- ira_allocno_conflict_iter_cond (&(ITER), &(A)); \
- ira_allocno_conflict_iter_next (&(ITER)))
+ ira_allocno_conflict_iter_cond (&(ITER), &(A));)
@@ -1270,8 +1161,8 @@ ira_allocate_and_set_costs (int **vec, e
reg_costs[i] = val;
}
-/* Allocate cost vector *VEC for hard registers of ACLASS and
- copy values of vector SRC into the vector if it is necessary */
+/* Allocate cost vector *VEC for hard registers of ACLASS and copy
+ values of vector SRC into the vector if it is necessary */
static inline void
ira_allocate_and_copy_costs (int **vec, enum reg_class aclass, int *src)
{
@@ -1284,11 +1175,10 @@ ira_allocate_and_copy_costs (int **vec,
memcpy (*vec, src, sizeof (int) * len);
}
-/* Allocate cost vector *VEC for hard registers of ACLASS and
- add values of vector SRC into the vector if it is necessary */
+/* Allocate cost vector *VEC for hard registers of ACLASS and add
+ values of vector SRC into the vector if it is necessary */
static inline void
-ira_allocate_and_accumulate_costs (int **vec, enum reg_class aclass,
- int *src)
+ira_allocate_and_accumulate_costs (int **vec, enum reg_class aclass, int *src)
{
int i, len;
@@ -1304,9 +1194,9 @@ ira_allocate_and_accumulate_costs (int *
(*vec)[i] += src[i];
}
-/* Allocate cost vector *VEC for hard registers of ACLASS and
- copy values of vector SRC into the vector or initialize it by VAL
- (if SRC is null). */
+/* Allocate cost vector *VEC for hard registers of ACLASS and copy
+ values of vector SRC into the vector or initialize it by VAL (if
+ SRC is null). */
static inline void
ira_allocate_and_set_or_copy_costs (int **vec, enum reg_class aclass,
int val, int *src)
@@ -833,11 +833,11 @@ process_single_reg_class_operands (bool
&& reg_class_size[cl] <= (unsigned) CLASS_MAX_NREGS (cl, mode))
{
int i, size;
- cost
- = (freq
- * (in_p
- ? ira_get_register_move_cost (mode, aclass, cl)
- : ira_get_register_move_cost (mode, cl, aclass)));
+
+ ira_init_register_move_cost_if_necessary (mode);
+ cost = freq * (in_p
+ ? ira_register_move_cost[mode][aclass][cl]
+ : ira_register_move_cost[mode][cl][aclass]);
ira_allocate_and_set_costs
(&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), aclass, 0);
size = ira_reg_class_max_nregs[aclass][mode];