Commit 589eed20 authored by Matthias Braun's avatar Matthias Braun
Browse files

bespillutil: cleanup, use C99

parent 380a9059
......@@ -310,7 +310,7 @@ static void displace(workset_t *const new_vals, bool const is_usage,
DB((dbg, DBG_DECIDE, " insert %+F\n", val));
if (is_usage) {
DB((dbg, DBG_SPILL, "Reload %+F before %+F\n", val, instr));
be_add_reload(senv, val, instr, cls, 1);
be_add_reload(senv, val, instr);
reloaded = true;
}
} else {
......@@ -827,7 +827,7 @@ static void fix_block_borders(ir_node *block, void *data)
/* node is not in register at the end of pred -> reload it */
DB((dbg, DBG_FIX, " reload %+F\n", node));
DB((dbg, DBG_SPILL, "Reload %+F before %+F,%d\n", node, block, i));
be_add_reload_on_edge(senv, node, block, i, cls, 1);
be_add_reload_on_edge(senv, node, block, i);
}
}
}
......
......@@ -108,9 +108,9 @@ static void spill_node(ir_node *node)
int in = get_edge_src_pos(edge);
ir_node *block = get_nodes_block(use);
be_add_reload_on_edge(spill_env, node, block, in, cls, 1);
be_add_reload_on_edge(spill_env, node, block, in);
} else {
be_add_reload(spill_env, node, use, cls, 1);
be_add_reload(spill_env, node, use);
}
}
......
......@@ -50,7 +50,7 @@ struct reloader_t {
ir_node *reloader;
ir_node *rematted_node;
int remat_cost_delta; /** costs needed for rematerialization,
compared to placing a reload */
compared to placing a reload */
};
typedef struct spill_t spill_t;
......@@ -62,14 +62,12 @@ struct spill_t {
typedef struct spill_info_t spill_info_t;
struct spill_info_t {
ir_node *to_spill; /**< the value that should get spilled */
reloader_t *reloaders; /**< list of places where the value should get
reloaded */
spill_t *spills; /**< list of latest places where spill must be
placed */
ir_node *to_spill; /**< the value that should get spilled */
reloader_t *reloaders; /**< list of places where the value should get
reloaded */
spill_t *spills; /**< list of latest places where spill must be
placed */
double spill_costs; /**< costs needed for spilling the value */
const arch_register_class_t *reload_cls; /** the register class in which the
reload should be placed */
bool spilled_phi; /* true when the whole Phi has been spilled and
will be replaced with a PhiM. false if only the
value of the Phi gets spilled */
......@@ -78,13 +76,12 @@ struct spill_info_t {
struct spill_env_t {
const arch_env_t *arch_env;
ir_graph *irg;
set *spills; /**< all spill_info_t's, which must be
placed */
spill_info_t **mem_phis; /**< set of all spilled phis. */
struct obstack obst;
int spill_cost; /**< the cost of a single spill node */
int reload_cost; /**< the cost of a reload node */
set *spills; /**< all spill_info_t's, which must be
placed */
spill_info_t **mem_phis; /**< set of all spilled phis. */
int spill_cost; /**< the cost of a single spill node */
int reload_cost; /**< the cost of a reload node */
unsigned spill_count;
unsigned reload_count;
unsigned remat_count;
......@@ -96,10 +93,9 @@ struct spill_env_t {
*/
static int cmp_spillinfo(const void *x, const void *y, size_t size)
{
(void)size;
const spill_info_t *xx = (const spill_info_t*)x;
const spill_info_t *yy = (const spill_info_t*)y;
(void) size;
return xx->to_spill != yy->to_spill;
}
......@@ -108,17 +104,15 @@ static int cmp_spillinfo(const void *x, const void *y, size_t size)
*/
static spill_info_t *get_spillinfo(const spill_env_t *env, ir_node *value)
{
spill_info_t info, *res;
int hash = hash_irn(value);
spill_info_t info;
info.to_spill = value;
res = set_find(spill_info_t, env->spills, &info, sizeof(info), hash);
int hash = hash_irn(value);
spill_info_t *res = set_find(spill_info_t, env->spills, &info, sizeof(info), hash);
if (res == NULL) {
info.reloaders = NULL;
info.spills = NULL;
info.spill_costs = -1;
info.reload_cls = NULL;
info.spilled_phi = false;
res = set_insert(spill_info_t, env->spills, &info, sizeof(info), hash);
}
......@@ -155,22 +149,8 @@ void be_delete_spill_env(spill_env_t *env)
free(env);
}
/*
* ____ _ ____ _ _
* | _ \| | __ _ ___ ___ | _ \ ___| | ___ __ _ __| |___
* | |_) | |/ _` |/ __/ _ \ | |_) / _ \ |/ _ \ / _` |/ _` / __|
* | __/| | (_| | (_| __/ | _ < __/ | (_) | (_| | (_| \__ \
* |_| |_|\__,_|\___\___| |_| \_\___|_|\___/ \__,_|\__,_|___/
*
*/
void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *after)
{
spill_info_t *spill_info = get_spillinfo(env, to_spill);
spill_t *spill;
spill_t *s;
spill_t *last;
assert(!arch_irn_is(skip_Proj_const(to_spill), dont_spill));
DB((dbg, LEVEL_1, "Add spill of %+F after %+F\n", to_spill, after));
......@@ -178,9 +158,9 @@ void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *after)
assert(!is_Phi(sched_next(after)));
/* spills that are dominated by others are not needed */
last = NULL;
s = spill_info->spills;
for ( ; s != NULL; s = s->next) {
spill_info_t *spill_info = get_spillinfo(env, to_spill);
for (spill_t *s = spill_info->spills, *last = NULL ; s != NULL;
s = s->next) {
/* no need to add this spill if it is dominated by another */
if (value_dominates(s->after, after)) {
DB((dbg, LEVEL_1, "...dominated by %+F, not added\n", s->after));
......@@ -199,23 +179,19 @@ void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *after)
}
}
spill = OALLOC(&env->obst, spill_t);
spill->after = after;
spill->next = spill_info->spills;
spill->spill = NULL;
spill_t *spill = OALLOC(&env->obst, spill_t);
spill->after = after;
spill->next = spill_info->spills;
spill->spill = NULL;
spill_info->spills = spill;
}
void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before, const arch_register_class_t *reload_cls, int allow_remat)
void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before)
{
spill_info_t *info;
reloader_t *rel;
assert(!arch_irn_is(skip_Proj_const(to_spill), dont_spill));
assert(!be_is_Keep(before));
info = get_spillinfo(env, to_spill);
spill_info_t *info = get_spillinfo(env, to_spill);
if (is_Phi(to_spill)) {
/* create spillinfos for the phi arguments */
foreach_irn_in(to_spill, i, arg) {
......@@ -223,21 +199,18 @@ void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before, const a
}
}
assert(!be_is_Keep(before));
/* put reload into list */
rel = OALLOC(&env->obst, reloader_t);
reloader_t *rel = OALLOC(&env->obst, reloader_t);
rel->next = info->reloaders;
rel->reloader = before;
rel->rematted_node = NULL;
rel->remat_cost_delta = allow_remat ? 0 : REMAT_COST_INFINITE;
rel->remat_cost_delta = 0;
info->reloaders = rel;
assert(info->reload_cls == NULL || info->reload_cls == reload_cls);
info->reload_cls = reload_cls;
info->reloaders = rel;
DBG((dbg, LEVEL_1, "creating spillinfo for %+F, will be reloaded before %+F, may%s be rematerialized\n",
to_spill, before, allow_remat ? "" : " not"));
DBG((dbg, LEVEL_1,
"creating spillinfo for %+F, will be reloaded before %+F\n",
to_spill, before));
}
ir_node *be_get_end_of_block_insertion_point(const ir_node *block)
......@@ -260,16 +233,16 @@ ir_node *be_get_end_of_block_insertion_point(const ir_node *block)
* determine final spill position: it should be after all phis, keep nodes
* and behind nodes marked as prolog
*/
static ir_node *determine_spill_point(ir_node *node)
static ir_node *determine_spill_point(ir_node *const node)
{
node = skip_Proj(node);
ir_node *n = skip_Proj(node);
while (true) {
ir_node *next = sched_next(node);
ir_node *next = sched_next(n);
if (!is_Phi(next) && !be_is_Keep(next) && !be_is_CopyKeep(next))
break;
node = next;
n = next;
}
return node;
return n;
}
/**
......@@ -278,8 +251,6 @@ static ir_node *determine_spill_point(ir_node *node)
*/
static ir_node *get_block_insertion_point(ir_node *block, int pos)
{
ir_node *predblock;
/* simply add the reload to the beginning of the block if we only have 1
* predecessor. We don't need to check for phis as there can't be any in a
* block with only 1 pred. */
......@@ -289,36 +260,31 @@ static ir_node *get_block_insertion_point(ir_node *block, int pos)
}
/* We have to reload the value in pred-block */
predblock = get_Block_cfgpred_block(block, pos);
ir_node *predblock = get_Block_cfgpred_block(block, pos);
return be_get_end_of_block_insertion_point(predblock);
}
void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block,
int pos, const arch_register_class_t *reload_cls,
int allow_remat)
int pos)
{
ir_node *before = get_block_insertion_point(block, pos);
be_add_reload(env, to_spill, before, reload_cls, allow_remat);
be_add_reload(env, to_spill, before);
}
void be_spill_phi(spill_env_t *env, ir_node *node)
{
ir_node *block;
spill_info_t *info;
assert(is_Phi(node));
info = get_spillinfo(env, node);
spill_info_t *info = get_spillinfo(env, node);
info->spilled_phi = true;
ARR_APP1(spill_info_t*, env->mem_phis, info);
/* create spills for the phi arguments */
block = get_nodes_block(node);
ir_node *block = get_nodes_block(node);
foreach_irn_in(node, i, arg) {
ir_node *insert;
/* some backends have virtual noreg/unknown nodes that are not scheduled
* and simply always available. */
ir_node *insert;
if (!sched_is_scheduled(arg)) {
ir_node *pred_block = get_Block_cfgpred_block(block, i);
insert = be_get_end_of_block_insertion_point(pred_block);
......@@ -326,20 +292,10 @@ void be_spill_phi(spill_env_t *env, ir_node *node)
} else {
insert = determine_spill_point(arg);
}
be_add_spill(env, arg, insert);
}
}
/*
* ____ _ ____ _ _ _
* / ___|_ __ ___ __ _| |_ ___ / ___| _ __ (_) | |___
* | | | '__/ _ \/ _` | __/ _ \ \___ \| '_ \| | | / __|
* | |___| | | __/ (_| | || __/ ___) | |_) | | | \__ \
* \____|_| \___|\__,_|\__\___| |____/| .__/|_|_|_|___/
* |_|
*/
static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo);
/**
......@@ -348,20 +304,17 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo);
* @param senv the spill environment
* @param irn the node that should be spilled
* @param ctx_irn an user of the spilled node
*
* @return a be_Spill node
*/
static void spill_irn(spill_env_t *env, spill_info_t *spillinfo)
{
ir_node *to_spill = spillinfo->to_spill;
const ir_node *insn = skip_Proj_const(to_spill);
spill_t *spill;
/* determine_spill_costs must have been run before */
assert(spillinfo->spill_costs >= 0);
/* some backends have virtual noreg/unknown nodes that are not scheduled
* and simply always available. */
ir_node *to_spill = spillinfo->to_spill;
const ir_node *insn = skip_Proj_const(to_spill);
if (!sched_is_scheduled(insn)) {
/* override spillinfos or create a new one */
ir_graph *irg = get_irn_irg(to_spill);
......@@ -371,8 +324,8 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo)
}
DBG((dbg, LEVEL_1, "spilling %+F ... \n", to_spill));
spill = spillinfo->spills;
for ( ; spill != NULL; spill = spill->next) {
for (spill_t *spill = spillinfo->spills; spill != NULL;
spill = spill->next) {
ir_node *after = spill->after;
after = determine_spill_point(after);
......@@ -397,27 +350,25 @@ static void spill_node(spill_env_t *env, spill_info_t *spillinfo);
*/
static void spill_phi(spill_env_t *env, spill_info_t *spillinfo)
{
ir_graph *irg = env->irg;
ir_node *phi = spillinfo->to_spill;
ir_node *block = get_nodes_block(phi);
spill_t *spill;
assert(!get_opt_cse());
ir_node *phi = spillinfo->to_spill;
DBG((dbg, LEVEL_1, "spilling Phi %+F:\n", phi));
/* build a new PhiM */
int const arity = get_Phi_n_preds(phi);
ir_node **const ins = ALLOCAN(ir_node*, arity);
ir_graph *const irg = env->irg;
ir_node *const unknown = new_r_Unknown(irg, mode_M);
for (int i = 0; i < arity; ++i) {
ins[i] = unknown;
}
/* override or replace spills list... */
spill = OALLOC(&env->obst, spill_t);
spill->after = determine_spill_point(phi);
spill->spill = be_new_Phi(block, arity, ins, mode_M, arch_no_register_req);
spill->next = NULL;
ir_node *block = get_nodes_block(phi);
spill_t *spill = OALLOC(&env->obst, spill_t);
spill->after = determine_spill_point(phi);
spill->spill = be_new_Phi(block, arity, ins, mode_M, arch_no_register_req);
spill->next = NULL;
sched_add_after(block, spill->spill);
spillinfo->spills = spill;
......@@ -454,44 +405,25 @@ static void spill_node(spill_env_t *env, spill_info_t *spillinfo)
}
}
/*
*
* ____ _ _ _ _
* | _ \ ___ _ __ ___ __ _| |_ ___ _ __(_) __ _| (_)_______
* | |_) / _ \ '_ ` _ \ / _` | __/ _ \ '__| |/ _` | | |_ / _ \
* | _ < __/ | | | | | (_| | || __/ | | | (_| | | |/ / __/
* |_| \_\___|_| |_| |_|\__,_|\__\___|_| |_|\__,_|_|_/___\___|
*
*/
/**
* Tests whether value @p arg is available before node @p reloader
* @returns 1 if value is available, 0 otherwise
* @returns true if value is available
*/
static int is_value_available(spill_env_t *env, const ir_node *arg,
const ir_node *reloader)
static bool is_value_available(spill_env_t *env, const ir_node *arg)
{
if (is_Unknown(arg) || is_NoMem(arg))
return 1;
return true;
if (arch_irn_is(skip_Proj_const(arg), spill))
return 1;
return true;
if (arg == get_irg_frame(env->irg))
return 1;
(void)reloader;
return true;
if (get_irn_mode(arg) == mode_T)
return 0;
/*
* Ignore registers are always available
*/
return false;
/* "Ignore registers" are always available */
if (arch_irn_is_ignore(arg))
return 1;
return true;
return 0;
return false;
}
/**
......@@ -505,17 +437,17 @@ static int is_value_available(spill_env_t *env, const ir_node *arg,
* >= REMAT_COST_INFINITE if remat is not possible.
*/
static int check_remat_conditions_costs(spill_env_t *env,
const ir_node *spilled, const ir_node *reloader, int parentcosts)
const ir_node *spilled,
const ir_node *reloader,
int parentcosts)
{
int argremats;
int costs = 0;
const ir_node *insn = skip_Proj_const(spilled);
assert(!arch_irn_is(insn, spill));
if (!arch_irn_is(insn, rematerializable))
return REMAT_COST_INFINITE;
costs += arch_get_op_estimated_cost(insn);
int costs = arch_get_op_estimated_cost(insn);
if (parentcosts + costs >= env->reload_cost + env->spill_cost)
return REMAT_COST_INFINITE;
......@@ -523,13 +455,12 @@ static int check_remat_conditions_costs(spill_env_t *env,
* (would be better to test whether the flags are actually live at point
* reloader...)
*/
if (arch_irn_is(insn, modify_flags)) {
if (arch_irn_is(insn, modify_flags))
return REMAT_COST_INFINITE;
}
argremats = 0;
int argremats = 0;
foreach_irn_in(insn, i, arg) {
if (is_value_available(env, arg, reloader))
if (is_value_available(env, arg))
continue;
/* we have to rematerialize the argument as well */
......@@ -558,11 +489,9 @@ static int check_remat_conditions_costs(spill_env_t *env,
*/
static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
{
ir_node **ins;
ins = ALLOCAN(ir_node*, get_irn_arity(spilled));
ir_node **ins = ALLOCAN(ir_node*, get_irn_arity(spilled));
foreach_irn_in(spilled, i, arg) {
if (is_value_available(env, arg, reloader)) {
if (is_value_available(env, arg)) {
ins[i] = arg;
} else {
ins[i] = do_remat(env, arg, reloader);
......@@ -576,9 +505,10 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
ir_node *const res = new_similar_node(spilled, bl, ins);
arch_env_mark_remat(env->arch_env, res);
DBG((dbg, LEVEL_1, "Insert remat %+F of %+F before reloader %+F\n", res, spilled, reloader));
DBG((dbg, LEVEL_1, "Insert remat %+F of %+F before reloader %+F\n", res,
spilled, reloader));
if (! is_Proj(res)) {
if (!is_Proj(res)) {
/* insert in schedule */
sched_reset(res);
sched_add_before(reloader, res);
......@@ -590,14 +520,14 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader)
double be_get_spill_costs(spill_env_t *env, ir_node *to_spill, ir_node *before)
{
(void)to_spill;
ir_node *block = get_nodes_block(before);
double freq = get_block_execfreq(block);
(void) to_spill;
return env->spill_cost * freq;
}
unsigned be_get_reload_costs_no_weight(spill_env_t *env, const ir_node *to_spill,
unsigned be_get_reload_costs_no_weight(spill_env_t *env,
const ir_node *to_spill,
const ir_node *before)
{
if (be_do_remats) {
......@@ -625,8 +555,8 @@ double be_get_reload_costs(spill_env_t *env, ir_node *to_spill, ir_node *before)
return env->reload_cost * freq;
}
int be_is_rematerializable(spill_env_t *env, const ir_node *to_remat,
const ir_node *before)
bool be_is_rematerializable(spill_env_t *env, const ir_node *to_remat,
const ir_node *before)
{
return check_remat_conditions_costs(env, to_remat, before, 0) < REMAT_COST_INFINITE;
}
......@@ -638,30 +568,17 @@ double be_get_reload_costs_on_edge(spill_env_t *env, ir_node *to_spill,
return be_get_reload_costs(env, to_spill, before);
}
/*
* ___ _ ____ _ _
* |_ _|_ __ ___ ___ _ __| |_ | _ \ ___| | ___ __ _ __| |___
* | || '_ \/ __|/ _ \ '__| __| | |_) / _ \ |/ _ \ / _` |/ _` / __|
* | || | | \__ \ __/ | | |_ | _ < __/ | (_) | (_| | (_| \__ \
* |___|_| |_|___/\___|_| \__| |_| \_\___|_|\___/ \__,_|\__,_|___/
*
*/
/**
* analyzes how to best spill a node and determine costs for that
*/
static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
{
ir_node *to_spill = spillinfo->to_spill;
const ir_node *insn = skip_Proj_const(to_spill);
ir_node *spill_block;
spill_t *spill;
double spill_execfreq;
/* already calculated? */
if (spillinfo->spill_costs >= 0)
return;
ir_node *to_spill = spillinfo->to_spill;
const ir_node *insn = skip_Proj_const(to_spill);
assert(!arch_irn_is(insn, dont_spill));
assert(!arch_irn_is(insn, reload));
......@@ -685,8 +602,8 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
return;
}
spill_block = get_nodes_block(insn);
spill_execfreq = get_block_execfreq(spill_block);
ir_node *spill_block = get_nodes_block(insn);
double spill_execfreq = get_block_execfreq(spill_block);
if (spillinfo->spilled_phi) {
/* TODO calculate correct costs...
......@@ -696,15 +613,11 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
}
if (spillinfo->spills != NULL) {
spill_t *s;
double spills_execfreq;
/* calculate sum of execution frequencies of individual spills */
spills_execfreq = 0;
s = spillinfo->spills;
for ( ; s != NULL; s = s->next) {
double spills_execfreq = 0;
for (spill_t *s = spillinfo->spills; s != NULL; s = s->next) {
ir_node *spill_block = get_block(s->after);
double freq = get_block_execfreq(spill_block);
double freq = get_block_execfreq(spill_block);
spills_execfreq += freq;
}
......@@ -722,10 +635,10 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
}
/* override spillinfos or create a new one */
spill = OALLOC(&env->obst, spill_t);
spill->after = determine_spill_point(to_spill);
spill->next = NULL;
spill->spill = NULL;
spill_t *spill = OALLOC(&env->obst, spill_t);
spill->after = determine_spill_point(to_spill);
spill->next = NULL;
spill->spill = NULL;
spillinfo->spills = spill;
spillinfo->spill_costs = spill_execfreq * env->spill_cost;
......@@ -735,30 +648,26 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo)
void make_spill_locations_dominate_irn(spill_env_t *env, ir_node *irn)
{
const spill_info_t *si = get_spillinfo(env, irn);
ir_node *start_block = get_irg_start_block(get_irn_irg(irn));
int n_blocks = get_Block_dom_max_subtree_pre_num(start_block);
bitset_t *reloads = bitset_alloca(n_blocks);
reloader_t *r;
spill_t *s;
if (si == NULL)
return;
/* Fill the bitset with the dominance pre-order numbers
* of the blocks the reloads are located in. */
for (r = si->reloaders; r != NULL; r = r->next) {
ir_node *bl = get_nodes_block(r->reloader);
bitset_set(reloads, get_Block_dom_tree_pre_num(bl));
ir_node *start_block = get_irg_start_block(get_irn_irg(irn));
unsigned n_blocks = get_Block_dom_max_subtree_pre_num(start_block);
bitset_t *reloads = bitset_alloca(n_blocks);
for (reloader_t *r = si->reloaders; r != NULL; r = r->next) {
ir_node *block = get_nodes_block(r->reloader);
bitset_set(reloads, get_Block_dom_tree_pre_num(block));
}
/* Now, cancel out all the blocks that are dominated by each spill.
* If the bitset is not empty after that, we have reloads that are
* not dominated by any spill. */
for (s = si->spills; s != NULL; s = s->next) {
ir_node *bl = get_nodes_block(s->after);
int start = get_Block_dom_tree_pre_num(bl);
int end = get_Block_dom_max_subtree_pre_num(bl);
for (spill_t *s = si->spills; s != NULL; s = s->next) {
ir_node *block = get_nodes_block(s->after);
unsigned start = get_Block_dom_tree_pre_num(block);