/* 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. */
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");
}
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];
/* 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;
/* 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
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;
}
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
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 ();
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);
+}
\f
/* A structure that holds local state for the loop in schedule_block. */
struct sched_block_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
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];
+ }
}
}