1b9e99fd46b5801685d4a61cf156476efea86b88
[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                 int idx;
230
231                 bitset_or(c1->nodes, c2->nodes);
232                 c1->weight_consistent = 0;
233
234                 bitset_foreach(c2->nodes, idx) {
235                         ir_node      *n  = get_idx_irn(env->co->irg, idx);
236                         co_mst_irn_t *mn = get_co_mst_irn(env, n);
237                         mn->chunk = c1;
238                 }
239
240                 delete_aff_chunk(env, c2);
241                 return 1;
242         }
243         return 0;
244 }
245
246 /**
247  * Returns the affinity chunk of @p irn or creates a new
248  * one with @p irn as element if there is none assigned.
249  */
250 static INLINE aff_chunk_t *get_or_set_aff_chunk(co_mst_env_t *env, ir_node *irn) {
251         co_mst_irn_t *node = get_co_mst_irn(env, irn);
252
253         if (node->chunk == NULL) {
254                 node->chunk = new_aff_chunk(env);
255                 aff_chunk_add_node(node->chunk, node);
256         }
257
258         return node->chunk;
259 }
260
261 /**
262  * Assures that the weight of the given chunk is consistent.
263  */
264 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c) {
265         if (! c->weight_consistent) {
266                 double w = 0.0;
267                 int    idx;
268
269                 bitset_foreach(c->nodes, idx) {
270                         ir_node         *n  = get_idx_irn(env->co->irg, idx);
271                         affinity_node_t *an = get_affinity_info(env->co, n);
272                         co_mst_irn_t    *n1 = get_co_mst_irn(env, n);
273
274                         if (an != NULL) {
275                                 neighb_t *neigh;
276                                 co_gs_foreach_neighb(an, neigh) {
277                                         ir_node      *m    = neigh->irn;
278                                         int          m_idx = get_irn_idx(m);
279                                         co_mst_irn_t *n2;
280
281                                         /* skip ignore nodes */
282                                         if (arch_irn_is(env->aenv, m, ignore))
283                                                 continue;
284
285                                         n2 = get_co_mst_irn(env, m);
286
287                                         /* record the edge in only one direction */
288                                         if (idx < m_idx)
289                                                 w += (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
290                                 }
291                         }
292                 }
293
294                 c->weight            = w;
295                 c->weight_consistent = 1;
296         }
297 }
298
299 /**
300  * Build chunks of nodes connected by affinity edges.
301  * We start at the heaviest affinity edge.
302  * The chunks of the two edge-defining nodes will be
303  * merged if there are no interference edges from one
304  * chunk to the other.
305  */
306 static void build_affinity_chunks(co_mst_env_t *env) {
307         void        *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
308         aff_edge_t  *edges    = NEW_ARR_F(aff_edge_t, 0);
309         ir_node     *n;
310         int         i;
311         aff_chunk_t *curr_chunk;
312         pset_new_iterator_t iter;
313
314         /* at first we create the affinity edge objects */
315         be_ifg_foreach_node(env->ifg, nodes_it, n) {
316                 int             n_idx = get_irn_idx(n);
317                 co_mst_irn_t    *n1;
318                 affinity_node_t *an;
319
320                 /* skip ignore nodes */
321                 if (arch_irn_is(env->aenv, n, ignore))
322                         continue;
323
324                 n1 = get_co_mst_irn(env, n);
325                 an = get_affinity_info(env->co, n);
326
327                 if (an != NULL) {
328                         neighb_t *neigh;
329                         co_gs_foreach_neighb(an, neigh) {
330                                 ir_node      *m    = neigh->irn;
331                                 int          m_idx = get_irn_idx(m);
332                                 co_mst_irn_t *n2;
333
334                                 /* skip ignore nodes */
335                                 if (arch_irn_is(env->aenv, m, ignore))
336                                         continue;
337
338                                 n2 = get_co_mst_irn(env, m);
339
340                                 /* record the edge in only one direction */
341                                 if (n_idx < m_idx) {
342                                         aff_edge_t edge;
343
344                                         edge.src    = n;
345                                         edge.tgt    = m;
346                                         edge.weight = (double)neigh->costs / (double)(1 + n1->int_neigh + n2->int_neigh);
347                                         ARR_APP1(aff_edge_t, edges, edge);
348                                 }
349                         }
350                 }
351         }
352
353         /* now: sort edges and build the affinity chunks */
354         qsort(edges, ARR_LEN(edges), sizeof(edges[0]), cmp_aff_edge);
355         for (i = 0; i < ARR_LEN(edges); ++i) {
356                 aff_chunk_t *c1 = get_or_set_aff_chunk(env, edges[i].src);
357                 aff_chunk_t *c2 = get_or_set_aff_chunk(env, edges[i].tgt);
358
359                 (void)aff_chunk_absorb(env, c1, c2);
360         }
361
362         /* now insert all chunks into a priority queue */
363         foreach_pset_new(&env->chunkset, curr_chunk, iter) {
364                 aff_chunk_assure_weight(env, curr_chunk);
365                 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
366         }
367
368         DEL_ARR_F(edges);
369 }
370
371 /**
372  * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
373  */
374 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
375         aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
376 {
377         waitq *nodes = new_waitq();
378
379         /* init queue and chunk */
380         waitq_put(nodes, node);
381         bitset_set(visited, get_irn_idx(node->irn));
382         aff_chunk_add_node(chunk, node);
383
384         /* as long as there are nodes in the queue */
385         while (! waitq_empty(nodes)) {
386                 co_mst_irn_t    *n    = waitq_get(nodes);
387                 affinity_node_t *an   = get_affinity_info(env->co, n->irn);
388                 int             n_idx = get_irn_idx(n->irn);
389
390                 /* check all affinity neighbors */
391                 if (an != NULL) {
392                         neighb_t *neigh;
393                         co_gs_foreach_neighb(an, neigh) {
394                                 ir_node      *m    = neigh->irn;
395                                 int          m_idx = get_irn_idx(m);
396                                 co_mst_irn_t *n2;
397
398                                 /* skip ignore nodes */
399                                 if (arch_irn_is(env->aenv, m, ignore))
400                                         continue;
401
402                                 n2 = get_co_mst_irn(env, m);
403
404                                 if (n_idx < m_idx                                 &&
405                                         ! bitset_is_set(visited, m_idx)               &&
406                                         decider(n2, col)                              &&
407                                         ! n2->fixed                                   &&
408                                         ! aff_chunks_interfere(env, chunk, n2->chunk) &&
409                                         bitset_is_set(orig_chunk->nodes, m_idx))
410                                 {
411                                         /*
412                                                 following conditions are met:
413                                                 - neighbour is not visited
414                                                 - neighbour likes the color
415                                                 - neighbour has not yet a fixed color
416                                                 - the new chunk doesn't interfere with the chunk of the neighbour
417                                                 - neighbour belongs or belonged once to the original chunk
418                                         */
419                                         bitset_set(visited, m_idx);
420                                         aff_chunk_add_node(chunk, n2);
421                                         /* enqueue for further search */
422                                         waitq_put(nodes, n2);
423                                 }
424                         }
425                 }
426         }
427
428         del_waitq(nodes);
429 }
430
431 /**
432  * Fragment the given chunk into chunks having given color and not having given color.
433  */
434 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp) {
435         bitset_t    *visited = bitset_irg_malloc(env->co->irg);
436         int         idx;
437         aff_chunk_t *best = NULL;
438
439         bitset_foreach(c->nodes, idx) {
440                 ir_node       *irn;
441                 co_mst_irn_t  *node;
442                 aff_chunk_t   *tmp_chunk;
443                 decide_func_t *decider;
444
445                 if (bitset_is_set(visited, idx))
446                         continue;
447
448                 irn  = get_idx_irn(env->co->irg, idx);
449                 node = get_co_mst_irn(env, irn);
450
451                 /* create a new chunk starting at current node */
452                 tmp_chunk = new_aff_chunk(env);
453                 waitq_put(tmp, tmp_chunk);
454                 decider = get_mst_irn_col(node) == col ? decider_has_color : decider_hasnot_color;
455                 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
456                 assert(bitset_popcnt(tmp_chunk->nodes) > 0 && "No nodes added to chunk");
457
458                 /* remember the local best */
459                 aff_chunk_assure_weight(env, tmp_chunk);
460                 if (! best || best->weight < tmp_chunk->weight)
461                         best = tmp_chunk;
462         }
463
464         assert(best && "No chunk found?");
465         bitset_free(visited);
466         return best;
467 }
468
469 /**
470  * Initializes an array of color-cost pairs.
471  * Sets forbidden colors to costs COL_COST_INFEASIBLE and all others to @p c.
472  */
473 static INLINE void col_cost_init(co_mst_env_t *env, col_cost_t *cost, double c) {
474         int i;
475
476         for (i = 0; i < env->n_regs; ++i) {
477                 cost[i].col = i;
478                 if (bitset_is_set(env->ignore_regs, i))
479                         cost[i].cost = COL_COST_INFEASIBLE;
480                 else
481                         cost[i].cost = c;
482         }
483 }
484
485 /**
486  * Initializes an array of color-cost pairs.
487  * Sets all colors except color @p col to COL_COST_INFEASIBLE and @p col to 0.0
488  */
489 static INLINE void col_cost_init_single(co_mst_env_t *env, col_cost_t *cost, int col) {
490         assert(! bitset_is_set(env->ignore_regs, col) && "Attempt to use forbidden color.");
491         col_cost_init(env, cost, COL_COST_INFEASIBLE);
492         cost[col].col = 0;
493         cost[0].col   = col;
494         cost[0].cost  = 0.0;
495 }
496
497 /**
498  * Resets the temporary fixed color of all nodes within wait queue @p nodes.
499  * ATTENTION: the queue is empty after calling this function!
500  */
501 static INLINE void reject_coloring(waitq *nodes) {
502         while (! waitq_empty(nodes)) {
503                 co_mst_irn_t *n = waitq_get(nodes);
504                 n->tmp_fixed = 0;
505         }
506 }
507
508 /**
509  * Determines the costs for each color if it would be assigned to node @p node.
510  */
511 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs) {
512         affinity_node_t *an       = get_affinity_info(env->co, node->irn);
513         void            *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
514         neighb_t        *aff_neigh;
515         ir_node         *int_neigh;
516         int             idx;
517
518         col_cost_init(env, costs, 0.0);
519
520         /* calculate (negative) costs for affinity neighbours */
521         co_gs_foreach_neighb(an, aff_neigh) {
522                 ir_node      *m     = aff_neigh->irn;
523                 co_mst_irn_t *neigh = get_co_mst_irn(env, m);
524                 double       c      = (double)aff_neigh->costs;
525
526                 /* calculate costs for fixed affinity neighbours */
527                 if (neigh->tmp_fixed || neigh->fixed) {
528                         int col = get_mst_irn_col(neigh);
529                         costs[col].cost -= c * AFF_NEIGHBOUR_FIX_BENEFIT;
530                 }
531         }
532
533         /* calculate (positive) costs for interfering neighbours */
534         be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, int_neigh) {
535                 co_mst_irn_t *neigh  = get_co_mst_irn(env, int_neigh);
536                 int          col     = get_mst_irn_col(neigh);
537                 int          col_cnt = bitset_popcnt(neigh->adm_colors);
538
539                 if (neigh->tmp_fixed || neigh->fixed) {
540                         /* colors of fixed interfering neighbours are infeasible */
541                         costs[col].cost = COL_COST_INFEASIBLE;
542                 }
543                 else if (col_cnt < env->k) {
544                         /* calculate costs for constrained interfering neighbours */
545                         double ratio = 1.0 - ((double)col_cnt / (double)env->k);
546
547                         bitset_foreach_clear(neigh->adm_colors, idx) {
548                                 /* check only explicitly forbidden colors (skip global forbidden ones) */
549                                 if (! bitset_is_set(env->ignore_regs, idx)) {
550                                         costs[col].cost += ratio * NEIGHBOUR_CONSTR_COSTS;
551                                 }
552                         }
553                 }
554         }
555
556         /* set all not admissible colors to COL_COST_INFEASIBLE */
557         bitset_foreach_clear(node->adm_colors, idx)
558                 costs[idx].cost = COL_COST_INFEASIBLE;
559 }
560
561 /* need forward declaration due to recursive call */
562 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones);
563
564 /**
565  * Tries to change node to a color but @p explude_col.
566  * @return 1 if succeeded, 0 otherwise.
567  */
568 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, waitq *changed_ones) {
569         int col = get_mst_irn_col(node);
570         int res = 0;
571
572         /* neighbours has already a different color -> good, temporary fix it */
573         if (col != exclude_col) {
574                 node->tmp_fixed = 1;
575                 node->tmp_col   = col;
576                 waitq_put(changed_ones, node);
577                 return 1;
578         }
579
580         /* The node has the color it should not have _and_ has not been visited yet. */
581         if (! (node->tmp_fixed || node->fixed)) {
582                 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
583
584                 /* Get the costs for giving the node a specific color. */
585                 determine_color_costs(env, node, costs);
586
587                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
588                 costs[exclude_col].cost = COL_COST_INFEASIBLE;
589
590                 /* sort the colors according costs, cheapest first. */
591                 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost);
592
593                 /* Try recoloring the node using the color list. */
594                 res = recolor_nodes(env, node, costs, changed_ones);
595         }
596
597         return res;
598 }
599
600 /**
601  * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
602  * ATTENTION: Expect @p costs already sorted by increasing costs.
603  * @return 1 if coloring could be applied, 0 otherwise.
604  */
605 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, waitq *changed_ones) {
606         int   i;
607         waitq *local_changed = new_waitq();
608
609         for (i = 0; i < env->n_regs; ++i) {
610                 void    *nodes_it = be_ifg_nodes_iter_alloca(env->ifg);
611                 int     tgt_col   = costs[i].col;
612                 int     neigh_ok  = 1;
613                 ir_node *neigh;
614
615                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
616                 if (costs[i].cost == COL_COST_INFEASIBLE) {
617                         node->tmp_fixed = 0;
618                         del_waitq(local_changed);
619                         return 0;
620                 }
621
622                 /* Set the new color of the node and mark the node as temporarily fixed. */
623                 assert(! node->tmp_fixed && "Node must not have been temporary fixed.");
624                 node->tmp_fixed = 1;
625                 node->tmp_col   = tgt_col;
626
627                 assert(waitq_empty(local_changed) && "Node queue should be empty here.");
628                 waitq_put(local_changed, node);
629
630                 /* try to color all interfering neighbours with current color forbidden */
631                 be_ifg_foreach_neighbour(env->ifg, nodes_it, node->irn, neigh) {
632                         co_mst_irn_t *nn = get_co_mst_irn(env, neigh);
633                         /*
634                                 Try to change the color of the neighbor and record all nodes which
635                                 get changed in the tmp list. Add this list to the "changed" list for
636                                 that color. If we did not succeed to change the color of the neighbor,
637                                 we bail out and try the next color.
638                         */
639                         if (get_mst_irn_col(nn) == tgt_col) {
640                                 waitq *tmp = new_waitq();
641
642                                 /* try to color neighbour with tgt_col forbidden */
643                                 neigh_ok = change_node_color_excluded(env, nn, tgt_col, tmp);
644
645                                 /* join lists of changed nodes */
646                                 while (! waitq_empty(tmp))
647                                         waitq_put(local_changed, waitq_get(tmp));
648                                 del_waitq(tmp);
649
650                                 if (! neigh_ok)
651                                         break;
652                         }
653                 }
654
655                 /*
656                         We managed to assign the target color to all neighbors, so from the perspective
657                         of the current node, every thing was ok and we can return safely.
658                 */
659                 if (neigh_ok) {
660                         /* append the local_changed ones to global ones */
661                         while (! waitq_empty(local_changed))
662                                 waitq_put(changed_ones, waitq_get(local_changed));
663                         del_waitq(local_changed);
664                         return 1;
665                 }
666                 else {
667                         /* coloring of neighbours failed, so we try next color */
668                         reject_coloring(local_changed);
669                 }
670         }
671
672         del_waitq(local_changed);
673         return 0;
674 }
675
676 /**
677  * Tries to bring node @p node and all it's neighbours to color @p tgt_col.
678  * @return 1 if color @p col could be applied, 0 otherwise
679  */
680 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, waitq *changed_ones) {
681         int col = get_mst_irn_col(node);
682
683         /* if node already has the target color -> good, temporary fix it */
684         if (col == tgt_col) {
685                 if (! node->tmp_fixed) {
686                         node->tmp_fixed = 1;
687                         node->tmp_col   = tgt_col;
688                         waitq_put(changed_ones, node);
689                 }
690                 return 1;
691         }
692
693         /*
694                 Node has not yet a fixed color and target color is admissible
695                 -> try to recolor node and it's affinity neighbours
696         */
697         if (! (node->fixed || node->tmp_fixed) && bitset_is_set(node->adm_colors, tgt_col)) {
698                 col_cost_t *costs = alloca(env->n_regs * sizeof(costs[0]));
699                 col_cost_init_single(env, costs, tgt_col);
700                 return recolor_nodes(env, node, costs, changed_ones);
701         }
702
703         return 0;
704 }
705
706 /**
707  * Tries to color an affinity chunk (or at least a part of it).
708  * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
709  */
710 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c) {
711         aff_chunk_t *best_chunk   = NULL;
712         int         best_color    = -1;
713         waitq       *changed_ones = new_waitq();
714         waitq       *tmp_chunks   = new_waitq();
715         bitset_t    *visited;
716         int         col, idx;
717
718         /* check which color is the "best" for the given chunk */
719         for (col = 0; col < env->k; ++col) {
720                 int         one_good = 0;
721                 aff_chunk_t *local_best;
722
723                 /* try to bring all nodes of given chunk to the current color. */
724                 bitset_foreach(c->nodes, idx) {
725                         ir_node      *irn  = get_idx_irn(env->co->irg, idx);
726                         co_mst_irn_t *node = get_co_mst_irn(env, irn);
727
728                         assert(! node->fixed && "Node must not have a fixed color.");
729
730                         one_good = change_node_color(env, node, col, changed_ones);
731
732                         if (one_good)
733                                 break;
734                 }
735
736                 /* try next color when failed */
737                 if (! one_good)
738                         continue;
739
740                 /* fragment the chunk according to the coloring */
741                 local_best = fragment_chunk(env, col, c, tmp_chunks);
742
743                 /* check if the local best is global best */
744                 if (local_best) {
745                         aff_chunk_assure_weight(env, local_best);
746
747                         if (! best_chunk || best_chunk->weight < local_best->weight) {
748                                 /* kill the old best */
749                                 if (best_chunk)
750                                         delete_aff_chunk(env, best_chunk);
751                                 best_chunk = local_best;
752                                 best_color = col;
753                         }
754                 }
755
756                 /* reject the coloring and bring the coloring to the initial state */
757                 reject_coloring(changed_ones);
758         }
759
760         /* free all intermediate created chunks except best one */
761         while (! waitq_empty(tmp_chunks)) {
762                 aff_chunk_t *tmp = waitq_get(tmp_chunks);
763                 if (tmp != best_chunk)
764                         delete_aff_chunk(env, tmp);
765         }
766         del_waitq(tmp_chunks);
767
768         /* return if coloring failed */
769         if (! best_chunk) {
770                 delete_aff_chunk(env, c);
771                 del_waitq(changed_ones);
772                 return;
773         }
774
775         /* get the best fragment from the best list and color it */
776         bitset_foreach(best_chunk->nodes, idx) {
777                 ir_node      *irn  = get_idx_irn(env->co->irg, idx);
778                 co_mst_irn_t *node = get_co_mst_irn(env, irn);
779                 int          res;
780
781                 res = change_node_color(env, node, best_color, changed_ones);
782                 assert(res && "Coloring failed");
783                 node->fixed = 1;
784                 node->col   = node->tmp_col;
785                 node->chunk = best_chunk;
786         }
787
788         /* fix colors */
789         while (! waitq_empty(changed_ones)) {
790                 co_mst_irn_t *n = waitq_get(changed_ones);
791                 n->fixed = 1;
792                 n->col   = n->tmp_col;
793         }
794
795         /* remove the nodes in best chunk from original chunk */
796         bitset_andnot(c->nodes, best_chunk->nodes);
797
798         /* fragment the remaining chunk */
799         visited = bitset_irg_malloc(env->co->irg);
800         bitset_or(visited, best_chunk->nodes);
801         bitset_foreach(c->nodes, idx) {
802                 if (! bitset_is_set(visited, idx)) {
803                         aff_chunk_t  *new_chunk = new_aff_chunk(env);
804                         ir_node      *irn       = get_idx_irn(env->co->irg, idx);
805                         co_mst_irn_t *node      = get_co_mst_irn(env, irn);
806
807                         expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
808                         aff_chunk_assure_weight(env, new_chunk);
809                         pqueue_put(env->chunks, new_chunk, new_chunk->weight);
810                 }
811         }
812
813         /* clear obsolete chunks and free some memory */
814         delete_aff_chunk(env, c);
815         delete_aff_chunk(env, best_chunk);
816         bitset_free(visited);
817         del_waitq(changed_ones);
818 }
819
820 /**
821  * Main driver for mst safe coalescing algorithm.
822  */
823 int co_solve_heuristic_mst(copy_opt_t *co)
824 {
825         unsigned     n_regs       = co->cenv->cls->n_regs;
826         bitset_t     *ignore_regs = bitset_alloca(n_regs);
827         unsigned     k;
828         co_mst_env_t mst_env;
829
830         memset(&mst_env, 0, sizeof(mst_env));
831
832         /* init phase */
833         phase_init(&mst_env.ph, "co_mst", co->irg, PHASE_DEFAULT_GROWTH, co_mst_irn_init, &mst_env);
834
835         k = be_put_ignore_regs(co->cenv->birg, co->cenv->cls, ignore_regs);
836         k = n_regs - k;
837
838         mst_env.n_regs      = n_regs;
839         mst_env.k           = k;
840         mst_env.chunks      = new_pqueue();
841         mst_env.co          = co;
842         mst_env.ignore_regs = ignore_regs;
843         mst_env.ifg         = co->cenv->ifg;
844         mst_env.aenv        = co->aenv;
845         pset_new_init(&mst_env.chunkset);
846
847         /* build affinity chunks */
848         build_affinity_chunks(&mst_env);
849
850         /* color chunks as long as there are some */
851         while (! pqueue_empty(mst_env.chunks)) {
852                 aff_chunk_t *chunk = pqueue_get(mst_env.chunks);
853                 color_aff_chunk(&mst_env, chunk);
854         }
855
856         /* free allocated memory */
857         del_pqueue(mst_env.chunks);
858         phase_free(&mst_env.ph);
859         pset_new_destroy(&mst_env.chunkset);
860
861         return 0;
862 }