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:
Maxim Kuvyrkov 2014-10-24 08:22:12 +00:00 committed by Maxim Kuvyrkov
parent ef1ea28c3c
commit 4dd9ac6c94
2 changed files with 90 additions and 13 deletions

View File

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

View File

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