mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-02-09 14:10:13 +08:00
re PR rtl-optimization/38583 (huge test case makes register allocator run out of memory while constructing the conflict graph)
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. From-SVN: r143112
This commit is contained in:
parent
9bfea41b05
commit
311aab0649
@ -1,3 +1,48 @@
|
||||
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.
|
||||
|
||||
2009-01-06 Ben Elliston <bje@au.ibm.com>
|
||||
|
||||
* gengtype-lex.l (YY_NO_INPUT): Define.
|
||||
|
@ -2860,7 +2860,7 @@ bitmap.o : bitmap.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
global.o : global.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
|
||||
insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
|
||||
$(TIMEVAR_H) vecprim.h $(DF_H) $(DBGCNT_H) $(RA_H)
|
||||
$(TIMEVAR_H) vecprim.h $(DF_H) $(DBGCNT_H) $(RA_H) ira.h
|
||||
ra-conflict.o : ra-conflict.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) \
|
||||
$(FLAGS_H) reload.h $(FUNCTION_H) $(RECOG_H) $(REGS_H) hard-reg-set.h \
|
||||
insn-config.h output.h $(TOPLEV_H) $(TM_P_H) $(MACHMODE_H) tree-pass.h \
|
||||
|
@ -7617,6 +7617,15 @@ given number of the most frequently executed loops will form regions
|
||||
for the regional register allocation. The default value of the
|
||||
parameter is 100.
|
||||
|
||||
@item ira-max-conflict-table-size
|
||||
Although IRA uses a sophisticated algorithm of compression conflict
|
||||
table, the table can be still big for huge functions. If the conflict
|
||||
table for a function could be more than size in MB given by the
|
||||
parameter, the conflict table is not built and faster, simpler, and
|
||||
lower quality register allocation algorithm will be used. The
|
||||
algorithm do not use pseudo-register conflicts. The default value of
|
||||
the parameter is 2000.
|
||||
|
||||
@end table
|
||||
@end table
|
||||
|
||||
|
@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#include "vecprim.h"
|
||||
#include "dbgcnt.h"
|
||||
#include "ra.h"
|
||||
#include "ira.h"
|
||||
|
||||
/* This pass of the compiler performs global register allocation.
|
||||
It assigns hard register numbers to all the pseudo registers
|
||||
@ -1394,7 +1395,7 @@ pseudo_for_reload_consideration_p (int regno)
|
||||
/* Consider spilled pseudos too for IRA because they still have a
|
||||
chance to get hard-registers in the reload when IRA is used. */
|
||||
return (reg_renumber[regno] >= 0
|
||||
|| (flag_ira && optimize && flag_ira_share_spill_slots));
|
||||
|| (flag_ira && ira_conflicts_p && flag_ira_share_spill_slots));
|
||||
}
|
||||
|
||||
/* Walk the insns of the current function and build reload_insn_chain,
|
||||
@ -1483,7 +1484,7 @@ build_insn_chain (void)
|
||||
|
||||
if ((regno < FIRST_PSEUDO_REGISTER
|
||||
|| reg_renumber[regno] >= 0
|
||||
|| (flag_ira && optimize))
|
||||
|| (flag_ira && ira_conflicts_p))
|
||||
&& (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
|
||||
{
|
||||
rtx reg = DF_REF_REG (def);
|
||||
|
225
gcc/ira-build.c
225
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)
|
||||
|
@ -3267,7 +3267,7 @@ fast_allocation (void)
|
||||
* ira_max_point);
|
||||
for (i = 0; i < ira_max_point; i++)
|
||||
CLEAR_HARD_REG_SET (used_hard_regs[i]);
|
||||
qsort (sorted_allocnos, ira_allocnos_num, sizeof (ira_allocno_t),
|
||||
qsort (sorted_allocnos, num, sizeof (ira_allocno_t),
|
||||
allocno_priority_compare_func);
|
||||
for (i = 0; i < num; i++)
|
||||
{
|
||||
@ -3329,7 +3329,7 @@ ira_color (void)
|
||||
ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
|
||||
ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a);
|
||||
}
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
color ();
|
||||
else
|
||||
fast_allocation ();
|
||||
|
@ -60,8 +60,10 @@ static IRA_INT_TYPE **conflicts;
|
||||
|
||||
|
||||
|
||||
/* Build allocno conflict table by processing allocno live ranges. */
|
||||
static void
|
||||
/* Build allocno conflict table by processing allocno live ranges.
|
||||
Return true if the table was built. The table is not built if it
|
||||
is too big. */
|
||||
static bool
|
||||
build_conflict_bit_table (void)
|
||||
{
|
||||
int i, num, id, allocated_words_num, conflict_bit_vec_words_num;
|
||||
@ -74,6 +76,26 @@ build_conflict_bit_table (void)
|
||||
int allocno_set_words;
|
||||
|
||||
allocno_set_words = (ira_allocnos_num + IRA_INT_BITS - 1) / IRA_INT_BITS;
|
||||
allocated_words_num = 0;
|
||||
FOR_EACH_ALLOCNO (allocno, ai)
|
||||
{
|
||||
if (ALLOCNO_MAX (allocno) < ALLOCNO_MIN (allocno))
|
||||
continue;
|
||||
conflict_bit_vec_words_num
|
||||
= ((ALLOCNO_MAX (allocno) - ALLOCNO_MIN (allocno) + IRA_INT_BITS)
|
||||
/ IRA_INT_BITS);
|
||||
allocated_words_num += conflict_bit_vec_words_num;
|
||||
if ((unsigned long long) allocated_words_num * sizeof (IRA_INT_TYPE)
|
||||
> (unsigned long long) IRA_MAX_CONFLICT_TABLE_SIZE * 1024 * 1024)
|
||||
{
|
||||
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
|
||||
fprintf
|
||||
(ira_dump_file,
|
||||
"+++Conflict table will be too big(>%dMB) -- don't use it\n",
|
||||
IRA_MAX_CONFLICT_TABLE_SIZE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
allocnos_live = sparseset_alloc (ira_allocnos_num);
|
||||
conflicts = (IRA_INT_TYPE **) ira_allocate (sizeof (IRA_INT_TYPE *)
|
||||
* ira_allocnos_num);
|
||||
@ -134,6 +156,7 @@ build_conflict_bit_table (void)
|
||||
sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (r->allocno));
|
||||
}
|
||||
sparseset_free (allocnos_live);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@ -743,29 +766,34 @@ ira_build_conflicts (void)
|
||||
ira_allocno_iterator ai;
|
||||
HARD_REG_SET temp_hard_reg_set;
|
||||
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
build_conflict_bit_table ();
|
||||
build_conflicts ();
|
||||
ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
|
||||
/* We need finished conflict table for the subsequent call. */
|
||||
if (flag_ira_region == IRA_REGION_ALL
|
||||
|| flag_ira_region == IRA_REGION_MIXED)
|
||||
propagate_copies ();
|
||||
/* Now we can free memory for the conflict table (see function
|
||||
build_allocno_conflicts for details). */
|
||||
FOR_EACH_ALLOCNO (a, ai)
|
||||
ira_conflicts_p = build_conflict_bit_table ();
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a) != conflicts[ALLOCNO_NUM (a)])
|
||||
ira_free (conflicts[ALLOCNO_NUM (a)]);
|
||||
build_conflicts ();
|
||||
ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies);
|
||||
/* We need finished conflict table for the subsequent call. */
|
||||
if (flag_ira_region == IRA_REGION_ALL
|
||||
|| flag_ira_region == IRA_REGION_MIXED)
|
||||
propagate_copies ();
|
||||
/* Now we can free memory for the conflict table (see function
|
||||
build_allocno_conflicts for details). */
|
||||
FOR_EACH_ALLOCNO (a, ai)
|
||||
{
|
||||
if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a)
|
||||
!= conflicts[ALLOCNO_NUM (a)])
|
||||
ira_free (conflicts[ALLOCNO_NUM (a)]);
|
||||
}
|
||||
ira_free (conflicts);
|
||||
}
|
||||
ira_free (conflicts);
|
||||
}
|
||||
if (! CLASS_LIKELY_SPILLED_P (BASE_REG_CLASS))
|
||||
CLEAR_HARD_REG_SET (temp_hard_reg_set);
|
||||
else
|
||||
{
|
||||
COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[BASE_REG_CLASS]);
|
||||
COPY_HARD_REG_SET (temp_hard_reg_set,
|
||||
reg_class_contents[BASE_REG_CLASS]);
|
||||
AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs);
|
||||
AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set);
|
||||
}
|
||||
@ -796,6 +824,7 @@ ira_build_conflicts (void)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (optimize && internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||
if (optimize && ira_conflicts_p
|
||||
&& internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
|
||||
print_conflicts (ira_dump_file, false);
|
||||
}
|
||||
|
17
gcc/ira.c
17
gcc/ira.c
@ -1827,6 +1827,10 @@ too_high_register_pressure_p (void)
|
||||
/* All natural loops. */
|
||||
struct loops ira_loops;
|
||||
|
||||
/* True if we have allocno conflicts. It is false for non-optimized
|
||||
mode or when the conflict table is too big. */
|
||||
bool ira_conflicts_p;
|
||||
|
||||
/* This is the main entry of IRA. */
|
||||
static void
|
||||
ira (FILE *f)
|
||||
@ -1851,6 +1855,7 @@ ira (FILE *f)
|
||||
ira_dump_file = stderr;
|
||||
}
|
||||
|
||||
ira_conflicts_p = optimize > 0;
|
||||
setup_prohibited_mode_move_regs ();
|
||||
|
||||
df_note_add_problem ();
|
||||
@ -1916,6 +1921,8 @@ ira (FILE *f)
|
||||
loops_p = ira_build (optimize
|
||||
&& (flag_ira_region == IRA_REGION_ALL
|
||||
|| flag_ira_region == IRA_REGION_MIXED));
|
||||
|
||||
ira_assert (ira_conflicts_p || !loops_p);
|
||||
|
||||
saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
|
||||
if (too_high_register_pressure_p ())
|
||||
@ -1929,7 +1936,7 @@ ira (FILE *f)
|
||||
|
||||
ira_emit (loops_p);
|
||||
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
max_regno = max_reg_num ();
|
||||
|
||||
@ -1963,7 +1970,7 @@ ira (FILE *f)
|
||||
calculate_allocation_cost ();
|
||||
|
||||
#ifdef ENABLE_IRA_CHECKING
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
check_allocation ();
|
||||
#endif
|
||||
|
||||
@ -1992,7 +1999,7 @@ ira (FILE *f)
|
||||
allocate_initial_values (reg_equiv_memory_loc);
|
||||
|
||||
overall_cost_before = ira_overall_cost;
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
fix_reg_equiv_init ();
|
||||
|
||||
@ -2015,13 +2022,13 @@ ira (FILE *f)
|
||||
df_set_flags (DF_NO_INSN_RESCAN);
|
||||
build_insn_chain ();
|
||||
|
||||
reload_completed = !reload (get_insns (), optimize > 0);
|
||||
reload_completed = !reload (get_insns (), ira_conflicts_p);
|
||||
|
||||
timevar_pop (TV_RELOAD);
|
||||
|
||||
timevar_push (TV_IRA);
|
||||
|
||||
if (optimize)
|
||||
if (ira_conflicts_p)
|
||||
{
|
||||
ira_free (ira_spilled_reg_stack_slots);
|
||||
|
||||
|
@ -20,6 +20,10 @@ You should have received a copy of the GNU General Public License
|
||||
along with GCC; see the file COPYING3. If not see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
/* True if we have allocno conflicts. It is false for non-optimized
|
||||
mode or when the conflict table is too big. */
|
||||
extern bool ira_conflicts_p;
|
||||
|
||||
extern void ira_init_once (void);
|
||||
extern void ira_init (void);
|
||||
extern void ira_finish_once (void);
|
||||
|
@ -750,6 +750,11 @@ DEFPARAM (PARAM_IRA_MAX_LOOPS_NUM,
|
||||
"max loops number for regional RA",
|
||||
100, 0, 0)
|
||||
|
||||
DEFPARAM (PARAM_IRA_MAX_CONFLICT_TABLE_SIZE,
|
||||
"ira-max-conflict-table-size",
|
||||
"max size of conflict table in MB",
|
||||
2000, 0, 0)
|
||||
|
||||
/* Switch initialization conversion will refuse to create arrays that are
|
||||
bigger than this parameter times the number of switch branches. */
|
||||
|
||||
|
@ -169,6 +169,8 @@ typedef enum compiler_param
|
||||
PARAM_VALUE (PARAM_USE_CANONICAL_TYPES)
|
||||
#define IRA_MAX_LOOPS_NUM \
|
||||
PARAM_VALUE (PARAM_IRA_MAX_LOOPS_NUM)
|
||||
#define IRA_MAX_CONFLICT_TABLE_SIZE \
|
||||
PARAM_VALUE (PARAM_IRA_MAX_CONFLICT_TABLE_SIZE)
|
||||
#define SWITCH_CONVERSION_BRANCH_RATIO \
|
||||
PARAM_VALUE (PARAM_SWITCH_CONVERSION_BRANCH_RATIO)
|
||||
#endif /* ! GCC_PARAMS_H */
|
||||
|
@ -557,7 +557,7 @@ compute_use_by_pseudos (HARD_REG_SET *to, regset from)
|
||||
which might still contain registers that have not
|
||||
actually been allocated since they have an
|
||||
equivalence. */
|
||||
gcc_assert ((flag_ira && optimize) || reload_completed);
|
||||
gcc_assert ((flag_ira && ira_conflicts_p) || reload_completed);
|
||||
}
|
||||
else
|
||||
add_to_hard_reg_set (to, PSEUDO_REGNO_MODE (regno), r);
|
||||
@ -901,7 +901,7 @@ reload (rtx first, int global)
|
||||
for (n = 0, i = LAST_VIRTUAL_REGISTER + 1; i < max_regno; i++)
|
||||
temp_pseudo_reg_arr[n++] = i;
|
||||
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
/* Ask IRA to order pseudo-registers for better stack slot
|
||||
sharing. */
|
||||
ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_width);
|
||||
@ -1055,7 +1055,7 @@ reload (rtx first, int global)
|
||||
|
||||
calculate_needs_all_insns (global);
|
||||
|
||||
if (! flag_ira || ! optimize)
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
/* Don't do it for IRA. We need this info because we don't
|
||||
change live_throughout and dead_or_set for chains when IRA
|
||||
is used. */
|
||||
@ -1614,7 +1614,7 @@ calculate_needs_all_insns (int global)
|
||||
reg_equiv_memory_loc
|
||||
[REGNO (SET_DEST (set))]))))
|
||||
{
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
/* Inform IRA about the insn deletion. */
|
||||
ira_mark_memory_move_deletion (REGNO (SET_DEST (set)),
|
||||
REGNO (SET_SRC (set)));
|
||||
@ -1723,7 +1723,7 @@ count_pseudo (int reg)
|
||||
|| REGNO_REG_SET_P (&spilled_pseudos, reg)
|
||||
/* Ignore spilled pseudo-registers which can be here only if IRA
|
||||
is used. */
|
||||
|| (flag_ira && optimize && r < 0))
|
||||
|| (flag_ira && ira_conflicts_p && r < 0))
|
||||
return;
|
||||
|
||||
SET_REGNO_REG_SET (&pseudos_counted, reg);
|
||||
@ -1804,7 +1804,7 @@ count_spilled_pseudo (int spilled, int spilled_nregs, int reg)
|
||||
|
||||
/* Ignore spilled pseudo-registers which can be here only if IRA is
|
||||
used. */
|
||||
if ((flag_ira && optimize && r < 0)
|
||||
if ((flag_ira && ira_conflicts_p && r < 0)
|
||||
|| REGNO_REG_SET_P (&spilled_pseudos, reg)
|
||||
|| spilled + spilled_nregs <= r || r + nregs <= spilled)
|
||||
return;
|
||||
@ -1876,7 +1876,7 @@ find_reg (struct insn_chain *chain, int order)
|
||||
if (! ok)
|
||||
continue;
|
||||
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
{
|
||||
/* Ask IRA to find a better pseudo-register for
|
||||
spilling. */
|
||||
@ -2158,7 +2158,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
||||
unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT;
|
||||
int adjust = 0;
|
||||
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
{
|
||||
/* Mark the spill for IRA. */
|
||||
SET_REGNO_REG_SET (&spilled_pseudos, i);
|
||||
@ -2177,7 +2177,8 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
||||
enough inherent space and enough total space.
|
||||
Otherwise, we allocate a new slot, making sure that it has no less
|
||||
inherent space, and no less total space, then the previous slot. */
|
||||
else if (from_reg == -1 || (!dont_share_p && flag_ira && optimize))
|
||||
else if (from_reg == -1
|
||||
|| (!dont_share_p && flag_ira && ira_conflicts_p))
|
||||
{
|
||||
rtx stack_slot;
|
||||
|
||||
@ -2202,7 +2203,7 @@ alter_reg (int i, int from_reg, bool dont_share_p)
|
||||
adjust);
|
||||
}
|
||||
|
||||
if (! dont_share_p && flag_ira && optimize)
|
||||
if (! dont_share_p && flag_ira && ira_conflicts_p)
|
||||
/* Inform IRA about allocation a new stack slot. */
|
||||
ira_mark_new_stack_slot (stack_slot, i, total_size);
|
||||
}
|
||||
@ -3904,7 +3905,7 @@ finish_spills (int global)
|
||||
spill_reg_order[i] = -1;
|
||||
|
||||
EXECUTE_IF_SET_IN_REG_SET (&spilled_pseudos, FIRST_PSEUDO_REGISTER, i, rsi)
|
||||
if (! flag_ira || ! optimize || reg_renumber[i] >= 0)
|
||||
if (! flag_ira || ! ira_conflicts_p || reg_renumber[i] >= 0)
|
||||
{
|
||||
/* Record the current hard register the pseudo is allocated to
|
||||
in pseudo_previous_regs so we avoid reallocating it to the
|
||||
@ -3914,7 +3915,7 @@ finish_spills (int global)
|
||||
SET_HARD_REG_BIT (pseudo_previous_regs[i], reg_renumber[i]);
|
||||
/* Mark it as no longer having a hard register home. */
|
||||
reg_renumber[i] = -1;
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (i);
|
||||
/* We will need to scan everything again. */
|
||||
@ -3944,7 +3945,7 @@ finish_spills (int global)
|
||||
}
|
||||
}
|
||||
|
||||
if (! flag_ira || ! optimize)
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
{
|
||||
/* Retry allocating the spilled pseudos. For each reg,
|
||||
merge the various reg sets that indicate which hard regs
|
||||
@ -3996,7 +3997,7 @@ finish_spills (int global)
|
||||
HARD_REG_SET used_by_pseudos;
|
||||
HARD_REG_SET used_by_pseudos2;
|
||||
|
||||
if (! flag_ira || ! optimize)
|
||||
if (! flag_ira || ! ira_conflicts_p)
|
||||
{
|
||||
/* Don't do it for IRA because IRA and the reload still can
|
||||
assign hard registers to the spilled pseudos on next
|
||||
@ -6999,7 +7000,7 @@ emit_input_reload_insns (struct insn_chain *chain, struct reload *rl,
|
||||
&& REG_N_SETS (REGNO (old)) == 1)
|
||||
{
|
||||
reg_renumber[REGNO (old)] = REGNO (reloadreg);
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (REGNO (old));
|
||||
alter_reg (REGNO (old), -1, false);
|
||||
@ -8540,7 +8541,7 @@ delete_output_reload (rtx insn, int j, int last_reload_reg, rtx new_reload_reg)
|
||||
|
||||
/* For the debugging info, say the pseudo lives in this reload reg. */
|
||||
reg_renumber[REGNO (reg)] = REGNO (new_reload_reg);
|
||||
if (flag_ira && optimize)
|
||||
if (flag_ira && ira_conflicts_p)
|
||||
/* Inform IRA about the change. */
|
||||
ira_mark_allocation_change (REGNO (reg));
|
||||
alter_reg (REGNO (reg), -1, false);
|
||||
|
Loading…
Reference in New Issue
Block a user