534434aada35254753fcba756061eb7b888276af
[libfirm] / ir / be / becopyheur4.c
1 /**
2  * This is the C implementation of the trivial mst algo
3  * originally written in Java by Sebastian Hack.
4  * Performs simple copy minimzation.
5  *
6  * @author Christian Wuerdig
7  * @date   27.04.2007
8  * @id     $Id$
9  */
10
11 #ifdef HAVE_CONFIG_H
12 #include "config.h"
13 #endif /* HAVE_CONFIG_H */
14
15 #include <float.h>
16
17 #include "array.h"
18 #include "irnode.h"
19 #include "bitset.h"
20 #include "raw_bitset.h"
21 #include "irphase_t.h"
22 #include "pqueue.h"
23 #include "pset_new.h"
24 #include "xmalloc.h"
25 #include "pdeq.h"
26
27 #include "bearch.h"
28 #include "beifg.h"
29 #include "be_t.h"
30 #include "becopyopt_t.h"
31 #include "irbitset.h"
32
33 #define COL_COST_INFEASIBLE       DBL_MAX
34 #define AFF_NEIGHBOUR_FIX_BENEFIT 128.0
35 #define NEIGHBOUR_CONSTR_COSTS    64.0
36
37 typedef struct _col_cost_t {
38         int    col;
39         double cost;
40 } col_cost_t;
41
42 typedef struct _aff_chunk_t {
43         bitset_t *nodes;
44         double   weight;
45         unsigned weight_consistent : 1;
46 } aff_chunk_t;
47
48 typedef struct _aff_edge_t {
49         ir_node *src;
50         ir_node *tgt;
51         double  weight;
52 } aff_edge_t;
53
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 */
65 } co_mst_env_t;
66
67 /* stores coalescing related information for a node */
68 typedef struct _co_mst_irn_t {
69         ir_node     *irn;
70         aff_chunk_t *chunk;
71         bitset_t    *adm_colors;
72         int         int_neigh;
73         int         col;
74         int         tmp_col;
75         unsigned    fixed     : 1;
76         unsigned    tmp_fixed : 1;
77 } co_mst_irn_t;
78
79
80 #define get_co_mst_irn(mst_env, irn) (phase_get_or_set_irn_data(&(mst_env)->ph, (irn)))
81
82 typedef int decide_func_t(co_mst_irn_t *node, int col);
83
84 static INLINE int get_mst_irn_col(co_mst_irn_t *node) {
85         return node->tmp_fixed ? node->tmp_col : node->col;
86 }
87
88 /**
89  * @return 1 if node @p node has color @p col, 0 otherwise.
90  */
91 static int decider_has_color(co_mst_irn_t *node, int col) {
92         return get_mst_irn_col(node) == col;
93 }
94
95 /**
96  * @return 1 if node @p node has not color @p col, 0 otherwise.
97  */
98 static int decider_hasnot_color(co_mst_irn_t *node, int col) {
99         return get_mst_irn_col(node) != col;
100 }
101
102 /**
103  * Always returns true.
104  */
105 static int decider_always_yes(co_mst_irn_t *node, int col) {
106         return 1;
107 }
108
109 /* compares two affinity edges */
110 static int cmp_aff_edge(const void *a, const void *b) {
111         const aff_edge_t *e1 = a;
112         const aff_edge_t *e2 = b;
113
114         /* sort in descending order */
115         return e1->weight < e2->weight ? 1 : -1;
116 }
117
118 /* compares to color-cost pairs */
119 static int cmp_col_cost(const void *a, const void *b) {
120         const col_cost_t *c1 = a;
121         const col_cost_t *c2 = b;
122
123         return c1->cost < c2->cost ? -1 : 1;
124 }
125
126 /**
127  * In case there is no phase information for irn, initialize it.
128  */
129 static void *co_mst_irn_init(ir_phase *ph, ir_node *irn, void *old) {
130         co_mst_irn_t *res = old ? old : phase_alloc(ph, sizeof(res[0]));
131         co_mst_env_t *env = ph->priv;
132
133         if (res != old) {
134                 void                      *neigh_it = be_ifg_neighbours_iter_alloca(env->ifg);
135                 const arch_register_req_t *req;
136                 ir_node                   *m;
137
138                 res->irn       = irn;
139                 res->chunk     = NULL;
140                 res->fixed     = 0;
141                 res->tmp_fixed = 0;
142                 res->tmp_col   = -1;
143                 res->int_neigh = 0;
144                 res->col       = arch_register_get_index(arch_get_irn_register(env->aenv, irn));
145
146                 /* set admissible registers */
147                 res->adm_colors = bitset_obstack_alloc(phase_obst(ph), env->n_regs);
148
149                 /* Exclude colors not assignable to the irn */
150                 req = arch_get_register_req(env->aenv, irn, -1);
151                 if (arch_register_req_is(req, limited))
152                         rbitset_copy_to_bitset(req->limited, res->adm_colors);
153
154                 /* exclude global ignore registers as well */
155                 bitset_andnot(res->adm_colors, env->ignore_regs);
156
157                 /* calculate the number of interfering neighbours */
158                 be_ifg_foreach_neighbour(env->ifg, neigh_it, irn, m) {
159                         if (! arch_irn_is(env->aenv, m, ignore))
160                                 res->int_neigh++;
161                 }
162
163         }
164
165         return res;
166 }
167
168 /**
169  * Creates a new affinity chunk
170  */
171 static INLINE aff_chunk_t *new_aff_chunk(co_mst_env_t *env) {
172         aff_chunk_t *c = xmalloc(sizeof(*c));
173         c->weight_consistent = 0;
174         c->nodes             = bitset_irg_malloc(env->co->irg);
175         pset_new_insert(&env->chunkset, c);
176         return c;
177 }
178
179 /**
180  * Frees all memory allocated by an affinity chunk.
181  */
182 static INLINE void delete_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
183         pset_new_remove(&env->chunkset, c);
184         bitset_free(c->nodes);
185         free(c);
186 }
187
188 /**
189  * Adds a node to an affinity chunk
190  */
191 static INLINE void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node) {
192         c->weight_consistent = 0;
193         node->chunk          = c;
194         bitset_set(c->nodes, get_irn_idx(node->irn));
195 }
196
197 /**
198  * Check if there are interference edges from c1 to c2.
199  * @param env   The global co_mst environment
200  * @param c1    A chunk
201  * @param c2    Another chunk
202  * @return 1 if there are interferences between nodes of c1 and c2, 0 otherwise.
203  */
204 static INLINE int aff_chunks_interfere(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
205         void *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
206         int  idx;
207
208         /* check if there is a node in c1 having an interfering neighbour in c2 */
209         bitset_foreach(c1->nodes, idx) {
210                 ir_node *n = get_idx_irn(env->co->irg, idx);
211                 ir_node *neigh;
212
213                 be_ifg_foreach_neighbour(env->ifg, nodes_it, n, neigh) {
214                         if (bitset_is_set(c2->nodes, get_irn_idx(neigh)))
215                                 return 1;
216                 }
217         }
218
219         return 0;
220 }
221
222 /**
223  * Let c1 absorb the nodes of c2 (only possible when there
224  * are no interference edges from c1 to c2).
225  * @return 1 if successful, 0 if not possible
226  */
227 static INLINE int aff_chunk_absorb(co_mst_env_t *env, aff_chunk_t *c1, aff_chunk_t *c2) {
228         if (! aff_chunks_interfere(env, c1, c2)) {
229                 bitset_or(c1->nodes, c2->nodes);
230                 c1->weight_consistent = 0;
231                 return 1;
232         }
233         return 0;
234 }
235
236 /**
237  * Returns the affinity chunk of @p irn or creates a new
238  * one with @p irn as element if there is none assigned.
239  */
240 static INLINE aff_chunk_t *get_or_set_aff_chunk(co_mst_env_t *env, ir_node *irn) {
241         co_mst_irn_t *node = get_co_mst_irn(env, irn);
242
243         if (node->chunk == NULL) {
244                 node->chunk = new_aff_chunk(env);
245                 aff_chunk_add_node(node->chunk, node);
246         }
247
248         return node->chunk;
249 }
250
251 /**
252  * Assures that the weight of the given chunk is consistent.
253  */
254 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
255         if (! c->weight_consistent) {
256                 double w = 0.0;
257                 int    idx;
258
259                 bitset_foreach(c->nodes, idx) {
260                         ir_node         *n  = get_idx_irn(env->co->irg, idx);
261                         affinity_node_t *an = get_affinity_info(env->co, n);
262                         co_mst_irn_t    *n1 = get_co_mst_irn(env, n);
263
264                         if (an != NULL) {
265                                 neighb_t *neigh;
266                                 co_gs_foreach_neighb(an, neigh) {
267                                         ir_node      *m    = neigh->irn;
268                                         int          m_idx = get_irn_idx(m);
269                                         co_mst_irn_t *n2;
270
271                                         /* skip ignore nodes */
272                                         if (arch_irn_is(env->aenv, m, ignore))
273                                                 continue;
274
275                                         n2 = get_co_mst_irn(env, m);
276
277                                         /* record the edge in only one direction */
278                                         if (idx < m_idx)
279                                                 w += (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
280                                 }
281                         }
282                 }
283
284                 c->weight            = w;
285                 c->weight_consistent = 1;
286         }
287 }
288
289 /**
290  * Build chunks of nodes connected by affinity edges.
291  * We start at the heaviest affinity edge.
292  * The chunks of the two edge-defining nodes will be
293  * merged if there are no interference edges from one
294  * chunk to the other.
295  */
296 static void build_affinity_chunks(co_mst_env_t *env) {
297         void        *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
298         aff_edge_t  *edges    = NEW_ARR_F(aff_edge_t, 0);
299         ir_node     *n;
300         int         i;
301         aff_chunk_t *curr_chunk;
302         pset_new_iterator_t iter;
303
304         /* at first we create the affinity edge objects */
305         be_ifg_foreach_node(env->ifg, nodes_it, n) {
306                 int             n_idx = get_irn_idx(n);
307                 co_mst_irn_t    *n1;
308                 affinity_node_t *an;
309
310                 /* skip ignore nodes */
311                 if (arch_irn_is(env->aenv, n, ignore))
312                         continue;
313
314                 n1 = get_co_mst_irn(env, n);
315                 an = get_affinity_info(env->co, n);
316
317                 if (an != NULL) {
318                         neighb_t *neigh;
319                         co_gs_foreach_neighb(an, neigh) {
320                                 ir_node      *m    = neigh->irn;
321                                 int          m_idx = get_irn_idx(m);
322                                 co_mst_irn_t *n2;
323
324                                 /* skip ignore nodes */
325                                 if (arch_irn_is(env->aenv, m, ignore))
326                                         continue;
327
328                                 n2 = get_co_mst_irn(env, m);
329
330                                 /* record the edge in only one direction */
331                                 if (n_idx < m_idx) {
332                                         aff_edge_t edge;
333
334                                         edge.src    = n;
335                                         edge.tgt    = m;
336                                         edge.weight = (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
337                                         ARR_APP1(aff_edge_t, edges, edge);
338                                 }
339                         }
340                 }
341         }
342
343         /* now: sort edges and build the affinity chunks */
344         qsort(edges, ARR_LEN(edges), sizeof(edges[0]), cmp_aff_edge);
345         for (i = 0; i < ARR_LEN(edges); ++i) {
346                 aff_chunk_t *c1 = get_or_set_aff_chunk(env, edges[i].src);
347                 aff_chunk_t *c2 = get_or_set_aff_chunk(env, edges[i].tgt);
348                 int         res = aff_chunk_absorb(env, c1, c2);
349
350                 /* if c2 was absorbed by c1, we can remove c2 */
351                 if (res) {
352                         co_mst_irn_t *node = get_co_mst_irn(env, edges[i].tgt);
353                         node->chunk = c1;
354                         delete_aff_chunk(env, c2);
355                 }
356         }
357
358         /* now insert all chunks into a priority queue */
359         foreach_pset_new(&env->chunkset, curr_chunk, iter) {
360                 aff_chunk_assure_weight(env, curr_chunk);
361                 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
362         }
363
364         DEL_ARR_F(edges);
365 }
366
367 /**
368  * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
369  */
370 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
371         aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
372 {
373         waitq *nodes = new_waitq();
374
375         /* init queue and chunk */
376         waitq_put(nodes, node);
377         bitset_set(visited, get_irn_idx(node->irn));
378         aff_chunk_add_node(chunk, node);
379
380         /* as long as there are nodes in the queue */
381         while (! waitq_empty(nodes)) {
382                 co_mst_irn_t    *n    = waitq_get(nodes);
383                 affinity_node_t *an   = get_affinity_info(env->co, n->irn);
384                 int             n_idx = get_irn_idx(n->irn);
385
386                 /* check all affinity neighbors */
387                 if (an != NULL) {
388                         neighb_t *neigh;
389                         co_gs_foreach_neighb(an, neigh) {
390                                 ir_node      *m    = neigh->irn;
391                                 int          m_idx = get_irn_idx(m);
392                                 co_mst_irn_t *n2;
393
394                                 /* skip ignore nodes */
395                                 if (arch_irn_is(env->aenv, m, ignore))
396                                         continue;
397
398                                 n2 = get_co_mst_irn(env, m);
399
400                                 if (n_idx < m_idx                                 &&
401                                         ! bitset_is_set(visited, m_idx)               &&
402                                         decider(n2, col)                              &&
403                                         ! n2->fixed                                   &&
404                                         ! aff_chunks_interfere(env, chunk, n2->chunk) &&
405                                         bitset_is_set(orig_chunk->nodes, m_idx))
406                                 {
407                                         /*
408                                                 following conditions are met:
409                                                 - neighbour is not visited
410                                                 - neighbour likes the color
411                                                 - neighbour has not yet a fixed color
412                                                 - the new chunk doesn't interfere with the chunk of the neighbour
413                                                 - neighbour belongs or belonged once to the original chunk
414                                         */
415                                         bitset_set(visited, m_idx);
416                                         aff_chunk_add_node(chunk, n2);
417                                         /* enqueue for further search */
418                                         waitq_put(nodes, n2);
419                                 }
420                         }
421                 }
422         }
423
424         del_waitq(nodes);
425 }
426
427 /**
428  * Fragment the given chunk into chunks having given color and not having given color.
429  */
430 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp) {
431         bitset_t    *visited = bitset_irg_malloc(env->co->irg);
432         int         idx;
433         aff_chunk_t *best = NULL;
434
435         bitset_foreach(c->nodes, idx) {
436                 ir_node       *irn;
437                 co_mst_irn_t  *node;
438                 aff_chunk_t   *tmp_chunk;
439                 decide_func_t *decider;
440
441                 if (bitset_is_set(visited, idx))
442                         continue;
443
444                 irn  = get_idx_irn(env->co->irg, idx);
445                 node = get_co_mst_irn(env, irn);
446
447                 /* create a new chunk starting at current node */
448                 tmp_chunk = new_aff_chunk(env);
449                 waitq_put(tmp, tmp_chunk);
450                 decider = get_mst_irn_col(node) == col ? decider_has_color : decider_hasnot_color;
451                 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
452                 assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
453
454                 /* remember the local best */
455                 aff_chunk_assure_weight(env, tmp_chunk);
456                 if (! best || best->weight < tmp_chunk->weight)
457                         best = tmp_chunk;
458         }
459
460         assert(best && "No chunk found?");
461         bitset_free(visited);
462         return best;
463 }
464
465 /**
466  * Initializes an array of color-cost pairs.
467  * Sets forbidden colors to costs COL_COST_INFEASIBLE and all others to @p c.
468  */
469 static INLINE void col_cost_init(co_mst_env_t *env, col_cost_t *cost, double c) {
470         int i;
471
472         for (i = 0; i < env->n_regs; ++i) {
473                 cost[i].col = i;
474                 if (bitset_is_set(env->ignore_regs, i))
475                         cost[i].cost = COL_COST_INFEASIBLE;
476                 else
477                         cost[i].cost = c;
478         }
479 }
480
481 /**
482  * Initializes an array of color-cost pairs.
483  * Sets all colors except color @p col to COL_COST_INFEASIBLE and @p col to 0.0
484  */
485 static INLINE void col_cost_init_single(co_mst_env_t *env, col_cost_t *cost, int col) {
486         assert(! bitset_is_set(env->ignore_regs, col) && "Attempt to use forbidden color.");
487         col_cost_init(env, cost, COL_COST_INFEASIBLE);
488         cost[col].col = 0;
489         cost[0].col   = col;
490         cost[0].cost  = 0.0;
491 }
492
493 /**
494  * Resets the temporary fixed color of all nodes within wait queue @p nodes.
495  * ATTENTION: the queue is empty after calling this function!
496  */
497 static INLINE void reject_coloring(waitq *nodes) {
498         while (! waitq_empty(nodes)) {
499                 co_mst_irn_t *n = waitq_get(nodes);
500                 n->tmp_fixed = 0;
501         }
502 }
503
504 /**
505  * Determines the costs for each color if it would be assigned to node @p node.
506  */
507 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs) {
508         affinity_node_t *an       = get_affinity_info(env->co, node->irn);
509         void            *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
510         neighb_t        *aff_neigh;
511         ir_node         *int_neigh;
512         int             idx;
513
514         col_cost_init(env, costs, 0.0);
515
516         /* calculate (negative) costs for affinity neighbours */
517         co_gs_foreach_neighb(an, aff_neigh) {
518                 ir_node      *m     = aff_neigh->irn;
519                 co_mst_irn_t *neigh = get_co_mst_irn(env, m);
520                 double       c      = (double)aff_neigh->costs;
521
522                 /* calculate costs for fixed affinity neighbours */
523                 if (neigh->tmp_fixed || neigh->fixed) {
524                         int col = get_mst_irn_col(neigh);
525                         costs[col].cost -= c * AFF_NEIGHBOUR_FIX_BENEFIT;
526                 }
527         }
528
529         /* calculate (positive) costs for interfering neighbours */
530         be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, int_neigh) {
531                 co_mst_irn_t *neigh  = get_co_mst_irn(env, int_neigh);
532                 int          col     = get_mst_irn_col(neigh);
533                 int          col_cnt = bitset_popcnt(neigh->adm_colors);
534
535                 if (neigh->tmp_fixed || neigh->fixed) {
536                         /* colors of fixed interfering neighbours are infeasible */
537                         costs[col].cost = COL_COST_INFEASIBLE;
538                 }
539                 else if (col_cnt < env->k) {
540                         /* calculate costs for constrained interfering neighbours */
541                         double ratio = 1.0 - ((double)col_cnt / (double)env->k);
542
543                         bitset_foreach_clear(neigh->adm_colors, idx) {
544                                 /* check only explicitly forbidden colors (skip global forbidden ones) */
545                                 if (! bitset_is_set(env->ignore_regs, idx)) {
546                                         costs[col].cost += ratio * NEIGHBOUR_CONSTR_COSTS;
547                                 }
548                         }
549                 }
550         }
551
552         /* set all not admissible colors to COL_COST_INFEASIBLE */
553         bitset_foreach_clear(node->adm_colors, idx)
554                 costs[idx].cost = COL_COST_INFEASIBLE;
555 }
556
557 /* need forward declaration due to recursive call */
558 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones);
559
560 /**
561  * Tries to change node to a color but @p explude_col.
562  * @return 1 if succeeded, 0 otherwise.
563  */
564 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, waitq *changed_ones) {
565         int col = get_mst_irn_col(node);
566         int res = 0;
567
568         /* neighbours has already a different color -> good, temporary fix it */
569         if (col != exclude_col) {
570                 node->tmp_fixed = 1;
571                 node->tmp_col   = col;
572                 waitq_put(changed_ones, node);
573                 return 1;
574         }
575
576         /* The node has the color it should not have _and_ has not been visited yet. */
577         if (! (node->tmp_fixed || node->fixed)) {
578                 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
579
580                 /* Get the costs for giving the node a specific color. */
581                 determine_color_costs(env, node, costs);
582
583                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
584                 costs[exclude_col].cost = COL_COST_INFEASIBLE;
585
586                 /* sort the colors according costs, cheapest first. */
587                 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost);
588
589                 /* Try recoloring the node using the color list. */
590                 res = recolor_nodes(env, node, costs, changed_ones);
591         }
592
593         return res;
594 }
595
596 /**
597  * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
598  * ATTENTION: Expect @p costs already sorted by increasing costs.
599  * @return 1 if coloring could be applied, 0 otherwise.
600  */
601 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones) {
602         int   i;
603         waitq *local_changed = new_waitq();
604
605         for (i = 0; i < env->n_regs; ++i) {
606                 void    *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
607                 int     tgt_col   = costs[i].col;
608                 int     neigh_ok  = 1;
609                 ir_node *neigh;
610
611                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
612                 if (costs[i].cost == COL_COST_INFEASIBLE) {
613                         node->tmp_fixed = 0;
614                         del_waitq(local_changed);
615                         return 0;
616                 }
617
618                 /* Set the new color of the node and mark the node as temporarily fixed. */
619                 assert(! node->tmp_fixed && "Node must not have been temporary fixed.");
620                 node->tmp_fixed = 1;
621                 node->tmp_col   = tgt_col;
622
623                 assert(waitq_empty(local_changed) && "Node queue should be empty here.");
624                 waitq_put(local_changed, node);
625
626                 /* try to color all interfering neighbours with current color forbidden */
627                 be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, neigh) {
628                         co_mst_irn_t *nn = get_co_mst_irn(env, neigh);
629                         /*
630                                 Try to change the color of the neighbor and record all nodes which
631                                 get changed in the tmp list. Add this list to the "changed" list for
632                                 that color. If we did not succeed to change the color of the neighbor,
633                                 we bail out and try the next color.
634                         */
635                         if (get_mst_irn_col(nn) == tgt_col) {
636                                 waitq *tmp = new_waitq();
637
638                                 /* try to color neighbour with tgt_col forbidden */
639                                 neigh_ok = change_node_color_excluded(env, nn, tgt_col, tmp);
640
641                                 /* join lists of changed nodes */
642                                 while (! waitq_empty(tmp))
643                                         waitq_put(local_changed, waitq_get(tmp));
644                                 del_waitq(tmp);
645
646                                 if (! neigh_ok)
647                                         break;
648                         }
649                 }
650
651                 /*
652                         We managed to assign the target color to all neighbors, so from the perspective
653                         of the current node, every thing was ok and we can return safely.
654                 */
655                 if (neigh_ok) {
656                         /* append the local_changed ones to global ones */
657                         while (! waitq_empty(local_changed))
658                                 waitq_put(changed_ones, waitq_get(local_changed));
659                         del_waitq(local_changed);
660                         return 1;
661                 }
662                 else {
663                         /* coloring of neighbours failed, so we try next color */
664                         reject_coloring(local_changed);
665                 }
666         }
667
668         del_waitq(local_changed);
669         return 0;
670 }
671
672 /**
673  * Tries to bring node @p node and all it's neighbours to color @p tgt_col.
674  * @return 1 if color @p col could be applied, 0 otherwise
675  */
676 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, waitq *changed_ones) {
677         int col = get_mst_irn_col(node);
678
679         /* if node already has the target color -> good, temporary fix it */
680         if (col == tgt_col) {
681                 if (! node->tmp_fixed) {
682                         node->tmp_fixed = 1;
683                         node->tmp_col   = tgt_col;
684                         waitq_put(changed_ones, node);
685                 }
686                 return 1;
687         }
688
689         /*
690                 Node has not yet a fixed color and target color is admissible
691                 -> try to recolor node and it's affinity neighbours
692         */
693         if (! (node->fixed || node->tmp_fixed) && bitset_is_set(node->adm_colors, tgt_col)) {
694                 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
695                 col_cost_init_single(env, costs, tgt_col);
696                 return recolor_nodes(env, node, costs, changed_ones);
697         }
698
699         return 0;
700 }
701
702 /**
703  * Tries to color an affinity chunk (or at least a part of it).
704  * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
705  */
706 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
707         aff_chunk_t *best_chunk   = NULL;
708         int         best_color    = -1;
709         waitq       *changed_ones = new_waitq();
710         waitq       *tmp_chunks   = new_waitq();
711         bitset_t    *visited;
712         int         col, idx;
713
714         /* check which color is the "best" for the given chunk */
715         for (col = 0; col < env->k; ++col) {
716                 int         one_good = 0;
717                 aff_chunk_t *local_best;
718
719                 /* try to bring all nodes of given chunk to the current color. */
720                 bitset_foreach(c->nodes, idx) {
721                         ir_node      *irn  = get_idx_irn(env->co->irg, idx);
722                         co_mst_irn_t *node = get_co_mst_irn(env, irn);
723
724                         assert(! node->fixed && "Node must not have a fixed color.");
725
726                         one_good = change_node_color(env, node, col, changed_ones);
727
728                         if (one_good)
729                                 break;
730                 }
731
732                 /* try next color when failed */
733                 if (! one_good)
734                         continue;
735
736                 /* fragment the chunk according to the coloring */
737                 local_best = fragment_chunk(env, col, c, tmp_chunks);
738
739                 /* check if the local best is global best */
740                 if (local_best) {
741                         aff_chunk_assure_weight(env, local_best);
742
743                         if (! best_chunk || best_chunk->weight < local_best->weight) {
744                                 /* kill the old best */
745                                 if (best_chunk)
746                                         delete_aff_chunk(env, best_chunk);
747                                 best_chunk = local_best;
748                                 best_color = col;
749                         }
750                 }
751
752                 /* reject the coloring and bring the coloring to the initial state */
753                 reject_coloring(changed_ones);
754         }
755
756         /* free all intermediate created chunks except best one */
757         while (! waitq_empty(tmp_chunks)) {
758                 aff_chunk_t *tmp = waitq_get(tmp_chunks);
759                 if (tmp != best_chunk)
760                         delete_aff_chunk(env, tmp);
761         }
762         del_waitq(tmp_chunks);
763
764         /* return if coloring failed */
765         if (! best_chunk) {
766                 delete_aff_chunk(env, c);
767                 del_waitq(changed_ones);
768                 return;
769         }
770
771         /* get the best fragment from the best list and color it */
772         bitset_foreach(best_chunk->nodes, idx) {
773                 ir_node      *irn  = get_idx_irn(env->co->irg, idx);
774                 co_mst_irn_t *node = get_co_mst_irn(env, irn);
775                 int          res;
776
777                 res = change_node_color(env, node, col, changed_ones);
778                 assert(res && "Coloring failed");
779                 node->fixed = 1;
780                 node->col   = node->tmp_col;
781                 node->chunk = best_chunk;
782         }
783
784         /* fix colors */
785         while (! waitq_empty(changed_ones)) {
786                 co_mst_irn_t *n = waitq_get(changed_ones);
787                 n->fixed = 1;
788                 n->col   = n->tmp_col;
789         }
790
791         /* remove the nodes in best chunk from original chunk */
792         bitset_andnot(c->nodes, best_chunk->nodes);
793
794         /* fragment the remaining chunk */
795         visited = bitset_irg_malloc(env->co->irg);
796         bitset_or(visited, best_chunk->nodes);
797         bitset_foreach(c->nodes, idx) {
798                 if (! bitset_is_set(visited, idx)) {
799                         aff_chunk_t  *new_chunk = new_aff_chunk(env);
800                         ir_node      *irn       = get_idx_irn(env->co->irg, idx);
801                         co_mst_irn_t *node      = get_co_mst_irn(env, irn);
802
803                         expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
804                         aff_chunk_assure_weight(env, new_chunk);
805                         pqueue_put(env->chunks, new_chunk, new_chunk->weight);
806                 }
807         }
808
809         /* clear obsolete chunks and free some memory */
810         delete_aff_chunk(env, c);
811         delete_aff_chunk(env, best_chunk);
812         bitset_free(visited);
813         del_waitq(changed_ones);
814 }
815
816 /**
817  * Main driver for mst safe coalescing algorithm.
818  */
819 int co_solve_heuristic_mst(copy_opt_t *co)
820 {
821         unsigned     n_regs       = co->cenv->cls->n_regs;
822         bitset_t     *ignore_regs = bitset_alloca(n_regs);
823         unsigned     k;
824         co_mst_env_t mst_env;
825
826         /* init phase */
827         phase_init(&mst_env.ph, "co_mst", co->irg, PHASE_DEFAULT_GROWTH, co_mst_irn_init, &mst_env);
828
829         k = be_put_ignore_regs(co->cenv->birg, co->cenv->cls, ignore_regs);
830         k = n_regs - k;
831
832         mst_env.n_regs      = n_regs;
833         mst_env.k           = k;
834         mst_env.chunks      = new_pqueue();
835         mst_env.co          = co;
836         mst_env.ignore_regs = ignore_regs;
837         mst_env.ifg         = co->cenv->ifg;
838         pset_new_init(&mst_env.chunkset);
839
840         /* build affinity chunks */
841         build_affinity_chunks(&mst_env);
842
843         /* color chunks as long as there are some */
844         while (! pqueue_empty(mst_env.chunks)) {
845                 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
846                 color_aff_chunk(&mst_env, chunk);
847         }
848
849         /* free allocated memory */
850         del_pqueue(mst_env.chunks);
851         phase_free(&mst_env.ph);
852         pset_new_destroy(&mst_env.chunkset);
853
854         return 0;
855 }