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