dbe5acc87077f0ca241ae239f05d553e7bb8db3d
[libfirm] / ir / be / becopyheur4.c
1 /*
2  * This file is part of libFirm.
3  * Copyright (C) 2012 University of Karlsruhe.
4  */
5
6 /**
7  * @file
8  * @brief       Simple copy minimization heuristics.
9  * @author      Christian Wuerdig
10  * @date        27.04.2007
11  *
12  * This is the C implementation of the mst algorithm
13  * originally written in Java by Sebastian Hack.
14  * (also known as "heur3" :)
15  * Performs simple copy minimization.
16  */
17 #include "config.h"
18
19 #define DISABLE_STATEV
20
21 #include <float.h>
22
23 #include "array.h"
24 #include "irnode_t.h"
25 #include "bitset.h"
26 #include "raw_bitset.h"
27 #include "irnodemap.h"
28 #include "pqueue.h"
29 #include "xmalloc.h"
30 #include "pdeq.h"
31 #include "irprintf.h"
32 #include "util.h"
33 #include "irtools.h"
34 #include "error.h"
35 #include "list.h"
36 #include "statev_t.h"
37
38 #include "bearch.h"
39 #include "beifg.h"
40 #include "be_t.h"
41 #include "becopyopt_t.h"
42 #include "bemodule.h"
43
44
45 #ifdef DEBUG_libfirm
46
47 #define DBG_AFF_CHUNK(env, level, chunk) do { if (firm_dbg_get_mask(dbg) & (level)) dbg_aff_chunk((env), (chunk)); } while (0)
48 #define DBG_COL_COST(env, level, cost)   do { if (firm_dbg_get_mask(dbg) & (level)) dbg_col_cost((env), (cost)); } while (0)
49
50 static firm_dbg_module_t *dbg = NULL;
51
52 #else
53
54 #define DBG_AFF_CHUNK(env, level, chunk)
55 #define DBG_COL_COST(env, level, cost)
56
57 #endif
58
59 typedef float real_t;
60 #define REAL(C)   (C ## f)
61
62 static unsigned last_chunk_id   = 0;
63 static int recolor_limit        = 7;
64 static double dislike_influence = REAL(0.1);
65
66 typedef struct col_cost_t {
67         int     col;
68         real_t  cost;
69 } col_cost_t;
70
71 /**
72  * An affinity chunk.
73  */
74 typedef struct aff_chunk_t {
75         const ir_node  **n;                     /**< An ARR_F containing all nodes of the chunk. */
76         const ir_node  **interfere;             /**< An ARR_F containing all inference. */
77         int              weight;                /**< Weight of this chunk */
78         unsigned         weight_consistent : 1; /**< Set if the weight is consistent. */
79         unsigned         deleted           : 1; /**< For debugging: Set if the was deleted. */
80         unsigned         id;                    /**< An id of this chunk. */
81         unsigned         visited;
82         list_head        list;
83         col_cost_t       color_affinity[1];
84 } aff_chunk_t;
85
86 /**
87  * An affinity edge.
88  */
89 typedef struct aff_edge_t {
90         const ir_node *src;                   /**< Source node. */
91         const ir_node *tgt;                   /**< Target node. */
92         int           weight;                 /**< The weight of this edge. */
93 } aff_edge_t;
94
95 /* main coalescing environment */
96 typedef struct co_mst_env_t {
97         int              n_regs;         /**< number of regs in class */
98         bitset_t const   *allocatable_regs; /**< set containing all global ignore registers */
99         ir_nodemap        map;           /**< phase object holding data for nodes */
100         struct obstack    obst;
101         pqueue_t         *chunks;        /**< priority queue for chunks */
102         list_head         chunklist;     /**< list holding all chunks */
103         be_ifg_t         *ifg;           /**< the interference graph */
104         copy_opt_t       *co;            /**< the copy opt object */
105         unsigned         chunk_visited;
106         col_cost_t      **single_cols;
107 } co_mst_env_t;
108
109 /* stores coalescing related information for a node */
110 typedef struct co_mst_irn_t {
111         const ir_node    *irn;              /**< the irn this information belongs to */
112         aff_chunk_t      *chunk;            /**< the chunk this irn belongs to */
113         bitset_t         *adm_colors;       /**< set of admissible colors for this irn */
114         ir_node          **int_neighs;      /**< array of all interfering neighbours (cached for speed reasons) */
115         int              n_neighs;          /**< length of the interfering neighbours array. */
116         int              int_aff_neigh;     /**< number of interfering affinity neighbours */
117         int              col;               /**< color currently assigned */
118         int              init_col;          /**< the initial color */
119         int              tmp_col;           /**< a temporary assigned color */
120         unsigned         fixed     : 1;     /**< the color is fixed */
121         struct list_head list;              /**< Queue for coloring undo. */
122         real_t           constr_factor;
123 } co_mst_irn_t;
124
125 /**
126  * In case there is no phase information for irn, initialize it.
127  */
128 static co_mst_irn_t *co_mst_irn_init(co_mst_env_t *env, const ir_node *irn)
129 {
130         co_mst_irn_t *res = OALLOC(&env->obst, co_mst_irn_t);
131
132         const arch_register_req_t *req;
133         neighbours_iter_t nodes_it;
134         unsigned len;
135
136         res->irn           = irn;
137         res->chunk         = NULL;
138         res->fixed         = 0;
139         res->tmp_col       = -1;
140         res->int_neighs    = NULL;
141         res->int_aff_neigh = 0;
142         res->col           = arch_get_irn_register(irn)->index;
143         res->init_col      = res->col;
144         INIT_LIST_HEAD(&res->list);
145
146         DB((dbg, LEVEL_4, "Creating phase info for %+F\n", irn));
147
148         /* set admissible registers */
149         res->adm_colors = bitset_obstack_alloc(&env->obst, env->n_regs);
150
151         /* Exclude colors not assignable to the irn */
152         req = arch_get_irn_register_req(irn);
153         if (arch_register_req_is(req, limited)) {
154                 rbitset_copy_to_bitset(req->limited, res->adm_colors);
155                 /* exclude global ignore registers as well */
156                 bitset_and(res->adm_colors, env->allocatable_regs);
157         } else {
158                 bitset_copy(res->adm_colors, env->allocatable_regs);
159         }
160
161         /* compute the constraint factor */
162         res->constr_factor = (real_t) (1 + env->n_regs - bitset_popcount(res->adm_colors)) / env->n_regs;
163
164         /* set the number of interfering affinity neighbours to -1, they are calculated later */
165         res->int_aff_neigh = -1;
166
167         /* build list of interfering neighbours */
168         len = 0;
169         be_ifg_foreach_neighbour(env->ifg, &nodes_it, irn, neigh) {
170                 if (!arch_irn_is_ignore(neigh)) {
171                         obstack_ptr_grow(&env->obst, neigh);
172                         ++len;
173                 }
174         }
175         res->int_neighs = (ir_node**)obstack_finish(&env->obst);
176         res->n_neighs   = len;
177         return res;
178 }
179
180 static co_mst_irn_t *get_co_mst_irn(co_mst_env_t *env, const ir_node *node)
181 {
182         co_mst_irn_t *res = ir_nodemap_get(co_mst_irn_t, &env->map, node);
183         if (res == NULL) {
184                 res = co_mst_irn_init(env, node);
185                 ir_nodemap_insert(&env->map, node, res);
186         }
187         return res;
188 }
189
190 typedef int decide_func_t(const co_mst_irn_t *node, int col);
191
192 #ifdef DEBUG_libfirm
193
194 /**
195  * Write a chunk to stderr for debugging.
196  */
197 static void dbg_aff_chunk(const co_mst_env_t *env, const aff_chunk_t *c)
198 {
199         int i, l;
200         (void) env;
201         if (c->weight_consistent)
202                 ir_fprintf(stderr, " $%d ", c->weight);
203         ir_fprintf(stderr, "{");
204         for (i = 0, l = ARR_LEN(c->n); i < l; ++i) {
205                 const ir_node *n = c->n[i];
206                 ir_fprintf(stderr, " %+F,", n);
207         }
208         ir_fprintf(stderr, "}");
209 }
210
211 /**
212  * Dump all admissible colors to stderr.
213  */
214 static void dbg_admissible_colors(const co_mst_env_t *env, const co_mst_irn_t *node)
215 {
216         (void) env;
217
218         if (bitset_popcount(node->adm_colors) < 1)
219                 fprintf(stderr, "no admissible colors?!?");
220         else {
221                 bitset_foreach(node->adm_colors, idx) {
222                         ir_fprintf(stderr, " %zu", idx);
223                 }
224         }
225 }
226
227 /**
228  * Dump color-cost pairs to stderr.
229  */
230 static void dbg_col_cost(const co_mst_env_t *env, const col_cost_t *cost)
231 {
232         int i;
233         for (i = 0; i < env->n_regs; ++i)
234                 fprintf(stderr, " (%d, %.4f)", cost[i].col, cost[i].cost);
235 }
236
237 #endif /* DEBUG_libfirm */
238
239 static inline int get_mst_irn_col(const co_mst_irn_t *node)
240 {
241         return node->tmp_col >= 0 ? node->tmp_col : node->col;
242 }
243
244 /**
245  * @return 1 if node @p node has color @p col, 0 otherwise.
246  */
247 static int decider_has_color(const co_mst_irn_t *node, int col)
248 {
249         return get_mst_irn_col(node) == col;
250 }
251
252 /**
253  * @return 1 if node @p node has not color @p col, 0 otherwise.
254  */
255 static int decider_hasnot_color(const co_mst_irn_t *node, int col)
256 {
257         return get_mst_irn_col(node) != col;
258 }
259
260 /**
261  * Always returns true.
262  */
263 static int decider_always_yes(const co_mst_irn_t *node, int col)
264 {
265         (void) node;
266         (void) col;
267         return 1;
268 }
269
270 /** compares two affinity edges by its weight */
271 static int cmp_aff_edge(const void *a, const void *b)
272 {
273         const aff_edge_t *e1 = (const aff_edge_t*)a;
274         const aff_edge_t *e2 = (const aff_edge_t*)b;
275
276         if (e2->weight == e1->weight) {
277                 if (e2->src->node_idx == e1->src->node_idx)
278                         return QSORT_CMP(e2->tgt->node_idx, e1->tgt->node_idx);
279                 else
280                         return QSORT_CMP(e2->src->node_idx, e1->src->node_idx);
281         }
282         /* sort in descending order */
283         return QSORT_CMP(e2->weight, e1->weight);
284 }
285
286 /** compares to color-cost pairs */
287 static __attribute__((unused)) int cmp_col_cost_lt(const void *a, const void *b)
288 {
289         const col_cost_t *c1 = (const col_cost_t*)a;
290         const col_cost_t *c2 = (const col_cost_t*)b;
291         real_t diff = c1->cost - c2->cost;
292
293         if (diff < 0)
294                 return 1;
295         if (diff > 0)
296                 return -1;
297
298         return QSORT_CMP(c1->col, c2->col);
299 }
300
301 static int cmp_col_cost_gt(const void *a, const void *b)
302 {
303         const col_cost_t *c1 = (const col_cost_t*)a;
304         const col_cost_t *c2 = (const col_cost_t*)b;
305         real_t diff = c2->cost - c1->cost;
306
307         if (diff > 0)
308                 return 1;
309         if (diff < 0)
310                 return -1;
311
312         return QSORT_CMP(c1->col, c2->col);
313 }
314
315 /**
316  * Creates a new affinity chunk
317  */
318 static inline aff_chunk_t *new_aff_chunk(co_mst_env_t *env)
319 {
320         aff_chunk_t *c = XMALLOCF(aff_chunk_t, color_affinity, env->n_regs);
321         c->n                 = NEW_ARR_F(const ir_node *, 0);
322         c->interfere         = NEW_ARR_F(const ir_node *, 0);
323         c->weight            = -1;
324         c->weight_consistent = 0;
325         c->deleted           = 0;
326         c->id                = ++last_chunk_id;
327         c->visited           = 0;
328         list_add(&c->list, &env->chunklist);
329         return c;
330 }
331
332 /**
333  * Frees all memory allocated by an affinity chunk.
334  */
335 static inline void delete_aff_chunk(aff_chunk_t *c)
336 {
337         list_del(&c->list);
338         DEL_ARR_F(c->interfere);
339         DEL_ARR_F(c->n);
340         c->deleted = 1;
341         free(c);
342 }
343
344 /**
345  * binary search of sorted nodes.
346  *
347  * @return the position where n is found in the array arr or ~pos
348  * if the nodes is not here.
349  */
350 static inline int nodes_bsearch(const ir_node **arr, const ir_node *n)
351 {
352         int hi = ARR_LEN(arr);
353         int lo = 0;
354
355         while (lo < hi) {
356                 int md = lo + ((hi - lo) >> 1);
357
358                 if (arr[md] == n)
359                         return md;
360                 if (arr[md] < n)
361                         lo = md + 1;
362                 else
363                         hi = md;
364         }
365
366         return ~lo;
367 }
368
369 /** Check if a node n can be found inside arr. */
370 static int node_contains(const ir_node **arr, const ir_node *n)
371 {
372         int i = nodes_bsearch(arr, n);
373         return i >= 0;
374 }
375
376 /**
377  * Insert a node into the sorted nodes list.
378  *
379  * @return 1 if the node was inserted, 0 else
380  */
381 static int nodes_insert(const ir_node ***arr, const ir_node *irn)
382 {
383         int idx = nodes_bsearch(*arr, irn);
384
385         if (idx < 0) {
386                 int i, n = ARR_LEN(*arr);
387                 const ir_node **l;
388
389                 ARR_APP1(const ir_node *, *arr, irn);
390
391                 /* move it */
392                 idx = ~idx;
393                 l = *arr;
394                 for (i = n - 1; i >= idx; --i)
395                         l[i + 1] = l[i];
396                 l[idx] = irn;
397                 return 1;
398         }
399         return 0;
400 }
401
402 /**
403  * Adds a node to an affinity chunk
404  */
405 static inline void aff_chunk_add_node(aff_chunk_t *c, co_mst_irn_t *node)
406 {
407         int i;
408
409         if (! nodes_insert(&c->n, node->irn))
410                 return;
411
412         c->weight_consistent = 0;
413         node->chunk          = c;
414
415         for (i = node->n_neighs - 1; i >= 0; --i) {
416                 ir_node *neigh = node->int_neighs[i];
417                 nodes_insert(&c->interfere, neigh);
418         }
419 }
420
421 /**
422  * Check if affinity chunk @p chunk interferes with node @p irn.
423  */
424 static inline int aff_chunk_interferes(const aff_chunk_t *chunk, const ir_node *irn)
425 {
426         return node_contains(chunk->interfere, irn);
427 }
428
429 /**
430  * Check if there are interference edges from c1 to c2.
431  * @param c1    A chunk
432  * @param c2    Another chunk
433  * @return 1 if there are interferences between nodes of c1 and c2, 0 otherwise.
434  */
435 static inline int aff_chunks_interfere(const aff_chunk_t *c1, const aff_chunk_t *c2)
436 {
437         int i;
438
439         if (c1 == c2)
440                 return 0;
441
442         /* check if there is a node in c2 having an interfering neighbor in c1 */
443         for (i = ARR_LEN(c2->n) - 1; i >= 0; --i) {
444                 const ir_node *irn = c2->n[i];
445
446                 if (node_contains(c1->interfere, irn))
447                         return 1;
448         }
449         return 0;
450 }
451
452 /**
453  * Returns the affinity chunk of @p irn or creates a new
454  * one with @p irn as element if there is none assigned.
455  */
456 static inline aff_chunk_t *get_aff_chunk(co_mst_env_t *env, const ir_node *irn)
457 {
458         co_mst_irn_t *node = get_co_mst_irn(env, irn);
459         return node->chunk;
460 }
461
462 /**
463  * Let chunk(src) absorb the nodes of chunk(tgt) (only possible when there
464  * are no interference edges from chunk(src) to chunk(tgt)).
465  * @return 1 if successful, 0 if not possible
466  */
467 static int aff_chunk_absorb(co_mst_env_t *env, const ir_node *src, const ir_node *tgt)
468 {
469         aff_chunk_t *c1 = get_aff_chunk(env, src);
470         aff_chunk_t *c2 = get_aff_chunk(env, tgt);
471
472 #ifdef DEBUG_libfirm
473                 DB((dbg, LEVEL_4, "Attempt to let c1 (id %u): ", c1 ? c1->id : 0));
474                 if (c1) {
475                         DBG_AFF_CHUNK(env, LEVEL_4, c1);
476                 } else {
477                         DB((dbg, LEVEL_4, "{%+F}", src));
478                 }
479                 DB((dbg, LEVEL_4, "\n\tabsorb c2 (id %u): ", c2 ? c2->id : 0));
480                 if (c2) {
481                         DBG_AFF_CHUNK(env, LEVEL_4, c2);
482                 } else {
483                         DB((dbg, LEVEL_4, "{%+F}", tgt));
484                 }
485                 DB((dbg, LEVEL_4, "\n"));
486 #endif
487
488         if (c1 == NULL) {
489                 if (c2 == NULL) {
490                         /* no chunk exists */
491                         co_mst_irn_t *mirn = get_co_mst_irn(env, src);
492                         int i;
493
494                         for (i = mirn->n_neighs - 1; i >= 0; --i) {
495                                 if (mirn->int_neighs[i] == tgt)
496                                         break;
497                         }
498                         if (i < 0) {
499                                 /* create one containing both nodes */
500                                 c1 = new_aff_chunk(env);
501                                 aff_chunk_add_node(c1, get_co_mst_irn(env, src));
502                                 aff_chunk_add_node(c1, get_co_mst_irn(env, tgt));
503                                 goto absorbed;
504                         }
505                 } else {
506                         /* c2 already exists */
507                         if (! aff_chunk_interferes(c2, src)) {
508                                 aff_chunk_add_node(c2, get_co_mst_irn(env, src));
509                                 goto absorbed;
510                         }
511                 }
512         } else if (c2 == NULL) {
513                 /* c1 already exists */
514                 if (! aff_chunk_interferes(c1, tgt)) {
515                         aff_chunk_add_node(c1, get_co_mst_irn(env, tgt));
516                         goto absorbed;
517                 }
518         } else if (c1 != c2 && ! aff_chunks_interfere(c1, c2)) {
519                 int idx, len;
520
521                 for (idx = 0, len = ARR_LEN(c2->n); idx < len; ++idx)
522                         aff_chunk_add_node(c1, get_co_mst_irn(env, c2->n[idx]));
523
524                 for (idx = 0, len = ARR_LEN(c2->interfere); idx < len; ++idx) {
525                         const ir_node *irn = c2->interfere[idx];
526                         nodes_insert(&c1->interfere, irn);
527                 }
528
529                 c1->weight_consistent = 0;
530
531                 delete_aff_chunk(c2);
532                 goto absorbed;
533         }
534         DB((dbg, LEVEL_4, " ... c1 interferes with c2, skipped\n"));
535         return 0;
536
537 absorbed:
538         DB((dbg, LEVEL_4, " ... absorbed\n"));
539         return 1;
540 }
541
542 /**
543  * Assures that the weight of the given chunk is consistent.
544  */
545 static void aff_chunk_assure_weight(co_mst_env_t *env, aff_chunk_t *c)
546 {
547         if (! c->weight_consistent) {
548                 int w = 0;
549                 int idx, len, i;
550
551                 for (i = 0; i < env->n_regs; ++i) {
552                         c->color_affinity[i].col = i;
553                         c->color_affinity[i].cost = REAL(0.0);
554                 }
555
556                 for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
557                         const ir_node         *n       = c->n[idx];
558                         const affinity_node_t *an      = get_affinity_info(env->co, n);
559                         co_mst_irn_t          *node    = get_co_mst_irn(env, n);
560
561                         node->chunk = c;
562                         if (node->constr_factor > REAL(0.0)) {
563                                 bitset_foreach (node->adm_colors, col)
564                                         c->color_affinity[col].cost += node->constr_factor;
565                         }
566
567                         if (an != NULL) {
568                                 co_gs_foreach_neighb(an, neigh) {
569                                         const ir_node *m = neigh->irn;
570
571                                         if (arch_irn_is_ignore(m))
572                                                 continue;
573
574                                         w += node_contains(c->n, m) ? neigh->costs : 0;
575                                 }
576                         }
577                 }
578
579                 for (i = 0; i < env->n_regs; ++i)
580                         c->color_affinity[i].cost *= (REAL(1.0) / ARR_LEN(c->n));
581
582                 c->weight            = w;
583                 // c->weight            = bitset_popcount(c->nodes);
584                 c->weight_consistent = 1;
585         }
586 }
587
588 /**
589  * Count the number of interfering affinity neighbours
590  */
591 static int count_interfering_aff_neighs(co_mst_env_t *env, const affinity_node_t *an)
592 {
593         const ir_node      *irn  = an->irn;
594         const co_mst_irn_t *node = get_co_mst_irn(env, irn);
595         int                res   = 0;
596
597         co_gs_foreach_neighb(an, neigh) {
598                 const ir_node *n = neigh->irn;
599                 int           i;
600
601                 if (arch_irn_is_ignore(n))
602                         continue;
603
604                 /* check if the affinity neighbour interfere */
605                 for (i = 0; i < node->n_neighs; ++i) {
606                         if (node->int_neighs[i] == n) {
607                                 ++res;
608                                 break;
609                         }
610                 }
611         }
612         return res;
613 }
614
615
616 /**
617  * Build chunks of nodes connected by affinity edges.
618  * We start at the heaviest affinity edge.
619  * The chunks of the two edge-defining nodes will be
620  * merged if there are no interference edges from one
621  * chunk to the other.
622  */
623 static void build_affinity_chunks(co_mst_env_t *env)
624 {
625         aff_edge_t *edges = NEW_ARR_F(aff_edge_t, 0);
626
627         /* at first we create the affinity edge objects */
628         be_ifg_foreach_node(env->ifg, n) {
629                 int             n_idx = get_irn_idx(n);
630                 co_mst_irn_t    *n1;
631                 affinity_node_t *an;
632
633                 if (arch_irn_is_ignore(n))
634                         continue;
635
636                 n1 = get_co_mst_irn(env, n);
637                 an = get_affinity_info(env->co, n);
638
639                 if (an != NULL) {
640                         if (n1->int_aff_neigh < 0)
641                                 n1->int_aff_neigh = count_interfering_aff_neighs(env, an);
642
643                         /* build the affinity edges */
644                         co_gs_foreach_neighb(an, neigh) {
645                                 const ir_node *m     = neigh->irn;
646                                 int            m_idx = get_irn_idx(m);
647
648                                 /* record the edge in only one direction */
649                                 if (n_idx < m_idx) {
650                                         co_mst_irn_t *n2;
651                                         aff_edge_t   edge;
652
653                                         /* skip ignore nodes */
654                                         if (arch_irn_is_ignore(m))
655                                                 continue;
656
657                                         edge.src = n;
658                                         edge.tgt = m;
659
660                                         n2 = get_co_mst_irn(env, m);
661                                         if (n2->int_aff_neigh < 0) {
662                                                 affinity_node_t *am = get_affinity_info(env->co, m);
663                                                 n2->int_aff_neigh = count_interfering_aff_neighs(env, am);
664                                         }
665                                         /*
666                                          * these weights are pure hackery ;-).
667                                          * It's not chriswue's fault but mine.
668                                          */
669                                         edge.weight = neigh->costs;
670                                         ARR_APP1(aff_edge_t, edges, edge);
671                                 }
672                         }
673                 }
674         }
675
676         /* now: sort edges and build the affinity chunks */
677         size_t const len = ARR_LEN(edges);
678         qsort(edges, len, sizeof(edges[0]), cmp_aff_edge);
679         for (size_t i = 0; i < len; ++i) {
680                 DBG((dbg, LEVEL_1, "edge (%u,%u) %f\n", edges[i].src->node_idx, edges[i].tgt->node_idx, edges[i].weight));
681
682                 (void)aff_chunk_absorb(env, edges[i].src, edges[i].tgt);
683         }
684
685         /* now insert all chunks into a priority queue */
686         list_for_each_entry(aff_chunk_t, curr_chunk, &env->chunklist, list) {
687                 aff_chunk_assure_weight(env, curr_chunk);
688
689                 DBG((dbg, LEVEL_1, "entry #%u", curr_chunk->id));
690                 DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
691                 DBG((dbg, LEVEL_1, "\n"));
692
693                 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
694         }
695
696         for (size_t pn = 0; pn < ARR_LEN(env->map.data); ++pn) {
697                 co_mst_irn_t *mirn = (co_mst_irn_t*)env->map.data[pn];
698                 if (mirn == NULL)
699                         continue;
700                 if (mirn->chunk != NULL)
701                         continue;
702
703                 /* no chunk is allocated so far, do it now */
704                 aff_chunk_t *curr_chunk = new_aff_chunk(env);
705                 aff_chunk_add_node(curr_chunk, mirn);
706
707                 aff_chunk_assure_weight(env, curr_chunk);
708
709                 DBG((dbg, LEVEL_1, "entry #%u", curr_chunk->id));
710                 DBG_AFF_CHUNK(env, LEVEL_1, curr_chunk);
711                 DBG((dbg, LEVEL_1, "\n"));
712
713                 pqueue_put(env->chunks, curr_chunk, curr_chunk->weight);
714         }
715
716         DEL_ARR_F(edges);
717 }
718
719 static __attribute__((unused)) void chunk_order_nodes(co_mst_env_t *env, aff_chunk_t *chunk)
720 {
721         pqueue_t      *grow       = new_pqueue();
722         ir_node const *max_node   = NULL;
723         int            max_weight = 0;
724         size_t         i;
725
726         for (i = ARR_LEN(chunk->n); i != 0;) {
727                 const ir_node   *irn = chunk->n[--i];
728                 affinity_node_t *an  = get_affinity_info(env->co, irn);
729                 int w = 0;
730
731                 if (arch_irn_is_ignore(irn))
732                         continue;
733
734                 if (an) {
735                         co_gs_foreach_neighb(an, neigh)
736                                 w += neigh->costs;
737
738                         if (w > max_weight) {
739                                 max_weight = w;
740                                 max_node   = irn;
741                         }
742                 }
743         }
744
745         if (max_node) {
746                 bitset_t *visited = bitset_malloc(get_irg_last_idx(env->co->irg));
747
748                 for (i = ARR_LEN(chunk->n); i != 0;)
749                         bitset_set(visited, get_irn_idx(chunk->n[--i]));
750
751                 pqueue_put(grow, (void *) max_node, max_weight);
752                 bitset_clear(visited, get_irn_idx(max_node));
753                 i = 0;
754                 while (!pqueue_empty(grow)) {
755                         ir_node *irn = (ir_node*)pqueue_pop_front(grow);
756                         affinity_node_t *an = get_affinity_info(env->co, irn);
757
758                         if (arch_irn_is_ignore(irn))
759                                 continue;
760
761                         assert(i <= ARR_LEN(chunk->n));
762                         chunk->n[i++] = irn;
763
764                         assert(an);
765
766                         /* build the affinity edges */
767                         co_gs_foreach_neighb(an, neigh) {
768                                 co_mst_irn_t *node = get_co_mst_irn(env, neigh->irn);
769
770                                 if (bitset_is_set(visited, get_irn_idx(node->irn))) {
771                                         pqueue_put(grow, (void *) neigh->irn, neigh->costs);
772                                         bitset_clear(visited, get_irn_idx(node->irn));
773                                 }
774                         }
775                 }
776
777                 del_pqueue(grow);
778                 bitset_free(visited);
779         }
780 }
781
782 /**
783  * Greedy collect affinity neighbours into thew new chunk @p chunk starting at node @p node.
784  */
785 static void expand_chunk_from(co_mst_env_t *env, co_mst_irn_t *node, bitset_t *visited,
786         aff_chunk_t *chunk, aff_chunk_t *orig_chunk, decide_func_t *decider, int col)
787 {
788         waitq *nodes = new_waitq();
789
790         DBG((dbg, LEVEL_1, "\n\tExpanding new chunk (#%u) from %+F, color %d:", chunk->id, node->irn, col));
791
792         /* init queue and chunk */
793         waitq_put(nodes, node);
794         bitset_set(visited, get_irn_idx(node->irn));
795         aff_chunk_add_node(chunk, node);
796         DB((dbg, LEVEL_1, " %+F", node->irn));
797
798         /* as long as there are nodes in the queue */
799         while (! waitq_empty(nodes)) {
800                 co_mst_irn_t    *n  = (co_mst_irn_t*)waitq_get(nodes);
801                 affinity_node_t *an = get_affinity_info(env->co, n->irn);
802
803                 /* check all affinity neighbors */
804                 if (an != NULL) {
805                         co_gs_foreach_neighb(an, neigh) {
806                                 const ir_node *m    = neigh->irn;
807                                 int            m_idx = get_irn_idx(m);
808                                 co_mst_irn_t *n2;
809
810                                 if (arch_irn_is_ignore(m))
811                                         continue;
812
813                                 n2 = get_co_mst_irn(env, m);
814
815                                 if (! bitset_is_set(visited, m_idx)  &&
816                                         decider(n2, col)                 &&
817                                         ! n2->fixed                      &&
818                                         ! aff_chunk_interferes(chunk, m) &&
819                                         node_contains(orig_chunk->n, m))
820                                 {
821                                         /*
822                                                 following conditions are met:
823                                                 - neighbour is not visited
824                                                 - neighbour likes the color
825                                                 - neighbour has not yet a fixed color
826                                                 - the new chunk doesn't interfere with the neighbour
827                                                 - neighbour belongs or belonged once to the original chunk
828                                         */
829                                         bitset_set(visited, m_idx);
830                                         aff_chunk_add_node(chunk, n2);
831                                         DB((dbg, LEVEL_1, " %+F", n2->irn));
832                                         /* enqueue for further search */
833                                         waitq_put(nodes, n2);
834                                 }
835                         }
836                 }
837         }
838
839         DB((dbg, LEVEL_1, "\n"));
840
841         del_waitq(nodes);
842 }
843
844 /**
845  * Fragment the given chunk into chunks having given color and not having given color.
846  */
847 static aff_chunk_t *fragment_chunk(co_mst_env_t *env, int col, aff_chunk_t *c, waitq *tmp)
848 {
849         bitset_t    *visited = bitset_malloc(get_irg_last_idx(env->co->irg));
850         int         idx, len;
851         aff_chunk_t *best = NULL;
852
853         for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
854                 const ir_node *irn;
855                 co_mst_irn_t  *node;
856                 aff_chunk_t   *tmp_chunk;
857                 decide_func_t *decider;
858                 int           check_for_best;
859
860                 irn = c->n[idx];
861                 if (bitset_is_set(visited, get_irn_idx(irn)))
862                         continue;
863
864                 node = get_co_mst_irn(env, irn);
865
866                 if (get_mst_irn_col(node) == col) {
867                         decider        = decider_has_color;
868                         check_for_best = 1;
869                         DBG((dbg, LEVEL_4, "\tcolor %d wanted\n", col));
870                 }
871                 else {
872                         decider        = decider_hasnot_color;
873                         check_for_best = 0;
874                         DBG((dbg, LEVEL_4, "\tcolor %d forbidden\n", col));
875                 }
876
877                 /* create a new chunk starting at current node */
878                 tmp_chunk = new_aff_chunk(env);
879                 waitq_put(tmp, tmp_chunk);
880                 expand_chunk_from(env, node, visited, tmp_chunk, c, decider, col);
881                 assert(ARR_LEN(tmp_chunk->n) > 0 && "No nodes added to chunk");
882
883                 /* remember the local best */
884                 aff_chunk_assure_weight(env, tmp_chunk);
885                 if (check_for_best && (! best || best->weight < tmp_chunk->weight))
886                         best = tmp_chunk;
887         }
888
889         assert(best && "No chunk found?");
890         bitset_free(visited);
891         return best;
892 }
893
894 /**
895  * Resets the temporary fixed color of all nodes within wait queue @p nodes.
896  * ATTENTION: the queue is empty after calling this function!
897  */
898 static inline void reject_coloring(struct list_head *nodes)
899 {
900         DB((dbg, LEVEL_4, "\treject coloring for"));
901         list_for_each_entry_safe(co_mst_irn_t, n, temp, nodes, list) {
902                 DB((dbg, LEVEL_4, " %+F", n->irn));
903                 assert(n->tmp_col >= 0);
904                 n->tmp_col = -1;
905                 list_del_init(&n->list);
906         }
907         DB((dbg, LEVEL_4, "\n"));
908 }
909
910 static inline void materialize_coloring(struct list_head *nodes)
911 {
912         list_for_each_entry_safe(co_mst_irn_t, n, temp, nodes, list) {
913                 assert(n->tmp_col >= 0);
914                 n->col     = n->tmp_col;
915                 n->tmp_col = -1;
916                 list_del_init(&n->list);
917         }
918 }
919
920 static inline void set_temp_color(co_mst_irn_t *node, int col, struct list_head *changed)
921 {
922         assert(col >= 0);
923         assert(!node->fixed);
924         assert(node->tmp_col < 0);
925         assert(node->list.next == &node->list && node->list.prev == &node->list);
926         assert(bitset_is_set(node->adm_colors, col));
927
928         list_add_tail(&node->list, changed);
929         node->tmp_col = col;
930 }
931
932 static inline int is_loose(co_mst_irn_t *node)
933 {
934         return !node->fixed && node->tmp_col < 0;
935 }
936
937 /**
938  * Determines the costs for each color if it would be assigned to node @p node.
939  */
940 static void determine_color_costs(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs)
941 {
942         int   *neigh_cols = ALLOCAN(int, env->n_regs);
943         int    n_loose    = 0;
944         real_t coeff;
945         int    i;
946
947         for (i = 0; i < env->n_regs; ++i) {
948                 neigh_cols[i] = 0;
949                 costs[i].col = i;
950                 costs[i].cost = bitset_is_set(node->adm_colors, i) ? node->constr_factor : REAL(0.0);
951         }
952
953         for (i = 0; i < node->n_neighs; ++i) {
954                 co_mst_irn_t *n = get_co_mst_irn(env, node->int_neighs[i]);
955                 int col = get_mst_irn_col(n);
956                 if (is_loose(n)) {
957                         ++n_loose;
958                         ++neigh_cols[col];
959                 } else
960                         costs[col].cost = REAL(0.0);
961         }
962
963         if (n_loose > 0) {
964                 coeff = REAL(1.0) / n_loose;
965                 for (i = 0; i < env->n_regs; ++i)
966                         costs[i].cost *= REAL(1.0) - coeff * neigh_cols[i];
967         }
968 }
969
970 /* need forward declaration due to recursive call */
971 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, struct list_head *changed_ones, int depth, int *max_depth, int *trip);
972
973 /**
974  * Tries to change node to a color but @p explude_col.
975  * @return 1 if succeeded, 0 otherwise.
976  */
977 static int change_node_color_excluded(co_mst_env_t *env, co_mst_irn_t *node, int exclude_col, struct list_head *changed, int depth, int *max_depth, int *trip)
978 {
979         int col = get_mst_irn_col(node);
980         int res = 0;
981
982         /* neighbours has already a different color -> good, temporary fix it */
983         if (col != exclude_col) {
984                 if (is_loose(node))
985                         set_temp_color(node, col, changed);
986                 return 1;
987         }
988
989         /* The node has the color it should not have _and_ has not been visited yet. */
990         if (is_loose(node)) {
991                 col_cost_t *costs = ALLOCAN(col_cost_t, env->n_regs);
992
993                 /* Get the costs for giving the node a specific color. */
994                 determine_color_costs(env, node, costs);
995
996                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
997                 costs[exclude_col].cost = REAL(0.0);
998
999                 /* sort the colors according costs, cheapest first. */
1000                 qsort(costs, env->n_regs, sizeof(costs[0]), cmp_col_cost_gt);
1001
1002                 /* Try recoloring the node using the color list. */
1003                 res = recolor_nodes(env, node, costs, changed, depth + 1, max_depth, trip);
1004         }
1005
1006         return res;
1007 }
1008
1009 /**
1010  * Tries to bring node @p node to cheapest color and color all interfering neighbours with other colors.
1011  * ATTENTION: Expect @p costs already sorted by increasing costs.
1012  * @return 1 if coloring could be applied, 0 otherwise.
1013  */
1014 static int recolor_nodes(co_mst_env_t *env, co_mst_irn_t *node, col_cost_t *costs, struct list_head *changed, int depth, int *max_depth, int *trip)
1015 {
1016         int   i;
1017         struct list_head local_changed;
1018
1019         ++*trip;
1020         if (depth > *max_depth)
1021                 *max_depth = depth;
1022
1023         DBG((dbg, LEVEL_4, "\tRecoloring %+F with color-costs", node->irn));
1024         DBG_COL_COST(env, LEVEL_4, costs);
1025         DB((dbg, LEVEL_4, "\n"));
1026
1027         if (depth >= recolor_limit) {
1028                 DBG((dbg, LEVEL_4, "\tHit recolor limit\n"));
1029                 return 0;
1030         }
1031
1032         for (i = 0; i < env->n_regs; ++i) {
1033                 int tgt_col  = costs[i].col;
1034                 int neigh_ok = 1;
1035                 int j;
1036
1037                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
1038                 if (costs[i].cost == REAL(0.0)) {
1039                         DBG((dbg, LEVEL_4, "\tAll further colors forbidden\n"));
1040                         return 0;
1041                 }
1042
1043                 /* Set the new color of the node and mark the node as temporarily fixed. */
1044                 assert(node->tmp_col < 0 && "Node must not have been temporary fixed.");
1045                 INIT_LIST_HEAD(&local_changed);
1046                 set_temp_color(node, tgt_col, &local_changed);
1047                 DBG((dbg, LEVEL_4, "\tTemporary setting %+F to color %d\n", node->irn, tgt_col));
1048
1049                 /* try to color all interfering neighbours with current color forbidden */
1050                 for (j = 0; j < node->n_neighs; ++j) {
1051                         co_mst_irn_t *nn;
1052                         ir_node      *neigh;
1053
1054                         neigh = node->int_neighs[j];
1055
1056                         if (arch_irn_is_ignore(neigh))
1057                                 continue;
1058
1059                         nn = get_co_mst_irn(env, neigh);
1060                         DB((dbg, LEVEL_4, "\tHandling neighbour %+F, at position %d (fixed: %d, tmp_col: %d, col: %d)\n",
1061                                 neigh, j, nn->fixed, nn->tmp_col, nn->col));
1062
1063                         /*
1064                                 Try to change the color of the neighbor and record all nodes which
1065                                 get changed in the tmp list. Add this list to the "changed" list for
1066                                 that color. If we did not succeed to change the color of the neighbor,
1067                                 we bail out and try the next color.
1068                         */
1069                         if (get_mst_irn_col(nn) == tgt_col) {
1070                                 /* try to color neighbour with tgt_col forbidden */
1071                                 neigh_ok = change_node_color_excluded(env, nn, tgt_col, &local_changed, depth + 1, max_depth, trip);
1072
1073                                 if (!neigh_ok)
1074                                         break;
1075                         }
1076                 }
1077
1078                 /*
1079                         We managed to assign the target color to all neighbors, so from the perspective
1080                         of the current node, every thing was ok and we can return safely.
1081                 */
1082                 if (neigh_ok) {
1083                         /* append the local_changed ones to global ones */
1084                         list_splice(&local_changed, changed);
1085                         return 1;
1086                 }
1087                 else {
1088                         /* coloring of neighbours failed, so we try next color */
1089                         reject_coloring(&local_changed);
1090                 }
1091         }
1092
1093         DBG((dbg, LEVEL_4, "\tAll colors failed\n"));
1094         return 0;
1095 }
1096
1097 /**
1098  * Tries to bring node @p node and all its neighbours to color @p tgt_col.
1099  * @return 1 if color @p col could be applied, 0 otherwise
1100  */
1101 static int change_node_color(co_mst_env_t *env, co_mst_irn_t *node, int tgt_col, struct list_head *changed)
1102 {
1103         int col = get_mst_irn_col(node);
1104
1105         /* if node already has the target color -> good, temporary fix it */
1106         if (col == tgt_col) {
1107                 DBG((dbg, LEVEL_4, "\t\tCNC: %+F has already color %d, fix temporary\n", node->irn, tgt_col));
1108                 if (is_loose(node))
1109                         set_temp_color(node, tgt_col, changed);
1110                 return 1;
1111         }
1112
1113         /*
1114                 Node has not yet a fixed color and target color is admissible
1115                 -> try to recolor node and its affinity neighbours
1116         */
1117         if (is_loose(node) && bitset_is_set(node->adm_colors, tgt_col)) {
1118                 col_cost_t *costs = env->single_cols[tgt_col];
1119                 int res, max_depth, trip;
1120
1121                 max_depth = 0;
1122                 trip      = 0;
1123
1124                 DBG((dbg, LEVEL_4, "\t\tCNC: Attempt to recolor %+F ===>>\n", node->irn));
1125                 res = recolor_nodes(env, node, costs, changed, 0, &max_depth, &trip);
1126                 DBG((dbg, LEVEL_4, "\t\tCNC: <<=== Recoloring of %+F %s\n", node->irn, res ? "succeeded" : "failed"));
1127                 stat_ev_int("heur4_recolor_depth_max", max_depth);
1128                 stat_ev_int("heur4_recolor_trip", trip);
1129
1130
1131                 return res;
1132         }
1133
1134 #ifdef DEBUG_libfirm
1135                 if (firm_dbg_get_mask(dbg) & LEVEL_4) {
1136                         if (!is_loose(node))
1137                                 DB((dbg, LEVEL_4, "\t\tCNC: %+F has already fixed color %d\n", node->irn, col));
1138                         else {
1139                                 DB((dbg, LEVEL_4, "\t\tCNC: color %d not admissible for %+F (", tgt_col, node->irn));
1140                                 dbg_admissible_colors(env, node);
1141                                 DB((dbg, LEVEL_4, ")\n"));
1142                         }
1143                 }
1144 #endif
1145
1146         return 0;
1147 }
1148
1149 /**
1150  * Tries to color an affinity chunk (or at least a part of it).
1151  * Inserts uncolored parts of the chunk as a new chunk into the priority queue.
1152  */
1153 static void color_aff_chunk(co_mst_env_t *env, aff_chunk_t *c)
1154 {
1155         aff_chunk_t *best_chunk   = NULL;
1156         int         n_nodes       = ARR_LEN(c->n);
1157         int         best_color    = -1;
1158         int         n_int_chunks  = 0;
1159         waitq       *tmp_chunks   = new_waitq();
1160         waitq       *best_starts  = NULL;
1161         col_cost_t  *order        = ALLOCANZ(col_cost_t, env->n_regs);
1162         bitset_t    *visited;
1163         int         i;
1164         size_t      idx;
1165         size_t      len;
1166         size_t      nidx;
1167         size_t      pos;
1168         struct list_head changed;
1169
1170         DB((dbg, LEVEL_2, "fragmentizing chunk #%u", c->id));
1171         DBG_AFF_CHUNK(env, LEVEL_2, c);
1172         DB((dbg, LEVEL_2, "\n"));
1173
1174         stat_ev_ctx_push_fmt("heur4_color_chunk", "%u", c->id);
1175
1176         ++env->chunk_visited;
1177
1178         /* compute color preference */
1179         for (pos = 0, len = ARR_LEN(c->interfere); pos < len; ++pos) {
1180                 const ir_node *n = c->interfere[pos];
1181                 co_mst_irn_t *node = get_co_mst_irn(env, n);
1182                 aff_chunk_t *chunk = node->chunk;
1183
1184                 if (is_loose(node) && chunk && chunk->visited < env->chunk_visited) {
1185                         assert(!chunk->deleted);
1186                         chunk->visited = env->chunk_visited;
1187                         ++n_int_chunks;
1188
1189                         aff_chunk_assure_weight(env, chunk);
1190                         for (i = 0; i < env->n_regs; ++i)
1191                                 order[i].cost += chunk->color_affinity[i].cost;
1192                 }
1193         }
1194
1195         for (i = 0; i < env->n_regs; ++i) {
1196                 real_t dislike = n_int_chunks > 0 ? REAL(1.0) - order[i].cost / n_int_chunks : REAL(0.0);
1197                 order[i].col  = i;
1198                 order[i].cost = (REAL(1.0) - dislike_influence) * c->color_affinity[i].cost + dislike_influence * dislike;
1199         }
1200
1201         qsort(order, env->n_regs, sizeof(order[0]), cmp_col_cost_gt);
1202
1203         DBG_COL_COST(env, LEVEL_2, order);
1204         DB((dbg, LEVEL_2, "\n"));
1205
1206         /* check which color is the "best" for the given chunk.
1207          * if we found a color which was ok for all nodes, we take it
1208          * and do not look further. (see did_all flag usage below.)
1209          * If we have many colors which fit all nodes it is hard to decide
1210          * which one to take anyway.
1211          * TODO Sebastian: Perhaps we should at all nodes and figure out
1212          * a suitable color using costs as done above (determine_color_costs).
1213          */
1214         for (i = 0; i < env->n_regs; ++i) {
1215                 int         col = order[i].col;
1216                 waitq       *good_starts;
1217                 aff_chunk_t *local_best;
1218                 int          n_succeeded;
1219
1220                 /* skip ignore colors */
1221                 if (!bitset_is_set(env->allocatable_regs, col))
1222                         continue;
1223
1224                 DB((dbg, LEVEL_2, "\ttrying color %d\n", col));
1225
1226                 n_succeeded = 0;
1227                 good_starts = new_waitq();
1228
1229                 /* try to bring all nodes of given chunk to the current color. */
1230                 for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
1231                         const ir_node   *irn  = c->n[idx];
1232                         co_mst_irn_t    *node = get_co_mst_irn(env, irn);
1233                         int              good;
1234
1235                         assert(! node->fixed && "Node must not have a fixed color.");
1236                         DB((dbg, LEVEL_4, "\t\tBringing %+F from color %d to color %d ...\n", irn, node->col, col));
1237
1238                         /*
1239                                 The order of the colored nodes is important, so we record the successfully
1240                                 colored ones in the order they appeared.
1241                         */
1242                         INIT_LIST_HEAD(&changed);
1243                         stat_ev_tim_push();
1244                         good = change_node_color(env, node, col, &changed);
1245                         stat_ev_tim_pop("heur4_recolor");
1246                         if (good) {
1247                                 waitq_put(good_starts, node);
1248                                 materialize_coloring(&changed);
1249                                 node->fixed = 1;
1250                         }
1251
1252                         else
1253                                 reject_coloring(&changed);
1254
1255                         n_succeeded += good;
1256                         DB((dbg, LEVEL_4, "\t\t... %+F attempt from %d to %d %s\n", irn, node->col, col, good ? "succeeded" : "failed"));
1257                 }
1258
1259                 /* unfix all nodes */
1260                 for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
1261                         co_mst_irn_t *node = get_co_mst_irn(env, c->n[idx]);
1262                         node->fixed = 0;
1263                 }
1264
1265                 /* try next color when failed */
1266                 if (n_succeeded == 0) {
1267                         del_waitq(good_starts);
1268                         continue;
1269                 }
1270
1271                 /* fragment the chunk according to the coloring */
1272                 local_best = fragment_chunk(env, col, c, tmp_chunks);
1273
1274                 /* search the best of the good list
1275                    and make it the new best if it is better than the current */
1276                 if (local_best) {
1277                         aff_chunk_assure_weight(env, local_best);
1278
1279                         DB((dbg, LEVEL_3, "\t\tlocal best chunk (id %u) for color %d: ", local_best->id, col));
1280                         DBG_AFF_CHUNK(env, LEVEL_3, local_best);
1281
1282                         if (! best_chunk || best_chunk->weight < local_best->weight) {
1283                                 best_chunk = local_best;
1284                                 best_color = col;
1285                                 if (best_starts)
1286                                         del_waitq(best_starts);
1287                                 best_starts = good_starts;
1288                                 DB((dbg, LEVEL_3, "\n\t\t... setting global best chunk (id %u), color %d\n", best_chunk->id, best_color));
1289                         } else {
1290                                 DB((dbg, LEVEL_3, "\n\t\t... omitting, global best is better\n"));
1291                                 del_waitq(good_starts);
1292                         }
1293                 }
1294                 else {
1295                         del_waitq(good_starts);
1296                 }
1297
1298                 /* if all nodes were recolored, bail out */
1299                 if (n_succeeded == n_nodes)
1300                         break;
1301         }
1302
1303         stat_ev_int("heur4_colors_tried", i);
1304
1305         /* free all intermediate created chunks except best one */
1306         while (! waitq_empty(tmp_chunks)) {
1307                 aff_chunk_t *tmp = (aff_chunk_t*)waitq_get(tmp_chunks);
1308                 if (tmp != best_chunk)
1309                         delete_aff_chunk(tmp);
1310         }
1311         del_waitq(tmp_chunks);
1312
1313         /* return if coloring failed */
1314         if (! best_chunk) {
1315                 if (best_starts)
1316                         del_waitq(best_starts);
1317                 return;
1318         }
1319
1320         DB((dbg, LEVEL_2, "\tbest chunk #%u ", best_chunk->id));
1321         DBG_AFF_CHUNK(env, LEVEL_2, best_chunk);
1322         DB((dbg, LEVEL_2, "using color %d\n", best_color));
1323
1324         for (idx = 0, len = ARR_LEN(best_chunk->n); idx < len; ++idx) {
1325                 const ir_node *irn  = best_chunk->n[idx];
1326                 co_mst_irn_t  *node = get_co_mst_irn(env, irn);
1327                 int res;
1328
1329                 /* bring the node to the color. */
1330                 DB((dbg, LEVEL_4, "\tManifesting color %d for %+F, chunk #%u\n", best_color, node->irn, best_chunk->id));
1331                 INIT_LIST_HEAD(&changed);
1332                 stat_ev_tim_push();
1333                 res = change_node_color(env, node, best_color, &changed);
1334                 stat_ev_tim_pop("heur4_recolor");
1335                 if (res) {
1336                         materialize_coloring(&changed);
1337                         node->fixed = 1;
1338                 }
1339                 assert(list_empty(&changed));
1340         }
1341
1342         /* remove the nodes in best chunk from original chunk */
1343         len = ARR_LEN(best_chunk->n);
1344         for (idx = 0; idx < len; ++idx) {
1345                 const ir_node *irn = best_chunk->n[idx];
1346                 int pos = nodes_bsearch(c->n, irn);
1347
1348                 if (pos > 0)
1349                         c->n[pos] = NULL;
1350         }
1351         len = ARR_LEN(c->n);
1352         for (idx = nidx = 0; idx < len; ++idx) {
1353                 const ir_node *irn = c->n[idx];
1354
1355                 if (irn != NULL) {
1356                         c->n[nidx++] = irn;
1357                 }
1358         }
1359         ARR_SHRINKLEN(c->n, nidx);
1360
1361
1362         /* we have to get the nodes back into the original chunk because they are scattered over temporary chunks */
1363         for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
1364                 const ir_node *n  = c->n[idx];
1365                 co_mst_irn_t  *nn = get_co_mst_irn(env, n);
1366                 nn->chunk = c;
1367         }
1368
1369         /* fragment the remaining chunk */
1370         visited = bitset_malloc(get_irg_last_idx(env->co->irg));
1371         for (idx = 0, len = ARR_LEN(best_chunk->n); idx < len; ++idx)
1372                 bitset_set(visited, get_irn_idx(best_chunk->n[idx]));
1373
1374         for (idx = 0, len = ARR_LEN(c->n); idx < len; ++idx) {
1375                 const ir_node *irn = c->n[idx];
1376                 if (! bitset_is_set(visited, get_irn_idx(irn))) {
1377                         aff_chunk_t  *new_chunk = new_aff_chunk(env);
1378                         co_mst_irn_t *node      = get_co_mst_irn(env, irn);
1379
1380                         expand_chunk_from(env, node, visited, new_chunk, c, decider_always_yes, 0);
1381                         aff_chunk_assure_weight(env, new_chunk);
1382                         pqueue_put(env->chunks, new_chunk, new_chunk->weight);
1383                 }
1384         }
1385
1386         for (idx = 0, len = ARR_LEN(best_chunk->n); idx < len; ++idx) {
1387                 const ir_node *n  = best_chunk->n[idx];
1388                 co_mst_irn_t  *nn = get_co_mst_irn(env, n);
1389                 nn->chunk = NULL;
1390         }
1391
1392         /* clear obsolete chunks and free some memory */
1393         delete_aff_chunk(best_chunk);
1394         bitset_free(visited);
1395         if (best_starts)
1396                 del_waitq(best_starts);
1397
1398         stat_ev_ctx_pop("heur4_color_chunk");
1399 }
1400
1401 /**
1402  * Main driver for mst safe coalescing algorithm.
1403  */
1404 static int co_solve_heuristic_mst(copy_opt_t *co)
1405 {
1406         last_chunk_id = 0;
1407
1408         stat_ev_tim_push();
1409
1410         /* init phase */
1411         co_mst_env_t mst_env;
1412         ir_nodemap_init(&mst_env.map, co->irg);
1413         obstack_init(&mst_env.obst);
1414
1415         unsigned const n_regs = co->cls->n_regs;
1416
1417         mst_env.n_regs           = n_regs;
1418         mst_env.chunks           = new_pqueue();
1419         mst_env.co               = co;
1420         mst_env.allocatable_regs = co->cenv->allocatable_regs;
1421         mst_env.ifg              = co->cenv->ifg;
1422         INIT_LIST_HEAD(&mst_env.chunklist);
1423         mst_env.chunk_visited    = 0;
1424         mst_env.single_cols      = OALLOCN(&mst_env.obst, col_cost_t*, n_regs);
1425
1426         for (unsigned i = 0; i < n_regs; ++i) {
1427                 col_cost_t *vec = OALLOCN(&mst_env.obst, col_cost_t, n_regs);
1428
1429                 mst_env.single_cols[i] = vec;
1430                 for (unsigned j = 0; j < n_regs; ++j) {
1431                         vec[j].col  = j;
1432                         vec[j].cost = REAL(0.0);
1433                 }
1434                 vec[i].col  = 0;
1435                 vec[0].col  = i;
1436                 vec[0].cost = REAL(1.0);
1437         }
1438
1439         DBG((dbg, LEVEL_1, "==== Coloring %+F, class %s ====\n", co->irg, co->cls->name));
1440
1441         /* build affinity chunks */
1442         stat_ev_tim_push();
1443         build_affinity_chunks(&mst_env);
1444         stat_ev_tim_pop("heur4_initial_chunk");
1445
1446         /* color chunks as long as there are some */
1447         while (! pqueue_empty(mst_env.chunks)) {
1448                 aff_chunk_t *chunk = (aff_chunk_t*)pqueue_pop_front(mst_env.chunks);
1449
1450                 color_aff_chunk(&mst_env, chunk);
1451                 DB((dbg, LEVEL_4, "<<<====== Coloring chunk (%u) done\n", chunk->id));
1452                 delete_aff_chunk(chunk);
1453         }
1454
1455         /* apply coloring */
1456         for (size_t pn = 0; pn < ARR_LEN(mst_env.map.data); ++pn) {
1457                 co_mst_irn_t *mirn = (co_mst_irn_t*)mst_env.map.data[pn];
1458                 const arch_register_t *reg;
1459                 if (mirn == NULL)
1460                         continue;
1461                 ir_node *const irn = get_idx_irn(co->irg, pn);
1462                 if (arch_irn_is_ignore(irn))
1463                         continue;
1464
1465                 /* skip nodes where color hasn't changed */
1466                 if (mirn->init_col == mirn->col)
1467                         continue;
1468
1469                 reg = arch_register_for_index(co->cls, mirn->col);
1470                 arch_set_irn_register(irn, reg);
1471                 DB((dbg, LEVEL_1, "%+F set color from %d to %d\n", irn, mirn->init_col, mirn->col));
1472         }
1473
1474         /* free allocated memory */
1475         del_pqueue(mst_env.chunks);
1476         obstack_free(&mst_env.obst, NULL);
1477         ir_nodemap_destroy(&mst_env.map);
1478
1479         stat_ev_tim_pop("heur4_total");
1480
1481         return 0;
1482 }
1483
1484 static const lc_opt_table_entry_t options[] = {
1485         LC_OPT_ENT_INT      ("limit", "limit recoloring",  &recolor_limit),
1486         LC_OPT_ENT_DBL      ("di",    "dislike influence", &dislike_influence),
1487         LC_OPT_LAST
1488 };
1489
1490 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyheur4)
1491 void be_init_copyheur4(void)
1492 {
1493         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
1494         lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
1495         lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
1496         lc_opt_entry_t *co_grp = lc_opt_get_grp(chordal_grp, "co");
1497         lc_opt_entry_t *heur4_grp = lc_opt_get_grp(co_grp, "heur4");
1498
1499         static co_algo_info copyheur = {
1500                 co_solve_heuristic_mst, 0
1501         };
1502
1503         lc_opt_add_table(heur4_grp, options);
1504         be_register_copyopt("heur4", &copyheur);
1505
1506         FIRM_DBG_REGISTER(dbg, "firm.be.co.heur4");
1507 }