X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbespill.c;h=40339e8b75fb4810718d65324bbc9746899590c3;hb=b9d45e08e23bcf058fa8f2d9e18dd78e8cccd044;hp=449f8ba7a5ab071ed74e89e05d559403fb4043d2;hpb=fd1a2c6ca51ee2b6ff838581b79cf7a3c4553e36;p=libfirm diff --git a/ir/be/bespill.c b/ir/be/bespill.c index 449f8ba7a..40339e8b7 100644 --- a/ir/be/bespill.c +++ b/ir/be/bespill.c @@ -14,6 +14,7 @@ #include "irnode_t.h" #include "ircons_t.h" #include "iredges_t.h" +#include "irbackedge_t.h" #include "irprintf.h" #include "ident_t.h" #include "type_t.h" @@ -32,10 +33,11 @@ #include "benode_t.h" #include "bechordal_t.h" #include "bejavacoal.h" +#include "benodesets.h" // only rematerialise when costs are less than REMAT_COST_LIMIT // TODO determine a good value here... -#define REMAT_COST_LIMIT 80 +#define REMAT_COST_LIMIT 20 typedef struct _reloader_t reloader_t; @@ -45,10 +47,16 @@ struct _reloader_t { }; typedef struct _spill_info_t { + /** the value that should get spilled */ ir_node *spilled_node; + /** list of places where the value should get reloaded */ reloader_t *reloaders; + /** the spill node, or a PhiM node */ ir_node *spill; + /** if we had the value of a phi spilled before but not the phi itself then + * this field contains the spill for the phi value */ + ir_node *old_spill; } spill_info_t; struct _spill_env_t { @@ -76,7 +84,7 @@ 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_PTR(value); + int hash = nodeset_hash(value); info.spilled_node = value; res = set_find(env->spills, &info, sizeof(info), hash); @@ -84,6 +92,7 @@ static spill_info_t *get_spillinfo(const spill_env_t *env, ir_node *value) { if (res == NULL) { info.reloaders = NULL; info.spill = NULL; + info.old_spill = NULL; res = set_insert(env->spills, &info, sizeof(info), hash); } @@ -178,6 +187,7 @@ void be_add_reload_on_edge(spill_env_t *env, ir_node *to_spill, ir_node *block, } void be_spill_phi(spill_env_t *env, ir_node *node) { + spill_info_t* spill; int i, arity; assert(is_Phi(node)); @@ -185,11 +195,18 @@ void be_spill_phi(spill_env_t *env, ir_node *node) { pset_insert_ptr(env->mem_phis, node); // create spillinfos for the phi arguments - get_spillinfo(env, node); + spill = get_spillinfo(env, node); for(i = 0, arity = get_irn_arity(node); i < arity; ++i) { ir_node *arg = get_irn_n(node, i); get_spillinfo(env, arg); } + + // if we had a spill for the phi value before, then remove this spill from + // schedule, as we will remove it in the insert spill/reload phase + if(spill->spill != NULL && !is_Phi(spill->spill)) { + spill->old_spill = spill->spill; + spill->spill = NULL; + } } /* @@ -292,6 +309,17 @@ static void spill_phi(spill_env_t *env, spill_info_t *spillinfo) { set_irn_n(spillinfo->spill, i, arg_info->spill); } + + // rewire reloads from old_spill to phi + if(spillinfo->old_spill != NULL) { + const ir_edge_t *edge, *next; + foreach_out_edge_safe(spillinfo->old_spill, edge, next) { + ir_node* reload = get_edge_src_irn(edge); + assert(be_is_Reload(reload) || is_Phi(reload)); + set_irn_n(reload, get_edge_src_pos(edge), spillinfo->spill); + } + spillinfo->old_spill = NULL; + } } /** @@ -377,15 +405,9 @@ static int is_remat_node(spill_env_t *env, ir_node *node) { assert(!be_is_Spill(node)); - if(be_is_Reload(node)) - return 1; - - // TODO why does arch_irn_is say rematerializable anyway? - if(be_is_Barrier(node)) - return 0; - - if(arch_irn_is(arch_env, node, rematerializable)) + if(arch_irn_is(arch_env, node, rematerializable)) { return 1; + } if(be_is_StackParam(node)) return 1; @@ -416,8 +438,9 @@ static int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled, ir_n } else { costs += arch_get_op_estimated_cost(env->arch_env, spilled); } - if(parentcosts + costs >= REMAT_COST_LIMIT) + if(parentcosts + costs >= REMAT_COST_LIMIT) { return REMAT_COST_LIMIT; + } argremats = 0; for(i = 0, arity = get_irn_arity(spilled); i < arity; ++i) { @@ -435,7 +458,6 @@ static int check_remat_conditions_costs(spill_env_t *env, ir_node *spilled, ir_n } argremats++; - // TODO can we get more accurate costs than +1? costs += check_remat_conditions_costs(env, arg, reloader, parentcosts + costs); if(parentcosts + costs >= REMAT_COST_LIMIT) return REMAT_COST_LIMIT; @@ -481,6 +503,7 @@ static ir_node *do_remat(spill_env_t *env, ir_node *spilled, ir_node *reloader) get_irn_arity(spilled), ins); copy_node_attr(spilled, res); + new_backedge_info(res); DBG((env->dbg, LEVEL_1, "Insert remat %+F before reloader %+F\n", res, reloader)); @@ -505,7 +528,6 @@ void be_insert_spills_reloads(spill_env_t *env) { spill_info_t *si; /* process each spilled node */ - DBG((env->dbg, LEVEL_1, "Insert spills and reloads:\n")); for(si = set_first(env->spills); si; si = set_next(env->spills)) { reloader_t *rld; ir_mode *mode = get_irn_mode(si->spilled_node); @@ -536,13 +558,10 @@ void be_insert_spills_reloads(spill_env_t *env) { } del_pset(values); - } - // reloads are placed now, but we might reuse the spill environment for further spilling decisions - del_set(env->spills); - env->spills = new_set(cmp_spillinfo, 1024); + si->reloaders = NULL; + } be_remove_dead_nodes_from_schedule(env->chordal_env->irg); - //be_liveness_add_missing(env->chordal_env->lv); be_liveness_recompute(env->chordal_env->lv); }