From: Daniel Grund Date: Thu, 16 Mar 2006 14:56:31 +0000 (+0000) Subject: Refactoring, Bugfixes, added path constraints X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=87d3e7eba011a02e25e216fc299dd41f82d6e30d;p=libfirm Refactoring, Bugfixes, added path constraints --- diff --git a/ir/be/becopyilp.c b/ir/be/becopyilp.c index 93d329c2c..ee1a6f3ce 100644 --- a/ir/be/becopyilp.c +++ b/ir/be/becopyilp.c @@ -3,18 +3,11 @@ * Date: 28.02.2006 * Copyright: (c) Universitaet Karlsruhe * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. - * $Id$ * * Common stuff used by all ILP fomulations. * */ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#ifdef WITH_ILP - #include "becopyilp_t.h" #include "beifg_t.h" @@ -76,7 +69,11 @@ void sr_remove(size_red_t *sr) { while (redo) { redo = 0; be_ifg_foreach_node(ifg, iter, irn) { - if (!sr_is_removed(sr, irn) && !co_is_optimizable_root(sr->co, irn) && !co_is_optimizable_arg(sr->co, irn)) { + arch_register_req_t req; + + arch_get_register_req(sr->co->aenv, &req, irn, -1); + + if (!arch_register_req_is(&req, limited) && !sr_is_removed(sr, irn) && !co_gs_is_optimizable(sr->co, irn)) { if (sr_is_simplicial(sr, irn)) { coloring_suffix_t *cs = obstack_alloc(&sr->ob, sizeof(*cs)); @@ -137,6 +134,8 @@ void free_size_red(size_red_t *sr) { *****************************************************************************/ +#include + ilp_env_t *new_ilp_env(copy_opt_t *co, ilp_callback build, ilp_callback apply, void *env) { ilp_env_t *res = malloc(sizeof(*res)); assert(res); @@ -151,6 +150,9 @@ ilp_env_t *new_ilp_env(copy_opt_t *co, ilp_callback build, ilp_callback apply, v } lpp_sol_state_t ilp_go(ilp_env_t *ienv) { + FILE *f; + char buf[256]; + sr_remove(ienv->sr); ienv->build(ienv); @@ -161,6 +163,11 @@ lpp_sol_state_t ilp_go(ilp_env_t *ienv) { lpp_solve_cplex(ienv->lp); #endif + snprintf(buf, sizeof(buf), "%s.ilp", ienv->co->name); + f = fopen(buf, "wt"); + lpp_dump_plain(ienv->lp, f); + fclose(f); + ienv->apply(ienv); sr_reinsert(ienv->sr); @@ -173,10 +180,3 @@ void free_ilp_env(ilp_env_t *ienv) { free_lpp(ienv->lp); free(ienv); } - -#else /* WITH_ILP */ - -static void only_that_you_can_compile_without_WITH_ILP_defined(void) { -} - -#endif /* WITH_ILP */ diff --git a/ir/be/becopyilp1.c b/ir/be/becopyilp1.c index 7a1af2d3e..5dae7a6f6 100644 --- a/ir/be/becopyilp1.c +++ b/ir/be/becopyilp1.c @@ -18,262 +18,6 @@ #ifdef WITH_ILP -#include "becopyilp_t.h" -#include "benumb_t.h" -#include "belive_t.h" -#include "irdom_t.h" -#include "irgwalk.h" -#include "xmalloc.h" -#include "pset.h" -#include "irprog.h" -#include "irdom_t.h" -#include "iredges_t.h" - -#include "becopystat.h" -#include "besched_t.h" -#include "phiclass.h" - -#if 0 //temporary - -#define PATH_CONSTRAINTS_FOR_CLASSES - -typedef struct _problem_instance_t { - const copy_opt_t *co; /**< the copy opt problem */ - size_red_t *sr; /**< problem size reduction. removes simple nodes */ - lpp_t *lp; /**< the linear programming problem */ - - /* Helpers for maintaining indices and finding variables */ - int first_nnc_var_idx; /**< the first index of a constraint belonging to no-null-colors stuff*/ - int cst_counter, first_x_var, last_x_var; - char buf[32]; - pset *done; -} problem_instance_t; - -#define is_color_possible(irn,color) arch_reg_is_allocatable(pi->co->aenv, irn, -1, arch_register_for_index(pi->co->cls, color)) - -/* - * Some stuff for variable name handling. - */ -#define mangle_cst(buf, prefix, nr) \ - snprintf((buf), sizeof(buf), "%c%d", (prefix), (nr)) - -#define mangle_var1(buf, prefix, color) \ - snprintf((buf), sizeof(buf), "%c%d", (prefix), (color)) - -#define mangle_var2(buf, prefix, node_nr, color) \ - snprintf((buf), sizeof(buf), "%c%d_%d", (prefix), (node_nr), (color)) - -#define mangle_var3(buf, prefix, n1, n2, col) \ - snprintf((buf), sizeof(buf), "%c%d_%d_%d", (prefix), (n1), (n2), (col)) - -#define mangle_var_irn(buf, prefix, irn, color) \ - mangle_var2((buf), (prefix), get_irn_graph_nr(irn), (color)) - -#define split_var(var, nnr, col) \ - sscanf(var, "x%d_%d", (nnr), (col)) - - -#ifndef PATH_CONSTRAINTS_FOR_CLASSES -/** - * Matrix P: Path contraints. - * If 2 nodes interfere and there is a path of equal-color-edges - * connecting them, then at least one of those equal-color-edges - * will break and cause some costs. - */ -static void pi_add_path_cstr(problem_instance_t *pi) { - unit_t *curr; - int cst_counter = 0; - DBG((dbg, LEVEL_2, "Adding path constraints...\n")); - - /* for all optimization units (only phis) */ - list_for_each_entry(unit_t, curr, &pi->co->units, units) { - int i, o, rootnr; - - if (curr->min_nodes_costs == 0) - continue; - - rootnr = get_irn_graph_nr(curr->nodes[0]); - /* check all argument pairs for interference */ - for (i=1; inode_count; ++i) { - const ir_node *arg1 = curr->nodes[i]; - int arg1nr = get_irn_graph_nr(arg1); - for (o=i+1; onode_count; ++o) { - const ir_node *arg2 = curr->nodes[o]; - int arg2nr = get_irn_graph_nr(arg2); - if (nodes_interfere(pi->co->cenv, arg1, arg2)) { - int cst_idx, y_idx; - char buf[32]; - - mangle_cst(buf, 'P', cst_counter++); - cst_idx = lpp_add_cst(pi->curr_lp, buf, lpp_greater, 1); - - mangle_var2(buf, 'y', rootnr, arg1nr); - y_idx = lpp_get_var_idx(pi->curr_lp, buf); - lpp_set_factor_fast(pi->curr_lp, cst_idx, y_idx, 1); - - mangle_var2(buf, 'y', rootnr, arg2nr); - y_idx = lpp_get_var_idx(pi->curr_lp, buf); - lpp_set_factor_fast(pi->curr_lp, cst_idx, y_idx, 1); - } - } - } - } -} -#endif - -#ifdef PATH_CONSTRAINTS_FOR_CLASSES -static INLINE int get_y_var_idx(problem_instance_t *pi, int nnr1, int nnr2) { - int res; - char buf[30]; - - mangle_var2(buf, 'y', nnr1, nnr2); - if ((res = lpp_get_var_idx(pi->curr_lp, buf)) != -1) - return res; - - mangle_var2(buf, 'y', nnr2, nnr1); - if ((res = lpp_get_var_idx(pi->curr_lp, buf)) != -1) - return res; - - assert(0 && "One of them must work"); - return -1; -} - -static void check_ecc_and_add_cut(problem_instance_t *pi, ir_node **path, int length, pset *remain, ir_node *tgt) { - if (path[length-1] == tgt) { /* we found a path */ - int cst_idx, var_idx, i, nnr1, nnr2; - char buf[30]; - - /* add cut to ilp */ - mangle_cst(buf, 'Q', pi->cst_counter++); - cst_idx = lpp_add_cst(pi->curr_lp, buf, lpp_greater, 1); - - /* add all vars along the path */ - nnr2 = get_irn_graph_nr(path[0]); - for (i=1; icurr_lp, cst_idx, var_idx, 1); - } - } else { /* try to extend the path */ - be_chordal_env_t *cenv = pi->co->cenv; - const ir_edge_t *edge; - ir_node *end = path[length-1]; - ir_node **next = alloca(pset_count(remain) * sizeof(*next)); - int i, o, max, next_pos = 0; - pset *done = pset_new_ptr_default(); - - /* find all potential next nodes on path */ - /* args of phis */ - if (is_Phi(end)) - for(i=0, max=get_irn_arity(end); isrc; - if (is_Phi(user) && !pset_find_ptr(done, user) && pset_find_ptr(remain, user)) { - next[next_pos++] = user; - pset_insert_ptr(done, user); - } - } - del_pset(done); - - - /* delete all potential nodes with interferences to other nodes in the path */ - for (i=0; i 1) ? 1 : 0; - - for(; odone, class)) - return; - - pset_insert_ptr(pi->done, class); - - /* pset to array */ - max = pset_count(class); - cls = alloca(max * sizeof(*cls)); - for(i=0, m = pset_first(class); m; i++, m = pset_next(class)) { - DBG((dbg, LEVEL_1, " class member: %+F\n", m)); - cls[i] = m; - } - - cenv = pi->co->cenv; - for(i=0; icst_counter = 0; - pi->done = pset_new_ptr_default(); - irg_walk_graph(pi->co->irg, path_cstr_for_classes_walker, NULL, pi); - del_pset(pi->done); -} -#endif - -static void pi_construct(problem_instance_t *pi) { - pi_add_path_cstr_for_classes(pi); - pi_add_path_cstr(pi); - pi_add_clique_path_cstr(pi); -} -#endif - #include "becopyilp_t.h" #define DEBUG_LVL 1 diff --git a/ir/be/becopyilp2.c b/ir/be/becopyilp2.c index b323464e5..f1703fb7d 100644 --- a/ir/be/becopyilp2.c +++ b/ir/be/becopyilp2.c @@ -32,6 +32,9 @@ #ifdef WITH_ILP +#include +#include "pdeq.h" + #include "irtools.h" #include "irgwalk.h" #include "becopyilp_t.h" @@ -113,8 +116,13 @@ static void build_interference_cstr(ilp_env_t *ienv) { /* for each maximal clique */ be_ifg_foreach_clique(ifg, iter, clique, &size) { + int realsize = 0; + + for (i=0; isr, clique[i])) + ++realsize; - if (size < 2) + if (realsize < 2) continue; /* for all colors */ @@ -166,7 +174,7 @@ static void build_affinity_cstr(ilp_env_t *ienv) { lpp_set_factor_fast(ienv->lp, cst_idx, root_idx, 1.0); lpp_set_factor_fast(ienv->lp, cst_idx, arg_idx, -1.0); - lpp_set_factor_fast(ienv->lp, cst_idx, root_idx, -1.0); + lpp_set_factor_fast(ienv->lp, cst_idx, y_idx, -1.0); } } } @@ -198,7 +206,7 @@ static INLINE edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, int *counte new_edge.n1 = n2; new_edge.n2 = n1; } - *counter++; + (*counter)++; return set_insert(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge)); } @@ -229,7 +237,7 @@ static INLINE void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte if (e) { e->n1 = NULL; e->n2 = NULL; - *counter--; + (*counter)--; } } @@ -241,13 +249,13 @@ static INLINE void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counte * At most 1 node of the clique can be colored equally with the external node. */ static void build_clique_star_cstr(ilp_env_t *ienv) { - node_t *node; + affinity_t *aff; /* for each node with affinity edges */ - co_gs_foreach_node(ienv->co, node) { + co_gs_foreach_aff_node(ienv->co, aff) { struct obstack ob; neighb_t *nbr; - ir_node *center = node->irn; + ir_node *center = aff->irn; ir_node **nodes; set *edges; int i, o, n_nodes, n_edges; @@ -257,7 +265,7 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { /* get all affinity neighbours */ n_nodes = 0; - co_gs_foreach_neighb(node, nbr) { + co_gs_foreach_neighb(aff, nbr) { obstack_ptr_grow(&ob, nbr->irn); ++n_nodes; } @@ -280,9 +288,9 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { for (e=set_first(edges); !e->n1; e=set_next(edges)) /*nothing*/ ; - remove_edge(edges, e->n1, e->n2, &n_edges); pset_insert_ptr(clique, e->n1); pset_insert_ptr(clique, e->n2); + remove_edge(edges, e->n1, e->n2, &n_edges); /* while the clique is growing */ do { @@ -345,11 +353,86 @@ static void build_clique_star_cstr(ilp_env_t *ienv) { } } + +static void extend_path(ilp_env_t *ienv, pdeq *path, ir_node *irn) { + be_ifg_t *ifg = ienv->co->cenv->ifg; + int i, len; + ir_node **curr_path; + affinity_t *aff; + neighb_t *nbr; + + /* do not walk backwards or in circles */ + if (pdeq_contains(path, irn)) + return; + + /* insert the new irn */ + pdeq_putr(path, irn); + + + + /* check for forbidden interferences */ + len = pdeq_len(path); + curr_path = alloca(len * sizeof(*curr_path)); + pdeq_copyl(path, curr_path); + + for (i=1; i 2) { + /* finally build the constraint */ + int cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_greater, 1.0); + for (i=1; ilp, name_cdd_sorted(buf, 'y', nr_1, nr_2)); + lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0); + } + } + + /* this path cannot be extended anymore */ + goto end; + } + + + + /* recursively extend the path */ + aff = get_affinity_info(ienv->co, irn); + co_gs_foreach_neighb(aff, nbr) + extend_path(ienv, path, nbr->irn); + + +end: + /* remove the irn */ + pdeq_getr(path); + +} + /** - * + * Search a path of affinity edges, whose ends are connected + * by an interference edge and there are no other interference + * edges in between. + * Then at least one of these affinity edges must break. */ static void build_path_cstr(ilp_env_t *ienv) { + affinity_t *aff_info; + + /* for each node with affinity edges */ + co_gs_foreach_aff_node(ienv->co, aff_info) { + pdeq *path = new_pdeq(); + extend_path(ienv, path, aff_info->irn); + + del_pdeq(path); + } } static void ilp2_build(ilp_env_t *ienv) { @@ -374,28 +457,32 @@ static void ilp2_apply(ilp_env_t *ienv) { lpp_sol_state_t state; int i, count; - count = lenv->last_x_var - lenv->first_x_var + 1; - sol = xmalloc(count * sizeof(sol[0])); - state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var); - if (state != lpp_optimal) { - printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, state); - assert(state >= lpp_feasible && "The solution should at least be feasible!"); - } + /* first check if there was sth. to optimize */ + if (lenv->first_x_var >= 0) { + + count = lenv->last_x_var - lenv->first_x_var + 1; + sol = xmalloc(count * sizeof(sol[0])); + state = lpp_get_solution(ienv->lp, sol, lenv->first_x_var, lenv->last_x_var); + if (state != lpp_optimal) { + printf("WARNING %s: Solution state is not 'optimal': %d\n", ienv->co->name, state); + assert(state >= lpp_feasible && "The solution should at least be feasible!"); + } - for (i=0; i 1-EPSILON) { /* split variable name into components */ - lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name)); + if (sol[i] > 1-EPSILON) { /* split variable name into components */ + lpp_get_var_name(ienv->lp, lenv->first_x_var+i, var_name, sizeof(var_name)); - if (sscanf(var_name, "x_%d_%d", &nodenr, &color) == 2) { - ir_node *irn = pmap_get(lenv->nr_2_irn, INT_TO_PTR(nodenr)); - assert(irn && "This node number must be present in the map"); + if (sscanf(var_name, "x_%d_%d", &nodenr, &color) == 2) { + ir_node *irn = pmap_get(lenv->nr_2_irn, INT_TO_PTR(nodenr)); + assert(irn && "This node number must be present in the map"); - set_irn_col(ienv->co, irn, color); - } else - assert(0 && "This should be a x-var"); + set_irn_col(ienv->co, irn, color); + } else + assert(0 && "This should be a x-var"); + } } } diff --git a/ir/be/becopyopt.c b/ir/be/becopyopt.c index 25989e71f..abbf85896 100644 --- a/ir/be/becopyopt.c +++ b/ir/be/becopyopt.c @@ -88,6 +88,8 @@ int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) { int co_is_optimizable_arg(const copy_opt_t *co, ir_node *irn) { const ir_edge_t *edge; + assert(0 && "Is buggy and obsolete. Do not use"); + if (arch_irn_is_ignore(co->aenv, irn)) return 0; @@ -419,22 +421,22 @@ int co_get_lower_bound(const copy_opt_t *co) { |_| |___/ ******************************************************************************/ -static int compare_node_t(const void *k1, const void *k2, size_t size) { - const node_t *n1 = k1; - const node_t *n2 = k2; +static int compare_affinity_t(const void *k1, const void *k2, size_t size) { + const affinity_t *n1 = k1; + const affinity_t *n2 = k2; return (n1->irn != n2->irn); } static void add_edge(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) { - node_t new_node, *node; + affinity_t new_node, *node; neighb_t new_nbr, *nbr; int allocnew; new_node.irn = n1; new_node.count = 0; new_node.neighbours = NULL; - node = set_insert(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn)); + node = set_insert(co->nodes, &new_node, sizeof(new_node), HASH_PTR(new_node.irn)); allocnew = 1; for (nbr = node->neighbours; nbr; nbr = nbr->next) @@ -493,7 +495,7 @@ static void build_graph_walker(ir_node *irn, void *env) { void co_build_graph_structure(copy_opt_t *co) { obstack_init(&co->obst); - co->nodes = new_set(compare_node_t, 32); + co->nodes = new_set(compare_affinity_t, 32); irg_walk_graph(co->irg, build_graph_walker, NULL, co); } @@ -506,10 +508,10 @@ void co_free_graph_structure(copy_opt_t *co) { /* co_solve_ilp1() co_solve_ilp2() are implemented in becopyilpX.c */ int co_gs_is_optimizable(copy_opt_t *co, ir_node *irn) { - node_t new_node, *n; + affinity_t new_node, *n; new_node.irn = irn; - n = set_find(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn)); + n = set_find(co->nodes, &new_node, sizeof(new_node), HASH_PTR(new_node.irn)); if (n) { return (n->count > 0); } else diff --git a/ir/be/becopyopt_t.h b/ir/be/becopyopt_t.h index bee1e1598..2be79b028 100644 --- a/ir/be/becopyopt_t.h +++ b/ir/be/becopyopt_t.h @@ -96,7 +96,7 @@ typedef struct _unit_t { ******************************************************************************/ typedef struct _neighb_t neighb_t; -typedef struct _node_t node_t; +typedef struct _affinity_t affinity_t; struct _neighb_t { @@ -105,17 +105,25 @@ struct _neighb_t { int costs; /** the costs of the edge (node_t->irn, neighb_t->irn) */ }; -struct _node_t { +struct _affinity_t { ir_node *irn; /** a node with affinity edges */ int count; /** number of affinity edges in the linked list below */ neighb_t *neighbours; /** a linked list of all affinity neighbours */ }; + +static INLINE affinity_t *get_affinity_info(const copy_opt_t *co, ir_node *irn) { + affinity_t find; + + find.irn = irn; + return set_find(co->nodes, &find, sizeof(find), HASH_PTR(irn)); +} + #define co_gs_nodes_begin(co) set_first((co)->nodes) #define co_gs_nodes_next(co) set_next((co)->nodes) #define co_gs_nodes_break(co) set_break((co)->nodes) -#define co_gs_foreach_node(co, node) for (node = co_gs_nodes_begin(co); node; node = co_gs_nodes_next(co)) +#define co_gs_foreach_aff_node(co, aff_node) for (aff_node = co_gs_nodes_begin(co); aff_node; aff_node = co_gs_nodes_next(co)) -#define co_gs_foreach_neighb(node, neighb) for (neighb = node->neighbours; neighb; neighb = neighb->next) +#define co_gs_foreach_neighb(aff_node, neighb) for (neighb = aff_node->neighbours; neighb; neighb = neighb->next) #endif diff --git a/ir/be/becopystat.c b/ir/be/becopystat.c index 33505486a..1a4c195ab 100644 --- a/ir/be/becopystat.c +++ b/ir/be/becopystat.c @@ -289,10 +289,8 @@ void copystat_collect_cls(be_chordal_env_t *cenv) { ir_graph *irg = cenv->irg; arch_env_t *aenv = cenv->birg->main_env->arch_env; - if (last_irg != irg) { - copystat_reset(); - copystat_collect_irg(irg, aenv); - } + copystat_reset(); + copystat_collect_irg(irg, aenv); for (n = pset_first(all_phi_nodes); n; n = pset_next(all_phi_nodes)) if (arch_get_irn_reg_class(aenv, n, -1) == cenv->cls) @@ -461,6 +459,7 @@ void co_compare_solvers(be_chordal_env_t *chordal_env) { int costs_inevit, costs_init, costs_heur, costs_ilp1, costs_ilp2, lower_bound; phi_class_compute(chordal_env->irg); + copystat_collect_cls(chordal_env); co = new_copy_opt(chordal_env, co_get_costs_loop_depth); co_build_ou_structure(co); @@ -472,6 +471,7 @@ void co_compare_solvers(be_chordal_env_t *chordal_env) { saver.chordal_env = chordal_env; saver.saved_colors = pmap_create(); save_colors(&saver); + be_ra_chordal_check(co->cenv); /* initial values */ costs_inevit = co_get_inevit_copy_costs(co); @@ -494,6 +494,8 @@ void co_compare_solvers(be_chordal_env_t *chordal_env) { co_solve_heuristic(co); lc_timer_stop(timer); + + be_ra_chordal_check(co->cenv); costs_heur = co_get_copy_costs(co); DBG((dbg, LEVEL_1, "HEUR costs: %3d\n", costs_heur)); copystat_add_heur_time(lc_timer_elapsed_msec(timer)); @@ -519,6 +521,7 @@ void co_compare_solvers(be_chordal_env_t *chordal_env) { co_solve_ilp2(co, 60.0); + be_ra_chordal_check(co->cenv); costs_ilp2 = co_get_copy_costs(co); DBG((dbg, LEVEL_1, "ILP2 costs: %3d\n", costs_ilp2)); copystat_add_opt_costs(costs_ilp2); /*TODO ADAPT */