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:
Vladimir Makarov 2009-01-06 03:50:07 +00:00 committed by Vladimir Makarov
parent 9bfea41b05
commit 311aab0649
12 changed files with 324 additions and 92 deletions

View File

@ -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.

View File

@ -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 \

View File

@ -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

View File

@ -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);

View File

@ -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)

View File

@ -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 ();

View File

@ -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);
}

View File

@ -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);

View File

@ -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);

View File

@ -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. */

View File

@ -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 */

View File

@ -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);