Commit 94b02881 authored by Daniel Grund's avatar Daniel Grund
Browse files

Added star constraints with all needed helpers

parent 50361736
......@@ -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; i<n_nodes; ++i)
for (o=0; o<i; ++o)
if (be_ifg_connected(ienv->co->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; i<n_nodes; ++i) {
ir_node *member, *cand = nodes[i];
int is_cand;
/* if its already in the clique try the next */
if (pset_find_ptr(clique, cand))
continue;
/* are there all necessary interferences? */
is_cand = 1;
pset_foreach(clique, member) {
if (!find_edge(edges, cand, member)) {
is_cand = 0;
pset_break(clique);
break;
}
}
/* now we know if we have a clique extender */
if (is_cand) {
/* first remove all covered edges */
pset_foreach(clique, member)
remove_edge(edges, cand, member, &n_edges);
/* insert into clique */
pset_insert_ptr(clique, cand);
growed = 1;
break;
}
}
} while (growed);
/* now the clique is maximal. Finally add the constraint */
{
ir_node *member;
int var_idx, cst_idx, center_nr, member_nr;
char buf[16];
cst_idx = lpp_add_cst(ienv->lp, 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);
}
}
/**
......
......@@ -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;
}
......@@ -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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment