typedef struct reloader_t reloader_t;
struct reloader_t {
reloader_t *next;
+ ir_node *can_spill_after;
ir_node *reloader;
ir_node *rematted_node;
int remat_cost_delta; /** costs needed for rematerialization,
to_spill, before));
}
-void be_add_reload(spill_env_t *env, ir_node *to_spill, ir_node *before,
+void be_add_reload2(spill_env_t *env, ir_node *to_spill, ir_node *before, ir_node *can_spill_after,
const arch_register_class_t *reload_cls, int allow_remat)
{
spill_info_t *info;
assert(!is_Proj(before) && !be_is_Keep(before));
/* put reload into list */
- rel = obstack_alloc(&env->obst, sizeof(rel[0]));
- rel->next = info->reloaders;
- rel->reloader = before;
- rel->rematted_node = NULL;
- if(!allow_remat) {
- rel->remat_cost_delta = REMAT_COST_INFINITE;
- } else {
- rel->remat_cost_delta = 0;
- }
+ rel = obstack_alloc(&env->obst, sizeof(rel[0]));
+ rel->next = info->reloaders;
+ rel->reloader = before;
+ rel->rematted_node = NULL;
+ rel->can_spill_after = can_spill_after;
+ rel->remat_cost_delta = allow_remat ? 0 : REMAT_COST_INFINITE;
info->reloaders = rel;
assert(info->reload_cls == NULL || info->reload_cls == reload_cls);
to_spill, before, allow_remat ? "" : " not"));
}
+void be_add_reload(spill_env_t *senv, ir_node *to_spill, ir_node *before,
+ const arch_register_class_t *reload_cls, int allow_remat)
+{
+ be_add_reload2(senv, to_spill, before, to_spill, reload_cls, allow_remat);
+
+}
+
+ir_node *be_get_end_of_block_insertion_point(const ir_node *block)
+{
+ ir_node *last = sched_last(block);
+
+ /* we might have projs and keepanys behind the jump... */
+ while(is_Proj(last) || be_is_Keep(last)) {
+ last = sched_prev(last);
+ assert(!sched_is_end(last));
+ }
+
+ if(!is_cfop(last)) {
+ last = sched_next(last);
+ /* last node must be a cfop, only exception is the start block */
+ assert(last == get_irg_start_block(get_irn_irg(block)));
+ }
+
+ /* add the reload before the (cond-)jump */
+ return last;
+}
+
/**
* Returns the point at which you can insert a node that should be executed
* before block @p block when coming from pred @p pos.
static
ir_node *get_block_insertion_point(ir_node *block, int pos)
{
- ir_node *predblock, *last;
+ 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
/* We have to reload the value in pred-block */
predblock = get_Block_cfgpred_block(block, pos);
- last = sched_last(predblock);
-
- /* we might have projs and keepanys behind the jump... */
- while(is_Proj(last) || be_is_Keep(last)) {
- last = sched_prev(last);
- assert(!sched_is_end(last));
- }
-
- if(!is_cfop(last)) {
- last = sched_next(last);
- /* last node must be a cfop, only exception is the start block */
- assert(last == get_irg_start_block(get_irn_irg(block)));
- }
+ return be_get_end_of_block_insertion_point(predblock);
+}
- /* add the reload before the (cond-)jump */
- return last;
+void be_add_reload_at_end(spill_env_t *env, ir_node *to_spill, const ir_node *block,
+ const arch_register_class_t *reload_cls,
+ int allow_remat)
+{
+ ir_node *before = be_get_end_of_block_insertion_point(block);
+ be_add_reload(env, to_spill, before, reload_cls, allow_remat);
}
void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block,
* @returns 1 if value is available, 0 otherwise
*/
static
-int is_value_available(spill_env_t *env, ir_node *arg, ir_node *reloader)
+int is_value_available(spill_env_t *env, const ir_node *arg, const ir_node *reloader)
{
if(is_Unknown(arg) || arg == new_NoMem())
return 1;
* Checks whether the node can principally be rematerialized
*/
static
-int is_remat_node(spill_env_t *env, ir_node *node)
+int is_remat_node(spill_env_t *env, const ir_node *node)
{
const arch_env_t *arch_env = env->arch_env;
* >= REMAT_COST_INFINITE if remat is not possible.
*/
static
-int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled,
- ir_node *reloader, int parentcosts)
+int check_remat_conditions_costs(spill_env_t *env, const ir_node *spilled,
+ const ir_node *reloader, int parentcosts)
{
int i, arity;
int argremats;
if(parentcosts + costs >= env->reload_cost + env->spill_cost) {
return REMAT_COST_INFINITE;
}
+ if(arch_irn_is(env->arch_env, spilled, modify_flags)) {
+ return REMAT_COST_INFINITE;
+ }
argremats = 0;
for(i = 0, arity = get_irn_arity(spilled); i < arity; ++i) {
return env->reload_cost * freq;
}
+int 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;
+}
+
double be_get_reload_costs_on_edge(spill_env_t *env, ir_node *to_spill,
ir_node *block, int pos)
{
remat_cost_delta = remat_cost - env->reload_cost;
rld->remat_cost_delta = remat_cost_delta;
- block = get_nodes_block(reloader);
+ block = is_Block(reloader) ? reloader : get_nodes_block(reloader);
freq = get_block_execfreq(exec_freq, block);
all_remat_costs += remat_cost_delta * freq;
DBG((dbg, LEVEL_2, "\tremat costs delta before %+F: "