2 * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Simple copy minimization heuristics.
27 * Copyrigth (C) 1995-2007 University of Karlsruhe. All right reserved.
29 * This file is part of libFirm.
31 * This file may be distributed and/or modified under the terms of the
32 * GNU General Public License version 2 as published by the Free Software
33 * Foundation and appearing in the file LICENSE.GPL included in the
34 * packaging of this file.
36 * Licensees holding valid libFirm Professional Edition licenses may use
37 * this file in accordance with the libFirm Commercial License.
38 * Agreement provided with the Software.
40 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
41 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
46 * This is the C implementation of the mst algorithm
47 * originally written in Java by Sebastian Hack.
48 * (also known as "heur3" :)
49 * Performs simple copy minimization.
54 #endif /* HAVE_CONFIG_H */
61 #include "raw_bitset.h"
62 #include "irphase_t.h"
72 #include "becopyopt_t.h"
75 #define COL_COST_INFEASIBLE DBL_MAX
76 #define AFF_NEIGHBOUR_FIX_BENEFIT 128.0
77 #define NEIGHBOUR_CONSTR_COSTS 64.0
79 #define DBG_AFF_CHUNK(env, level, chunk) DEBUG_ONLY(if (firm_dbg_get_mask((env)->dbg) & (level)) dbg_aff_chunk((env), (chunk));)
80 #define DBG_COL_COST(env, level, cost) DEBUG_ONLY(if (firm_dbg_get_mask((env)->dbg) & (level)) dbg_col_cost((env), (cost));)
82 static int last_chunk_id = 0;
84 typedef struct _col_cost_t {
89 typedef struct _aff_chunk_t {
92 unsigned weight_consistent : 1;
96 typedef struct _aff_edge_t {
102 /* main coalescing environment*/
103 typedef struct _co_mst_env_t {
104 int n_regs; /**< number of regs in class */
105 int k; /**< number of non-ignore registers in class */
106 bitset_t *ignore_regs; /**< set containing all global ignore registers */
107 ir_phase ph; /**< phase object holding data for nodes */
108 pqueue *chunks; /**< priority queue for chunks */
109 pset_new_t chunkset; /**< set holding all chunks */
110 be_ifg_t *ifg; /**< the interference graph */
111 const arch_env_t *aenv; /**< the arch environment */
112 copy_opt_t *co; /**< the copy opt object */
113 DEBUG_ONLY(firm_dbg_module_t *dbg);
116 /* stores coalescing related information for a node */
117 typedef struct _co_mst_irn_t {
118 ir_node *irn; /**< the irn this information belongs to */
119 aff_chunk_t *chunk; /**< the chunk this irn belongs to */
120 bitset_t *adm_colors; /**< set of admissible colors for this irn */
121 ir_node **int_neighs; /**< ARR_D of all interfering neighbours (cached for speed reasons) */
122 int int_aff_neigh; /**< number of interfering affinity neighbours */
123 int col; /**< color currently assigned */
124 int init_col; /**< the initial color */
125 int tmp_col; /**< a temporary assigned color */
126 unsigned fixed : 1; /**< the color is fixed */
127 unsigned tmp_fixed : 1; /**< the color is temporary fixed */
130 #define get_co_mst_irn(mst_env, irn) (phase_get_or_set_irn_data(&(mst_env)->ph, (irn)))
132 typedef int decide_func_t(co_mst_irn_t *node, int col);
137 * Write a chunk to stderr for debugging.
139 static void dbg_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
141 if (c->weight_consistent)
142 ir_fprintf(stderr, " $%d ", c->weight);
143 ir_fprintf(stderr, "{");
144 bitset_foreach(c->nodes, idx) {
145 ir_node *n = get_idx_irn(env->co->irg, idx);
146 ir_fprintf(stderr, " %+F,", n);
148 ir_fprintf(stderr, "}");
152 * Dump all admissible colors to stderr.
154 static void dbg_admissible_colors(co_mst_env_t *env, co_mst_irn_t *node) {
156 if (bitset_popcnt(node->adm_colors) < 1)
157 fprintf(stderr, "no admissible colors?!?");
159 bitset_foreach(node->adm_colors, idx)
160 fprintf(stderr, " %d", idx);
165 * Dump color-cost pairs to stderr.
167 static void dbg_col_cost(co_mst_env_t *env, col_cost_t *cost) {
169 for (i = 0; i < env->n_regs; ++i) {
170 if (cost[i].cost == COL_COST_INFEASIBLE)
171 fprintf(stderr, " (%d, INF)", cost[i].col);
173 fprintf(stderr, " (%d, %.1f)", cost[i].col, cost[i].cost);
177 #endif /* DEBUG_libfirm */
179 static INLINE int get_mst_irn_col(co_mst_irn_t *node) {
180 return node->tmp_fixed ? node->tmp_col : node->col;
184 * @return 1 if node @p node has color @p col, 0 otherwise.
186 static int decider_has_color(co_mst_irn_t *node, int col) {
187 return get_mst_irn_col(node) == col;
191 * @return 1 if node @p node has not color @p col, 0 otherwise.
193 static int decider_hasnot_color(co_mst_irn_t *node, int col) {
194 return get_mst_irn_col(node) != col;
198 * Always returns true.
200 static int decider_always_yes(co_mst_irn_t *node, int col) {
204 /* > compares two affinity edges by its weight */
205 static int cmp_aff_edge(const void *a, const void *b) {
206 const aff_edge_t *e1 = a;
207 const aff_edge_t *e2 = b;
209 if (e2->weight == e1->weight) {
210 if (e2->src->node_idx == e1->src->node_idx)
211 return QSORT_CMP(e2->tgt->node_idx, e1->tgt->node_idx);
213 return QSORT_CMP(e2->src->node_idx, e1->src->node_idx);
215 /* sort in descending order */
216 return QSORT_CMP(e2->weight, e1->weight);
219 /* compares to color-cost pairs */
220 static int cmp_col_cost(const void *a, const void *b) {
221 const col_cost_t *c1 = a;
222 const col_cost_t *c2 = b;
224 return c1->cost < c2->cost ? -1 : 1;
228 * Creates a new affinity chunk
230 static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
231 aff_chunk_t *c = xmalloc(sizeof(*c));
233 c->weight_consistent = 0;
234 c->nodes = bitset_irg_malloc(env->co->irg);
235 c->id = last_chunk_id++;
236 pset_new_insert(&env->chunkset, c);
241 * Frees all memory allocated by an affinity chunk.
243 static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
244 pset_new_remove(&env->chunkset, c);
245 bitset_free(c->nodes);
250 * Adds a node to an affinity chunk
252 static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
253 c->weight_consistent = 0;
255 bitset_set(c->nodes, get_irn_idx(node->irn));
259 * In case there is no phase information for irn, initialize it.
261 static void *co_mst_irn_init(ir_phase *ph, ir_node *irn, void *old) {
262 co_mst_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
263 co_mst_env_t *env = ph->priv;
266 const arch_register_req_t *req;
267 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
272 res->chunk = new_aff_chunk(env);
276 res->int_neighs = NULL;
277 res->int_aff_neigh = 0;
278 res->col = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
279 res->init_col = res->col;
281 /* add note to new chunk */
282 aff_chunk_add_node(res->chunk, res);
284 DB((env->dbg, LEVEL_4, "Creating phase info for %+F, chunk %d\n", irn, res->chunk->id));
286 /* set admissible registers */
287 res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
289 /* Exclude colors not assignable to the irn */
290 req = arch_get_register_req(env->aenv, irn, -1);
291 if (arch_register_req_is(req, limited))
292 rbitset_copy_to_bitset(req->limited, res->adm_colors);
294 bitset_set_all(res->adm_colors);
296 /* exclude global ignore registers as well */
297 bitset_andnot(res->adm_colors, env->ignore_regs);
299 /* set the number of interfering affinity neighbours to -1, they are calculated later */
300 res->int_aff_neigh = -1;
302 /* build list of interfering neighbours */
304 /* count them first as an obstack array cannot be extended */
305 be_ifg_foreach_neighbour(env->ifg, nodes_it, irn, neigh)
307 res->int_neighs = NEW_ARR_D(ir_node *, phase_obst(ph), len);
309 be_ifg_foreach_neighbour(env->ifg, nodes_it, irn, neigh)
310 res->int_neighs[len++] = neigh;
316 * Check if affinity chunk @p chunk interferes with node @p irn.
318 static INLINE int aff_chunk_interferes(co_mst_env_t *env, aff_chunk_t *chunk, ir_node *irn) {
319 co_mst_irn_t *node = get_co_mst_irn(env, irn);
323 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
324 neigh = node->int_neighs[i];
325 if (! arch_irn_is(env->aenv, neigh, ignore) && bitset_is_set(chunk->nodes, get_irn_idx(neigh)))
333 * Check if there are interference edges from c1 to c2.
334 * @param env The global co_mst environment
336 * @param c2 Another chunk
337 * @return 1 if there are interferences between nodes of c1 and c2, 0 otherwise.
339 static INLINE int aff_chunks_interfere(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
345 /* check if there is a node in c2 having an interfering neighbor in c1 */
346 bitset_foreach(c2->nodes, idx) {
347 ir_node *n = get_idx_irn(env->co->irg, idx);
349 if (aff_chunk_interferes(env, c1, n))
357 * Let c1 absorb the nodes of c2 (only possible when there
358 * are no interference edges from c1 to c2).
359 * @return 1 if successful, 0 if not possible
361 static int aff_chunk_absorb(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
362 DB((env->dbg, LEVEL_4, "Attempt to let c1 (id %d): ", c1->id));
363 DBG_AFF_CHUNK(env, LEVEL_4, c1);
364 DB((env->dbg, LEVEL_4, "\n\tabsorb c2 (id %d): ", c2->id));
365 DBG_AFF_CHUNK(env, LEVEL_4, c2);
366 DB((env->dbg, LEVEL_4, "\n"));
368 if (c1 != c2 && ! aff_chunks_interfere(env, c1, c2)) {
371 bitset_or(c1->nodes, c2->nodes);
372 c1->weight_consistent = 0;
374 bitset_foreach(c2->nodes, idx) {
375 ir_node *n = get_idx_irn(env->co->irg, idx);
376 co_mst_irn_t *mn = get_co_mst_irn(env, n);
380 DB((env->dbg, LEVEL_4, " ... absorbed, c2 deleted\n"));
381 delete_aff_chunk(env, c2);
384 DB((env->dbg, LEVEL_4, " ... c1 interferes with c2, skipped\n"));
389 * Returns the affinity chunk of @p irn or creates a new
390 * one with @p irn as element if there is none assigned.
392 static INLINE aff_chunk_t *get_aff_chunk(co_mst_env_t *env, ir_node *irn) {
393 co_mst_irn_t *node = get_co_mst_irn(env, irn);
394 assert(node->chunk && "Node should have a chunk.");
399 * Assures that the weight of the given chunk is consistent.
401 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
402 if (! c->weight_consistent) {
406 bitset_foreach(c->nodes, idx) {
407 ir_node *n = get_idx_irn(env->co->irg, idx);
408 affinity_node_t *an = get_affinity_info(env->co, n);
412 co_gs_foreach_neighb(an, neigh) {
413 ir_node *m = neigh->irn;
414 int m_idx = get_irn_idx(m);
416 /* skip ignore nodes */
417 if (arch_irn_is(env->aenv, m, ignore))
420 w += bitset_is_set(c->nodes, m_idx) ? neigh->costs : 0;
426 c->weight_consistent = 1;
431 * Count the number of interfering affinity neighbours
433 static int count_interfering_aff_neighs(co_mst_env_t *env, affinity_node_t *an) {
435 ir_node *irn = an->irn;
436 co_mst_irn_t *node = get_co_mst_irn(env, irn);
439 co_gs_foreach_neighb(an, neigh) {
440 ir_node *n = neigh->irn;
443 /* skip ignore nodes */
444 if (arch_irn_is(env->aenv, n, ignore))
447 /* check if the affinity neighbour interfere */
448 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
449 if (node->int_neighs[i] == n) {
460 * Build chunks of nodes connected by affinity edges.
461 * We start at the heaviest affinity edge.
462 * The chunks of the two edge-defining nodes will be
463 * merged if there are no interference edges from one
464 * chunk to the other.
466 static void build_affinity_chunks(co_mst_env_t *env) {
467 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
468 aff_edge_t *edges = NEW_ARR_F(aff_edge_t, 0);
471 aff_chunk_t *curr_chunk;
472 pset_new_iterator_t iter;
474 /* at first we create the affinity edge objects */
475 be_ifg_foreach_node(env->ifg, nodes_it, n) {
476 int n_idx = get_irn_idx(n);
480 /* skip ignore nodes */
481 if (arch_irn_is(env->aenv, n, ignore))
484 n1 = get_co_mst_irn(env, n);
485 an = get_affinity_info(env->co, n);
490 if (n1->int_aff_neigh < 0)
491 n1->int_aff_neigh = count_interfering_aff_neighs(env, an);
492 co_gs_foreach_neighb(an, neigh) {
493 ir_node *m = neigh->irn;
494 int m_idx = get_irn_idx(m);
496 /* record the edge in only one direction */
501 /* skip ignore nodes */
502 if (arch_irn_is(env->aenv, m, ignore))
508 n2 = get_co_mst_irn(env, m);
509 if (n2->int_aff_neigh < 0) {
510 affinity_node_t *am = get_affinity_info(env->co, m);
511 n2->int_aff_neigh = count_interfering_aff_neighs(env, am);
513 edge.weight = (double)neigh->costs / (double)(1 + n1->int_aff_neigh + n2->int_aff_neigh);
514 ARR_APP1(aff_edge_t, edges, edge);
520 /* now: sort edges and build the affinity chunks */
521 len = ARR_LEN(edges);
522 qsort(edges, len, sizeof(edges[0]), cmp_aff_edge);
523 for (i = 0; i < len; ++i) {
524 aff_chunk_t *c1 = get_aff_chunk(env, edges[i].src);
525 aff_chunk_t *c2 = get_aff_chunk(env, edges[i].tgt);
527 DBG((env->dbg, LEVEL_1, "edge (%u,%u) %f\n", edges[i].src->node_idx, edges[i].tgt->node_idx, edges[i].weight));
529 (void)aff_chunk_absorb(env, c1, c2);
532 /* now insert all chunks into a priority queue */
533 foreach_pset_new(&env->chunkset, curr_chunk, iter) {
534 aff_chunk_assure_weight(env, curr_chunk);
536 DBG((env->dbg, LEVEL_1, "entry #%d", curr_chunk->id));
537 DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
538 DBG((env->dbg, LEVEL_1, "\n"));
541 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
548 * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
550 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
551 aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
553 waitq *nodes = new_waitq();
555 DBG((env->dbg, LEVEL_1, "\nExpanding new chunk (id %d) from %+F:", chunk->id, node->irn));
557 /* init queue and chunk */
558 waitq_put(nodes, node);
559 bitset_set(visited, get_irn_idx(node->irn));
560 aff_chunk_add_node(chunk, node);
561 DB((env->dbg, LEVEL_1, " %+F", node->irn));
563 /* as long as there are nodes in the queue */
564 while (! waitq_empty(nodes)) {
565 co_mst_irn_t *n = waitq_get(nodes);
566 affinity_node_t *an = get_affinity_info(env->co, n->irn);
568 /* check all affinity neighbors */
571 co_gs_foreach_neighb(an, neigh) {
572 ir_node *m = neigh->irn;
573 int m_idx = get_irn_idx(m);
576 /* skip ignore nodes */
577 if (arch_irn_is(env->aenv, m, ignore))
580 n2 = get_co_mst_irn(env, m);
582 if (! bitset_is_set(visited, m_idx) &&
585 ! aff_chunk_interferes(env, chunk, m) &&
586 bitset_is_set(orig_chunk->nodes, m_idx))
589 following conditions are met:
590 - neighbour is not visited
591 - neighbour likes the color
592 - neighbour has not yet a fixed color
593 - the new chunk doesn't interfere with the neighbour
594 - neighbour belongs or belonged once to the original chunk
596 bitset_set(visited, m_idx);
597 aff_chunk_add_node(chunk, n2);
598 DB((env->dbg, LEVEL_1, " %+F", n2->irn));
599 /* enqueue for further search */
600 waitq_put(nodes, n2);
606 DB((env->dbg, LEVEL_1, "\n"));
612 * Fragment the given chunk into chunks having given color and not having given color.
614 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp) {
615 bitset_t *visited = bitset_irg_malloc(env->co->irg);
617 aff_chunk_t *best = NULL;
619 bitset_foreach(c->nodes, idx) {
622 aff_chunk_t *tmp_chunk;
623 decide_func_t *decider;
626 if (bitset_is_set(visited, idx))
629 irn = get_idx_irn(env->co->irg, idx);
630 node = get_co_mst_irn(env, irn);
632 if (get_mst_irn_col(node) == col) {
633 decider = decider_has_color;
637 decider = decider_hasnot_color;
641 /* create a new chunk starting at current node */
642 tmp_chunk = new_aff_chunk(env);
643 waitq_put(tmp, tmp_chunk);
644 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
645 assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
647 /* remember the local best */
648 aff_chunk_assure_weight(env, tmp_chunk);
649 if (check_for_best && (! best || best->weight < tmp_chunk->weight))
653 assert(best && "No chunk found?");
654 bitset_free(visited);
659 * Initializes an array of color-cost pairs.
660 * Sets forbidden colors to costs COL_COST_INFEASIBLE and all others to @p c.
662 static INLINE void col_cost_init(co_mst_env_t *env, col_cost_t *cost, double c) {
665 for (i = 0; i < env->n_regs; ++i) {
667 if (bitset_is_set(env->ignore_regs, i))
668 cost[i].cost = COL_COST_INFEASIBLE;
675 * Initializes an array of color-cost pairs.
676 * Sets all colors except color @p col to COL_COST_INFEASIBLE and @p col to 0.0
678 static INLINE void col_cost_init_single(co_mst_env_t *env, col_cost_t *cost, int col) {
679 assert(! bitset_is_set(env->ignore_regs, col) && "Attempt to use forbidden color.");
680 col_cost_init(env, cost, COL_COST_INFEASIBLE);
687 * Resets the temporary fixed color of all nodes within wait queue @p nodes.
688 * ATTENTION: the queue is empty after calling this function!
690 static INLINE void reject_coloring(waitq *nodes) {
691 while (! waitq_empty(nodes)) {
692 co_mst_irn_t *n = waitq_get(nodes);
698 * Determines the costs for each color if it would be assigned to node @p node.
700 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs) {
701 affinity_node_t *an = get_affinity_info(env->co, node->irn);
705 col_cost_init(env, costs, 0.0);
707 /* calculate (negative) costs for affinity neighbours */
709 co_gs_foreach_neighb(an, aff_neigh) {
710 ir_node *m = aff_neigh->irn;
714 /* skip ignore nodes */
715 if (arch_irn_is(env->aenv, m, ignore))
718 neigh = get_co_mst_irn(env, m);
719 c = (double)aff_neigh->costs;
721 /* calculate costs for fixed affinity neighbours */
722 if (neigh->tmp_fixed || neigh->fixed) {
723 int col = get_mst_irn_col(neigh);
724 costs[col].cost -= c * AFF_NEIGHBOUR_FIX_BENEFIT;
729 /* calculate (positive) costs for interfering neighbours */
730 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
735 int_neigh = node->int_neighs[i];
737 /* skip ignore nodes */
738 if (arch_irn_is(env->aenv, int_neigh, ignore))
741 neigh = get_co_mst_irn(env, int_neigh);
742 col = get_mst_irn_col(neigh);
743 col_cnt = bitset_popcnt(neigh->adm_colors);
745 if (neigh->tmp_fixed || neigh->fixed) {
746 /* colors of fixed interfering neighbours are infeasible */
747 costs[col].cost = COL_COST_INFEASIBLE;
749 else if (col_cnt < env->k) {
750 /* calculate costs for constrained interfering neighbours */
751 double ratio = 1.0 - ((double)col_cnt / (double)env->k);
753 bitset_foreach_clear(neigh->adm_colors, idx) {
754 /* check only explicitly forbidden colors (skip global forbidden ones) */
755 if (! bitset_is_set(env->ignore_regs, idx)) {
756 costs[col].cost += ratio * NEIGHBOUR_CONSTR_COSTS;
762 /* set all not admissible colors to COL_COST_INFEASIBLE */
763 bitset_foreach_clear(node->adm_colors, idx)
764 costs[idx].cost = COL_COST_INFEASIBLE;
767 /* need forward declaration due to recursive call */
768 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones);
771 * Tries to change node to a color but @p explude_col.
772 * @return 1 if succeeded, 0 otherwise.
774 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, waitq *changed_ones) {
775 int col = get_mst_irn_col(node);
778 /* neighbours has already a different color -> good, temporary fix it */
779 if (col != exclude_col) {
782 waitq_put(changed_ones, node);
786 /* The node has the color it should not have _and_ has not been visited yet. */
787 if (! (node->tmp_fixed || node->fixed)) {
788 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
790 /* Get the costs for giving the node a specific color. */
791 determine_color_costs(env, node, costs);
793 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
794 costs[exclude_col].cost = COL_COST_INFEASIBLE;
796 /* sort the colors according costs, cheapest first. */
797 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost);
799 /* Try recoloring the node using the color list. */
800 res = recolor_nodes(env, node, costs, changed_ones);
807 * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
808 * ATTENTION: Expect @p costs already sorted by increasing costs.
809 * @return 1 if coloring could be applied, 0 otherwise.
811 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones) {
813 waitq *local_changed = new_waitq();
814 waitq *tmp = new_waitq();
816 DBG((env->dbg, LEVEL_1, "\tRecoloring %+F with color-costs", node->irn));
817 DBG_COL_COST(env, LEVEL_1, costs);
818 DB((env->dbg, LEVEL_1, "\n"));
820 for (i = 0; i < env->n_regs; ++i) {
821 int tgt_col = costs[i].col;
825 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
826 if (costs[i].cost == COL_COST_INFEASIBLE) {
828 del_waitq(local_changed);
833 /* Set the new color of the node and mark the node as temporarily fixed. */
834 assert(! node->tmp_fixed && "Node must not have been temporary fixed.");
836 node->tmp_col = tgt_col;
838 assert(waitq_empty(local_changed) && "Node queue should be empty here.");
839 waitq_put(local_changed, node);
841 /* try to color all interfering neighbours with current color forbidden */
842 for (j = 0; j < ARR_LEN(node->int_neighs); ++j) {
846 neigh = node->int_neighs[j];
848 /* skip ignore nodes */
849 if (arch_irn_is(env->aenv, neigh, ignore))
852 nn = get_co_mst_irn(env, neigh);
855 Try to change the color of the neighbor and record all nodes which
856 get changed in the tmp list. Add this list to the "changed" list for
857 that color. If we did not succeed to change the color of the neighbor,
858 we bail out and try the next color.
860 if (get_mst_irn_col(nn) == tgt_col) {
861 /* try to color neighbour with tgt_col forbidden */
862 neigh_ok = change_node_color_excluded(env, nn, tgt_col, tmp);
864 /* join lists of changed nodes */
865 while (! waitq_empty(tmp))
866 waitq_put(local_changed, waitq_get(tmp));
874 We managed to assign the target color to all neighbors, so from the perspective
875 of the current node, every thing was ok and we can return safely.
878 /* append the local_changed ones to global ones */
879 while (! waitq_empty(local_changed))
880 waitq_put(changed_ones, waitq_get(local_changed));
881 del_waitq(local_changed);
886 /* coloring of neighbours failed, so we try next color */
887 reject_coloring(local_changed);
891 del_waitq(local_changed);
897 * Tries to bring node @p node and all it's neighbours to color @p tgt_col.
898 * @return 1 if color @p col could be applied, 0 otherwise
900 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, waitq *changed_ones) {
901 int col = get_mst_irn_col(node);
903 /* if node already has the target color -> good, temporary fix it */
904 if (col == tgt_col) {
905 DBG((env->dbg, LEVEL_4, "\t\tCNC: %+F has already color %d, fix temporary\n", node->irn, tgt_col));
906 if (! node->tmp_fixed) {
908 node->tmp_col = tgt_col;
909 waitq_put(changed_ones, node);
915 Node has not yet a fixed color and target color is admissible
916 -> try to recolor node and it's affinity neighbours
918 if (! (node->fixed || node->tmp_fixed) && bitset_is_set(node->adm_colors, tgt_col)) {
919 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
922 col_cost_init_single(env, costs, tgt_col);
924 DBG((env->dbg, LEVEL_4, "\t\tCNC: Attempt to recolor %+F ===>>\n", node->irn));
925 res = recolor_nodes(env, node, costs, changed_ones);
926 DBG((env->dbg, LEVEL_4, "\t\tCNC: <<=== Recoloring of %+F %s\n", node->irn, res ? "succeeded" : "failed"));
932 if (firm_dbg_get_mask(env->dbg) & LEVEL_4) {
933 if (node->fixed || node->tmp_fixed)
934 DB((env->dbg, LEVEL_4, "\t\tCNC: %+F has already fixed color %d\n", node->irn, col));
936 DB((env->dbg, LEVEL_4, "\t\tCNC: color %d not admissible for %+F (", tgt_col, node->irn));
937 dbg_admissible_colors(env, node);
938 DB((env->dbg, LEVEL_4, ")\n"));
947 * Tries to color an affinity chunk (or at least a part of it).
948 * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
950 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
951 aff_chunk_t *best_chunk = NULL;
953 waitq *changed_ones = new_waitq();
954 waitq *tmp_chunks = new_waitq();
958 DB((env->dbg, LEVEL_2, "fragmentizing chunk #%d", c->id));
959 DBG_AFF_CHUNK(env, LEVEL_2, c);
960 DB((env->dbg, LEVEL_2, "\n"));
963 /* check which color is the "best" for the given chunk */
964 for (col = 0; col < env->k; ++col) {
966 aff_chunk_t *local_best;
968 DB((env->dbg, LEVEL_3, "\ttrying color %d\n", col));
970 /* try to bring all nodes of given chunk to the current color. */
971 bitset_foreach(c->nodes, idx) {
972 ir_node *irn = get_idx_irn(env->co->irg, idx);
973 co_mst_irn_t *node = get_co_mst_irn(env, irn);
975 assert(! node->fixed && "Node must not have a fixed color.");
977 DB((env->dbg, LEVEL_4, "\t\tBringing %+F from color %d to color %d ...\n", irn, node->col, col));
978 one_good |= change_node_color(env, node, col, changed_ones);
979 DB((env->dbg, LEVEL_4, "\t\t... %+F attempt from %d to %d %s\n", irn, node->col, col, one_good ? "succeeded" : "failed"));
982 /* try next color when failed */
986 /* fragment the chunk according to the coloring */
987 local_best = fragment_chunk(env, col, c, tmp_chunks);
989 /* search the best of the good list
990 and make it the new best if it is better than the current */
992 aff_chunk_assure_weight(env, local_best);
994 DB((env->dbg, LEVEL_4, "\t\tlocal best chunk (id %d) for color %d: ", local_best->id, col));
995 DBG_AFF_CHUNK(env, LEVEL_4, local_best);
997 if (! best_chunk || best_chunk->weight < local_best->weight) {
998 best_chunk = local_best;
1000 DB((env->dbg, LEVEL_4, "\n\t\t... setting global best chunk (id %d), color %d\n", best_chunk->id, best_color));
1002 DB((env->dbg, LEVEL_4, "\n\t\t... omitting, global best is better\n"));
1006 /* reject the coloring and bring the coloring to the initial state */
1007 reject_coloring(changed_ones);
1010 /* free all intermediate created chunks except best one */
1011 while (! waitq_empty(tmp_chunks)) {
1012 aff_chunk_t *tmp = waitq_get(tmp_chunks);
1013 if (tmp != best_chunk)
1014 delete_aff_chunk(env, tmp);
1016 del_waitq(tmp_chunks);
1018 /* return if coloring failed */
1020 delete_aff_chunk(env, c);
1021 del_waitq(changed_ones);
1025 DB((env->dbg, LEVEL_2, "\tbest chunk #%d ", best_chunk->id));
1026 DBG_AFF_CHUNK(env, LEVEL_2, best_chunk);
1027 DB((env->dbg, LEVEL_2, "using color %d\n", best_color));
1029 /* get the best fragment from the best list and color it */
1030 bitset_foreach(best_chunk->nodes, idx) {
1031 ir_node *irn = get_idx_irn(env->co->irg, idx);
1032 co_mst_irn_t *node = get_co_mst_irn(env, irn);
1035 res = change_node_color(env, node, best_color, changed_ones);
1036 assert(res && "color manifesting failed");
1038 node->chunk = best_chunk;
1041 /* materialize colors on changed nodes */
1042 while (! waitq_empty(changed_ones)) {
1043 co_mst_irn_t *n = waitq_get(changed_ones);
1045 n->col = n->tmp_col;
1048 /* remove the nodes in best chunk from original chunk */
1049 bitset_andnot(c->nodes, best_chunk->nodes);
1051 /* we have to get the nodes back into the original chunk because they are scattered over temporary chunks */
1052 bitset_foreach(c->nodes, idx) {
1053 ir_node *n = get_idx_irn(env->co->irg, idx);
1054 co_mst_irn_t *nn = get_co_mst_irn(env, n);
1058 /* fragment the remaining chunk */
1059 visited = bitset_irg_malloc(env->co->irg);
1060 bitset_or(visited, best_chunk->nodes);
1061 bitset_foreach(c->nodes, idx) {
1062 if (! bitset_is_set(visited, idx)) {
1063 aff_chunk_t *new_chunk = new_aff_chunk(env);
1064 ir_node *irn = get_idx_irn(env->co->irg, idx);
1065 co_mst_irn_t *node = get_co_mst_irn(env, irn);
1067 expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
1068 aff_chunk_assure_weight(env, new_chunk);
1069 pqueue_put(env->chunks, new_chunk, new_chunk->weight);
1073 /* clear obsolete chunks and free some memory */
1074 delete_aff_chunk(env, best_chunk);
1075 bitset_free(visited);
1076 del_waitq(changed_ones);
1080 * Main driver for mst safe coalescing algorithm.
1082 int co_solve_heuristic_mst(copy_opt_t *co)
1084 unsigned n_regs = co->cls->n_regs;
1085 bitset_t *ignore_regs = bitset_alloca(n_regs);
1088 co_mst_env_t mst_env;
1091 phase_init(&mst_env.ph, "co_mst", co->irg, PHASE_DEFAULT_GROWTH, co_mst_irn_init, &mst_env);
1093 k = be_put_ignore_regs(co->cenv->birg, co->cls, ignore_regs);
1096 FIRM_DBG_REGISTER(mst_env.dbg, "firm.be.co.heur4");
1097 mst_env.n_regs = n_regs;
1099 mst_env.chunks = new_pqueue();
1101 mst_env.ignore_regs = ignore_regs;
1102 mst_env.ifg = co->cenv->ifg;
1103 mst_env.aenv = co->aenv;
1104 pset_new_init(&mst_env.chunkset);
1106 DBG((mst_env.dbg, LEVEL_1, "==== Coloring %+F, class %s ====\n", co->irg, co->cls->name));
1108 /* build affinity chunks */
1109 build_affinity_chunks(&mst_env);
1111 /* color chunks as long as there are some */
1112 while (! pqueue_empty(mst_env.chunks)) {
1113 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
1115 color_aff_chunk(&mst_env, chunk);
1116 DB((mst_env.dbg, LEVEL_4, "<<<====== Coloring chunk (%d) done\n", chunk->id));
1117 delete_aff_chunk(&mst_env, chunk);
1120 /* apply coloring */
1121 foreach_phase_irn(&mst_env.ph, irn) {
1122 co_mst_irn_t *mirn = get_co_mst_irn(&mst_env, irn);
1123 const arch_register_t *reg;
1125 if (arch_irn_is(mst_env.aenv, irn, ignore))
1128 assert(mirn->fixed && "Node should have fixed color");
1130 /* skip nodes where color hasn't changed */
1131 if (mirn->init_col == mirn->col)
1134 reg = arch_register_for_index(co->cls, mirn->col);
1135 arch_set_irn_register(co->aenv, irn, reg);
1136 DB((mst_env.dbg, LEVEL_1, "%+F set color from %d to %d\n", irn, mirn->init_col, mirn->col));
1139 /* free allocated memory */
1140 del_pqueue(mst_env.chunks);
1141 phase_free(&mst_env.ph);
1142 pset_new_destroy(&mst_env.chunkset);