X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbecopyopt.c;h=f6715b9257c1dd35b2d9b9837cb43678c9864a2d;hb=3c751b006ff4ad049b3733a082efd2f30c8fdbca;hp=8ed83f9106c09fd9767d211037c8c82b4e3675e9;hpb=3a2cc1d47466d98f2f09a22425d122051a37a5e7;p=libfirm diff --git a/ir/be/becopyopt.c b/ir/be/becopyopt.c index 8ed83f910..f6715b925 100644 --- a/ir/be/becopyopt.c +++ b/ir/be/becopyopt.c @@ -18,66 +18,106 @@ #include "irloop_t.h" #include "xmalloc.h" +#include "beutil.h" #include "bechordal_t.h" #include "becopyopt.h" #include "becopystat.h" static firm_dbg_module_t *dbg = NULL; -#define is_curr_reg_class(irn) (arch_get_irn_reg_class(co->chordal_env->arch_env, irn, arch_pos_make_out(0)) == co->chordal_env->cls) +#define is_curr_reg_class(irn) \ + (arch_get_irn_reg_class(get_arch_env(co), \ + irn, -1) == co->chordal_env->cls) #define MIN(a,b) ((aco->chordal_env; + ir_node **safe, **unsafe; + int i, o, safe_count, safe_costs, unsafe_count, *unsafe_costs; bitset_t *curr; + int max, pos, curr_weight, best_weight = 0; - irns = alloca((ou->node_count-1) * sizeof(*irns)); - curr = bitset_alloca(ou->node_count-1); - - /* brute force the best set */ - bitset_set_all(curr); - while ((max = bitset_popcnt(curr)) != 0) { - /* check if curr is a stable set */ - int i, o, is_stable_set = 1; - - /* copy the irns */ - i = 0; - bitset_foreach(curr, pos) - irns[i++] = ou->nodes[1+pos]; - assert(i==max); - - for(i=0; ico->chordal_env, irns[i], irns[o])) { - is_stable_set = 0; + /* assign the nodes into two groups. + * safe: node has no interference, hence it is in every max stable set. + * unsafe: node has an interference + */ + safe = alloca((ou->node_count-1) * sizeof(*safe)); + safe_costs = 0; + safe_count = 0; + unsafe = alloca((ou->node_count-1) * sizeof(*unsafe)); + unsafe_costs = alloca((ou->node_count-1) * sizeof(*unsafe_costs)); + unsafe_count = 0; + for(i=1; inode_count; ++i) { + int is_safe = 1; + for(o=1; onode_count; ++o) { + if (i==o) + continue; + if (nodes_interfere(chordal_env, ou->nodes[i], ou->nodes[o])) { + unsafe_costs[unsafe_count] = ou->costs[i]; + unsafe[unsafe_count] = ou->nodes[i]; + ++unsafe_count; + is_safe = 0; + break; + } + } + if (is_safe) { + safe_costs += ou->costs[i]; + safe[safe_count++] = ou->nodes[i]; + } + } + + + /* now compute the best set out of the unsafe nodes*/ + if (unsafe_count > MIS_HEUR_TRIGGER) { + bitset_t *best = bitset_alloca(unsafe_count); + /* Heuristik: Greedy trial and error form index 0 to unsafe_count-1 */ + for (i=0; icosts[1+pos]; + curr_weight += unsafe_costs[pos]; /* any better ? */ - if (curr_weight > best_weight) + if (curr_weight > best_weight) { best_weight = curr_weight; - } + } - bitset_minus1(curr); + no_stable_set: + bitset_minus1(curr); + } } - return best_weight; + + return safe_costs+best_weight; } /** @@ -104,46 +144,49 @@ static void co_append_unit(copy_opt_t *co, ir_node *root) { arity = get_irn_arity(root); unit = xcalloc(1, sizeof(*unit)); unit->co = co; - unit->node_count = 1; unit->nodes = xmalloc((arity+1) * sizeof(*unit->nodes)); unit->costs = xmalloc((arity+1) * sizeof(*unit->costs)); + unit->node_count = 1; unit->nodes[0] = root; - unit->complete_costs = 0; - unit->sort_key = 0; INIT_LIST_HEAD(&unit->queue); /* check all args */ - if (is_Phi(root)) { + if (is_Phi(root) && is_firm_be_mode(get_irn_mode(root))) { for (i=0; ichordal_env, root, arg)) - assert(0 && "root and arg interfere"); - DBG((dbg, LEVEL_1, "\t Member: %n %N\n", arg, arg)); - - /* check if arg has occurred at a prior position in the arg/list */ - for (o=0; onode_count; ++o) - if (unit->nodes[o] == arg) { - arg_pos = o; - break; - } - - if (!arg_pos) { /* a new argument */ - /* insert node, set costs */ - unit->nodes[unit->node_count] = arg; - unit->costs[unit->node_count] = co->get_costs(root, arg, i); - unit->node_count++; - } else { /* arg has occured before in same phi */ - /* increase costs for existing arg */ - unit->costs[arg_pos] = co->get_costs(root, arg, i); + if (arg == root) + continue; + if (nodes_interfere(co->chordal_env, root, arg)) { + unit->inevitable_costs += co->get_costs(root, arg, i); + continue; + } + + /* Else insert the argument of the phi to the members of this ou */ + DBG((dbg, LEVEL_1, "\t Member: %n %N\n", arg, arg)); + + /* Check if arg has occurred at a prior position in the arg/list */ + for (o=0; onode_count; ++o) + if (unit->nodes[o] == arg) { + arg_pos = o; + break; } + + if (!arg_pos) { /* a new argument */ + /* insert node, set costs */ + unit->nodes[unit->node_count] = arg; + unit->costs[unit->node_count] = co->get_costs(root, arg, i); + unit->node_count++; + } else { /* arg has occured before in same phi */ + /* increase costs for existing arg */ + unit->costs[arg_pos] += co->get_costs(root, arg, i); } } unit->nodes = xrealloc(unit->nodes, unit->node_count * sizeof(*unit->nodes)); unit->costs = xrealloc(unit->costs, unit->node_count * sizeof(*unit->costs)); - } else if (is_Copy(co->chordal_env->arch_env, root)) { + } else if (is_Copy(get_arch_env(co), root)) { assert(!nodes_interfere(co->chordal_env, root, get_Copy_src(root))); unit->nodes[1] = get_Copy_src(root); unit->costs[1] = co->get_costs(root, unit->nodes[1], -1); @@ -155,19 +198,20 @@ static void co_append_unit(copy_opt_t *co, ir_node *root) { /* TODO add ou's for 2-addr-code instructions */ + /* Determine the maximum costs this unit can cause: all_nodes_cost */ for(i=1; inode_count; ++i) { unit->sort_key = MAX(unit->sort_key, unit->costs[i]); - unit->complete_costs += unit->costs[i]; + unit->all_nodes_costs += unit->costs[i]; } - /* insert according to average costs */ + /* Determine the minimal costs this unit will cause: min_nodes_costs */ + unit->min_nodes_costs += unit->all_nodes_costs - ou_max_ind_set_costs(unit); + + /* Insert the new ou according to its sort_key */ tmp = &co->units; while (tmp->next != &co->units && list_entry_units(tmp->next)->sort_key > unit->sort_key) tmp = tmp->next; list_add(&unit->units, tmp); - - /* Init ifg_mis_size to node_count. So get_lower_bound returns correct results. */ - unit->minimal_costs = unit->complete_costs - ou_max_ind_set_costs(unit); } static void co_collect_in_block(ir_node *block, void *env) { @@ -176,14 +220,14 @@ static void co_collect_in_block(ir_node *block, void *env) { border_t *curr; list_for_each_entry_reverse(border_t, curr, head, list) - if (curr->is_def && curr->is_real && is_optimizable(co->chordal_env->arch_env, curr->irn)) + if (curr->is_def && curr->is_real && is_optimizable(get_arch_env(co), curr->irn)) co_append_unit(co, curr->irn); } static void co_collect_units(copy_opt_t *co) { DBG((dbg, LEVEL_1, "\tCollecting optimization units\n")); co->roots = pset_new_ptr(64); - dom_tree_walk_irg(co->chordal_env->irg, co_collect_in_block, NULL, co); + dom_tree_walk_irg(get_irg(co), co_collect_in_block, NULL, co); del_pset(co->roots); } @@ -200,7 +244,7 @@ copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, int (*get_costs)(ir_node co->get_costs = get_costs; s1 = get_irp_prog_name(); - s2 = get_entity_name(get_irg_entity(co->chordal_env->irg)); + s2 = get_entity_name(get_irg_entity(get_irg(co))); s3 = chordal_env->cls->name; len = strlen(s1) + strlen(s2) + strlen(s3) + 5; co->name = xmalloc(len); @@ -228,7 +272,8 @@ int is_optimizable_arg(const copy_opt_t *co, ir_node *irn) { int i, max; for(i=0, max=get_irn_n_outs(irn); ichordal_env->arch_env, n)) && (irn == n || !nodes_interfere(co->chordal_env, irn, n))) + if (((is_Phi(n) && is_firm_be_mode(get_irn_mode(n))) || + is_Perm(get_arch_env(co), n)) && (irn == n || !nodes_interfere(co->chordal_env, irn, n))) return 1; } return 0; @@ -247,8 +292,10 @@ int get_costs_loop_depth(ir_node *root, ir_node* arg, int pos) { /* for phis the copies are placed in the corresponding pred-block */ loop = get_irn_loop(get_Block_cfgpred_block(root_block, pos)); } - if (loop) - cost = 2*get_loop_depth(loop); + if (loop) { + int d = get_loop_depth(loop); + cost = d*d; + } return cost+1; } @@ -256,16 +303,39 @@ int get_costs_all_one(ir_node *root, ir_node* arg, int pos) { return 1; } +int co_get_max_copy_costs(const copy_opt_t *co) { + int i, res = 0; + unit_t *curr; + + list_for_each_entry(unit_t, curr, &co->units, units) { + res += curr->inevitable_costs; + for (i=1; inode_count; ++i) + res += curr->costs[i]; + } + return res; +} + +int co_get_inevit_copy_costs(const copy_opt_t *co) { + int res = 0; + unit_t *curr; + + list_for_each_entry(unit_t, curr, &co->units, units) + res += curr->inevitable_costs; + return res; +} + int co_get_copy_costs(const copy_opt_t *co) { int i, res = 0; unit_t *curr; + list_for_each_entry(unit_t, curr, &co->units, units) { int root_col = get_irn_col(co, curr->nodes[0]); - DBG((dbg, LEVEL_1, " Adding costs for root %+F color %d\n", curr->nodes[0], root_col)); + DBG((dbg, LEVEL_1, " %3d costs for root %+F color %d\n", curr->inevitable_costs, curr->nodes[0], root_col)); + res += curr->inevitable_costs; for (i=1; inode_count; ++i) { int arg_col = get_irn_col(co, curr->nodes[i]); if (root_col != arg_col) { - DBG((dbg, LEVEL_1, " Arg %+F color %d costs %d\n", curr->nodes[i], arg_col, curr->costs[i])); + DBG((dbg, LEVEL_1, " %3d for arg %+F color %d\n", curr->costs[i], curr->nodes[i], arg_col)); res += curr->costs[i]; } } @@ -277,6 +347,6 @@ int co_get_lower_bound(const copy_opt_t *co) { int res = 0; unit_t *curr; list_for_each_entry(unit_t, curr, &co->units, units) - res += curr->minimal_costs; + res += curr->inevitable_costs + curr->min_nodes_costs; return res; }