X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbecopyilp2.c;h=2d8320c8ab20a1a6381af0d63c06e45a7ae082c7;hb=6e3e499d6c68aee0c6a9ada6a99f16c4f6f8445b;hp=b323464e583a203689bea22c8bfcdd1957c02b20;hpb=94b02881010e09aabe313564771b2e99273c4196;p=libfirm diff --git a/ir/be/becopyilp2.c b/ir/be/becopyilp2.c index b323464e5..2d8320c8a 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 */ @@ -134,6 +142,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,7 +180,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 +212,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 +243,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 +255,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_node_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 +271,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 +294,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 +359,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_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) { @@ -374,28 +463,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"); + } } } @@ -413,11 +506,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_REGISTER(my.dbg, "ir.be.coilp2"); firm_dbg_set_mask(my.dbg, DEBUG_LVL); ienv = new_ilp_env(co, ilp2_build, ilp2_apply, &my);