参照元†
返り値†
/* This is the main entry of IRA. */
static void
ira (FILE *f)
{
bool loops_p;
int ira_max_point_before_emit;
bool saved_flag_caller_saves = flag_caller_saves;
enum ira_region saved_flag_ira_region = flag_ira_region;
clear_bb_flags ();
/* Determine if the current function is a leaf before running IRA
since this can impact optimizations done by the prologue and
epilogue thus changing register elimination offsets.
Other target callbacks may use crtl->is_leaf too, including
SHRINK_WRAPPING_ENABLED, so initialize as early as possible. */
crtl->is_leaf = leaf_function_p ();
/* Perform target specific PIC register initialization. */
targetm.init_pic_reg ();
ira_conflicts_p = optimize > 0;
/* If there are too many pseudos and/or basic blocks (e.g. 10K
pseudos and 10K blocks or 100K pseudos and 1K blocks), we will
use simplified and faster algorithms in LRA. */
lra_simple_p
= (ira_use_lra_p
&& max_reg_num () >= (1 << 26) / last_basic_block_for_fn (cfun));
if (lra_simple_p)
{
/* It permits to skip live range splitting in LRA. */
flag_caller_saves = false;
/* There is no sense to do regional allocation when we use
simplified LRA. */
flag_ira_region = IRA_REGION_ONE;
ira_conflicts_p = false;
}
#ifndef IRA_NO_OBSTACK
gcc_obstack_init (&ira_obstack);
#endif
bitmap_obstack_initialize (&ira_bitmap_obstack);
/* LRA uses its own infrastructure to handle caller save registers. */
if (flag_caller_saves && !ira_use_lra_p)
init_caller_save ();
if (flag_ira_verbose < 10)
{
internal_flag_ira_verbose = flag_ira_verbose;
ira_dump_file = f;
}
else
{
internal_flag_ira_verbose = flag_ira_verbose - 10;
ira_dump_file = stderr;
}
setup_prohibited_mode_move_regs ();
decrease_live_ranges_number ();
df_note_add_problem ();
/* DF_LIVE can't be used in the register allocator, too many other
parts of the compiler depend on using the "classic" liveness
interpretation of the DF_LR problem. See PR38711.
Remove the problem, so that we don't spend time updating it in
any of the df_analyze() calls during IRA/LRA. */
if (optimize > 1)
df_remove_problem (df_live);
gcc_checking_assert (df_live == NULL);
if (flag_checking)
df->changeable_flags |= DF_VERIFY_SCHEDULED;
df_analyze ();
init_reg_equiv ();
if (ira_conflicts_p)
{
calculate_dominance_info (CDI_DOMINATORS);
if (split_live_ranges_for_shrink_wrap ())
df_analyze ();
free_dominance_info (CDI_DOMINATORS);
}
df_clear_flags (DF_NO_INSN_RESCAN);
indirect_jump_optimize ();
if (delete_trivially_dead_insns (get_insns (), max_reg_num ()))
df_analyze ();
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. */
if (warn_clobbered)
generate_setjmp_warnings ();
if (resize_reg_info () && flag_ira_loop_pressure)
ira_set_pseudo_classes (true, ira_dump_file);
init_alias_analysis ();
loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
reg_equiv = XCNEWVEC (struct equivalence, max_reg_num ());
update_equiv_regs ();
/* Don't move insns if live range shrinkage or register
pressure-sensitive scheduling were done because it will not
improve allocation but likely worsen insn scheduling. */
if (optimize
&& !flag_live_range_shrinkage
&& !(flag_sched_pressure && flag_schedule_insns))
combine_and_move_insns ();
/* Gather additional equivalences with memory. */
if (optimize)
add_store_equivs ();
loop_optimizer_finalize ();
free_dominance_info (CDI_DOMINATORS);
end_alias_analysis ();
free (reg_equiv);
setup_reg_equiv ();
grow_reg_equivs ();
setup_reg_equiv_init ();
allocated_reg_info_size = max_reg_num ();
/* It is not worth to do such improvement when we use a simple
allocation because of -O0 usage or because the function is too
big. */
if (ira_conflicts_p)
find_moveable_pseudos ();
max_regno_before_ira = max_reg_num ();
ira_setup_eliminable_regset ();
ira_overall_cost = ira_reg_cost = ira_mem_cost = 0;
ira_load_cost = ira_store_cost = ira_shuffle_cost = 0;
ira_move_loops_num = ira_additional_jumps_num = 0;
ira_assert (current_loops == NULL);
if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED)
loop_optimizer_init (AVOID_CFG_MODIFICATIONS | LOOPS_HAVE_RECORDED_EXITS);
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "Building IRA IR\n");
loops_p = ira_build ();
ira_assert (ira_conflicts_p || !loops_p);
saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots;
if (too_high_register_pressure_p () || cfun->calls_setjmp)
/* It is just wasting compiler's time to pack spilled pseudos into
stack slots in this case -- prohibit it. We also do this if
there is setjmp call because a variable not modified between
setjmp and longjmp the compiler is required to preserve its
value and sharing slots does not guarantee it. */
flag_ira_share_spill_slots = FALSE;
ira_color ();
ira_max_point_before_emit = ira_max_point;
ira_initiate_emit_data ();
ira_emit (loops_p);
max_regno = max_reg_num ();
if (ira_conflicts_p)
{
if (! loops_p)
{
if (! ira_use_lra_p)
ira_initiate_assign ();
}
else
{
expand_reg_info ();
if (ira_use_lra_p)
{
ira_allocno_t a;
ira_allocno_iterator ai;
FOR_EACH_ALLOCNO (a, ai)
{
int old_regno = ALLOCNO_REGNO (a);
int new_regno = REGNO (ALLOCNO_EMIT_DATA (a)->reg);
ALLOCNO_REGNO (a) = new_regno;
if (old_regno != new_regno)
setup_reg_classes (new_regno, reg_preferred_class (old_regno),
reg_alternate_class (old_regno),
reg_allocno_class (old_regno));
}
}
else
{
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "Flattening IR\n");
ira_flattening (max_regno_before_ira, ira_max_point_before_emit);
}
/* New insns were generated: add notes and recalculate live
info. */
df_analyze ();
/* ??? Rebuild the loop tree, but why? Does the loop tree
change if new insns were generated? Can that be handled
by updating the loop tree incrementally? */
loop_optimizer_finalize ();
free_dominance_info (CDI_DOMINATORS);
loop_optimizer_init (AVOID_CFG_MODIFICATIONS
| LOOPS_HAVE_RECORDED_EXITS);
if (! ira_use_lra_p)
{
setup_allocno_assignment_flags ();
ira_initiate_assign ();
ira_reassign_conflict_allocnos (max_regno);
}
}
}
ira_finish_emit_data ();
setup_reg_renumber ();
calculate_allocation_cost ();
#ifdef ENABLE_IRA_CHECKING
if (ira_conflicts_p && ! ira_use_lra_p)
/* Opposite to reload pass, LRA does not use any conflict info
from IRA. We don't rebuild conflict info for LRA (through
ira_flattening call) and can not use the check here. We could
rebuild this info for LRA in the check mode but there is a risk
that code generated with the check and without it will be a bit
different. Calling ira_flattening in any mode would be a
wasting CPU time. So do not check the allocation for LRA. */
check_allocation ();
#endif
if (max_regno != max_regno_before_ira)
{
regstat_free_n_sets_and_refs ();
regstat_free_ri ();
regstat_init_n_sets_and_refs ();
regstat_compute_ri ();
}
overall_cost_before = ira_overall_cost;
if (! ira_conflicts_p)
grow_reg_equivs ();
else
{
fix_reg_equiv_init ();
#ifdef ENABLE_IRA_CHECKING
print_redundant_copies ();
#endif
if (! ira_use_lra_p)
{
ira_spilled_reg_stack_slots_num = 0;
ira_spilled_reg_stack_slots
= ((struct ira_spilled_reg_stack_slot *)
ira_allocate (max_regno
* sizeof (struct ira_spilled_reg_stack_slot)));
memset (ira_spilled_reg_stack_slots, 0,
max_regno * sizeof (struct ira_spilled_reg_stack_slot));
}
}
allocate_initial_values ();
/* See comment for find_moveable_pseudos call. */
if (ira_conflicts_p)
move_unallocated_pseudos ();
/* Restore original values. */
if (lra_simple_p)
{
flag_caller_saves = saved_flag_caller_saves;
flag_ira_region = saved_flag_ira_region;
}
}
コメント†