X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbecopyilp2.c;h=ee02479044edeb8fcce88258797115369fa868d0;hb=b1ba3383b1807b7b506b394eb5b3e0992ad60f34;hp=93cb741318df81bd97da62db8778d995a09056d8;hpb=76c0c4f215716a69cebe49fbcba24c17a9595f32;p=libfirm diff --git a/ir/be/becopyilp2.c b/ir/be/becopyilp2.c index 93cb74131..ee0247904 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" @@ -41,10 +44,10 @@ #define DEBUG_LVL 1 typedef struct _local_env_t { - firm_dbg_module_t *dbg; double time_limit; int first_x_var, last_x_var; pmap *nr_2_irn; + DEBUG_ONLY(firm_dbg_module_t *dbg;) } local_env_t; static void build_coloring_cstr(ilp_env_t *ienv) { @@ -71,8 +74,10 @@ static void build_coloring_cstr(ilp_env_t *ienv) { /* get assignable colors */ if (arch_register_req_is(&req, limited)) req.limited(req.limited_env, colors); - else - arch_put_non_ignore_regs(ienv->co->aenv, req.cls, colors); + else { + arch_register_class_put(req.cls, colors); + // bitset_andnot(colors, ienv->co->cenv->ignore_colors); + } /* add the coloring constraint */ cst_idx = lpp_add_cst(ienv->lp, NULL, lpp_equal, 1.0); @@ -113,8 +118,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 */ @@ -134,6 +144,12 @@ static void build_interference_cstr(ilp_env_t *ienv) { } } + +/** + * TODO: Remove the dependency of the opt-units data structure + * by walking over all affinity edges. Graph structure + * does not provide this walker, yet. + */ static void build_affinity_cstr(ilp_env_t *ienv) { unit_t *curr; int n_colors = arch_register_class_n_regs(ienv->co->cls); @@ -166,24 +182,265 @@ 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); } } } } /** - * + * Helping stuff for build_clique_star_cstr + */ +typedef struct _edge_t { + ir_node *n1, *n2; +} edge_t; + +static int compare_edge_t(const void *k1, const void *k2, size_t size) { + const edge_t *e1 = k1; + const edge_t *e2 = k2; + + return ! (e1->n1 == e2->n1 && e1->n2 == e2->n2); +} + +#define HASH_EDGE(e) (HASH_PTR((e)->n1) ^ HASH_PTR((e)->n2)) + +static INLINE edge_t *add_edge(set *edges, ir_node *n1, ir_node *n2, int *counter) { + edge_t new_edge; + + if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) { + new_edge.n1 = n1; + new_edge.n2 = n2; + } else { + new_edge.n1 = n2; + new_edge.n2 = n1; + } + (*counter)++; + return set_insert(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge)); +} + +static INLINE edge_t *find_edge(set *edges, ir_node *n1, ir_node *n2) { + edge_t new_edge; + + if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) { + new_edge.n1 = n1; + new_edge.n2 = n2; + } else { + new_edge.n1 = n2; + new_edge.n2 = n1; + } + return set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge)); +} + +static INLINE void remove_edge(set *edges, ir_node *n1, ir_node *n2, int *counter) { + edge_t new_edge, *e; + + if (PTR_TO_INT(n1) < PTR_TO_INT(n2)) { + new_edge.n1 = n1; + new_edge.n2 = n2; + } else { + new_edge.n1 = n2; + new_edge.n2 = n1; + } + e = set_find(edges, &new_edge, sizeof(new_edge), HASH_EDGE(&new_edge)); + if (e) { + e->n1 = NULL; + e->n2 = NULL; + (*counter)--; + } +} + +#define pset_foreach(pset, irn) for(irn=pset_first(pset); irn; irn=pset_next(pset)) + +/** + * Search for an interference clique and an external node + * with affinity edges to all nodes of the clique. + * 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) { + affinity_node_t *aff; + + /* for each node with affinity edges */ + co_gs_foreach_aff_node(ienv->co, aff) { + struct obstack ob; + neighb_t *nbr; + ir_node *center = aff->irn; + ir_node **nodes; + set *edges; + int i, o, n_nodes, n_edges; + + obstack_init(&ob); + edges = new_set(compare_edge_t, 8); + + /* get all affinity neighbours */ + n_nodes = 0; + co_gs_foreach_neighb(aff, nbr) { + obstack_ptr_grow(&ob, nbr->irn); + ++n_nodes; + } + nodes = obstack_finish(&ob); + + /* get all interference edges between these */ + n_edges = 0; + for (i=0; ico->cenv->ifg, nodes[i], nodes[o])) + add_edge(edges, nodes[i], nodes[o], &n_edges); + + /* cover all these interference edges with maximal cliques */ + while (n_edges) { + edge_t *e; + pset *clique = pset_new_ptr(8); + int growed; + + /* get 2 starting nodes to form a clique */ + for (e=set_first(edges); !e->n1; e=set_next(edges)) + /*nothing*/ ; + + 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 { + growed = 0; + + /* search for a candidate to extend the clique */ + for (i=0; ilp, NULL, lpp_greater, pset_count(clique)-1); + center_nr = get_irn_node_nr(center); + + pset_foreach(clique, member) { + member_nr = get_irn_node_nr(member); + var_idx = lpp_get_var_idx(ienv->lp, name_cdd_sorted(buf, 'y', center_nr, member_nr)); + lpp_set_factor_fast(ienv->lp, cst_idx, var_idx, 1.0); + } + } + + del_pset(clique); + } + + del_set(edges); + obstack_free(&ob, NULL); + } +} + + +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_node_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, (const void **)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_node_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) { @@ -208,28 +465,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) { - for (i=0; ilast_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"); + } } } @@ -247,12 +508,14 @@ int co_solve_ilp2(copy_opt_t *co, double time_limit) { ilp_env_t *ienv; local_env_t my; + ASSERT_OU_AVAIL(co); //See build_clique_st + ASSERT_GS_AVAIL(co); + my.time_limit = time_limit; my.first_x_var = -1; my.last_x_var = -1; my.nr_2_irn = pmap_create(); - my.dbg = firm_dbg_register("ir.be.coilp2"); - firm_dbg_set_mask(my.dbg, DEBUG_LVL); + FIRM_DBG_REGISTER(my.dbg, "firm.be.coilp2"); ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my);