#include "integrate.h"
#include "ggc.h"
#include "ira-int.h"
+#include "dce.h"
struct target_ira default_target_ira;
stack slots used in current function so far. */
struct ira_spilled_reg_stack_slot *ira_spilled_reg_stack_slots;
-/* Correspondingly overall cost of the allocation, cost of the
- allocnos assigned to hard-registers, cost of the allocnos assigned
- to memory, cost of loads, stores and register move insns generated
- for pseudo-register live range splitting (see ira-emit.c). */
-int ira_overall_cost;
+/* Correspondingly overall cost of the allocation, overall cost before
+ reload, cost of the allocnos assigned to hard-registers, cost of
+ the allocnos assigned to memory, cost of loads, stores and register
+ move insns generated for pseudo-register live range splitting (see
+ ira-emit.c). */
+int ira_overall_cost, overall_cost_before;
int ira_reg_cost, ira_mem_cost;
int ira_load_cost, ira_store_cost, ira_shuffle_cost;
int ira_move_loops_num, ira_additional_jumps_num;
ira_max_memory_move_cost[mode][cl][0]
= ira_memory_move_cost[mode][cl][0]
= memory_move_cost ((enum machine_mode) mode,
- (enum reg_class) cl, false);
+ (reg_class_t) cl, false);
ira_max_memory_move_cost[mode][cl][1]
= ira_memory_move_cost[mode][cl][1]
= memory_move_cost ((enum machine_mode) mode,
- (enum reg_class) cl, true);
+ (reg_class_t) cl, true);
/* Costs for NO_REGS are used in cost calculation on the
1st pass when the preferred register classes are not
known yet. In this case we take the best scenario. */
if ((bb = ALLOCNO_LOOP_TREE_NODE (a)->bb) != NULL)
fprintf (f, "b%-3d", bb->index);
else
- fprintf (f, "l%-3d", ALLOCNO_LOOP_TREE_NODE (a)->loop->num);
+ fprintf (f, "l%-3d", ALLOCNO_LOOP_TREE_NODE (a)->loop_num);
if (ALLOCNO_HARD_REGNO (a) >= 0)
fprintf (f, " %3d", ALLOCNO_HARD_REGNO (a));
else
{
if (ira_available_class_regs[cl] == 0)
continue;
- /* Check that the moves between any hard registers of the
- current class are not more expensive for a legal mode than
- load/store of the hard registers of the current class. Such
- class is a potential candidate to be a register pressure
- class. */
- for (m = 0; m < NUM_MACHINE_MODES; m++)
+ if (ira_available_class_regs[cl] != 1
+ /* A register class without subclasses may contain a few
+ hard registers and movement between them is costly
+ (e.g. SPARC FPCC registers). We still should consider it
+ as a candidate for a pressure class. */
+ && alloc_reg_class_subclasses[cl][0] != LIM_REG_CLASSES)
{
- COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
- AND_COMPL_HARD_REG_SET (temp_hard_regset,
- ira_prohibited_class_mode_regs[cl][m]);
- if (hard_reg_set_empty_p (temp_hard_regset))
+ /* Check that the moves between any hard registers of the
+ current class are not more expensive for a legal mode
+ than load/store of the hard registers of the current
+ class. Such class is a potential candidate to be a
+ register pressure class. */
+ for (m = 0; m < NUM_MACHINE_MODES; m++)
+ {
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset,
+ ira_prohibited_class_mode_regs[cl][m]);
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
+ ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
+ cost = ira_register_move_cost[m][cl][cl];
+ if (cost <= ira_max_memory_move_cost[m][cl][1]
+ || cost <= ira_max_memory_move_cost[m][cl][0])
+ break;
+ }
+ if (m >= NUM_MACHINE_MODES)
continue;
- ira_init_register_move_cost_if_necessary ((enum machine_mode) m);
- cost = ira_register_move_cost[m][cl][cl];
- if (cost <= ira_max_memory_move_cost[m][cl][1]
- || cost <= ira_max_memory_move_cost[m][cl][0])
- break;
}
- if (m >= NUM_MACHINE_MODES)
- continue;
curr = 0;
insert_p = true;
COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
&& (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
|| cl == (int) GENERAL_REGS))
continue;
+ if (hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset))
+ insert_p = false;
pressure_classes[curr++] = (enum reg_class) cl2;
}
/* If the current candidate is a subset of a so far added
n = curr;
}
#ifdef ENABLE_IRA_CHECKING
- /* Check pressure classes correctness: here we check that hard
- registers from all register pressure classes contains all hard
- registers available for the allocation. */
- CLEAR_HARD_REG_SET (temp_hard_regset);
- CLEAR_HARD_REG_SET (temp_hard_regset2);
- for (cl = 0; cl <= LIM_REG_CLASSES; cl++)
- {
- for (i = 0; i < n; i++)
- if ((int) pressure_classes[i] == cl)
- break;
- IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
- if (i >= n)
- IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
- }
- AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
- AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
- ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
+ {
+ HARD_REG_SET ignore_hard_regs;
+
+ /* Check pressure classes correctness: here we check that hard
+ registers from all register pressure classes contains all hard
+ registers available for the allocation. */
+ CLEAR_HARD_REG_SET (temp_hard_regset);
+ CLEAR_HARD_REG_SET (temp_hard_regset2);
+ COPY_HARD_REG_SET (ignore_hard_regs, no_unit_alloc_regs);
+ for (cl = 0; cl < LIM_REG_CLASSES; cl++)
+ {
+ /* For some targets (like MIPS with MD_REGS), there are some
+ classes with hard registers available for allocation but
+ not able to hold value of any mode. */
+ for (m = 0; m < NUM_MACHINE_MODES; m++)
+ if (contains_reg_of_mode[cl][m])
+ break;
+ if (m >= NUM_MACHINE_MODES)
+ {
+ IOR_HARD_REG_SET (ignore_hard_regs, reg_class_contents[cl]);
+ continue;
+ }
+ for (i = 0; i < n; i++)
+ if ((int) pressure_classes[i] == cl)
+ break;
+ IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+ if (i < n)
+ IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ }
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ /* Some targets (like SPARC with ICC reg) have alocatable regs
+ for which no reg class is defined. */
+ if (REGNO_REG_CLASS (i) == NO_REGS)
+ SET_HARD_REG_BIT (ignore_hard_regs, i);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, ignore_hard_regs);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset2, ignore_hard_regs);
+ ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
+ }
#endif
ira_pressure_classes_num = 0;
for (i = 0; i < n; i++)
/* Collect classes which contain unique sets of allocatable hard
registers. Prefer GENERAL_REGS to other classes containing the
same set of hard registers. */
- for (i = 0; i <= LIM_REG_CLASSES; i++)
+ for (i = 0; i < LIM_REG_CLASSES; i++)
{
COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
for (cl = 0; cl < N_REG_CLASSES; cl++)
ira_reg_class_max_nregs[cl][m]
= ira_reg_class_min_nregs[cl][m]
- = CLASS_MAX_NREGS ((enum reg_class) cl, (enum machine_mode) m);
+ = targetm.class_max_nregs ((reg_class_t) cl, (enum machine_mode) m);
for (cl = 0; cl < N_REG_CLASSES; cl++)
for (i = 0;
(cl2 = alloc_reg_class_subclasses[cl][i]) != LIM_REG_CLASSES;
if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j], hard_regno))
continue;
nregs = hard_regno_nregs[hard_regno][j];
+ if (hard_regno + nregs > FIRST_PSEUDO_REGISTER)
+ {
+ SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
+ hard_regno);
+ continue;
+ }
pclass = ira_pressure_class_translate[REGNO_REG_CLASS (hard_regno)];
for (nregs-- ;nregs >= 0; nregs--)
if (((enum reg_class) pclass
sizeof (move_table) * N_REG_CLASSES);
for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
{
+ /* Some subclasses are to small to have enough registers to hold
+ a value of MODE. Just ignore them. */
+ if (ira_reg_class_max_nregs[cl1][mode] > ira_available_class_regs[cl1])
+ continue;
COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
if (hard_reg_set_empty_p (temp_hard_regset))
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
{
- if (ira_max_register_move_cost[mode] != NULL)
- free (ira_max_register_move_cost[mode]);
- if (ira_may_move_in_cost[mode] != NULL)
- free (ira_may_move_in_cost[mode]);
- if (ira_may_move_out_cost[mode] != NULL)
- free (ira_may_move_out_cost[mode]);
- if (ira_max_may_move_in_cost[mode] != NULL)
- free (ira_max_may_move_in_cost[mode]);
- if (ira_max_may_move_out_cost[mode] != NULL)
- free (ira_max_may_move_out_cost[mode]);
+ free (ira_max_register_move_cost[mode]);
+ free (ira_may_move_in_cost[mode]);
+ free (ira_may_move_out_cost[mode]);
+ free (ira_max_may_move_in_cost[mode]);
+ free (ira_max_may_move_out_cost[mode]);
ira_register_move_cost[mode] = NULL;
ira_max_register_move_cost[mode] = NULL;
ira_may_move_in_cost[mode] = NULL;
{
df_ref def = *def_rec;
unsigned int dregno = DF_REF_REGNO (def);
- if (dregno < FIRST_PSEUDO_REGISTER)
- {
- unsigned int i;
- enum machine_mode mode = GET_MODE (DF_REF_REAL_REG (def));
- unsigned int end = dregno
- + hard_regno_nregs[dregno][mode] - 1;
-
- for (i = dregno; i <= end; ++i)
- SET_HARD_REG_BIT(crtl->asm_clobbers, i);
- }
+ if (HARD_REGISTER_NUM_P (dregno))
+ add_to_hard_reg_set (&crtl->asm_clobbers,
+ GET_MODE (DF_REF_REAL_REG (def)),
+ dregno);
}
}
}
reg_class_contents[pclass]);
}
if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
- && ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
- call_used_reg_set))
+ && ira_hard_reg_set_intersection_p (hard_regno, ALLOCNO_MODE (a),
+ call_used_reg_set))
{
ira_assert (!optimize || flag_caller_saves
|| regno >= ira_reg_equiv_len
|| ALLOCNO_EMIT_DATA (a)->mem_optimized_dest_p
|| (ALLOCNO_MEMORY_COST (a)
- ALLOCNO_CLASS_COST (a)) < 0);
- ira_assert (hard_regno < 0
- || ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
- reg_class_contents
- [ALLOCNO_CLASS (a)]));
+ ira_assert
+ (hard_regno < 0
+ || ira_hard_reg_in_set_p (hard_regno, ALLOCNO_MODE (a),
+ reg_class_contents[ALLOCNO_CLASS (a)]));
}
}
{
hard_regno = ALLOCNO_HARD_REGNO (a);
ira_assert (hard_regno < 0
- || ! ira_hard_reg_not_in_set_p
- (hard_regno, ALLOCNO_MODE (a),
- reg_class_contents[ALLOCNO_CLASS (a)]));
+ || (ira_hard_reg_in_set_p
+ (hard_regno, ALLOCNO_MODE (a),
+ reg_class_contents[ALLOCNO_CLASS (a)])));
if (hard_regno < 0)
{
cost = ALLOCNO_MEMORY_COST (a);
}
for (i = 0; i < (unsigned int) max_regno; i++)
- if (live_subregs[i])
- free (live_subregs[i]);
+ free (live_subregs[i]);
reload_insn_chain = c;
*p = NULL;
mode or when the conflict table is too big. */
bool ira_conflicts_p;
+/* Saved between IRA and reload. */
+static int saved_flag_ira_share_spill_slots;
+
/* This is the main entry of IRA. */
static void
ira (FILE *f)
{
- int overall_cost_before, allocated_reg_info_size;
+ int allocated_reg_info_size;
bool loops_p;
int max_regno_before_ira, ira_max_point_before_emit;
int rebuild_p;
- int saved_flag_ira_share_spill_slots;
- basic_block bb;
-
- timevar_push (TV_IRA);
if (flag_caller_saves)
init_caller_save ();
ira_move_loops_num = ira_additional_jumps_num = 0;
ira_assert (current_loops == NULL);
- flow_loops_find (&ira_loops);
- record_loop_exits ();
- current_loops = &ira_loops;
+ if (flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED)
+ {
+ flow_loops_find (&ira_loops);
+ record_loop_exits ();
+ current_loops = &ira_loops;
+ }
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "Building IRA IR\n");
- loops_p = ira_build (optimize
- && (flag_ira_region == IRA_REGION_ALL
- || flag_ira_region == IRA_REGION_MIXED));
+ loops_p = ira_build ();
ira_assert (ira_conflicts_p || !loops_p);
if (delete_trivially_dead_insns (get_insns (), max_reg_num ()))
df_analyze ();
- grow_reg_equivs ();
-
if (max_regno != max_regno_before_ira)
{
regstat_free_n_sets_and_refs ();
regstat_compute_ri ();
}
- allocate_initial_values (reg_equivs);
-
overall_cost_before = ira_overall_cost;
- if (ira_conflicts_p)
+ if (! ira_conflicts_p)
+ grow_reg_equivs ();
+ else
{
fix_reg_equiv_init ();
memset (ira_spilled_reg_stack_slots, 0,
max_regno * sizeof (struct ira_spilled_reg_stack_slot));
}
+ allocate_initial_values (reg_equivs);
+}
- timevar_pop (TV_IRA);
+static void
+do_reload (void)
+{
+ basic_block bb;
+ bool need_dce;
+
+ if (flag_ira_verbose < 10)
+ ira_dump_file = dump_file;
- timevar_push (TV_RELOAD);
df_set_flags (DF_NO_INSN_RESCAN);
build_insn_chain ();
- reload_completed = !reload (get_insns (), ira_conflicts_p);
-
- timevar_pop (TV_RELOAD);
+ need_dce = reload (get_insns (), ira_conflicts_p);
timevar_push (TV_IRA);
ira_free (ira_spilled_reg_stack_slots);
ira_finish_assign ();
-
}
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL
&& overall_cost_before != ira_overall_cost)
flag_ira_share_spill_slots = saved_flag_ira_share_spill_slots;
- flow_loops_free (&ira_loops);
- free_dominance_info (CDI_DOMINATORS);
+ if (current_loops != NULL)
+ {
+ flow_loops_free (&ira_loops);
+ free_dominance_info (CDI_DOMINATORS);
+ }
FOR_ALL_BB (bb)
bb->loop_father = NULL;
current_loops = NULL;
#endif
/* The code after the reload has changed so much that at this point
- we might as well just rescan everything. Not that
+ we might as well just rescan everything. Note that
df_rescan_all_insns is not going to help here because it does not
touch the artificial uses and defs. */
df_finish_pass (true);
if (optimize)
df_analyze ();
+ if (need_dce && optimize)
+ run_fast_dce ();
+
timevar_pop (TV_IRA);
}
-
\f
-
-static bool
-gate_ira (void)
-{
- return true;
-}
-
/* Run the integrated register allocator. */
static unsigned int
rest_of_handle_ira (void)
{
RTL_PASS,
"ira", /* name */
- gate_ira, /* gate */
+ NULL, /* gate */
rest_of_handle_ira, /* execute */
NULL, /* sub */
NULL, /* next */
0, /* static_pass_number */
- TV_NONE, /* tv_id */
+ TV_IRA, /* tv_id */
+ 0, /* properties_required */
+ 0, /* properties_provided */
+ 0, /* properties_destroyed */
+ 0, /* todo_flags_start */
+ TODO_dump_func /* todo_flags_finish */
+ }
+};
+
+static unsigned int
+rest_of_handle_reload (void)
+{
+ do_reload ();
+ return 0;
+}
+
+struct rtl_opt_pass pass_reload =
+{
+ {
+ RTL_PASS,
+ "reload", /* name */
+ NULL, /* gate */
+ rest_of_handle_reload, /* execute */
+ NULL, /* sub */
+ NULL, /* next */
+ 0, /* static_pass_number */
+ TV_RELOAD, /* tv_id */
0, /* properties_required */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_dump_func |
- TODO_ggc_collect /* todo_flags_finish */
+ TODO_dump_func | TODO_ggc_collect /* todo_flags_finish */
}
};