2 * This is the C implementation of the trivial mst algo
3 * originally written in Java by Sebastian Hack.
4 * Performs simple copy minimzation.
6 * @author Christian Wuerdig
13 #endif /* HAVE_CONFIG_H */
20 #include "raw_bitset.h"
21 #include "irphase_t.h"
30 #include "becopyopt_t.h"
33 #define COL_COST_INFEASIBLE DBL_MAX
34 #define AFF_NEIGHBOUR_FIX_BENEFIT 128.0
35 #define NEIGHBOUR_CONSTR_COSTS 64.0
37 typedef struct _col_cost_t {
42 typedef struct _aff_chunk_t {
45 unsigned weight_consistent : 1;
48 typedef struct _aff_edge_t {
54 /* main coalescing environment*/
55 typedef struct _co_mst_env_t {
56 int n_regs; /**< number of regs in class */
57 int k; /**< number of non-ignore registers in class */
58 bitset_t *ignore_regs; /**< set containing all global ignore registers */
59 ir_phase ph; /**< phase object holding data for nodes */
60 pqueue *chunks; /**< priority queue for chunks */
61 pset_new_t chunkset; /**< set holding all chunks */
62 be_ifg_t *ifg; /**< the interference graph */
63 const arch_env_t *aenv; /**< the arch environment */
64 copy_opt_t *co; /**< the copy opt object */
67 /* stores coalescing related information for a node */
68 typedef struct _co_mst_irn_t {
77 unsigned tmp_fixed : 1;
81 #define get_co_mst_irn(mst_env, irn) (phase_get_or_set_irn_data(&(mst_env)->ph, (irn)))
83 typedef int decide_func_t(co_mst_irn_t *node, int col);
85 static INLINE int get_mst_irn_col(co_mst_irn_t *node) {
86 return node->tmp_fixed ? node->tmp_col : node->col;
90 * @return 1 if node @p node has color @p col, 0 otherwise.
92 static int decider_has_color(co_mst_irn_t *node, int col) {
93 return get_mst_irn_col(node) == col;
97 * @return 1 if node @p node has not color @p col, 0 otherwise.
99 static int decider_hasnot_color(co_mst_irn_t *node, int col) {
100 return get_mst_irn_col(node) != col;
104 * Always returns true.
106 static int decider_always_yes(co_mst_irn_t *node, int col) {
110 /* compares two affinity edges */
111 static int cmp_aff_edge(const void *a, const void *b) {
112 const aff_edge_t *e1 = a;
113 const aff_edge_t *e2 = b;
115 /* sort in descending order */
116 return e1->weight < e2->weight ? 1 : -1;
119 /* compares to color-cost pairs */
120 static int cmp_col_cost(const void *a, const void *b) {
121 const col_cost_t *c1 = a;
122 const col_cost_t *c2 = b;
124 return c1->cost < c2->cost ? -1 : 1;
128 * Creates a new affinity chunk
130 static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
131 aff_chunk_t *c = xmalloc(sizeof(*c));
132 c->weight_consistent = 0;
133 c->nodes = bitset_irg_malloc(env->co->irg);
134 pset_new_insert(&env->chunkset, c);
139 * Frees all memory allocated by an affinity chunk.
141 static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
142 pset_new_remove(&env->chunkset, c);
143 bitset_free(c->nodes);
148 * Adds a node to an affinity chunk
150 static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
151 c->weight_consistent = 0;
153 bitset_set(c->nodes, get_irn_idx(node->irn));
158 * In case there is no phase information for irn, initialize it.
160 static void *co_mst_irn_init(ir_phase *ph, ir_node *irn, void *old) {
161 co_mst_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
162 co_mst_env_t *env = ph->priv;
165 void *neigh_it = be_ifg_neighbours_iter_alloca(env->ifg);
166 const arch_register_req_t *req;
170 res->chunk = new_aff_chunk(env);
175 res->col = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
176 res->init_col = res->col;
178 /* add note to new chunk */
179 aff_chunk_add_node(res->chunk, res);
181 /* set admissible registers */
182 res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
184 /* Exclude colors not assignable to the irn */
185 req = arch_get_register_req(env->aenv, irn, -1);
186 if (arch_register_req_is(req, limited))
187 rbitset_copy_to_bitset(req->limited, res->adm_colors);
189 /* exclude global ignore registers as well */
190 bitset_andnot(res->adm_colors, env->ignore_regs);
192 /* calculate the number of interfering neighbours */
193 be_ifg_foreach_neighbour(env->ifg, neigh_it, irn, m) {
194 if (! arch_irn_is(env->aenv, m, ignore))
204 * Check if there are interference edges from c1 to c2.
205 * @param env The global co_mst environment
207 * @param c2 Another chunk
208 * @return 1 if there are interferences between nodes of c1 and c2, 0 otherwise.
210 static INLINE int aff_chunks_interfere(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
211 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
214 /* check if there is a node in c1 having an interfering neighbour in c2 */
215 bitset_foreach(c1->nodes, idx) {
216 ir_node *n = get_idx_irn(env->co->irg, idx);
219 be_ifg_foreach_neighbour(env->ifg, nodes_it, n, neigh) {
220 if (bitset_is_set(c2->nodes, get_irn_idx(neigh)))
229 * Let c1 absorb the nodes of c2 (only possible when there
230 * are no interference edges from c1 to c2).
231 * @return 1 if successful, 0 if not possible
233 static INLINE int aff_chunk_absorb(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
234 if (! aff_chunks_interfere(env, c1, c2) && c1 != c2) {
237 bitset_or(c1->nodes, c2->nodes);
238 c1->weight_consistent = 0;
240 bitset_foreach(c2->nodes, idx) {
241 ir_node *n = get_idx_irn(env->co->irg, idx);
242 co_mst_irn_t *mn = get_co_mst_irn(env, n);
246 delete_aff_chunk(env, c2);
253 * Returns the affinity chunk of @p irn or creates a new
254 * one with @p irn as element if there is none assigned.
256 static INLINE aff_chunk_t *get_aff_chunk(co_mst_env_t *env, ir_node *irn) {
257 co_mst_irn_t *node = get_co_mst_irn(env, irn);
258 assert(node->chunk && "Node should have a chunk.");
263 * Assures that the weight of the given chunk is consistent.
265 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
266 if (! c->weight_consistent) {
270 bitset_foreach(c->nodes, idx) {
271 ir_node *n = get_idx_irn(env->co->irg, idx);
272 affinity_node_t *an = get_affinity_info(env->co, n);
273 co_mst_irn_t *n1 = get_co_mst_irn(env, n);
277 co_gs_foreach_neighb(an, neigh) {
278 ir_node *m = neigh->irn;
279 int m_idx = get_irn_idx(m);
282 /* skip ignore nodes */
283 if (arch_irn_is(env->aenv, m, ignore))
286 n2 = get_co_mst_irn(env, m);
288 /* record the edge in only one direction */
290 w += (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
296 c->weight_consistent = 1;
301 * Build chunks of nodes connected by affinity edges.
302 * We start at the heaviest affinity edge.
303 * The chunks of the two edge-defining nodes will be
304 * merged if there are no interference edges from one
305 * chunk to the other.
307 static void build_affinity_chunks(co_mst_env_t *env) {
308 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
309 aff_edge_t *edges = NEW_ARR_F(aff_edge_t, 0);
312 aff_chunk_t *curr_chunk;
313 pset_new_iterator_t iter;
315 /* at first we create the affinity edge objects */
316 be_ifg_foreach_node(env->ifg, nodes_it, n) {
317 int n_idx = get_irn_idx(n);
321 /* skip ignore nodes */
322 if (arch_irn_is(env->aenv, n, ignore))
325 n1 = get_co_mst_irn(env, n);
326 an = get_affinity_info(env->co, n);
330 co_gs_foreach_neighb(an, neigh) {
331 ir_node *m = neigh->irn;
332 int m_idx = get_irn_idx(m);
335 /* skip ignore nodes */
336 if (arch_irn_is(env->aenv, m, ignore))
339 n2 = get_co_mst_irn(env, m);
341 /* record the edge in only one direction */
347 edge.weight = (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
348 ARR_APP1(aff_edge_t, edges, edge);
354 /* now: sort edges and build the affinity chunks */
355 qsort(edges, ARR_LEN(edges), sizeof(edges[0]), cmp_aff_edge);
356 for (i = 0; i < ARR_LEN(edges); ++i) {
357 aff_chunk_t *c1 = get_aff_chunk(env, edges[i].src);
358 aff_chunk_t *c2 = get_aff_chunk(env, edges[i].tgt);
360 (void)aff_chunk_absorb(env, c1, c2);
363 /* now insert all chunks into a priority queue */
364 foreach_pset_new(&env->chunkset, curr_chunk, iter) {
365 aff_chunk_assure_weight(env, curr_chunk);
366 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
373 * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
375 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
376 aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
378 waitq *nodes = new_waitq();
380 /* init queue and chunk */
381 waitq_put(nodes, node);
382 bitset_set(visited, get_irn_idx(node->irn));
383 aff_chunk_add_node(chunk, node);
385 /* as long as there are nodes in the queue */
386 while (! waitq_empty(nodes)) {
387 co_mst_irn_t *n = waitq_get(nodes);
388 affinity_node_t *an = get_affinity_info(env->co, n->irn);
389 int n_idx = get_irn_idx(n->irn);
391 /* check all affinity neighbors */
394 co_gs_foreach_neighb(an, neigh) {
395 ir_node *m = neigh->irn;
396 int m_idx = get_irn_idx(m);
399 /* skip ignore nodes */
400 if (arch_irn_is(env->aenv, m, ignore))
403 n2 = get_co_mst_irn(env, m);
406 ! bitset_is_set(visited, m_idx) &&
409 ! aff_chunks_interfere(env, chunk, n2->chunk) &&
410 bitset_is_set(orig_chunk->nodes, m_idx))
413 following conditions are met:
414 - neighbour is not visited
415 - neighbour likes the color
416 - neighbour has not yet a fixed color
417 - the new chunk doesn't interfere with the chunk of the neighbour
418 - neighbour belongs or belonged once to the original chunk
420 bitset_set(visited, m_idx);
421 aff_chunk_add_node(chunk, n2);
422 /* enqueue for further search */
423 waitq_put(nodes, n2);
433 * Fragment the given chunk into chunks having given color and not having given color.
435 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp) {
436 bitset_t *visited = bitset_irg_malloc(env->co->irg);
438 aff_chunk_t *best = NULL;
440 bitset_foreach(c->nodes, idx) {
443 aff_chunk_t *tmp_chunk;
444 decide_func_t *decider;
447 if (bitset_is_set(visited, idx))
450 irn = get_idx_irn(env->co->irg, idx);
451 node = get_co_mst_irn(env, irn);
453 if (get_mst_irn_col(node) == col) {
454 decider = decider_has_color;
458 decider = decider_hasnot_color;
462 /* create a new chunk starting at current node */
463 tmp_chunk = new_aff_chunk(env);
464 waitq_put(tmp, tmp_chunk);
465 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
466 assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
468 /* remember the local best */
469 aff_chunk_assure_weight(env, tmp_chunk);
470 if (check_for_best && (! best || best->weight < tmp_chunk->weight))
474 assert(best && "No chunk found?");
475 bitset_free(visited);
480 * Initializes an array of color-cost pairs.
481 * Sets forbidden colors to costs COL_COST_INFEASIBLE and all others to @p c.
483 static INLINE void col_cost_init(co_mst_env_t *env, col_cost_t *cost, double c) {
486 for (i = 0; i < env->n_regs; ++i) {
488 if (bitset_is_set(env->ignore_regs, i))
489 cost[i].cost = COL_COST_INFEASIBLE;
496 * Initializes an array of color-cost pairs.
497 * Sets all colors except color @p col to COL_COST_INFEASIBLE and @p col to 0.0
499 static INLINE void col_cost_init_single(co_mst_env_t *env, col_cost_t *cost, int col) {
500 assert(! bitset_is_set(env->ignore_regs, col) && "Attempt to use forbidden color.");
501 col_cost_init(env, cost, COL_COST_INFEASIBLE);
508 * Resets the temporary fixed color of all nodes within wait queue @p nodes.
509 * ATTENTION: the queue is empty after calling this function!
511 static INLINE void reject_coloring(waitq *nodes) {
512 while (! waitq_empty(nodes)) {
513 co_mst_irn_t *n = waitq_get(nodes);
519 * Determines the costs for each color if it would be assigned to node @p node.
521 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs) {
522 affinity_node_t *an = get_affinity_info(env->co, node->irn);
523 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
528 col_cost_init(env, costs, 0.0);
530 /* calculate (negative) costs for affinity neighbours */
531 co_gs_foreach_neighb(an, aff_neigh) {
532 ir_node *m = aff_neigh->irn;
533 co_mst_irn_t *neigh = get_co_mst_irn(env, m);
534 double c = (double)aff_neigh->costs;
536 /* calculate costs for fixed affinity neighbours */
537 if (neigh->tmp_fixed || neigh->fixed) {
538 int col = get_mst_irn_col(neigh);
539 costs[col].cost -= c * AFF_NEIGHBOUR_FIX_BENEFIT;
543 /* calculate (positive) costs for interfering neighbours */
544 be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, int_neigh) {
545 co_mst_irn_t *neigh = get_co_mst_irn(env, int_neigh);
546 int col = get_mst_irn_col(neigh);
547 int col_cnt = bitset_popcnt(neigh->adm_colors);
549 if (neigh->tmp_fixed || neigh->fixed) {
550 /* colors of fixed interfering neighbours are infeasible */
551 costs[col].cost = COL_COST_INFEASIBLE;
553 else if (col_cnt < env->k) {
554 /* calculate costs for constrained interfering neighbours */
555 double ratio = 1.0 - ((double)col_cnt / (double)env->k);
557 bitset_foreach_clear(neigh->adm_colors, idx) {
558 /* check only explicitly forbidden colors (skip global forbidden ones) */
559 if (! bitset_is_set(env->ignore_regs, idx)) {
560 costs[col].cost += ratio * NEIGHBOUR_CONSTR_COSTS;
566 /* set all not admissible colors to COL_COST_INFEASIBLE */
567 bitset_foreach_clear(node->adm_colors, idx)
568 costs[idx].cost = COL_COST_INFEASIBLE;
571 /* need forward declaration due to recursive call */
572 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones);
575 * Tries to change node to a color but @p explude_col.
576 * @return 1 if succeeded, 0 otherwise.
578 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, waitq *changed_ones) {
579 int col = get_mst_irn_col(node);
582 /* neighbours has already a different color -> good, temporary fix it */
583 if (col != exclude_col) {
586 waitq_put(changed_ones, node);
590 /* The node has the color it should not have _and_ has not been visited yet. */
591 if (! (node->tmp_fixed || node->fixed)) {
592 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
594 /* Get the costs for giving the node a specific color. */
595 determine_color_costs(env, node, costs);
597 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
598 costs[exclude_col].cost = COL_COST_INFEASIBLE;
600 /* sort the colors according costs, cheapest first. */
601 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost);
603 /* Try recoloring the node using the color list. */
604 res = recolor_nodes(env, node, costs, changed_ones);
611 * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
612 * ATTENTION: Expect @p costs already sorted by increasing costs.
613 * @return 1 if coloring could be applied, 0 otherwise.
615 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones) {
617 waitq *local_changed = new_waitq();
619 for (i = 0; i < env->n_regs; ++i) {
620 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
621 int tgt_col = costs[i].col;
625 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
626 if (costs[i].cost == COL_COST_INFEASIBLE) {
628 del_waitq(local_changed);
632 /* Set the new color of the node and mark the node as temporarily fixed. */
633 assert(! node->tmp_fixed && "Node must not have been temporary fixed.");
635 node->tmp_col = tgt_col;
637 assert(waitq_empty(local_changed) && "Node queue should be empty here.");
638 waitq_put(local_changed, node);
640 /* try to color all interfering neighbours with current color forbidden */
641 be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, neigh) {
642 co_mst_irn_t *nn = get_co_mst_irn(env, neigh);
644 Try to change the color of the neighbor and record all nodes which
645 get changed in the tmp list. Add this list to the "changed" list for
646 that color. If we did not succeed to change the color of the neighbor,
647 we bail out and try the next color.
649 if (get_mst_irn_col(nn) == tgt_col) {
650 waitq *tmp = new_waitq();
652 /* try to color neighbour with tgt_col forbidden */
653 neigh_ok = change_node_color_excluded(env, nn, tgt_col, tmp);
655 /* join lists of changed nodes */
656 while (! waitq_empty(tmp))
657 waitq_put(local_changed, waitq_get(tmp));
666 We managed to assign the target color to all neighbors, so from the perspective
667 of the current node, every thing was ok and we can return safely.
670 /* append the local_changed ones to global ones */
671 while (! waitq_empty(local_changed))
672 waitq_put(changed_ones, waitq_get(local_changed));
673 del_waitq(local_changed);
677 /* coloring of neighbours failed, so we try next color */
678 reject_coloring(local_changed);
682 del_waitq(local_changed);
687 * Tries to bring node @p node and all it's neighbours to color @p tgt_col.
688 * @return 1 if color @p col could be applied, 0 otherwise
690 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, waitq *changed_ones) {
691 int col = get_mst_irn_col(node);
693 /* if node already has the target color -> good, temporary fix it */
694 if (col == tgt_col) {
695 if (! node->tmp_fixed) {
697 node->tmp_col = tgt_col;
698 waitq_put(changed_ones, node);
704 Node has not yet a fixed color and target color is admissible
705 -> try to recolor node and it's affinity neighbours
707 if (! (node->fixed || node->tmp_fixed) && bitset_is_set(node->adm_colors, tgt_col)) {
708 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
709 col_cost_init_single(env, costs, tgt_col);
710 return recolor_nodes(env, node, costs, changed_ones);
717 * Tries to color an affinity chunk (or at least a part of it).
718 * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
720 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
721 aff_chunk_t *best_chunk = NULL;
723 waitq *changed_ones = new_waitq();
724 waitq *tmp_chunks = new_waitq();
728 /* check which color is the "best" for the given chunk */
729 for (col = 0; col < env->k; ++col) {
731 aff_chunk_t *local_best;
733 /* try to bring all nodes of given chunk to the current color. */
734 bitset_foreach(c->nodes, idx) {
735 ir_node *irn = get_idx_irn(env->co->irg, idx);
736 co_mst_irn_t *node = get_co_mst_irn(env, irn);
738 assert(! node->fixed && "Node must not have a fixed color.");
740 one_good = change_node_color(env, node, col, changed_ones);
746 /* try next color when failed */
750 /* fragment the chunk according to the coloring */
751 local_best = fragment_chunk(env, col, c, tmp_chunks);
753 /* check if the local best is global best */
755 aff_chunk_assure_weight(env, local_best);
757 if (! best_chunk || best_chunk->weight < local_best->weight) {
758 best_chunk = local_best;
763 /* reject the coloring and bring the coloring to the initial state */
764 reject_coloring(changed_ones);
767 /* free all intermediate created chunks except best one */
768 while (! waitq_empty(tmp_chunks)) {
769 aff_chunk_t *tmp = waitq_get(tmp_chunks);
770 if (tmp != best_chunk)
771 delete_aff_chunk(env, tmp);
773 del_waitq(tmp_chunks);
775 /* return if coloring failed */
777 delete_aff_chunk(env, c);
778 del_waitq(changed_ones);
782 /* get the best fragment from the best list and color it */
783 bitset_foreach(best_chunk->nodes, idx) {
784 ir_node *irn = get_idx_irn(env->co->irg, idx);
785 co_mst_irn_t *node = get_co_mst_irn(env, irn);
788 res = change_node_color(env, node, best_color, changed_ones);
789 assert(res && "Coloring failed");
791 node->col = node->tmp_col;
792 node->chunk = best_chunk;
796 while (! waitq_empty(changed_ones)) {
797 co_mst_irn_t *n = waitq_get(changed_ones);
802 /* remove the nodes in best chunk from original chunk */
803 bitset_andnot(c->nodes, best_chunk->nodes);
805 /* we have to get the nodes back into the original chunk because they are scattered over temporary chunks */
806 bitset_foreach(c->nodes, idx) {
807 ir_node *n = get_idx_irn(env->co->irg, idx);
808 co_mst_irn_t *nn = get_co_mst_irn(env, n);
812 /* fragment the remaining chunk */
813 visited = bitset_irg_malloc(env->co->irg);
814 bitset_or(visited, best_chunk->nodes);
815 bitset_foreach(c->nodes, idx) {
816 if (! bitset_is_set(visited, idx)) {
817 aff_chunk_t *new_chunk = new_aff_chunk(env);
818 ir_node *irn = get_idx_irn(env->co->irg, idx);
819 co_mst_irn_t *node = get_co_mst_irn(env, irn);
821 expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
822 aff_chunk_assure_weight(env, new_chunk);
823 pqueue_put(env->chunks, new_chunk, new_chunk->weight);
827 /* clear obsolete chunks and free some memory */
828 delete_aff_chunk(env, c);
829 delete_aff_chunk(env, best_chunk);
830 bitset_free(visited);
831 del_waitq(changed_ones);
835 * Main driver for mst safe coalescing algorithm.
837 int co_solve_heuristic_mst(copy_opt_t *co)
839 unsigned n_regs = co->cenv->cls->n_regs;
840 bitset_t *ignore_regs = bitset_alloca(n_regs);
843 co_mst_env_t mst_env;
845 memset(&mst_env, 0, sizeof(mst_env));
848 phase_init(&mst_env.ph, "co_mst", co->irg, PHASE_DEFAULT_GROWTH, co_mst_irn_init, &mst_env);
850 k = be_put_ignore_regs(co->cenv->birg, co->cenv->cls, ignore_regs);
853 mst_env.n_regs = n_regs;
855 mst_env.chunks = new_pqueue();
857 mst_env.ignore_regs = ignore_regs;
858 mst_env.ifg = co->cenv->ifg;
859 mst_env.aenv = co->aenv;
860 pset_new_init(&mst_env.chunkset);
862 /* build affinity chunks */
863 build_affinity_chunks(&mst_env);
865 /* color chunks as long as there are some */
866 while (! pqueue_empty(mst_env.chunks)) {
867 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
868 color_aff_chunk(&mst_env, chunk);
872 foreach_phase_irn(&mst_env.ph, irn) {
873 co_mst_irn_t *mirn = get_co_mst_irn(&mst_env, irn);
874 const arch_register_t *reg;
876 assert(mirn->fixed && "Node should have fixed color");
878 reg = arch_register_for_index(co->cenv->cls, mirn->col);
879 arch_set_irn_register(co->aenv, irn, reg);
880 ir_printf("%+F set color from %d to %d\n", irn, mirn->init_col, mirn->col);
883 /* free allocated memory */
884 del_pqueue(mst_env.chunks);
885 phase_free(&mst_env.ph);
886 pset_new_destroy(&mst_env.chunkset);