Commit 311aab06 by Vladimir Makarov Committed by Vladimir Makarov

re PR rtl-optimization/38583 (huge test case makes register allocator run out of…

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
parent 9bfea41b
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);
......
......@@ -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);
}
......@@ -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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment