From: Daniel Grund Date: Tue, 14 Mar 2006 13:52:33 +0000 (+0000) Subject: Added star constraints with all needed helpers X-Git-Url: http://nsz.repo.hu/git/?a=commitdiff_plain;h=94b02881010e09aabe313564771b2e99273c4196;p=libfirm Added star constraints with all needed helpers --- diff --git a/ir/be/becopyilp2.c b/ir/be/becopyilp2.c index 93cb74131..b323464e5 100644 --- a/ir/be/becopyilp2.c +++ b/ir/be/becopyilp2.c @@ -173,10 +173,176 @@ static void build_affinity_cstr(ilp_env_t *ienv) { } /** - * + * 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) { + node_t *node; + + /* for each node with affinity edges */ + co_gs_foreach_node(ienv->co, node) { + struct obstack ob; + neighb_t *nbr; + ir_node *center = node->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(node, 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*/ ; + + remove_edge(edges, e->n1, e->n2, &n_edges); + pset_insert_ptr(clique, e->n1); + pset_insert_ptr(clique, e->n2); + + /* 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); + } } /** diff --git a/ir/be/becopyopt.c b/ir/be/becopyopt.c index 3526c17ee..25989e71f 100644 --- a/ir/be/becopyopt.c +++ b/ir/be/becopyopt.c @@ -506,8 +506,12 @@ 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; + node_t new_node, *n; - new_node.irn = irn; - return (int)set_find(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn)); + new_node.irn = irn; + n = set_find(co->nodes, new_node.irn, sizeof(new_node), HASH_PTR(new_node.irn)); + if (n) { + return (n->count > 0); + } else + return 0; } diff --git a/ir/be/becopyopt_t.h b/ir/be/becopyopt_t.h index 9d16e8810..bee1e1598 100644 --- a/ir/be/becopyopt_t.h +++ b/ir/be/becopyopt_t.h @@ -69,13 +69,13 @@ struct _copy_opt_t { typedef struct _unit_t { struct list_head units; /**< chain for all units */ - copy_opt_t *co; /**< the copy_opt this unit belongs to */ + copy_opt_t *co; /**< the copy opt this unit belongs to */ int node_count; /**< size of the nodes array */ ir_node **nodes; /**< [0] is the root-node, others are non interfering args of it. */ int *costs; /**< costs[i] are incurred, if nodes[i] has a different color */ int inevitable_costs; /**< sum of costs of all args interfering with root */ int all_nodes_costs; /**< sum of all costs[i] */ - int min_nodes_costs; /**< a lower bound for the costs in costs[], determined by a max indep. set */ + int min_nodes_costs; /**< a lower bound for the costs in costs[], determined by a max independent set */ int sort_key; /**< maximum costs. controls the order of ou's in the struct list_head units. */ /* for heuristic */ @@ -96,6 +96,8 @@ typedef struct _unit_t { ******************************************************************************/ typedef struct _neighb_t neighb_t; +typedef struct _node_t node_t; + struct _neighb_t { neighb_t *next; /** the next neighbour entry*/ @@ -103,11 +105,17 @@ struct _neighb_t { int costs; /** the costs of the edge (node_t->irn, neighb_t->irn) */ }; -typedef struct _node_t { +struct _node_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 */ -} node_t; +}; + +#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_neighb(node, neighb) for (neighb = node->neighbours; neighb; neighb = neighb->next) #endif