summaryrefslogtreecommitdiff
path: root/gcc/ira-build.c
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2009-01-06 03:50:07 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2009-01-06 03:50:07 +0000
commit95c83f01dfe88f30b6b4b16dff9765e4e6314257 (patch)
tree3ab87fe84116bf920cb2e70b665eec2ced158fdf /gcc/ira-build.c
parent23a0ce4330926bcd8c2968b92d477122c4831980 (diff)
downloadgcc-95c83f01dfe88f30b6b4b16dff9765e4e6314257.tar.gz
2009-01-05 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/38583 * params.h (IRA_MAX_CONFLICT_TABLE_SIZE): New macro. * params.def (ira-max-conflict-table-size): New. * doc/invoke.texi (ira-max-conflict-table-size): Decribe. * ira.h (ira_conflicts_p): New external definition. * ira-conflicts.c (build_conflict_bit_table): Do not build too big table. Report this. Return result of building. (ira_build_conflicts): Use ira_conflicts_p. Check result of building conflict table. * ira-color.c (fast_allocation): Use num instead of ira_allocnos_num. (ira_color): Use ira_conflicts_p. * global.c: Include ira.h. (pseudo_for_reload_consideration_p, build_insn_chain): Use ira_conflicts_p. * Makefile.in (global.o): Add ira.h. * ira-build.c (mark_all_loops_for_removal, propagate_some_info_from_allocno): New. (remove_unnecessary_allocnos): Call propagate_some_info_from_allocno. (remove_low_level_allocnos): New. (remove_unnecessary_regions): Add parameter. Call mark_all_loops_for_removal and remove_low_level_allocnos. Pass parameter to remove_unnecessary_regions. (ira_build): Remove all regions but root if the conflict table was not built. Update conflict hard regs for allocnos crossing calls. * ira.c (ira_conflicts_p): New global. (ira): Define and use ira_conflicts_p. * reload1.c (compute_use_by_pseudos, reload, count_pseudo, count_spilled_pseudo, find_reg, alter_reg, finish_spills, emit_input_reload_insns, delete_output_reload): Use ira_conflicts_p. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@143112 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira-build.c')
-rw-r--r--gcc/ira-build.c225
1 files changed, 177 insertions, 48 deletions
diff --git a/gcc/ira-build.c b/gcc/ira-build.c
index 9e47333d46e..00df69c6d2e 100644
--- a/gcc/ira-build.c
+++ b/gcc/ira-build.c
@@ -1751,6 +1751,33 @@ mark_loops_for_removal (void)
ira_free (sorted_loops);
}
+/* Mark all loops but root for removing. */
+static void
+mark_all_loops_for_removal (void)
+{
+ int i;
+ loop_p loop;
+
+ for (i = 0; VEC_iterate (loop_p, ira_loops.larray, i, loop); i++)
+ if (ira_loop_nodes[i].regno_allocno_map != NULL)
+ {
+ if (ira_loop_nodes[i].parent == NULL)
+ {
+ /* Don't remove the root. */
+ ira_loop_nodes[i].to_remove_p = false;
+ continue;
+ }
+ ira_loop_nodes[i].to_remove_p = true;
+ if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
+ fprintf
+ (ira_dump_file,
+ " Mark loop %d (header %d, freq %d, depth %d) for removal\n",
+ ira_loop_nodes[i].loop->num,
+ ira_loop_nodes[i].loop->header->index,
+ ira_loop_nodes[i].loop->header->frequency,
+ loop_depth (ira_loop_nodes[i].loop));
+ }
+}
/* Definition of vector of loop tree nodes. */
DEF_VEC_P(ira_loop_tree_node_t);
@@ -1856,6 +1883,43 @@ ira_rebuild_regno_allocno_list (int regno)
fprintf (ira_dump_file, " Rebuilding regno allocno list for %d\n", regno);
}
+/* Propagate info from allocno FROM_A to allocno A. */
+static void
+propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
+{
+ enum reg_class cover_class;
+
+ IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+ ALLOCNO_CONFLICT_HARD_REGS (from_a));
+#ifdef STACK_REGS
+ if (ALLOCNO_NO_STACK_REG_P (from_a))
+ ALLOCNO_NO_STACK_REG_P (a) = true;
+#endif
+ ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
+ ALLOCNO_FREQ (a) += ALLOCNO_FREQ (from_a);
+ ALLOCNO_CALL_FREQ (a) += ALLOCNO_CALL_FREQ (from_a);
+ IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from_a));
+ ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a);
+ ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
+ += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
+ if (! ALLOCNO_BAD_SPILL_P (from_a))
+ ALLOCNO_BAD_SPILL_P (a) = false;
+#ifdef STACK_REGS
+ if (ALLOCNO_TOTAL_NO_STACK_REG_P (from_a))
+ ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true;
+#endif
+ cover_class = ALLOCNO_COVER_CLASS (from_a);
+ ira_assert (cover_class == ALLOCNO_COVER_CLASS (a));
+ ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
+ ALLOCNO_HARD_REG_COSTS (from_a));
+ ira_allocate_and_accumulate_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
+ cover_class,
+ ALLOCNO_CONFLICT_HARD_REG_COSTS (from_a));
+ ALLOCNO_COVER_CLASS_COST (a) += ALLOCNO_COVER_CLASS_COST (from_a);
+ ALLOCNO_MEMORY_COST (a) += ALLOCNO_MEMORY_COST (from_a);
+}
+
/* Remove allocnos from loops removed from the allocation
consideration. */
static void
@@ -1863,7 +1927,6 @@ remove_unnecessary_allocnos (void)
{
int regno;
bool merged_p, rebuild_p;
- enum reg_class cover_class;
ira_allocno_t a, prev_a, next_a, parent_a;
ira_loop_tree_node_t a_node, parent;
allocno_live_range_t r;
@@ -1890,9 +1953,9 @@ remove_unnecessary_allocnos (void)
;
if (parent_a == NULL)
{
- /* There are no allocnos with the same regno in upper
- region -- just move the allocno to the upper
- region. */
+ /* There are no allocnos with the same regno in
+ upper region -- just move the allocno to the
+ upper region. */
prev_a = a;
ALLOCNO_LOOP_TREE_NODE (a) = parent;
parent->regno_allocno_map[regno] = a;
@@ -1911,43 +1974,10 @@ remove_unnecessary_allocnos (void)
change_allocno_in_range_list (r, parent_a);
ALLOCNO_LIVE_RANGES (parent_a)
= ira_merge_allocno_live_ranges
- (r, ALLOCNO_LIVE_RANGES (parent_a));
+ (r, ALLOCNO_LIVE_RANGES (parent_a));
merged_p = true;
ALLOCNO_LIVE_RANGES (a) = NULL;
- IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (parent_a),
- ALLOCNO_CONFLICT_HARD_REGS (a));
-#ifdef STACK_REGS
- if (ALLOCNO_NO_STACK_REG_P (a))
- ALLOCNO_NO_STACK_REG_P (parent_a) = true;
-#endif
- ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a);
- ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a);
- ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a);
- IOR_HARD_REG_SET
- (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a),
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
- ALLOCNO_CALLS_CROSSED_NUM (parent_a)
- += ALLOCNO_CALLS_CROSSED_NUM (a);
- ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
- += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
- if (! ALLOCNO_BAD_SPILL_P (a))
- ALLOCNO_BAD_SPILL_P (parent_a) = false;
-#ifdef STACK_REGS
- if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
- ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true;
-#endif
- cover_class = ALLOCNO_COVER_CLASS (a);
- ira_assert (cover_class == ALLOCNO_COVER_CLASS (parent_a));
- ira_allocate_and_accumulate_costs
- (&ALLOCNO_HARD_REG_COSTS (parent_a), cover_class,
- ALLOCNO_HARD_REG_COSTS (a));
- ira_allocate_and_accumulate_costs
- (&ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a),
- cover_class,
- ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
- ALLOCNO_COVER_CLASS_COST (parent_a)
- += ALLOCNO_COVER_CLASS_COST (a);
- ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a);
+ propagate_some_info_from_allocno (parent_a, a);
finish_allocno (a);
}
}
@@ -1968,15 +1998,88 @@ remove_unnecessary_allocnos (void)
ira_free (regno_allocnos);
}
-/* Remove loops from consideration. We remove loops for which a
- separate allocation will not improve the result. We have to do
- this after allocno creation and their costs and cover class
- evaluation because only after that the register pressure can be
- known and is calculated. */
+/* Remove allocnos from all loops but the root. */
static void
-remove_unnecessary_regions (void)
+remove_low_level_allocnos (void)
{
- mark_loops_for_removal ();
+ int regno;
+ bool merged_p, propagate_p;
+ ira_allocno_t a, top_a;
+ ira_loop_tree_node_t a_node, parent;
+ allocno_live_range_t r;
+ ira_allocno_iterator ai;
+
+ merged_p = false;
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ a_node = ALLOCNO_LOOP_TREE_NODE (a);
+ if (a_node == ira_loop_tree_root || ALLOCNO_CAP_MEMBER (a) != NULL)
+ continue;
+ regno = ALLOCNO_REGNO (a);
+ if ((top_a = ira_loop_tree_root->regno_allocno_map[regno]) == NULL)
+ {
+ ALLOCNO_LOOP_TREE_NODE (a) = ira_loop_tree_root;
+ ira_loop_tree_root->regno_allocno_map[regno] = a;
+ continue;
+ }
+ propagate_p = a_node->parent->regno_allocno_map[regno] == NULL;
+ /* Remove the allocno and update info of allocno in the upper
+ region. */
+ r = ALLOCNO_LIVE_RANGES (a);
+ change_allocno_in_range_list (r, top_a);
+ ALLOCNO_LIVE_RANGES (top_a)
+ = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (top_a));
+ merged_p = true;
+ ALLOCNO_LIVE_RANGES (a) = NULL;
+ if (propagate_p)
+ propagate_some_info_from_allocno (top_a, a);
+ }
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ a_node = ALLOCNO_LOOP_TREE_NODE (a);
+ if (a_node == ira_loop_tree_root)
+ continue;
+ parent = a_node->parent;
+ regno = ALLOCNO_REGNO (a);
+ if (ALLOCNO_CAP_MEMBER (a) != NULL)
+ ira_assert (ALLOCNO_CAP (a) != NULL);
+ else if (ALLOCNO_CAP (a) == NULL)
+ ira_assert (parent->regno_allocno_map[regno] != NULL);
+ }
+ FOR_EACH_ALLOCNO (a, ai)
+ {
+ regno = ALLOCNO_REGNO (a);
+ if (ira_loop_tree_root->regno_allocno_map[regno] == a)
+ {
+ ira_regno_allocno_map[regno] = a;
+ ALLOCNO_NEXT_REGNO_ALLOCNO (a) = NULL;
+ ALLOCNO_CAP_MEMBER (a) = NULL;
+ COPY_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+#ifdef STACK_REGS
+ if (ALLOCNO_TOTAL_NO_STACK_REG_P (a))
+ ALLOCNO_NO_STACK_REG_P (a) = true;
+#endif
+ }
+ else
+ finish_allocno (a);
+ }
+ if (merged_p)
+ ira_rebuild_start_finish_chains ();
+}
+
+/* Remove loops from consideration. We remove all loops except for
+ root if ALL_P or loops for which a separate allocation will not
+ improve the result. We have to do this after allocno creation and
+ their costs and cover class evaluation because only after that the
+ register pressure can be known and is calculated. */
+static void
+remove_unnecessary_regions (bool all_p)
+{
+ if (all_p)
+ mark_all_loops_for_removal ();
+ else
+ mark_loops_for_removal ();
children_vec
= VEC_alloc (ira_loop_tree_node_t, heap,
last_basic_block + VEC_length (loop_p, ira_loops.larray));
@@ -1985,7 +2088,10 @@ remove_unnecessary_regions (void)
last_basic_block + VEC_length (loop_p, ira_loops.larray));
remove_uneccesary_loop_nodes_from_loop_tree (ira_loop_tree_root) ;
VEC_free (ira_loop_tree_node_t, heap, children_vec);
- remove_unnecessary_allocnos ();
+ if (all_p)
+ remove_low_level_allocnos ();
+ else
+ remove_unnecessary_allocnos ();
while (VEC_length (ira_loop_tree_node_t, removed_loop_vec) > 0)
finish_loop_tree_node (VEC_pop (ira_loop_tree_node_t, removed_loop_vec));
VEC_free (ira_loop_tree_node_t, heap, removed_loop_vec);
@@ -2668,7 +2774,7 @@ ira_build (bool loops_p)
create_allocnos ();
ira_costs ();
ira_create_allocno_live_ranges ();
- remove_unnecessary_regions ();
+ remove_unnecessary_regions (false);
ira_compress_allocno_live_ranges ();
update_bad_spill_attribute ();
loops_p = more_one_region_p ();
@@ -2685,6 +2791,29 @@ ira_build (bool loops_p)
sort_conflict_id_allocno_map ();
setup_min_max_conflict_allocno_ids ();
ira_build_conflicts ();
+ if (! ira_conflicts_p)
+ {
+ ira_allocno_t a;
+ ira_allocno_iterator ai;
+
+ /* Remove all regions but root one. */
+ if (loops_p)
+ {
+ remove_unnecessary_regions (true);
+ loops_p = false;
+ }
+ /* We don't save hard registers around calls for fast allocation
+ -- add caller clobbered registers as conflicting ones to
+ allocno crossing calls. */
+ FOR_EACH_ALLOCNO (a, ai)
+ if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
+ {
+ IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+ call_used_reg_set);
+ IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
+ call_used_reg_set);
+ }
+ }
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
print_copies (ira_dump_file);
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)