Account for prologue spills in reg_pressure scheduling
* haifa-sched.c (sched_class_regs_num, call_used_regs_num): New static arrays. Use sched_class_regs_num instead of ira_class_hard_regs_num. (print_curr_reg_pressure, setup_insn_reg_pressure_info,) (model_update_pressure, model_spill_cost): Use sched_class_regs_num. (model_start_schedule): Update. (sched_pressure_start_bb): New static function. Calculate sched_class_regs_num. (schedule_block): Use it. (alloc_global_sched_pressure_data): Calculate call_used_regs_num. From-SVN: r216620
This commit is contained in:
parent
ef1ea28c3c
commit
4dd9ac6c94
|
@ -1,3 +1,15 @@
|
|||
2014-10-24 Maxim Kuvyrkov <maxim.kuvyrkov@gmail.com>
|
||||
|
||||
* haifa-sched.c (sched_class_regs_num, call_used_regs_num): New static
|
||||
arrays. Use sched_class_regs_num instead of ira_class_hard_regs_num.
|
||||
(print_curr_reg_pressure, setup_insn_reg_pressure_info,)
|
||||
(model_update_pressure, model_spill_cost): Use sched_class_regs_num.
|
||||
(model_start_schedule): Update.
|
||||
(sched_pressure_start_bb): New static function. Calculate
|
||||
sched_class_regs_num.
|
||||
(schedule_block): Use it.
|
||||
(alloc_global_sched_pressure_data): Calculate call_used_regs_num.
|
||||
|
||||
2014-10-24 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* Makefile.in (BUILD_CPPLIB): When in stage2+ use the
|
||||
|
|
|
@ -933,6 +933,13 @@ static bitmap saved_reg_live;
|
|||
/* Registers mentioned in the current region. */
|
||||
static bitmap region_ref_regs;
|
||||
|
||||
/* Effective number of available registers of a given class (see comment
|
||||
in sched_pressure_start_bb). */
|
||||
static int sched_class_regs_num[N_REG_CLASSES];
|
||||
/* Number of call_used_regs. This is a helper for calculating of
|
||||
sched_class_regs_num. */
|
||||
static int call_used_regs_num[N_REG_CLASSES];
|
||||
|
||||
/* Initiate register pressure relative info for scheduling the current
|
||||
region. Currently it is only clearing register mentioned in the
|
||||
current region. */
|
||||
|
@ -1116,7 +1123,7 @@ print_curr_reg_pressure (void)
|
|||
gcc_assert (curr_reg_pressure[cl] >= 0);
|
||||
fprintf (sched_dump, " %s:%d(%d)", reg_class_names[cl],
|
||||
curr_reg_pressure[cl],
|
||||
curr_reg_pressure[cl] - ira_class_hard_regs_num[cl]);
|
||||
curr_reg_pressure[cl] - sched_class_regs_num[cl]);
|
||||
}
|
||||
fprintf (sched_dump, "\n");
|
||||
}
|
||||
|
@ -1731,9 +1738,9 @@ setup_insn_reg_pressure_info (rtx_insn *insn)
|
|||
cl = ira_pressure_classes[i];
|
||||
gcc_assert (curr_reg_pressure[cl] >= 0);
|
||||
change = (int) pressure_info[i].set_increase - death[cl];
|
||||
before = MAX (0, max_reg_pressure[i] - ira_class_hard_regs_num[cl]);
|
||||
before = MAX (0, max_reg_pressure[i] - sched_class_regs_num[cl]);
|
||||
after = MAX (0, max_reg_pressure[i] + change
|
||||
- ira_class_hard_regs_num[cl]);
|
||||
- sched_class_regs_num[cl]);
|
||||
hard_regno = ira_class_hard_regs[cl][0];
|
||||
gcc_assert (hard_regno >= 0);
|
||||
mode = reg_raw_mode[hard_regno];
|
||||
|
@ -2070,7 +2077,7 @@ model_update_pressure (struct model_pressure_group *group,
|
|||
|
||||
/* Check whether the maximum pressure in the overall schedule
|
||||
has increased. (This means that the MODEL_MAX_PRESSURE of
|
||||
every point <= POINT will need to increae too; see below.) */
|
||||
every point <= POINT will need to increase too; see below.) */
|
||||
if (group->limits[pci].pressure < ref_pressure)
|
||||
group->limits[pci].pressure = ref_pressure;
|
||||
|
||||
|
@ -2347,7 +2354,7 @@ must_restore_pattern_p (rtx_insn *next, dep_t dep)
|
|||
/* Return the cost of increasing the pressure in class CL from FROM to TO.
|
||||
|
||||
Here we use the very simplistic cost model that every register above
|
||||
ira_class_hard_regs_num[CL] has a spill cost of 1. We could use other
|
||||
sched_class_regs_num[CL] has a spill cost of 1. We could use other
|
||||
measures instead, such as one based on MEMORY_MOVE_COST. However:
|
||||
|
||||
(1) In order for an instruction to be scheduled, the higher cost
|
||||
|
@ -2371,7 +2378,7 @@ must_restore_pattern_p (rtx_insn *next, dep_t dep)
|
|||
static int
|
||||
model_spill_cost (int cl, int from, int to)
|
||||
{
|
||||
from = MAX (from, ira_class_hard_regs_num[cl]);
|
||||
from = MAX (from, sched_class_regs_num[cl]);
|
||||
return MAX (to, from) - from;
|
||||
}
|
||||
|
||||
|
@ -2477,7 +2484,7 @@ model_set_excess_costs (rtx_insn **insns, int count)
|
|||
bool print_p;
|
||||
|
||||
/* Record the baseECC value for each instruction in the model schedule,
|
||||
except that negative costs are converted to zero ones now rather thatn
|
||||
except that negative costs are converted to zero ones now rather than
|
||||
later. Do not assign a cost to debug instructions, since they must
|
||||
not change code-generation decisions. Experiments suggest we also
|
||||
get better results by not assigning a cost to instructions from
|
||||
|
@ -3727,15 +3734,13 @@ model_dump_pressure_summary (void)
|
|||
scheduling region. */
|
||||
|
||||
static void
|
||||
model_start_schedule (void)
|
||||
model_start_schedule (basic_block bb)
|
||||
{
|
||||
basic_block bb;
|
||||
|
||||
model_next_priority = 1;
|
||||
model_schedule.create (sched_max_luid);
|
||||
model_insns = XCNEWVEC (struct model_insn_info, sched_max_luid);
|
||||
|
||||
bb = BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head));
|
||||
gcc_assert (bb == BLOCK_FOR_INSN (NEXT_INSN (current_sched_info->prev_head)));
|
||||
initiate_reg_pressure_info (df_get_live_in (bb));
|
||||
|
||||
model_analyze_insns ();
|
||||
|
@ -3773,6 +3778,53 @@ model_end_schedule (void)
|
|||
model_finalize_pressure_group (&model_before_pressure);
|
||||
model_schedule.release ();
|
||||
}
|
||||
|
||||
/* Prepare reg pressure scheduling for basic block BB. */
|
||||
static void
|
||||
sched_pressure_start_bb (basic_block bb)
|
||||
{
|
||||
/* Set the number of available registers for each class taking into account
|
||||
relative probability of current basic block versus function prologue and
|
||||
epilogue.
|
||||
* If the basic block executes much more often than the prologue/epilogue
|
||||
(e.g., inside a hot loop), then cost of spill in the prologue is close to
|
||||
nil, so the effective number of available registers is
|
||||
(ira_class_hard_regs_num[cl] - 0).
|
||||
* If the basic block executes as often as the prologue/epilogue,
|
||||
then spill in the block is as costly as in the prologue, so the effective
|
||||
number of available registers is
|
||||
(ira_class_hard_regs_num[cl] - call_used_regs_num[cl]).
|
||||
Note that all-else-equal, we prefer to spill in the prologue, since that
|
||||
allows "extra" registers for other basic blocks of the function.
|
||||
* If the basic block is on the cold path of the function and executes
|
||||
rarely, then we should always prefer to spill in the block, rather than
|
||||
in the prologue/epilogue. The effective number of available register is
|
||||
(ira_class_hard_regs_num[cl] - call_used_regs_num[cl]). */
|
||||
{
|
||||
int i;
|
||||
int entry_freq = ENTRY_BLOCK_PTR_FOR_FN (cfun)->frequency;
|
||||
int bb_freq = bb->frequency;
|
||||
|
||||
if (bb_freq == 0)
|
||||
{
|
||||
if (entry_freq == 0)
|
||||
entry_freq = bb_freq = 1;
|
||||
}
|
||||
if (bb_freq < entry_freq)
|
||||
bb_freq = entry_freq;
|
||||
|
||||
for (i = 0; i < ira_pressure_classes_num; ++i)
|
||||
{
|
||||
enum reg_class cl = ira_pressure_classes[i];
|
||||
sched_class_regs_num[cl] = ira_class_hard_regs_num[cl];
|
||||
sched_class_regs_num[cl]
|
||||
-= (call_used_regs_num[cl] * entry_freq) / bb_freq;
|
||||
}
|
||||
}
|
||||
|
||||
if (sched_pressure == SCHED_PRESSURE_MODEL)
|
||||
model_start_schedule (bb);
|
||||
}
|
||||
|
||||
/* A structure that holds local state for the loop in schedule_block. */
|
||||
struct sched_block_state
|
||||
|
@ -6053,8 +6105,8 @@ schedule_block (basic_block *target_bb, state_t init_state)
|
|||
in try_ready () (which is called through init_ready_list ()). */
|
||||
(*current_sched_info->init_ready_list) ();
|
||||
|
||||
if (sched_pressure == SCHED_PRESSURE_MODEL)
|
||||
model_start_schedule ();
|
||||
if (sched_pressure)
|
||||
sched_pressure_start_bb (*target_bb);
|
||||
|
||||
/* The algorithm is O(n^2) in the number of ready insns at any given
|
||||
time in the worst case. Before reload we are more likely to have
|
||||
|
@ -6701,6 +6753,19 @@ alloc_global_sched_pressure_data (void)
|
|||
saved_reg_live = BITMAP_ALLOC (NULL);
|
||||
region_ref_regs = BITMAP_ALLOC (NULL);
|
||||
}
|
||||
|
||||
/* Calculate number of CALL_USED_REGS in register classes that
|
||||
we calculate register pressure for. */
|
||||
for (int c = 0; c < ira_pressure_classes_num; ++c)
|
||||
{
|
||||
enum reg_class cl = ira_pressure_classes[c];
|
||||
|
||||
call_used_regs_num[cl] = 0;
|
||||
|
||||
for (int i = 0; i < ira_class_hard_regs_num[cl]; ++i)
|
||||
if (call_used_regs[ira_class_hard_regs[cl][i]])
|
||||
++call_used_regs_num[cl];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue