Commit 4f7329d7 authored by Matthias Braun's avatar Matthias Braun
Browse files

more intelligent spill placement, should move spills out of loops in most cases

[r16200]
parent 2176caea
......@@ -59,8 +59,8 @@ static INLINE int _value_strictly_dominates_intrablock(const ir_node *a, const i
*/
static INLINE int _value_dominates(const ir_node *a, const ir_node *b)
{
const ir_node *block_a = get_block(a);
const ir_node *block_b = get_block(b);
const ir_node *block_a = get_block_const(a);
const ir_node *block_b = get_block_const(b);
/*
* a and b are not in the same block,
......@@ -85,8 +85,8 @@ static INLINE int _value_dominates(const ir_node *a, const ir_node *b)
*/
static INLINE int _value_strictly_dominates(const ir_node *a, const ir_node *b)
{
const ir_node *block_a = get_block(a);
const ir_node *block_b = get_block(b);
const ir_node *block_a = get_block_const(a);
const ir_node *block_b = get_block_const(b);
/*
* a and b are not in the same block,
......
......@@ -1073,16 +1073,15 @@ int be_get_IncSP_offset(const ir_node *irn)
return a->offset;
}
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn)
ir_node *be_spill(const arch_env_t *arch_env, ir_node *block, ir_node *irn)
{
ir_node *bl = get_nodes_block(irn);
ir_graph *irg = get_irn_irg(bl);
ir_graph *irg = get_irn_irg(block);
ir_node *frame = get_irg_frame(irg);
const arch_register_class_t *cls = arch_get_irn_reg_class(arch_env, irn, -1);
const arch_register_class_t *cls_frame = arch_get_irn_reg_class(arch_env, frame, -1);
ir_node *spill;
spill = be_new_Spill(cls, cls_frame, irg, bl, frame, irn);
spill = be_new_Spill(cls, cls_frame, irg, block, frame, irn);
return spill;
}
......
......@@ -379,7 +379,7 @@ ir_node *be_RegParams_append_out_reg(ir_node *regparams,
* @param spill_ctx The context in which the spill is introduced (This is mostly == irn up to the case of Phis).
* @return The new spill node.
*/
ir_node *be_spill(const arch_env_t *arch_env, ir_node *irn);
ir_node *be_spill(const arch_env_t *arch_env, ir_node *block, ir_node *irn);
/**
* Make a reload and insert it into the schedule.
......
......@@ -48,7 +48,7 @@ ir_node *sched_prev(const ir_node *irn);
ir_node *sched_first(const ir_node *block);
ir_node *sched_last(const ir_node *block);
void sched_add_before(ir_node *before, ir_node *irn);
void sched_add_after(ir_node *before, ir_node *irn);
void sched_add_after(ir_node *after, ir_node *irn);
void sched_init_block(ir_node *block);
void sched_reset(ir_node *node);
void sched_remove(ir_node *irn);
......
This diff is collapsed.
......@@ -48,6 +48,11 @@ void be_delete_spill_env(spill_env_t *senv);
ir_node *be_get_end_of_block_insertion_point(const ir_node *block);
/**
* marks a point until which a node must be spilled
*/
void be_add_spill(spill_env_t *senv, ir_node *to_spill, ir_node *before);
/**
* Inserts a new entry into the list of reloads to place (the real nodes will
* be created when be_insert_spills_reloads is run). You don't have to
......@@ -112,7 +117,7 @@ void be_spill_phi(spill_env_t *env, ir_node *node);
* instructions. The value is weighted by the estimated execution frequency of
* the spill.
*/
double be_get_spill_costs(spill_env_t *env, ir_node *to_spill, ir_node *after);
double be_get_spill_costs(spill_env_t *env, ir_node *to_spill, ir_node *before);
/**
* Returns the estimated costs if a node would get reloaded at a specific place
......
......@@ -329,7 +329,12 @@ static void displace(belady_env_t *env, workset_t *new_vals, int is_usage) {
for (i = max_allowed; i < ws->len; ++i) {
ir_node *irn = ws->vals[i].irn;
DBG((dbg, DBG_DECIDE, " disposing %+F (%u)\n", irn, workset_get_time(ws, i)));
DBG((dbg, DBG_DECIDE, " disposing %+F (%u)\n", irn,
workset_get_time(ws, i)));
if(!USES_IS_INFINITE(ws->vals[i].time)) {
be_add_spill(env->senv, irn, env->instr);
}
if (is_Phi(irn))
continue;
......@@ -479,9 +484,9 @@ static void compute_live_ins(ir_node *block, void *data) {
}
/* spill all delayed phis which didn't make it into start workset */
for (i = ARR_LEN(delayed) - 1; i >= 0; --i) {
for ( ; i < ARR_LEN(delayed); ++i) {
ir_node *irn = delayed[i].irn;
if (irn && is_Phi(irn)) {
if (irn && is_Phi(irn) && get_nodes_block(irn) == block) {
DBG((dbg, DBG_START, " spilling delayed phi %+F\n", irn));
be_spill_phi(env->senv, irn);
}
......@@ -637,56 +642,78 @@ static void belady(ir_node *block, void *data) {
* about the set of live-ins. Thus we must adapt the
* live-outs to the live-ins at each block-border.
*/
static void fix_block_borders(ir_node *block, void *data) {
belady_env_t *env = data;
workset_t *wsb;
ir_graph *irg = get_irn_irg(block);
ir_node *startblock = get_irg_start_block(irg);
int i, max, iter, iter2;
if(block == startblock)
return;
static void fix_block_borders(ir_node *block, void *data)
{
ir_graph *irg = get_irn_irg(block);
ir_node *startblock = get_irg_start_block(irg);
belady_env_t *env = data;
workset_t *start_workset;
int arity;
int i;
int iter;
if(block == startblock)
return;
DBG((dbg, DBG_FIX, "\n"));
DBG((dbg, DBG_FIX, "Fixing %+F\n", block));
wsb = get_block_info(block)->ws_start;
start_workset = get_block_info(block)->ws_start;
/* process all pred blocks */
for (i=0, max=get_irn_arity(block); i<max; ++i) {
ir_node *irnb, *irnp, *pred = get_Block_cfgpred_block(block, i);
workset_t *wsp = get_block_info(pred)->ws_end;
arity = get_irn_arity(block);
for (i = 0; i < arity; ++i) {
ir_node *pred = get_Block_cfgpred_block(block, i);
workset_t *workset_pred_end = get_block_info(pred)->ws_end;
ir_node *node;
DBG((dbg, DBG_FIX, " Pred %+F\n", pred));
workset_foreach(wsb, irnb, iter) {
/* if irnb is a phi of the current block we reload
* the corresponding argument, else irnb itself */
if(is_Phi(irnb) && block == get_nodes_block(irnb)) {
irnb = get_irn_n(irnb, i);
/* spill all values not used anymore */
workset_foreach(workset_pred_end, node, iter) {
ir_node *n2;
int iter2;
int found = 0;
workset_foreach(start_workset, n2, iter2) {
if(n2 == node) {
found = 1;
break;
}
/* note that we do not look at phi inputs, becuase the values
* will be either live-end and need no spill or
* they have other users in which must be somewhere else in the
* workset */
}
// we might have unknowns as argument for the phi
if(!arch_irn_consider_in_reg_alloc(env->arch, env->cls, irnb))
continue;
if(!found && be_is_live_out(env->lv, pred, node)) {
ir_node *insert_point
= be_get_end_of_block_insertion_point(pred);
DBG((dbg, DBG_SPILL, "Spill %+F before %+F\n", node,
insert_point));
be_add_spill(env->senv, node, insert_point);
}
}
/* Unknowns are available everywhere */
if(get_irn_opcode(irnb) == iro_Unknown)
continue;
/* reload missing values in predecessors */
workset_foreach(start_workset, node, iter) {
/* if node is a phi of the current block we reload
* the corresponding argument, else node itself */
if(is_Phi(node) && block == get_nodes_block(node)) {
node = get_irn_n(node, i);
/* check if irnb is in a register at end of pred */
workset_foreach(wsp, irnp, iter2) {
if (irnb == irnp)
goto next_value;
/* we might have unknowns as argument for the phi */
if(!arch_irn_consider_in_reg_alloc(env->arch, env->cls, node))
continue;
}
/* irnb is not in memory at the end of pred, so we have to reload it */
DBG((dbg, DBG_FIX, " reload %+F\n", irnb));
DBG((dbg, DBG_SPILL, "Reload %+F before %+F,%d\n", irnb, block, i));
be_add_reload_on_edge(env->senv, irnb, block, i, env->cls, 1);
/* check if node is in a register at end of pred */
if(workset_contains(workset_pred_end, node))
continue;
next_value:
/*epsilon statement :)*/;
/* node is not in memory at the end of pred -> reload it */
DBG((dbg, DBG_FIX, " reload %+F\n", node));
DBG((dbg, DBG_SPILL, "Reload %+F before %+F,%d\n", node, block, i));
be_add_reload_on_edge(env->senv, node, block, i, env->cls, 1);
}
}
}
......
......@@ -54,7 +54,12 @@ pset *be_empty_set(void);
* @return The block of the node, or the node itself, if the node is a
* block.
*/
static INLINE const ir_node *get_block(const ir_node *irn)
static INLINE ir_node *get_block(ir_node *irn)
{
return is_Block(irn) ? irn : get_nodes_block(irn);
}
static INLINE const ir_node *get_block_const(const ir_node *irn)
{
return is_Block(irn) ? irn : get_nodes_block(irn);
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment