X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbespillutil.c;h=ea4d2f04ca4ae63d0222c2b73a414cef1b5fadc8;hb=7142e46b9e442cacddec26387d8735444fb4421b;hp=fd5c477026576c07551300e544a30c19f655e172;hpb=302872956d772c0480f371bfa57fe88471cee02c;p=libfirm diff --git a/ir/be/bespillutil.c b/ir/be/bespillutil.c index fd5c47702..ea4d2f04c 100644 --- a/ir/be/bespillutil.c +++ b/ir/be/bespillutil.c @@ -21,7 +21,7 @@ * @file * @brief implementation of the spill/reload placement abstraction layer * @author Daniel Grund, Sebastian Hack, Matthias Braun - * @date 29.09.2005 + * @date 29.09.2005 * @version $Id$ */ #include "config.h" @@ -57,6 +57,7 @@ #include "bestatevent.h" #include "bessaconstr.h" #include "beirg.h" +#include "beirgmod.h" #include "beintlive_t.h" #include "bemodule.h" #include "be_t.h" @@ -98,7 +99,6 @@ struct spill_env_t { const arch_env_t *arch_env; ir_graph *irg; struct obstack obst; - be_irg_t *birg; 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 @@ -119,8 +119,8 @@ struct spill_env_t { */ static int cmp_spillinfo(const void *x, const void *y, size_t size) { - const spill_info_t *xx = x; - const spill_info_t *yy = y; + 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; @@ -135,32 +135,31 @@ static spill_info_t *get_spillinfo(const spill_env_t *env, ir_node *value) int hash = hash_irn(value); info.to_spill = value; - res = set_find(env->spills, &info, sizeof(info), hash); + res = (spill_info_t*)set_find(env->spills, &info, sizeof(info), hash); if (res == NULL) { info.reloaders = NULL; info.spills = NULL; info.spill_costs = -1; info.reload_cls = NULL; - res = set_insert(env->spills, &info, sizeof(info), hash); + res = (spill_info_t*)set_insert(env->spills, &info, sizeof(info), hash); } return res; } -spill_env_t *be_new_spill_env(be_irg_t *birg) +spill_env_t *be_new_spill_env(ir_graph *irg) { - const arch_env_t *arch_env = birg->main_env->arch_env; + const arch_env_t *arch_env = be_get_irg_arch_env(irg); spill_env_t *env = XMALLOC(spill_env_t); - env->spills = new_set(cmp_spillinfo, 1024); - env->irg = be_get_birg_irg(birg); - env->birg = birg; + env->spills = new_set(cmp_spillinfo, 1024); + env->irg = irg; env->arch_env = arch_env; ir_nodeset_init(&env->mem_phis); env->spill_cost = arch_env->spill_cost; env->reload_cost = arch_env->reload_cost; - env->exec_freq = be_get_birg_exec_freq(birg); + env->exec_freq = be_get_irg_exec_freq(irg); obstack_init(&env->obst); #ifdef FIRM_STATISTICS @@ -193,12 +192,11 @@ void be_delete_spill_env(spill_env_t *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); - const ir_node *insn = skip_Proj_const(to_spill); spill_t *spill; spill_t *s; spill_t *last; - assert(!arch_irn_is(insn, dont_spill)); + 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)); /* Just for safety make sure that we do not insert the spill in front of a phi */ @@ -234,38 +232,14 @@ void be_add_spill(spill_env_t *env, ir_node *to_spill, ir_node *after) spill_info->spills = spill; } -void be_add_remat(spill_env_t *env, ir_node *to_spill, ir_node *before, - ir_node *rematted_node) -{ - spill_info_t *spill_info; - reloader_t *reloader; - - spill_info = get_spillinfo(env, to_spill); - - /* add the remat information */ - reloader = OALLOC(&env->obst, reloader_t); - reloader->next = spill_info->reloaders; - reloader->reloader = before; - reloader->rematted_node = rematted_node; - reloader->remat_cost_delta = 0; /* We will never have a cost win over a - reload since we're not even allowed to - create a reload */ - - spill_info->reloaders = reloader; - - DBG((dbg, LEVEL_1, "creating spillinfo for %+F, will be rematerialized before %+F\n", - to_spill, 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; reloader_t *rel; - const ir_node *insn = skip_Proj_const(to_spill); - assert(!arch_irn_is(insn, dont_spill)); + assert(!arch_irn_is(skip_Proj_const(to_spill), dont_spill)); info = get_spillinfo(env, to_spill); @@ -281,6 +255,14 @@ void be_add_reload2(spill_env_t *env, ir_node *to_spill, ir_node *before, assert(!is_Proj(before) && !be_is_Keep(before)); + /* adjust before point to not be in the epilog */ + while (true) { + ir_node *before_prev = sched_prev(before); + if (! (arch_irn_get_flags(before_prev) & arch_irn_flags_epilog)) + break; + before = sched_prev(before); + } + /* put reload into list */ rel = OALLOC(&env->obst, reloader_t); rel->next = info->reloaders; @@ -320,11 +302,17 @@ ir_node *be_get_end_of_block_insertion_point(const ir_node *block) return last; } -static ir_node *skip_keeps_phis(ir_node *node) +/** + * 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) { + node = skip_Proj(node); while (true) { ir_node *next = sched_next(node); - if (!is_Phi(next) && !be_is_Keep(next) && !be_is_CopyKeep(next)) + if (!is_Phi(next) && !be_is_Keep(next) && !be_is_CopyKeep(next) + && !(arch_irn_get_flags(next) & arch_irn_flags_prolog)) break; node = next; } @@ -362,7 +350,7 @@ void be_add_reload_at_end(spill_env_t *env, ir_node *to_spill, } 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 pos, const arch_register_class_t *reload_cls, int allow_remat) { ir_node *before = get_block_insertion_point(block, pos); @@ -391,7 +379,7 @@ void be_spill_phi(spill_env_t *env, ir_node *node) insert = be_get_end_of_block_insertion_point(pred_block); insert = sched_prev(insert); } else { - insert = skip_keeps_phis(arg); + insert = determine_spill_point(arg); } be_add_spill(env, arg, insert); @@ -431,7 +419,8 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) * and simply always available. */ if (!sched_is_scheduled(insn)) { /* override spillinfos or create a new one */ - spillinfo->spills->spill = new_NoMem(); + ir_graph *irg = get_irn_irg(to_spill); + spillinfo->spills->spill = new_r_NoMem(irg); DB((dbg, LEVEL_1, "don't spill %+F use NoMem\n", to_spill)); return; } @@ -442,7 +431,7 @@ static void spill_irn(spill_env_t *env, spill_info_t *spillinfo) ir_node *after = spill->after; ir_node *block = get_block(after); - after = skip_keeps_phis(after); + after = determine_spill_point(after); spill->spill = be_spill(block, to_spill); sched_add_after(skip_Proj(after), spill->spill); @@ -491,9 +480,10 @@ static void spill_phi(spill_env_t *env, spill_info_t *spillinfo) /* override or replace spills list... */ spill = OALLOC(&env->obst, spill_t); - spill->after = skip_keeps_phis(phi); - spill->spill = new_r_Phi(block, arity, ins, mode_M); + spill->after = determine_spill_point(phi); + spill->spill = be_new_Phi(block, arity, ins, mode_M, NULL); spill->next = NULL; + sched_add_after(block, spill->spill); spillinfo->spills = spill; #ifdef FIRM_STATISTICS @@ -553,7 +543,7 @@ static void spill_node(spill_env_t *env, spill_info_t *spillinfo) static int is_value_available(spill_env_t *env, const ir_node *arg, const ir_node *reloader) { - if (is_Unknown(arg) || arg == new_NoMem()) + if (is_Unknown(arg) || is_NoMem(arg)) return 1; if (be_is_Spill(skip_Proj_const(arg))) @@ -573,7 +563,7 @@ static int is_value_available(spill_env_t *env, const ir_node *arg, if (arch_irn_is_ignore(arg)) return 1; - return 0; + return 0; } /** @@ -607,7 +597,7 @@ static int check_remat_conditions_costs(spill_env_t *env, return REMAT_COST_INFINITE; } /* never rematerialize a node which modifies the flags. - * (would be better to test wether the flags are actually live at point + * (would be better to test whether the flags are actually live at point * reloader...) */ if (arch_irn_is(insn, modify_flags)) { @@ -777,11 +767,12 @@ static void determine_spill_costs(spill_env_t *env, spill_info_t *spillinfo) * predecessor (of a PhiM) but this test might match other things too... */ if (!sched_is_scheduled(insn)) { + ir_graph *irg = get_irn_irg(to_spill); /* override spillinfos or create a new one */ spill_t *spill = OALLOC(&env->obst, spill_t); spill->after = NULL; spill->next = NULL; - spill->spill = new_NoMem(); + spill->spill = new_r_NoMem(irg); spillinfo->spills = spill; spillinfo->spill_costs = 0; @@ -828,7 +819,7 @@ 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 = skip_keeps_phis(to_spill); + spill->after = determine_spill_point(to_spill); spill->next = NULL; spill->spill = NULL; @@ -888,7 +879,7 @@ void be_insert_spills_reloads(spill_env_t *env) } /* process each spilled node */ - for (si = set_first(env->spills); si; si = set_next(env->spills)) { + foreach_set(env->spills, spill_info_t*, si) { reloader_t *rld; ir_node *to_spill = si->to_spill; ir_mode *mode = get_irn_mode(to_spill); @@ -991,9 +982,9 @@ void be_insert_spills_reloads(spill_env_t *env) * SSA form for the spilled value */ if (ARR_LEN(copies) > 0) { be_ssa_construction_env_t senv; - /* be_lv_t *lv = be_get_birg_liveness(env->birg); */ + /* be_lv_t *lv = be_get_irg_liveness(env->irg); */ - be_ssa_construction_init(&senv, env->birg); + be_ssa_construction_init(&senv, env->irg); be_ssa_construction_add_copy(&senv, to_spill); be_ssa_construction_add_copies(&senv, copies, ARR_LEN(copies)); be_ssa_construction_fix_users(&senv, to_spill); @@ -1017,7 +1008,7 @@ void be_insert_spills_reloads(spill_env_t *env) be_ssa_construction_env_t senv; - be_ssa_construction_init(&senv, env->birg); + be_ssa_construction_init(&senv, env->irg); spill = si->spills; for ( ; spill != NULL; spill = spill->next) { /* maybe we rematerialized the value and need no spill */ @@ -1045,9 +1036,9 @@ void be_insert_spills_reloads(spill_env_t *env) /* Matze: In theory be_ssa_construction should take care of the liveness... * try to disable this again in the future */ - be_liveness_invalidate(env->birg->lv); + be_liveness_invalidate(be_get_irg_liveness(env->irg)); - be_remove_dead_nodes_from_schedule(env->birg); + be_remove_dead_nodes_from_schedule(env->irg); be_timer_pop(T_RA_SPILL_APPLY); }