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