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.
23 * @author Christian Wuerdig
27 * This is the C implementation of the mst algorithm
28 * originally written in Java by Sebastian Hack.
29 * (also known as "heur3" :)
30 * Performs simple copy minimization.
34 #endif /* HAVE_CONFIG_H */
41 #include "raw_bitset.h"
42 #include "irphase_t.h"
53 #include "becopyopt_t.h"
55 #define COL_COST_INFEASIBLE DBL_MAX
56 #define AFF_NEIGHBOUR_FIX_BENEFIT 128.0
57 #define NEIGHBOUR_CONSTR_COSTS 64.0
59 #define DBG_AFF_CHUNK(env, level, chunk) DEBUG_ONLY(if (firm_dbg_get_mask((env)->dbg) & (level)) dbg_aff_chunk((env), (chunk));)
60 #define DBG_COL_COST(env, level, cost) DEBUG_ONLY(if (firm_dbg_get_mask((env)->dbg) & (level)) dbg_col_cost((env), (cost));)
62 static int last_chunk_id = 0;
64 typedef struct _col_cost_t {
69 typedef struct _aff_chunk_t {
72 unsigned weight_consistent : 1;
76 typedef struct _aff_edge_t {
82 /* main coalescing environment*/
83 typedef struct _co_mst_env_t {
84 int n_regs; /**< number of regs in class */
85 int k; /**< number of non-ignore registers in class */
86 bitset_t *ignore_regs; /**< set containing all global ignore registers */
87 ir_phase ph; /**< phase object holding data for nodes */
88 pqueue *chunks; /**< priority queue for chunks */
89 pset_new_t chunkset; /**< set holding all chunks */
90 be_ifg_t *ifg; /**< the interference graph */
91 const arch_env_t *aenv; /**< the arch environment */
92 copy_opt_t *co; /**< the copy opt object */
93 DEBUG_ONLY(firm_dbg_module_t *dbg);
96 /* stores coalescing related information for a node */
97 typedef struct _co_mst_irn_t {
98 ir_node *irn; /**< the irn this information belongs to */
99 aff_chunk_t *chunk; /**< the chunk this irn belongs to */
100 bitset_t *adm_colors; /**< set of admissible colors for this irn */
101 ir_node **int_neighs; /**< ARR_D of all interfering neighbours (cached for speed reasons) */
102 int int_aff_neigh; /**< number of interfering affinity neighbours */
103 int col; /**< color currently assigned */
104 int init_col; /**< the initial color */
105 int tmp_col; /**< a temporary assigned color */
106 unsigned fixed : 1; /**< the color is fixed */
107 unsigned tmp_fixed : 1; /**< the color is temporary fixed */
110 #define get_co_mst_irn(mst_env, irn) (phase_get_or_set_irn_data(&(mst_env)->ph, (irn)))
112 typedef int decide_func_t(co_mst_irn_t *node, int col);
117 * Write a chunk to stderr for debugging.
119 static void dbg_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
121 if (c->weight_consistent)
122 ir_fprintf(stderr, " $%d ", c->weight);
123 ir_fprintf(stderr, "{");
124 bitset_foreach(c->nodes, idx) {
125 ir_node *n = get_idx_irn(env->co->irg, idx);
126 ir_fprintf(stderr, " %+F,", n);
128 ir_fprintf(stderr, "}");
132 * Dump all admissible colors to stderr.
134 static void dbg_admissible_colors(co_mst_env_t *env, co_mst_irn_t *node) {
136 if (bitset_popcnt(node->adm_colors) < 1)
137 fprintf(stderr, "no admissible colors?!?");
139 bitset_foreach(node->adm_colors, idx)
140 fprintf(stderr, " %d", idx);
145 * Dump color-cost pairs to stderr.
147 static void dbg_col_cost(co_mst_env_t *env, col_cost_t *cost) {
149 for (i = 0; i < env->n_regs; ++i) {
150 if (cost[i].cost == COL_COST_INFEASIBLE)
151 fprintf(stderr, " (%d, INF)", cost[i].col);
153 fprintf(stderr, " (%d, %.1f)", cost[i].col, cost[i].cost);
157 #endif /* DEBUG_libfirm */
159 static INLINE int get_mst_irn_col(co_mst_irn_t *node) {
160 return node->tmp_fixed ? node->tmp_col : node->col;
164 * @return 1 if node @p node has color @p col, 0 otherwise.
166 static int decider_has_color(co_mst_irn_t *node, int col) {
167 return get_mst_irn_col(node) == col;
171 * @return 1 if node @p node has not color @p col, 0 otherwise.
173 static int decider_hasnot_color(co_mst_irn_t *node, int col) {
174 return get_mst_irn_col(node) != col;
178 * Always returns true.
180 static int decider_always_yes(co_mst_irn_t *node, int col) {
184 /* > compares two affinity edges by its weight */
185 static int cmp_aff_edge(const void *a, const void *b) {
186 const aff_edge_t *e1 = a;
187 const aff_edge_t *e2 = b;
189 if (e2->weight == e1->weight) {
190 if (e2->src->node_idx == e1->src->node_idx)
191 return QSORT_CMP(e2->tgt->node_idx, e1->tgt->node_idx);
193 return QSORT_CMP(e2->src->node_idx, e1->src->node_idx);
195 /* sort in descending order */
196 return QSORT_CMP(e2->weight, e1->weight);
199 /* compares to color-cost pairs */
200 static int cmp_col_cost(const void *a, const void *b) {
201 const col_cost_t *c1 = a;
202 const col_cost_t *c2 = b;
204 return c1->cost < c2->cost ? -1 : 1;
208 * Creates a new affinity chunk
210 static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
211 aff_chunk_t *c = xmalloc(sizeof(*c));
213 c->weight_consistent = 0;
214 c->nodes = bitset_irg_malloc(env->co->irg);
215 c->id = last_chunk_id++;
216 pset_new_insert(&env->chunkset, c);
221 * Frees all memory allocated by an affinity chunk.
223 static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
224 pset_new_remove(&env->chunkset, c);
225 bitset_free(c->nodes);
230 * Adds a node to an affinity chunk
232 static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
233 c->weight_consistent = 0;
235 bitset_set(c->nodes, get_irn_idx(node->irn));
239 * In case there is no phase information for irn, initialize it.
241 static void *co_mst_irn_init(ir_phase *ph, ir_node *irn, void *old) {
242 co_mst_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
243 co_mst_env_t *env = ph->priv;
246 const arch_register_req_t *req;
247 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
252 res->chunk = new_aff_chunk(env);
256 res->int_neighs = NULL;
257 res->int_aff_neigh = 0;
258 res->col = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
259 res->init_col = res->col;
261 /* add note to new chunk */
262 aff_chunk_add_node(res->chunk, res);
264 DB((env->dbg, LEVEL_4, "Creating phase info for %+F, chunk %d\n", irn, res->chunk->id));
266 /* set admissible registers */
267 res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
269 /* Exclude colors not assignable to the irn */
270 req = arch_get_register_req(env->aenv, irn, -1);
271 if (arch_register_req_is(req, limited))
272 rbitset_copy_to_bitset(req->limited, res->adm_colors);
274 bitset_set_all(res->adm_colors);
276 /* exclude global ignore registers as well */
277 bitset_andnot(res->adm_colors, env->ignore_regs);
279 /* set the number of interfering affinity neighbours to -1, they are calculated later */
280 res->int_aff_neigh = -1;
282 /* build list of interfering neighbours */
284 /* count them first as an obstack array cannot be extended */
285 be_ifg_foreach_neighbour(env->ifg, nodes_it, irn, neigh)
287 res->int_neighs = NEW_ARR_D(ir_node *, phase_obst(ph), len);
289 be_ifg_foreach_neighbour(env->ifg, nodes_it, irn, neigh)
290 res->int_neighs[len++] = neigh;
296 * Check if affinity chunk @p chunk interferes with node @p irn.
298 static INLINE int aff_chunk_interferes(co_mst_env_t *env, aff_chunk_t *chunk, ir_node *irn) {
299 co_mst_irn_t *node = get_co_mst_irn(env, irn);
303 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
304 neigh = node->int_neighs[i];
305 if (! arch_irn_is(env->aenv, neigh, ignore) && bitset_is_set(chunk->nodes, get_irn_idx(neigh)))
313 * Check if there are interference edges from c1 to c2.
314 * @param env The global co_mst environment
316 * @param c2 Another chunk
317 * @return 1 if there are interferences between nodes of c1 and c2, 0 otherwise.
319 static INLINE int aff_chunks_interfere(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
325 /* check if there is a node in c2 having an interfering neighbor in c1 */
326 bitset_foreach(c2->nodes, idx) {
327 ir_node *n = get_idx_irn(env->co->irg, idx);
329 if (aff_chunk_interferes(env, c1, n))
337 * Let c1 absorb the nodes of c2 (only possible when there
338 * are no interference edges from c1 to c2).
339 * @return 1 if successful, 0 if not possible
341 static int aff_chunk_absorb(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
342 DB((env->dbg, LEVEL_4, "Attempt to let c1 (id %d): ", c1->id));
343 DBG_AFF_CHUNK(env, LEVEL_4, c1);
344 DB((env->dbg, LEVEL_4, "\n\tabsorb c2 (id %d): ", c2->id));
345 DBG_AFF_CHUNK(env, LEVEL_4, c2);
346 DB((env->dbg, LEVEL_4, "\n"));
348 if (c1 != c2 && ! aff_chunks_interfere(env, c1, c2)) {
351 bitset_or(c1->nodes, c2->nodes);
352 c1->weight_consistent = 0;
354 bitset_foreach(c2->nodes, idx) {
355 ir_node *n = get_idx_irn(env->co->irg, idx);
356 co_mst_irn_t *mn = get_co_mst_irn(env, n);
360 DB((env->dbg, LEVEL_4, " ... absorbed, c2 deleted\n"));
361 delete_aff_chunk(env, c2);
364 DB((env->dbg, LEVEL_4, " ... c1 interferes with c2, skipped\n"));
369 * Returns the affinity chunk of @p irn or creates a new
370 * one with @p irn as element if there is none assigned.
372 static INLINE aff_chunk_t *get_aff_chunk(co_mst_env_t *env, ir_node *irn) {
373 co_mst_irn_t *node = get_co_mst_irn(env, irn);
374 assert(node->chunk && "Node should have a chunk.");
379 * Assures that the weight of the given chunk is consistent.
381 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
382 if (! c->weight_consistent) {
386 bitset_foreach(c->nodes, idx) {
387 ir_node *n = get_idx_irn(env->co->irg, idx);
388 affinity_node_t *an = get_affinity_info(env->co, n);
392 co_gs_foreach_neighb(an, neigh) {
393 ir_node *m = neigh->irn;
394 int m_idx = get_irn_idx(m);
396 /* skip ignore nodes */
397 if (arch_irn_is(env->aenv, m, ignore))
400 w += bitset_is_set(c->nodes, m_idx) ? neigh->costs : 0;
406 c->weight_consistent = 1;
411 * Count the number of interfering affinity neighbours
413 static int count_interfering_aff_neighs(co_mst_env_t *env, affinity_node_t *an) {
415 ir_node *irn = an->irn;
416 co_mst_irn_t *node = get_co_mst_irn(env, irn);
419 co_gs_foreach_neighb(an, neigh) {
420 ir_node *n = neigh->irn;
423 /* skip ignore nodes */
424 if (arch_irn_is(env->aenv, n, ignore))
427 /* check if the affinity neighbour interfere */
428 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
429 if (node->int_neighs[i] == n) {
440 * Build chunks of nodes connected by affinity edges.
441 * We start at the heaviest affinity edge.
442 * The chunks of the two edge-defining nodes will be
443 * merged if there are no interference edges from one
444 * chunk to the other.
446 static void build_affinity_chunks(co_mst_env_t *env) {
447 void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
448 aff_edge_t *edges = NEW_ARR_F(aff_edge_t, 0);
451 aff_chunk_t *curr_chunk;
452 pset_new_iterator_t iter;
454 /* at first we create the affinity edge objects */
455 be_ifg_foreach_node(env->ifg, nodes_it, n) {
456 int n_idx = get_irn_idx(n);
460 /* skip ignore nodes */
461 if (arch_irn_is(env->aenv, n, ignore))
464 n1 = get_co_mst_irn(env, n);
465 an = get_affinity_info(env->co, n);
470 if (n1->int_aff_neigh < 0)
471 n1->int_aff_neigh = count_interfering_aff_neighs(env, an);
472 co_gs_foreach_neighb(an, neigh) {
473 ir_node *m = neigh->irn;
474 int m_idx = get_irn_idx(m);
476 /* record the edge in only one direction */
481 /* skip ignore nodes */
482 if (arch_irn_is(env->aenv, m, ignore))
488 n2 = get_co_mst_irn(env, m);
489 if (n2->int_aff_neigh < 0) {
490 affinity_node_t *am = get_affinity_info(env->co, m);
491 n2->int_aff_neigh = count_interfering_aff_neighs(env, am);
493 edge.weight = (double)neigh->costs / (double)(1 + n1->int_aff_neigh + n2->int_aff_neigh);
494 ARR_APP1(aff_edge_t, edges, edge);
500 /* now: sort edges and build the affinity chunks */
501 len = ARR_LEN(edges);
502 qsort(edges, len, sizeof(edges[0]), cmp_aff_edge);
503 for (i = 0; i < len; ++i) {
504 aff_chunk_t *c1 = get_aff_chunk(env, edges[i].src);
505 aff_chunk_t *c2 = get_aff_chunk(env, edges[i].tgt);
507 DBG((env->dbg, LEVEL_1, "edge (%u,%u) %f\n", edges[i].src->node_idx, edges[i].tgt->node_idx, edges[i].weight));
509 (void)aff_chunk_absorb(env, c1, c2);
512 /* now insert all chunks into a priority queue */
513 foreach_pset_new(&env->chunkset, curr_chunk, iter) {
514 aff_chunk_assure_weight(env, curr_chunk);
516 DBG((env->dbg, LEVEL_1, "entry #%d", curr_chunk->id));
517 DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
518 DBG((env->dbg, LEVEL_1, "\n"));
521 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
528 * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
530 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
531 aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
533 waitq *nodes = new_waitq();
535 DBG((env->dbg, LEVEL_1, "\nExpanding new chunk (id %d) from %+F:", chunk->id, node->irn));
537 /* init queue and chunk */
538 waitq_put(nodes, node);
539 bitset_set(visited, get_irn_idx(node->irn));
540 aff_chunk_add_node(chunk, node);
541 DB((env->dbg, LEVEL_1, " %+F", node->irn));
543 /* as long as there are nodes in the queue */
544 while (! waitq_empty(nodes)) {
545 co_mst_irn_t *n = waitq_get(nodes);
546 affinity_node_t *an = get_affinity_info(env->co, n->irn);
548 /* check all affinity neighbors */
551 co_gs_foreach_neighb(an, neigh) {
552 ir_node *m = neigh->irn;
553 int m_idx = get_irn_idx(m);
556 /* skip ignore nodes */
557 if (arch_irn_is(env->aenv, m, ignore))
560 n2 = get_co_mst_irn(env, m);
562 if (! bitset_is_set(visited, m_idx) &&
565 ! aff_chunk_interferes(env, chunk, m) &&
566 bitset_is_set(orig_chunk->nodes, m_idx))
569 following conditions are met:
570 - neighbour is not visited
571 - neighbour likes the color
572 - neighbour has not yet a fixed color
573 - the new chunk doesn't interfere with the neighbour
574 - neighbour belongs or belonged once to the original chunk
576 bitset_set(visited, m_idx);
577 aff_chunk_add_node(chunk, n2);
578 DB((env->dbg, LEVEL_1, " %+F", n2->irn));
579 /* enqueue for further search */
580 waitq_put(nodes, n2);
586 DB((env->dbg, LEVEL_1, "\n"));
592 * Fragment the given chunk into chunks having given color and not having given color.
594 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp) {
595 bitset_t *visited = bitset_irg_malloc(env->co->irg);
597 aff_chunk_t *best = NULL;
599 bitset_foreach(c->nodes, idx) {
602 aff_chunk_t *tmp_chunk;
603 decide_func_t *decider;
606 if (bitset_is_set(visited, idx))
609 irn = get_idx_irn(env->co->irg, idx);
610 node = get_co_mst_irn(env, irn);
612 if (get_mst_irn_col(node) == col) {
613 decider = decider_has_color;
617 decider = decider_hasnot_color;
621 /* create a new chunk starting at current node */
622 tmp_chunk = new_aff_chunk(env);
623 waitq_put(tmp, tmp_chunk);
624 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
625 assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
627 /* remember the local best */
628 aff_chunk_assure_weight(env, tmp_chunk);
629 if (check_for_best && (! best || best->weight < tmp_chunk->weight))
633 assert(best && "No chunk found?");
634 bitset_free(visited);
639 * Initializes an array of color-cost pairs.
640 * Sets forbidden colors to costs COL_COST_INFEASIBLE and all others to @p c.
642 static INLINE void col_cost_init(co_mst_env_t *env, col_cost_t *cost, double c) {
645 for (i = 0; i < env->n_regs; ++i) {
647 if (bitset_is_set(env->ignore_regs, i))
648 cost[i].cost = COL_COST_INFEASIBLE;
655 * Initializes an array of color-cost pairs.
656 * Sets all colors except color @p col to COL_COST_INFEASIBLE and @p col to 0.0
658 static INLINE void col_cost_init_single(co_mst_env_t *env, col_cost_t *cost, int col) {
659 assert(! bitset_is_set(env->ignore_regs, col) && "Attempt to use forbidden color.");
660 col_cost_init(env, cost, COL_COST_INFEASIBLE);
667 * Resets the temporary fixed color of all nodes within wait queue @p nodes.
668 * ATTENTION: the queue is empty after calling this function!
670 static INLINE void reject_coloring(waitq *nodes) {
671 while (! waitq_empty(nodes)) {
672 co_mst_irn_t *n = waitq_get(nodes);
678 * Determines the costs for each color if it would be assigned to node @p node.
680 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs) {
681 affinity_node_t *an = get_affinity_info(env->co, node->irn);
685 col_cost_init(env, costs, 0.0);
687 /* calculate (negative) costs for affinity neighbours */
689 co_gs_foreach_neighb(an, aff_neigh) {
690 ir_node *m = aff_neigh->irn;
694 /* skip ignore nodes */
695 if (arch_irn_is(env->aenv, m, ignore))
698 neigh = get_co_mst_irn(env, m);
699 c = (double)aff_neigh->costs;
701 /* calculate costs for fixed affinity neighbours */
702 if (neigh->tmp_fixed || neigh->fixed) {
703 int col = get_mst_irn_col(neigh);
704 costs[col].cost -= c * AFF_NEIGHBOUR_FIX_BENEFIT;
709 /* calculate (positive) costs for interfering neighbours */
710 for (i = 0; i < ARR_LEN(node->int_neighs); ++i) {
715 int_neigh = node->int_neighs[i];
717 /* skip ignore nodes */
718 if (arch_irn_is(env->aenv, int_neigh, ignore))
721 neigh = get_co_mst_irn(env, int_neigh);
722 col = get_mst_irn_col(neigh);
723 col_cnt = bitset_popcnt(neigh->adm_colors);
725 if (neigh->tmp_fixed || neigh->fixed) {
726 /* colors of fixed interfering neighbours are infeasible */
727 costs[col].cost = COL_COST_INFEASIBLE;
729 else if (col_cnt < env->k) {
730 /* calculate costs for constrained interfering neighbours */
731 double ratio = 1.0 - ((double)col_cnt / (double)env->k);
733 bitset_foreach_clear(neigh->adm_colors, idx) {
734 /* check only explicitly forbidden colors (skip global forbidden ones) */
735 if (! bitset_is_set(env->ignore_regs, idx)) {
736 costs[col].cost += ratio * NEIGHBOUR_CONSTR_COSTS;
742 /* set all not admissible colors to COL_COST_INFEASIBLE */
743 bitset_foreach_clear(node->adm_colors, idx)
744 costs[idx].cost = COL_COST_INFEASIBLE;
747 /* need forward declaration due to recursive call */
748 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones);
751 * Tries to change node to a color but @p explude_col.
752 * @return 1 if succeeded, 0 otherwise.
754 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, waitq *changed_ones) {
755 int col = get_mst_irn_col(node);
758 /* neighbours has already a different color -> good, temporary fix it */
759 if (col != exclude_col) {
762 waitq_put(changed_ones, node);
766 /* The node has the color it should not have _and_ has not been visited yet. */
767 if (! (node->tmp_fixed || node->fixed)) {
768 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
770 /* Get the costs for giving the node a specific color. */
771 determine_color_costs(env, node, costs);
773 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
774 costs[exclude_col].cost = COL_COST_INFEASIBLE;
776 /* sort the colors according costs, cheapest first. */
777 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost);
779 /* Try recoloring the node using the color list. */
780 res = recolor_nodes(env, node, costs, changed_ones);
787 * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
788 * ATTENTION: Expect @p costs already sorted by increasing costs.
789 * @return 1 if coloring could be applied, 0 otherwise.
791 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones) {
793 waitq *local_changed = new_waitq();
794 waitq *tmp = new_waitq();
796 DBG((env->dbg, LEVEL_1, "\tRecoloring %+F with color-costs", node->irn));
797 DBG_COL_COST(env, LEVEL_1, costs);
798 DB((env->dbg, LEVEL_1, "\n"));
800 for (i = 0; i < env->n_regs; ++i) {
801 int tgt_col = costs[i].col;
805 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
806 if (costs[i].cost == COL_COST_INFEASIBLE) {
808 del_waitq(local_changed);
813 /* Set the new color of the node and mark the node as temporarily fixed. */
814 assert(! node->tmp_fixed && "Node must not have been temporary fixed.");
816 node->tmp_col = tgt_col;
818 assert(waitq_empty(local_changed) && "Node queue should be empty here.");
819 waitq_put(local_changed, node);
821 /* try to color all interfering neighbours with current color forbidden */
822 for (j = 0; j < ARR_LEN(node->int_neighs); ++j) {
826 neigh = node->int_neighs[j];
828 /* skip ignore nodes */
829 if (arch_irn_is(env->aenv, neigh, ignore))
832 nn = get_co_mst_irn(env, neigh);
835 Try to change the color of the neighbor and record all nodes which
836 get changed in the tmp list. Add this list to the "changed" list for
837 that color. If we did not succeed to change the color of the neighbor,
838 we bail out and try the next color.
840 if (get_mst_irn_col(nn) == tgt_col) {
841 /* try to color neighbour with tgt_col forbidden */
842 neigh_ok = change_node_color_excluded(env, nn, tgt_col, tmp);
844 /* join lists of changed nodes */
845 while (! waitq_empty(tmp))
846 waitq_put(local_changed, waitq_get(tmp));
854 We managed to assign the target color to all neighbors, so from the perspective
855 of the current node, every thing was ok and we can return safely.
858 /* append the local_changed ones to global ones */
859 while (! waitq_empty(local_changed))
860 waitq_put(changed_ones, waitq_get(local_changed));
861 del_waitq(local_changed);
866 /* coloring of neighbours failed, so we try next color */
867 reject_coloring(local_changed);
871 del_waitq(local_changed);
877 * Tries to bring node @p node and all it's neighbours to color @p tgt_col.
878 * @return 1 if color @p col could be applied, 0 otherwise
880 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, waitq *changed_ones) {
881 int col = get_mst_irn_col(node);
883 /* if node already has the target color -> good, temporary fix it */
884 if (col == tgt_col) {
885 DBG((env->dbg, LEVEL_4, "\t\tCNC: %+F has already color %d, fix temporary\n", node->irn, tgt_col));
886 if (! node->tmp_fixed) {
888 node->tmp_col = tgt_col;
889 waitq_put(changed_ones, node);
895 Node has not yet a fixed color and target color is admissible
896 -> try to recolor node and it's affinity neighbours
898 if (! (node->fixed || node->tmp_fixed) && bitset_is_set(node->adm_colors, tgt_col)) {
899 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
902 col_cost_init_single(env, costs, tgt_col);
904 DBG((env->dbg, LEVEL_4, "\t\tCNC: Attempt to recolor %+F ===>>\n", node->irn));
905 res = recolor_nodes(env, node, costs, changed_ones);
906 DBG((env->dbg, LEVEL_4, "\t\tCNC: <<=== Recoloring of %+F %s\n", node->irn, res ? "succeeded" : "failed"));
912 if (firm_dbg_get_mask(env->dbg) & LEVEL_4) {
913 if (node->fixed || node->tmp_fixed)
914 DB((env->dbg, LEVEL_4, "\t\tCNC: %+F has already fixed color %d\n", node->irn, col));
916 DB((env->dbg, LEVEL_4, "\t\tCNC: color %d not admissible for %+F (", tgt_col, node->irn));
917 dbg_admissible_colors(env, node);
918 DB((env->dbg, LEVEL_4, ")\n"));
927 * Tries to color an affinity chunk (or at least a part of it).
928 * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
930 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
931 aff_chunk_t *best_chunk = NULL;
933 waitq *changed_ones = new_waitq();
934 waitq *tmp_chunks = new_waitq();
938 DB((env->dbg, LEVEL_2, "fragmentizing chunk #%d", c->id));
939 DBG_AFF_CHUNK(env, LEVEL_2, c);
940 DB((env->dbg, LEVEL_2, "\n"));
943 /* check which color is the "best" for the given chunk */
944 for (col = 0; col < env->k; ++col) {
946 aff_chunk_t *local_best;
948 DB((env->dbg, LEVEL_3, "\ttrying color %d\n", col));
950 /* try to bring all nodes of given chunk to the current color. */
951 bitset_foreach(c->nodes, idx) {
952 ir_node *irn = get_idx_irn(env->co->irg, idx);
953 co_mst_irn_t *node = get_co_mst_irn(env, irn);
955 assert(! node->fixed && "Node must not have a fixed color.");
957 DB((env->dbg, LEVEL_4, "\t\tBringing %+F from color %d to color %d ...\n", irn, node->col, col));
958 one_good |= change_node_color(env, node, col, changed_ones);
959 DB((env->dbg, LEVEL_4, "\t\t... %+F attempt from %d to %d %s\n", irn, node->col, col, one_good ? "succeeded" : "failed"));
962 /* try next color when failed */
966 /* fragment the chunk according to the coloring */
967 local_best = fragment_chunk(env, col, c, tmp_chunks);
969 /* search the best of the good list
970 and make it the new best if it is better than the current */
972 aff_chunk_assure_weight(env, local_best);
974 DB((env->dbg, LEVEL_4, "\t\tlocal best chunk (id %d) for color %d: ", local_best->id, col));
975 DBG_AFF_CHUNK(env, LEVEL_4, local_best);
977 if (! best_chunk || best_chunk->weight < local_best->weight) {
978 best_chunk = local_best;
980 DB((env->dbg, LEVEL_4, "\n\t\t... setting global best chunk (id %d), color %d\n", best_chunk->id, best_color));
982 DB((env->dbg, LEVEL_4, "\n\t\t... omitting, global best is better\n"));
986 /* reject the coloring and bring the coloring to the initial state */
987 reject_coloring(changed_ones);
990 /* free all intermediate created chunks except best one */
991 while (! waitq_empty(tmp_chunks)) {
992 aff_chunk_t *tmp = waitq_get(tmp_chunks);
993 if (tmp != best_chunk)
994 delete_aff_chunk(env, tmp);
996 del_waitq(tmp_chunks);
998 /* return if coloring failed */
1000 delete_aff_chunk(env, c);
1001 del_waitq(changed_ones);
1005 DB((env->dbg, LEVEL_2, "\tbest chunk #%d ", best_chunk->id));
1006 DBG_AFF_CHUNK(env, LEVEL_2, best_chunk);
1007 DB((env->dbg, LEVEL_2, "using color %d\n", best_color));
1009 /* get the best fragment from the best list and color it */
1010 bitset_foreach(best_chunk->nodes, idx) {
1011 ir_node *irn = get_idx_irn(env->co->irg, idx);
1012 co_mst_irn_t *node = get_co_mst_irn(env, irn);
1015 res = change_node_color(env, node, best_color, changed_ones);
1016 assert(res && "color manifesting failed");
1018 node->chunk = best_chunk;
1021 /* materialize colors on changed nodes */
1022 while (! waitq_empty(changed_ones)) {
1023 co_mst_irn_t *n = waitq_get(changed_ones);
1025 n->col = n->tmp_col;
1028 /* remove the nodes in best chunk from original chunk */
1029 bitset_andnot(c->nodes, best_chunk->nodes);
1031 /* we have to get the nodes back into the original chunk because they are scattered over temporary chunks */
1032 bitset_foreach(c->nodes, idx) {
1033 ir_node *n = get_idx_irn(env->co->irg, idx);
1034 co_mst_irn_t *nn = get_co_mst_irn(env, n);
1038 /* fragment the remaining chunk */
1039 visited = bitset_irg_malloc(env->co->irg);
1040 bitset_or(visited, best_chunk->nodes);
1041 bitset_foreach(c->nodes, idx) {
1042 if (! bitset_is_set(visited, idx)) {
1043 aff_chunk_t *new_chunk = new_aff_chunk(env);
1044 ir_node *irn = get_idx_irn(env->co->irg, idx);
1045 co_mst_irn_t *node = get_co_mst_irn(env, irn);
1047 expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
1048 aff_chunk_assure_weight(env, new_chunk);
1049 pqueue_put(env->chunks, new_chunk, new_chunk->weight);
1053 /* clear obsolete chunks and free some memory */
1054 delete_aff_chunk(env, best_chunk);
1055 bitset_free(visited);
1056 del_waitq(changed_ones);
1060 * Main driver for mst safe coalescing algorithm.
1062 int co_solve_heuristic_mst(copy_opt_t *co)
1064 unsigned n_regs = co->cls->n_regs;
1065 bitset_t *ignore_regs = bitset_alloca(n_regs);
1068 co_mst_env_t mst_env;
1071 phase_init(&mst_env.ph, "co_mst", co->irg, PHASE_DEFAULT_GROWTH, co_mst_irn_init, &mst_env);
1073 k = be_put_ignore_regs(co->cenv->birg, co->cls, ignore_regs);
1076 FIRM_DBG_REGISTER(mst_env.dbg, "firm.be.co.heur4");
1077 mst_env.n_regs = n_regs;
1079 mst_env.chunks = new_pqueue();
1081 mst_env.ignore_regs = ignore_regs;
1082 mst_env.ifg = co->cenv->ifg;
1083 mst_env.aenv = co->aenv;
1084 pset_new_init(&mst_env.chunkset);
1086 DBG((mst_env.dbg, LEVEL_1, "==== Coloring %+F, class %s ====\n", co->irg, co->cls->name));
1088 /* build affinity chunks */
1089 build_affinity_chunks(&mst_env);
1091 /* color chunks as long as there are some */
1092 while (! pqueue_empty(mst_env.chunks)) {
1093 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
1095 color_aff_chunk(&mst_env, chunk);
1096 DB((mst_env.dbg, LEVEL_4, "<<<====== Coloring chunk (%d) done\n", chunk->id));
1097 delete_aff_chunk(&mst_env, chunk);
1100 /* apply coloring */
1101 foreach_phase_irn(&mst_env.ph, irn) {
1102 co_mst_irn_t *mirn = get_co_mst_irn(&mst_env, irn);
1103 const arch_register_t *reg;
1105 if (arch_irn_is(mst_env.aenv, irn, ignore))
1108 assert(mirn->fixed && "Node should have fixed color");
1110 /* skip nodes where color hasn't changed */
1111 if (mirn->init_col == mirn->col)
1114 reg = arch_register_for_index(co->cls, mirn->col);
1115 arch_set_irn_register(co->aenv, irn, reg);
1116 DB((mst_env.dbg, LEVEL_1, "%+F set color from %d to %d\n", irn, mirn->init_col, mirn->col));
1119 /* free allocated memory */
1120 del_pqueue(mst_env.chunks);
1121 phase_free(&mst_env.ph);
1122 pset_new_destroy(&mst_env.chunkset);