bitset_t *adm_colors;
int int_neigh;
int col;
+ int init_col;
int tmp_col;
unsigned fixed : 1;
unsigned tmp_fixed : 1;
return c1->cost < c2->cost ? -1 : 1;
}
+/**
+ * Creates a new affinity chunk
+ */
+static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
+ aff_chunk_t *c = xmalloc(sizeof(*c));
+ c->weight_consistent = 0;
+ c->nodes = bitset_irg_malloc(env->co->irg);
+ pset_new_insert(&env->chunkset, c);
+ return c;
+}
+
+/**
+ * Frees all memory allocated by an affinity chunk.
+ */
+static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
+ pset_new_remove(&env->chunkset, c);
+ bitset_free(c->nodes);
+ free(c);
+}
+
+/**
+ * Adds a node to an affinity chunk
+ */
+static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
+ c->weight_consistent = 0;
+ node->chunk = c;
+ bitset_set(c->nodes, get_irn_idx(node->irn));
+}
+
+
/**
* In case there is no phase information for irn, initialize it.
*/
ir_node *m;
res->irn = irn;
- res->chunk = NULL;
+ res->chunk = new_aff_chunk(env);
res->fixed = 0;
res->tmp_fixed = 0;
res->tmp_col = -1;
res->int_neigh = 0;
res->col = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
+ res->init_col = res->col;
+
+ /* add note to new chunk */
+ aff_chunk_add_node(res->chunk, res);
/* set admissible registers */
res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
return res;
}
-/**
- * Creates a new affinity chunk
- */
-static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
- aff_chunk_t *c = xmalloc(sizeof(*c));
- c->weight_consistent = 0;
- c->nodes = bitset_irg_malloc(env->co->irg);
- pset_new_insert(&env->chunkset, c);
- return c;
-}
-
-/**
- * Frees all memory allocated by an affinity chunk.
- */
-static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
- pset_new_remove(&env->chunkset, c);
- bitset_free(c->nodes);
- free(c);
-}
-
-/**
- * Adds a node to an affinity chunk
- */
-static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
- c->weight_consistent = 0;
- node->chunk = c;
- bitset_set(c->nodes, get_irn_idx(node->irn));
-}
-
/**
* Check if there are interference edges from c1 to c2.
* @param env The global co_mst environment
* @return 1 if successful, 0 if not possible
*/
static INLINE int aff_chunk_absorb(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
- if (! aff_chunks_interfere(env, c1, c2)) {
+ if (! aff_chunks_interfere(env, c1, c2) && c1 != c2) {
int idx;
bitset_or(c1->nodes, c2->nodes);
* Returns the affinity chunk of @p irn or creates a new
* one with @p irn as element if there is none assigned.
*/
-static INLINE aff_chunk_t *get_or_set_aff_chunk(co_mst_env_t *env, ir_node *irn) {
+static INLINE aff_chunk_t *get_aff_chunk(co_mst_env_t *env, ir_node *irn) {
co_mst_irn_t *node = get_co_mst_irn(env, irn);
-
- if (node->chunk == NULL) {
- node->chunk = new_aff_chunk(env);
- aff_chunk_add_node(node->chunk, node);
- }
-
+ assert(node->chunk && "Node should have a chunk.");
return node->chunk;
}
/* now: sort edges and build the affinity chunks */
qsort(edges, ARR_LEN(edges), sizeof(edges[0]), cmp_aff_edge);
for (i = 0; i < ARR_LEN(edges); ++i) {
- aff_chunk_t *c1 = get_or_set_aff_chunk(env, edges[i].src);
- aff_chunk_t *c2 = get_or_set_aff_chunk(env, edges[i].tgt);
+ aff_chunk_t *c1 = get_aff_chunk(env, edges[i].src);
+ aff_chunk_t *c2 = get_aff_chunk(env, edges[i].tgt);
(void)aff_chunk_absorb(env, c1, c2);
}
co_mst_irn_t *node;
aff_chunk_t *tmp_chunk;
decide_func_t *decider;
+ int check_for_best;
if (bitset_is_set(visited, idx))
continue;
irn = get_idx_irn(env->co->irg, idx);
node = get_co_mst_irn(env, irn);
+ if (get_mst_irn_col(node) == col) {
+ decider = decider_has_color;
+ check_for_best = 1;
+ }
+ else {
+ decider = decider_hasnot_color;
+ check_for_best = 0;
+ }
+
/* create a new chunk starting at current node */
tmp_chunk = new_aff_chunk(env);
waitq_put(tmp, tmp_chunk);
- decider = get_mst_irn_col(node) == col ? decider_has_color : decider_hasnot_color;
expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
/* remember the local best */
aff_chunk_assure_weight(env, tmp_chunk);
- if (! best || best->weight < tmp_chunk->weight)
+ if (check_for_best && (! best || best->weight < tmp_chunk->weight))
best = tmp_chunk;
}
aff_chunk_assure_weight(env, local_best);
if (! best_chunk || best_chunk->weight < local_best->weight) {
- /* kill the old best */
- if (best_chunk)
- delete_aff_chunk(env, best_chunk);
best_chunk = local_best;
best_color = col;
}
/* remove the nodes in best chunk from original chunk */
bitset_andnot(c->nodes, best_chunk->nodes);
+ /* we have to get the nodes back into the original chunk because they are scattered over temporary chunks */
+ bitset_foreach(c->nodes, idx) {
+ ir_node *n = get_idx_irn(env->co->irg, idx);
+ co_mst_irn_t *nn = get_co_mst_irn(env, n);
+ nn->chunk = c;
+ }
+
/* fragment the remaining chunk */
visited = bitset_irg_malloc(env->co->irg);
bitset_or(visited, best_chunk->nodes);
unsigned n_regs = co->cenv->cls->n_regs;
bitset_t *ignore_regs = bitset_alloca(n_regs);
unsigned k;
+ ir_node *irn;
co_mst_env_t mst_env;
memset(&mst_env, 0, sizeof(mst_env));
color_aff_chunk(&mst_env, chunk);
}
+ /* apply coloring */
+ foreach_phase_irn(&mst_env.ph, irn) {
+ co_mst_irn_t *mirn = get_co_mst_irn(&mst_env, irn);
+ const arch_register_t *reg;
+
+ assert(mirn->fixed && "Node should have fixed color");
+
+ reg = arch_register_for_index(co->cenv->cls, mirn->col);
+ arch_set_irn_register(co->aenv, irn, reg);
+ ir_printf("%+F set color from %d to %d\n", irn, mirn->init_col, mirn->col);
+ }
+
/* free allocated memory */
del_pqueue(mst_env.chunks);
phase_free(&mst_env.ph);