dcc363eee750a6c04d273096ffefc0b60f3d0789
[libfirm] / ir / be / becopyheur2.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       More experiments on coalescing.
23  * @author      Sebastian Hack
24  * @date        14.04.2006
25  * @version     $Id$
26  */
27 #ifdef HAVE_CONFIG_H
28 #include "config.h"
29 #endif
30
31 #include <stdlib.h>
32 #include <limits.h>
33
34 #include "list.h"
35 #include "pdeq.h"
36 #include "bitset.h"
37 #include "raw_bitset.h"
38
39 #include "debug.h"
40 #include "bitfiddle.h"
41
42 #include "irphase_t.h"
43 #include "irgraph_t.h"
44 #include "irnode_t.h"
45 #include "irprintf.h"
46 #include "irtools.h"
47
48 #include "bemodule.h"
49 #include "beabi.h"
50 #include "benode_t.h"
51 #include "becopyopt.h"
52 #include "becopyopt_t.h"
53 #include "bechordal_t.h"
54 #include "beirg_t.h"
55
56 #define DUMP_BEFORE 1
57 #define DUMP_AFTER  2
58 #define DUMP_CLOUD  4
59 #define DUMP_ALL    2 * DUMP_CLOUD - 1
60
61 static unsigned dump_flags      = 0;
62 static int      subtree_iter    = 4;
63 static int      max_depth       = 20;
64 static double   constr_factor   = 0.9;
65
66 #ifdef WITH_LIBCORE
67 #include <libcore/lc_opts.h>
68 #include <libcore/lc_opts_enum.h>
69
70 /* Options using libcore */
71 static const lc_opt_enum_mask_items_t dump_items[] = {
72         { "before",  DUMP_BEFORE },
73         { "after",   DUMP_AFTER  },
74         { "cloud",   DUMP_CLOUD  },
75         { "all",     DUMP_ALL    },
76         { NULL,      0 }
77 };
78
79 static lc_opt_enum_mask_var_t dump_var = {
80         &dump_flags, dump_items
81 };
82
83 static const lc_opt_table_entry_t options[] = {
84         LC_OPT_ENT_ENUM_MASK("dump", "dump ifg cloud",                                         &dump_var),
85         LC_OPT_ENT_INT      ("iter", "iterations for subtree nodes",                           &subtree_iter),
86         LC_OPT_ENT_DBL      ("cf",   "factor of constraint importance (between 0.0 and 1.0)",  &constr_factor),
87         LC_OPT_ENT_INT      ("max",  "maximum recursion depth",                                &max_depth),
88         LC_OPT_LAST
89 };
90 #endif /* WITH_LIBCORE */
91
92 void be_init_copyheur2(void)
93 {
94 #ifdef WITH_LIBCORE
95         lc_opt_entry_t *be_grp = lc_opt_get_grp(firm_opt_get_root(), "be");
96         lc_opt_entry_t *ra_grp = lc_opt_get_grp(be_grp, "ra");
97         lc_opt_entry_t *chordal_grp = lc_opt_get_grp(ra_grp, "chordal");
98         lc_opt_entry_t *co2_grp = lc_opt_get_grp(chordal_grp, "co2");
99
100         lc_opt_add_table(co2_grp, options);
101 #endif
102 }
103
104 BE_REGISTER_MODULE_CONSTRUCTOR(be_init_copyheur2);
105
106 /*
107   ____  _             _
108  / ___|| |_ __ _ _ __| |_
109  \___ \| __/ _` | '__| __|
110   ___) | || (_| | |  | |_
111  |____/ \__\__,_|_|   \__|
112
113 */
114
115 #define INFEASIBLE(cost) ((cost) == INT_MAX)
116
117 static be_ifg_dump_dot_cb_t ifg_dot_cb;
118
119 typedef unsigned col_t;
120
121 typedef struct _co2_irn_t       co2_irn_t;
122 typedef struct _co2_cloud_t     co2_cloud_t;
123 typedef struct _co2_cloud_irn_t co2_cloud_irn_t;
124
125 typedef struct {
126         col_t col;
127         int costs;
128 } col_cost_pair_t;
129
130 typedef struct {
131         ir_phase     ph;
132         copy_opt_t *co;
133         bitset_t   *ignore_regs;
134         co2_irn_t  *touched;
135         int         visited;
136         int         n_regs;
137         struct list_head cloud_head;
138         DEBUG_ONLY(firm_dbg_module_t *dbg;)
139 } co2_t;
140
141 struct _co2_irn_t {
142         ir_node         *irn;
143         affinity_node_t *aff;
144         co2_irn_t       *touched_next;
145         col_t            tmp_col;
146         col_t            orig_col;
147         int                              last_color_change;
148         bitset_t        *adm_cache;
149         unsigned         fixed          : 1;
150         unsigned         tmp_fixed      : 1;
151         unsigned         is_constrained : 1;
152         struct list_head changed_list;
153 };
154
155 struct _co2_cloud_irn_t {
156         struct _co2_irn_t  inh;
157         co2_cloud_t       *cloud;
158         int                visited;
159         int                index;
160         co2_cloud_irn_t   *mst_parent;
161         int                mst_costs;
162         int                mst_n_childs;
163         co2_cloud_irn_t  **mst_childs;
164         int               *col_costs;
165         int                costs;
166         int               *fronts;
167         int               *color_badness;
168         col_cost_pair_t   *tmp_coloring;
169         struct list_head   cloud_list;
170         struct list_head   mst_list;
171 };
172
173 struct _co2_cloud_t {
174         co2_t            *env;
175         struct obstack    obst;
176         int               costs;
177         int               mst_costs;
178         int               inevit;
179         int               best_costs;
180         int               n_memb;
181         int               n_constr;
182         int               max_degree;
183         int                           ticks;
184         double            freedom;
185         co2_cloud_irn_t  *master;
186         co2_cloud_irn_t  *mst_root;
187         co2_cloud_irn_t **seq;
188         struct list_head  members_head;
189         struct list_head  list;
190 };
191
192 typedef struct {
193         co2_cloud_irn_t *src, *tgt;
194         int costs;
195 } edge_t;
196
197 #define FRONT_BASE(ci,col)  ((ci)->fronts + col * (ci)->mst_n_childs)
198
199 #define get_co2_irn(co2, irn)         ((co2_irn_t *)       phase_get_or_set_irn_data(&co2->ph, irn))
200 #define get_co2_cloud_irn(co2, irn)   ((co2_cloud_irn_t *) phase_get_or_set_irn_data(&co2->ph, irn))
201
202 static void *co2_irn_init(ir_phase *ph, ir_node *irn, void *data)
203 {
204         co2_t *env         = (co2_t *) ph;
205         affinity_node_t *a = get_affinity_info(env->co, irn);
206         size_t size        = a ? sizeof(co2_cloud_irn_t) : sizeof(co2_irn_t);
207         co2_irn_t *ci      = data ? data : phase_alloc(ph, size);
208
209         memset(ci, 0, size);
210         INIT_LIST_HEAD(&ci->changed_list);
211         ci->touched_next = env->touched;
212         ci->orig_col     = get_irn_col(env->co, irn);
213         env->touched     = ci;
214         ci->irn          = irn;
215         ci->aff          = a;
216
217         if(a) {
218                 co2_cloud_irn_t *cci = (co2_cloud_irn_t *) ci;
219                 INIT_LIST_HEAD(&cci->cloud_list);
220                 cci->mst_parent   = cci;
221         }
222
223         return ci;
224 }
225
226 #define CLOUD_WEIGHT(c) ((1 - constr_factor) * (c)->costs + constr_factor * (c)->freedom)
227
228 static int cmp_clouds_gt(const void *a, const void *b)
229 {
230         const co2_cloud_t * const *p = a;
231         const co2_cloud_t * const *q = b;
232         double c = CLOUD_WEIGHT(*p);
233         double d = CLOUD_WEIGHT(*q);
234         return QSORT_CMP(d, c);
235 }
236
237 /**
238  * An order on color/costs pairs.
239  * If the costs are equal, we use the color as a kind of normalization.
240  */
241 static int col_cost_pair_lt(const void *a, const void *b)
242 {
243         const col_cost_pair_t *p = a;
244         const col_cost_pair_t *q = b;
245         int c = p->costs;
246         int d = q->costs;
247         return QSORT_CMP(c, d);
248 }
249
250 int cmp_edges(const void *a, const void *b)
251 {
252         const edge_t *p = a;
253         const edge_t *q = b;
254         return QSORT_CMP(q->costs, p->costs);
255 }
256
257 static col_t get_col(co2_t *env, ir_node *irn)
258 {
259         co2_irn_t *ci = get_co2_irn(env, irn);
260         return ci->tmp_fixed ? ci->tmp_col : ci->orig_col;
261 }
262
263 static INLINE int color_is_fix(co2_t *env, ir_node *irn)
264 {
265         co2_irn_t *ci = get_co2_irn(env, irn);
266         return ci->fixed || ci->tmp_fixed;
267 }
268
269 static INLINE bitset_t *get_adm(co2_t *env, co2_irn_t *ci)
270 {
271         if(ci->adm_cache == NULL) {
272                 const arch_register_req_t *req;
273                 ci->adm_cache = bitset_obstack_alloc(phase_obst(&env->ph), env->n_regs);
274                 req = arch_get_register_req(env->co->aenv, ci->irn, BE_OUT_POS(0));
275
276                 if(arch_register_req_is(req, limited)) {
277                         int i, n;
278
279                         n = env->n_regs;
280                         for(i = 0; i < n; ++i) {
281                                 if(rbitset_is_set(req->limited, i))
282                                         bitset_set(ci->adm_cache, i);
283                         }
284                         ci->is_constrained = 1;
285                 } else {
286                         bitset_copy(ci->adm_cache, env->ignore_regs);
287                         bitset_flip_all(ci->adm_cache);
288                 }
289         }
290
291         return ci->adm_cache;
292 }
293
294 static INLINE bitset_t *admissible_colors(co2_t *env, co2_irn_t *ci, bitset_t *bs)
295 {
296         bitset_copy(bs, get_adm(env, ci));
297         return bs;
298 }
299
300 static INLINE int is_color_admissible(co2_t *env, co2_irn_t *ci, col_t col)
301 {
302         bitset_t *bs = get_adm(env, ci);
303         return bitset_is_set(bs, col);
304 }
305
306 static INLINE int is_constrained(co2_t *env, co2_irn_t *ci)
307 {
308         if(!ci->adm_cache)
309                 get_adm(env, ci);
310         return ci->is_constrained;
311 }
312
313 static void incur_constraint_costs(co2_t *env, ir_node *irn, col_cost_pair_t *col_costs, int costs)
314 {
315         const arch_register_req_t *req;
316
317         req = arch_get_register_req(env->co->aenv, irn, BE_OUT_POS(0));
318
319         if (arch_register_req_is(req, limited)) {
320                 unsigned n_regs   = env->co->cls->n_regs;
321                 unsigned n_constr = 0;
322                 unsigned i;
323
324                 n_constr = rbitset_popcnt(req->limited, n_regs);
325                 for (i = 0; i < n_regs; ++i) {
326                         if (rbitset_is_set(req->limited, i)) {
327                                 col_costs[i].costs = add_saturated(col_costs[i].costs, costs / n_constr);
328                         }
329                 }
330         }
331 }
332
333 /**
334  * Determine costs which shall indicate how cheap/expensive it is to try
335  * to assign a node some color.
336  * The costs are computed for all colors. INT_MAX means that it is impossible
337  * to give the node that specific color.
338  *
339  * @param env       The co2 this pointer.
340  * @param irn       The node.
341  * @param col_costs An array of colors x costs where the costs are written to.
342  */
343 static void determine_color_costs(co2_t *env, co2_irn_t *ci, col_cost_pair_t *col_costs)
344 {
345         ir_node *irn       = ci->irn;
346         be_ifg_t *ifg      = env->co->cenv->ifg;
347         int n_regs         = env->co->cls->n_regs;
348         bitset_t *forb     = bitset_alloca(n_regs);
349         affinity_node_t *a = ci->aff;
350
351         bitset_pos_t elm;
352         ir_node *pos;
353         void *it;
354         int i;
355
356         /* Put all forbidden colors into the aux bitset. */
357         admissible_colors(env, ci, forb);
358         bitset_flip_all(forb);
359
360         for(i = 0; i < n_regs; ++i) {
361                 col_costs[i].col   = i;
362                 col_costs[i].costs = 0;
363         }
364
365         if(a) {
366                 neighb_t *n;
367
368                 co_gs_foreach_neighb(a, n) {
369                         if(color_is_fix(env, n->irn)) {
370                                 col_t col = get_col(env, n->irn);
371                                 col_costs[col].costs = add_saturated(col_costs[col].costs, -n->costs * 128);
372                         }
373
374                         incur_constraint_costs(env, n->irn, col_costs, -n->costs);
375                 }
376         }
377
378         it = be_ifg_neighbours_iter_alloca(ifg);
379         be_ifg_foreach_neighbour(ifg, it, irn, pos) {
380                 col_t col = get_col(env, pos);
381                 if(color_is_fix(env, pos)) {
382                         col_costs[col].costs  = INT_MAX;
383                 }
384                 else {
385                         incur_constraint_costs(env, pos, col_costs, INT_MAX);
386                         col_costs[col].costs = add_saturated(col_costs[col].costs, 8 * be_ifg_degree(ifg, pos));
387                 }
388         }
389         be_ifg_neighbours_break(ifg, it);
390
391         /* Set the costs to infinity for each color which is not allowed at this node. */
392         bitset_foreach(forb, elm) {
393                 col_costs[elm].costs  = INT_MAX;
394         }
395
396 }
397
398 static void single_color_cost(co2_t *env, co2_irn_t *ci, col_t col, col_cost_pair_t *seq)
399 {
400         int n_regs = env->co->cls->n_regs;
401         int i;
402
403         for(i = 0; i < n_regs; ++i) {
404                 seq[i].col   = i;
405                 seq[i].costs = INT_MAX;
406         }
407
408         assert(is_color_admissible(env, ci, col));
409         seq[col].col = 0;
410         seq[0].col   = col;
411         seq[0].costs = 0;
412 }
413
414 static void reject_coloring(struct list_head *h)
415 {
416         co2_irn_t *pos;
417
418         list_for_each_entry(co2_irn_t, pos, h, changed_list)
419                 pos->tmp_fixed = 0;
420 }
421
422 static void materialize_coloring(struct list_head *h)
423 {
424         co2_irn_t *pos;
425
426         list_for_each_entry(co2_irn_t, pos, h, changed_list) {
427                 pos->orig_col  = pos->tmp_col;
428                 pos->tmp_fixed = 0;
429         }
430 }
431
432 static int change_color_not(co2_t *env, ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth);
433
434 static int recolor(co2_t *env, ir_node *irn, col_cost_pair_t *col_list, struct list_head *parent_changed, int depth)
435 {
436         int n_regs         = env->co->cls->n_regs;
437         be_ifg_t *ifg      = env->co->cenv->ifg;
438         co2_irn_t *ci      = get_co2_irn(env, irn);
439         int res            = 0;
440
441         int i;
442
443         if(depth >= max_depth)
444           return 0;
445
446         for(i = 0; i < n_regs; ++i) {
447                 col_t tgt_col  = col_list[i].col;
448                 unsigned costs = col_list[i].costs;
449                 int neigh_ok   = 1;
450
451                 struct list_head changed;
452                 ir_node *n;
453                 void *it;
454
455                 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying color %d(%d) on %+F\n", depth, tgt_col, costs, irn));
456
457                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
458                 if(INFEASIBLE(costs)) {
459                         DB((env->dbg, LEVEL_4, "\t\t%2{firm:indent}color %d infeasible\n", depth, tgt_col));
460                         ci->tmp_fixed = 0;
461                         return 0;
462                 }
463
464                 /* Set the new color of the node and mark the node as temporarily fixed. */
465                 ci->tmp_col     = tgt_col;
466                 ci->tmp_fixed   = 1;
467
468                 /*
469                 If that color has costs > 0, there's at least one neighbor having that color,
470                 so we will try to change the neighbors' colors, too.
471                 */
472                 INIT_LIST_HEAD(&changed);
473                 list_add(&ci->changed_list, &changed);
474
475                 it = be_ifg_neighbours_iter_alloca(ifg);
476                 be_ifg_foreach_neighbour(ifg, it, irn, n) {
477
478                         /* try to re-color the neighbor if it has the target color. */
479                         if(get_col(env, n) == tgt_col) {
480                                 struct list_head tmp;
481
482                                 /*
483                                 Try to change the color of the neighbor and record all nodes which
484                                 get changed in the tmp list. Add this list to the "changed" list for
485                                 that color. If we did not succeed to change the color of the neighbor,
486                                 we bail out and try the next color.
487                                 */
488                                 INIT_LIST_HEAD(&tmp);
489                                 neigh_ok = change_color_not(env, n, tgt_col, &tmp, depth + 1);
490                                 list_splice(&tmp, &changed);
491                                 if(!neigh_ok)
492                                         break;
493                         }
494                 }
495                 be_ifg_neighbours_break(ifg, it);
496
497                 /*
498                 We managed to assign the target color to all neighbors, so from the perspective
499                 of the current node, every thing was ok and we can return safely.
500                 */
501                 if(neigh_ok) {
502                         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d(%d) was ok\n", depth, tgt_col, costs));
503                         list_splice(&changed, parent_changed);
504                         res = 1;
505                         break;
506                 }
507
508                 /*
509                 If not, that color did not succeed and we unfix all nodes we touched
510                 by traversing the changed list and setting tmp_fixed to 0 for these nodes.
511                 */
512                 else
513                         reject_coloring(&changed);
514         }
515
516         return res;
517 }
518
519 static int change_color_not(co2_t *env, ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth)
520 {
521         co2_irn_t *ci = get_co2_irn(env, irn);
522         int res       = 0;
523         col_t col     = get_col(env, irn);
524
525         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}clearing %+F(%d) of color %d\n", depth, irn, col, not_col));
526
527         /* the node does not have to forbidden color. That's fine, mark it as visited and return. */
528         if(col != not_col) {
529                 if(!ci->tmp_fixed) {
530                         ci->tmp_col     = col;
531                         ci->tmp_fixed   = 1;
532                 }
533
534                 list_add(&ci->changed_list, parent_changed);
535                 return 1;
536         }
537
538         /* The node has the color it should not have _and_ has not been visited yet. */
539         if(!color_is_fix(env, irn)) {
540                 int n_regs            = env->co->cls->n_regs;
541                 col_cost_pair_t *csts = alloca(n_regs * sizeof(csts[0]));
542
543                 /* Get the costs for giving the node a specific color. */
544                 determine_color_costs(env, ci, csts);
545
546                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
547                 csts[not_col].costs = INT_MAX;
548
549                 /* sort the colors according costs, cheapest first. */
550                 qsort(csts, n_regs, sizeof(csts[0]), col_cost_pair_lt);
551
552                 /* Try recoloring the node using the color list. */
553                 res = recolor(env, irn, csts, parent_changed, depth);
554         }
555
556         /* If we came here, everything went ok. */
557         return res;
558 }
559
560 static int change_color_single(co2_t *env, ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth)
561 {
562         co2_irn_t *ci = get_co2_irn(env, irn);
563         col_t col     = get_col(env, irn);
564         int res       = 0;
565
566         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying to set %+F(%d) to color %d\n", depth, irn, col, tgt_col));
567
568         /* the node has the wanted color. That's fine, mark it as visited and return. */
569         if(col == tgt_col) {
570                 if(!ci->tmp_fixed) {
571                         ci->tmp_col     = col;
572                         ci->tmp_fixed   = 1;
573                         list_add(&ci->changed_list, parent_changed);
574                 }
575
576                 res = 1;
577                 goto end;
578         }
579
580         if(!color_is_fix(env, irn) && is_color_admissible(env, ci, tgt_col)) {
581                 int n_regs           = env->co->cls->n_regs;
582                 col_cost_pair_t *seq = alloca(n_regs * sizeof(seq[0]));
583
584                 /* Get the costs for giving the node a specific color. */
585                 single_color_cost(env, ci, tgt_col, seq);
586
587                 /* Try recoloring the node using the color list. */
588                 res = recolor(env, irn, seq, parent_changed, depth);
589
590         }
591
592 end:
593         DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d %s for %+F\n", depth, tgt_col, res ? "was ok" : "failed", irn));
594         return res;
595 }
596
597 /**
598  * Examine the costs of the current coloring concerning a MST subtree.
599  * @param ci  The subtree root.
600  * @param col The color of @p ci.
601  * @return    The best coloring for that subtree under the assumption that @p ci has color @p col.
602  */
603 static int examine_subtree_coloring(co2_cloud_irn_t *ci, col_t col)
604 {
605         int *front = FRONT_BASE(ci, col);
606         int cost   = 0;
607         int i;
608
609         for(i = 0; i < ci->mst_n_childs; ++i) {
610                 co2_cloud_irn_t *chld = ci->mst_childs[i];
611                 col_t chld_col        = front[i];
612
613                 cost += examine_subtree_coloring(chld, chld_col);
614                 cost += col != chld_col ? chld->mst_costs : 0;
615         }
616
617         return cost;
618 }
619
620 /**
621  * Determine color badnesses of a node.
622  * Badness means that it is unlikely that the node in question can
623  * obtain a color. The higher the badness, the more unlikely it is that
624  * the node can be assigned that color.
625  * @param ci      The node.
626  * @param badness An integer array as long as there are registers.
627  * @note          The array <code>badness</code> is not cleared.
628  */
629 static void node_color_badness(co2_cloud_irn_t *ci, int *badness)
630 {
631         co2_t *env     = ci->cloud->env;
632         co2_irn_t *ir  = &ci->inh;
633         int n_regs     = env->n_regs;
634         be_ifg_t *ifg  = env->co->cenv->ifg;
635         bitset_t *bs   = bitset_alloca(n_regs);
636
637         bitset_pos_t elm;
638         ir_node *irn;
639         void *it;
640
641         admissible_colors(env, &ci->inh, bs);
642         bitset_flip_all(bs);
643         bitset_foreach(bs, elm)
644                 badness[elm] = ci->costs;
645
646         /* Use constrained/fixed interfering neighbors to influence the color badness */
647         it = be_ifg_neighbours_iter_alloca(ifg);
648         be_ifg_foreach_neighbour(ifg, it, ir->irn, irn) {
649                 co2_irn_t *ni = get_co2_irn(env, irn);
650
651                 admissible_colors(env, ni, bs);
652                 if(bitset_popcnt(bs) == 1) {
653                         bitset_pos_t c = bitset_next_set(bs, 0);
654                         badness[c] += ci->costs;
655                 }
656
657                 else if(ni->fixed) {
658                         col_t c = get_col(env, ni->irn);
659                         badness[c] += ci->costs;
660                 }
661         }
662         be_ifg_neighbours_break(ifg, it);
663 }
664
665 /**
666  * Determine the badness of a MST subtree.
667  * The badness is written into the <code>color_badness</code> array of each node and accumulated in the parents.
668  * @see node_color_badness() for a definition of badness.
669  * @param ci    The root of the subtree.
670  * @param depth Depth for debugging purposes.
671  */
672 static void determine_color_badness(co2_cloud_irn_t *ci, int depth)
673 {
674         co2_t *env     = ci->cloud->env;
675         int i, j;
676
677         node_color_badness(ci, ci->color_badness);
678
679         /* Collect the color badness for the whole subtree */
680         for(i = 0; i < ci->mst_n_childs; ++i) {
681                 co2_cloud_irn_t *child = ci->mst_childs[i];
682                 determine_color_badness(child, depth + 1);
683
684                 for(j = 0; j < env->n_regs; ++j)
685                         ci->color_badness[j] += child->color_badness[j];
686         }
687
688         for(j = 0; j < env->n_regs; ++j)
689                 DBG((env->dbg, LEVEL_2, "%2{firm:indent}%+F col %d badness %d\n", depth, ci->inh.irn, j, ci->color_badness[j]));
690 }
691
692 /**
693  * Unfix all nodes in a MST subtree.
694  */
695 static void unfix_subtree(co2_cloud_irn_t *ci)
696 {
697         int i;
698
699         ci->inh.fixed = 0;
700         for(i = 0; i < ci->mst_n_childs; ++i)
701                 unfix_subtree(ci->mst_childs[i]);
702 }
703
704 static int coalesce_top_down(co2_cloud_irn_t *ci, int child_nr, int depth)
705 {
706         co2_t *env           = ci->cloud->env;
707         col_cost_pair_t *seq = alloca(env->n_regs * sizeof(seq[0]));
708         int is_root          = ci->mst_parent == ci;
709         col_t parent_col     = is_root ? (col_t) -1 : get_col(env, ci->mst_parent->inh.irn);
710         int min_badness      = INT_MAX;
711         int best_col_costs   = INT_MAX;
712         int best_col         = -1;
713         int n_regs           = env->n_regs;
714         int n_iter           = is_root ? MIN(n_regs, subtree_iter) : 1;
715
716         struct list_head changed;
717         int ok, i, j;
718
719         for(i = 0; i < n_regs; ++i) {
720                 int badness = ci->color_badness[i];
721
722                 seq[i].col   = i;
723                 seq[i].costs = is_color_admissible(env, &ci->inh, i) ? badness : INT_MAX;
724
725                 min_badness = MIN(min_badness, badness);
726         }
727
728         /* If we are not the root and the parent's color is allowed for this node give it top prio. */
729         if(!is_root && is_color_admissible(env, &ci->inh, parent_col))
730                 seq[parent_col].costs = min_badness - 1;
731
732         /* Sort the colors. The will be processed in that ordering. */
733         qsort(seq, env->n_regs, sizeof(seq[0]), col_cost_pair_lt);
734
735         DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}starting top-down coalesce for %+F\n", depth, ci->inh.irn));
736         INIT_LIST_HEAD(&changed);
737         for(i = 0; i < (best_col < 0 ? n_regs : n_iter); ++i) {
738                 col_t col    = seq[i].col;
739                 int add_cost = !is_root && col != parent_col ? ci->mst_costs : 0;
740
741                 int subtree_costs, sum_costs;
742
743                 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}%+F trying color %d\n", depth, ci->inh.irn, col));
744
745                 unfix_subtree(ci);
746                 INIT_LIST_HEAD(&changed);
747                 ok = change_color_single(env, ci->inh.irn, col, &changed, depth);
748                 if(ok) {
749                         materialize_coloring(&changed);
750                         ci->inh.fixed = 1;
751                 }
752
753                 else
754                         continue;
755
756                 for(j = 0; j < ci->mst_n_childs; ++j) {
757                         co2_cloud_irn_t *child = ci->mst_childs[j];
758                         ok = coalesce_top_down(child, j, depth + 1) >= 0;
759                         if(ok)
760                                 child->inh.fixed = 1;
761                         else
762                                 break;
763                 }
764
765                 /* If the subtree could not be colored, we have to try another color. */
766                 if(!ok)
767                         continue;
768
769                 subtree_costs      = examine_subtree_coloring(ci, col);
770                 sum_costs          = subtree_costs + add_cost;
771                 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}-> %+F costing %d + %d is ok.\n", depth, ci->inh.irn, subtree_costs, add_cost));
772
773                 if(sum_costs < best_col_costs) {
774                         best_col           = col;
775                         best_col_costs     = sum_costs;
776                         ci->col_costs[col] = subtree_costs;
777                 }
778
779                 if(sum_costs == 0)
780                         break;
781         }
782
783         if(!is_root) {
784                 int *front = FRONT_BASE(ci->mst_parent, parent_col);
785                 front[child_nr] = best_col;
786         }
787
788         return best_col;
789 }
790
791 static void populate_cloud(co2_t *env, co2_cloud_t *cloud, affinity_node_t *a, int curr_costs)
792 {
793         be_ifg_t *ifg       = env->co->cenv->ifg;
794         co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
795         int costs           = 0;
796         neighb_t *n;
797
798         if(ci->cloud)
799                 return;
800
801         /* mark the node as visited and add it to the cloud. */
802         ci->cloud   = cloud;
803         list_add(&ci->cloud_list, &cloud->members_head);
804
805         DB((env->dbg, LEVEL_2, "\t%+F\n", ci->inh.irn));
806
807         /* determine the nodes costs */
808         co_gs_foreach_neighb(a, n) {
809                 costs += n->costs;
810                 DB((env->dbg, LEVEL_3, "\t\tneigh %+F cost %d\n", n->irn, n->costs));
811                 if(be_ifg_connected(ifg, a->irn, n->irn))
812                         cloud->inevit += n->costs;
813         }
814
815         /* add the node's cost to the total costs of the cloud. */
816         ci->costs          = costs;
817         cloud->costs      += costs;
818         cloud->n_constr   += is_constrained(env, &ci->inh);
819         cloud->freedom    += bitset_popcnt(get_adm(env, &ci->inh));
820         cloud->max_degree  = MAX(cloud->max_degree, ci->inh.aff->degree);
821         cloud->n_memb++;
822
823         /* If this is the heaviest node in the cloud, set it as the cloud's master. */
824         if(costs >= curr_costs) {
825                 curr_costs    = costs;
826                 cloud->master = ci;
827         }
828
829         /* add all the neighbors of the node to the cloud. */
830         co_gs_foreach_neighb(a, n) {
831                 affinity_node_t *an = get_affinity_info(env->co, n->irn);
832                 assert(an);
833                 populate_cloud(env, cloud, an, curr_costs);
834         }
835 }
836
837 static co2_cloud_t *new_cloud(co2_t *env, affinity_node_t *a)
838 {
839         co2_cloud_t *cloud = phase_alloc(&env->ph, sizeof(cloud[0]));
840         co2_cloud_irn_t *ci;
841         int i;
842
843         DBG((env->dbg, LEVEL_2, "new cloud with %+F\n", a->irn));
844         memset(cloud, 0, sizeof(cloud[0]));
845         INIT_LIST_HEAD(&cloud->members_head);
846         INIT_LIST_HEAD(&cloud->list);
847         list_add(&cloud->list, &env->cloud_head);
848         cloud->best_costs = INT_MAX;
849         cloud->env = env;
850         env->visited++;
851         populate_cloud(env, cloud, a, 0);
852         cloud->freedom = (cloud->n_memb * env->n_regs) / cloud->freedom;
853
854         /* Also allocate space for the node sequence and compute that sequence. */
855         cloud->seq    = phase_alloc(&env->ph, cloud->n_memb * sizeof(cloud->seq[0]));
856
857         i = 0;
858         list_for_each_entry(co2_cloud_irn_t, ci, &cloud->members_head, cloud_list) {
859                 ci->index       = i;
860                 cloud->seq[i++] = ci;
861         }
862         DBG((env->dbg, LEVEL_2, "cloud cost %d, freedom %f\n", cloud->costs, cloud->freedom));
863
864         return cloud;
865 }
866
867 static void apply_coloring(co2_cloud_irn_t *ci, col_t col, int depth)
868 {
869         ir_node *irn = ci->inh.irn;
870         int *front   = FRONT_BASE(ci, col);
871         int i, ok;
872         struct list_head changed;
873
874         INIT_LIST_HEAD(&changed);
875
876         DBG((ci->cloud->env->dbg, LEVEL_2, "%2{firm:indent}setting %+F to %d\n", depth, irn, col));
877         ok = change_color_single(ci->cloud->env, irn, col, &changed, depth);
878         // assert(ok && "Color changing may not fail while committing the coloring");
879         materialize_coloring(&changed);
880
881         for(i = 0; i < ci->mst_n_childs; ++i) {
882                 apply_coloring(ci->mst_childs[i], front[i], depth + 1);
883         }
884 }
885
886 static co2_cloud_irn_t *find_mst_root(co2_cloud_irn_t *ci)
887 {
888         while(ci != ci->mst_parent)
889                 ci = ci->mst_parent;
890         return ci;
891 }
892
893
894 static void process_cloud(co2_cloud_t *cloud)
895 {
896         co2_t *env  = cloud->env;
897         int n_regs  = env->n_regs;
898         int n_edges = 0;
899         int *mst_edges = xmalloc(cloud->n_memb * cloud->n_memb * sizeof(mst_edges[0]));
900         pdeq *q;
901
902         edge_t *edges;
903         int i;
904         int best_col;
905
906         memset(mst_edges, 0, cloud->n_memb * cloud->n_memb * sizeof(mst_edges[0]));
907
908         /* Collect all edges in the cloud on an obstack and sort the increasingly */
909         obstack_init(&cloud->obst);
910         for(i = 0; i < cloud->n_memb; ++i) {
911                 co2_cloud_irn_t *ci = cloud->seq[i];
912                 neighb_t *n;
913
914                 co_gs_foreach_neighb(ci->inh.aff, n) {
915                         co2_cloud_irn_t *ni = get_co2_cloud_irn(cloud->env, n->irn);
916                         if(ci->index < ni->index) {
917                                 edge_t e;
918                                 e.src   = ci;
919                                 e.tgt   = ni;
920                                 e.costs = n->costs;
921                                 obstack_grow(&cloud->obst, &e, sizeof(e));
922                                 n_edges++;
923                         }
924                 }
925         }
926         edges = obstack_finish(&cloud->obst);
927         qsort(edges, n_edges, sizeof(edges[0]), cmp_edges);
928
929         /* Compute the maximum spanning tree using Kruskal/Union-Find */
930         DBG((env->dbg, LEVEL_2, "computing spanning tree of cloud with master %+F\n", cloud->master->inh.irn));
931         for(i = 0; i < n_edges; ++i) {
932                 edge_t *e        = &edges[i];
933                 co2_cloud_irn_t *rs = find_mst_root(e->src);
934                 co2_cloud_irn_t *rt = find_mst_root(e->tgt);
935
936                 /* if the union/find roots are different */
937                 if(rs != rt) {
938                         int si = e->src->index;
939                         int ti = e->tgt->index;
940
941                         /* unify the sets */
942                         rs->mst_parent = rt;
943                         DBG((env->dbg, LEVEL_2, "\tadding edge %+F -- %+F cost %d\n", rs->inh.irn, rt->inh.irn, e->costs));
944
945                         /* this edge is in the MST, so set it in the bitset. */
946                         mst_edges[si * cloud->n_memb + ti] = e->costs;
947                         mst_edges[ti * cloud->n_memb + si] = e->costs;
948                 }
949         }
950         obstack_free(&cloud->obst, edges);
951
952         cloud->master->mst_parent = cloud->master;
953         cloud->mst_root = cloud->master;
954         q = new_pdeq1(cloud->master);
955         while(!pdeq_empty(q)) {
956                 co2_cloud_irn_t *ci = pdeq_getl(q);
957                 int ofs    = ci->index * cloud->n_memb;
958                 int end    = ofs + cloud->n_memb;
959                 int i;
960
961                 ci->mst_n_childs = 0;
962                 for(i = ofs; i < end; ++i) {
963                         if(mst_edges[i] != 0) {
964                                 int other = i - ofs;
965                                 co2_cloud_irn_t *child = cloud->seq[i - ofs];
966
967                                 /* put the child to the worklist */
968                                 pdeq_putr(q, child);
969
970                                 /* make ci the parent of the child and add the child to the children array of the parent */
971                                 child->mst_parent = ci;
972                                 child->mst_costs  = mst_edges[i];
973                                 ci->mst_n_childs++;
974                                 obstack_ptr_grow(&cloud->obst, child);
975
976                                 mst_edges[other * cloud->n_memb + ci->index] = 0;
977                                 mst_edges[i] = 0;
978                         }
979                 }
980
981                 obstack_ptr_grow(&cloud->obst, NULL);
982                 ci->mst_childs = obstack_finish(&cloud->obst);
983         }
984         del_pdeq(q);
985         free(mst_edges);
986
987
988         DBG((env->dbg, LEVEL_3, "mst:\n"));
989         for(i = 0; i < cloud->n_memb; ++i) {
990                 DEBUG_ONLY(co2_cloud_irn_t *ci = cloud->seq[i]);
991                 DBG((env->dbg, LEVEL_3, "\t%+F -> %+F\n", ci->inh.irn, ci->mst_parent->inh.irn));
992         }
993
994         for(i = 0; i < cloud->n_memb; ++i) {
995                 co2_cloud_irn_t *ci = cloud->seq[i];
996                 int n_childs = ci->mst_n_childs;
997                 int j;
998
999                 ci->col_costs       = obstack_alloc(&cloud->obst, n_regs * sizeof(ci->col_costs[0]));
1000                 ci->tmp_coloring    = obstack_alloc(&cloud->obst, n_regs * sizeof(ci->tmp_coloring[0]));
1001                 ci->fronts          = obstack_alloc(&cloud->obst, n_regs * n_childs * sizeof(ci->fronts[0]));
1002                 ci->color_badness   = obstack_alloc(&cloud->obst, n_regs * sizeof(ci->fronts[0]));
1003                 memset(ci->color_badness, 0, n_regs * sizeof(ci->color_badness[0]));
1004                 memset(ci->col_costs,     0, n_regs * sizeof(ci->col_costs[0]));
1005                 memset(ci->tmp_coloring,  0, n_regs * sizeof(ci->tmp_coloring[0]));
1006                 memset(ci->fronts,        0, n_regs * n_childs * sizeof(ci->fronts[0]));
1007
1008                 for(j = 0; j < env->n_regs; j++)
1009                         ci->col_costs[j] = INT_MAX;
1010
1011         }
1012
1013         determine_color_badness(cloud->mst_root, 0);
1014         best_col = coalesce_top_down(cloud->mst_root, -1, 0);
1015         unfix_subtree(cloud->mst_root);
1016         apply_coloring(cloud->mst_root, best_col, 0);
1017
1018         /* The coloring should represent the one with the best costs. */
1019         //materialize_coloring(&changed);
1020         DBG((env->dbg, LEVEL_2, "\tbest coloring for root %+F was %d costing %d\n",
1021                 cloud->mst_root->inh.irn, best_col, examine_subtree_coloring(cloud->mst_root, best_col)));
1022
1023         /* Fix all nodes in the cloud. */
1024         for(i = 0; i < cloud->n_memb; ++i)
1025                 cloud->seq[i]->inh.fixed = 1;
1026
1027         /* Free all space used while optimizing this cloud. */
1028         obstack_free(&cloud->obst, NULL);
1029 }
1030
1031 static int cloud_costs(co2_cloud_t *cloud)
1032 {
1033         int i, costs = 0;
1034         neighb_t *n;
1035
1036         for(i = 0; i < cloud->n_memb; ++i) {
1037                 co2_irn_t *ci = (co2_irn_t *) cloud->seq[i];
1038                 col_t col = get_col(cloud->env, ci->irn);
1039                 co_gs_foreach_neighb(ci->aff, n) {
1040                         col_t n_col = get_col(cloud->env, n->irn);
1041                         costs += col != n_col ? n->costs : 0;
1042                 }
1043         }
1044
1045         return costs / 2;
1046 }
1047
1048 static void process(co2_t *env)
1049 {
1050         affinity_node_t *a;
1051         co2_cloud_t *pos;
1052         co2_cloud_t **clouds;
1053         int n_clouds;
1054         int i;
1055         int init_costs  = 0;
1056         int all_costs   = 0;
1057         int final_costs = 0;
1058
1059         n_clouds = 0;
1060         co_gs_foreach_aff_node(env->co, a) {
1061                 co2_cloud_irn_t *ci = get_co2_cloud_irn(env, a->irn);
1062
1063                 if(!ci->cloud) {
1064                         new_cloud(env, a);
1065                         n_clouds++;
1066                 }
1067         }
1068
1069         i = 0;
1070         clouds = xmalloc(n_clouds * sizeof(clouds[0]));
1071         list_for_each_entry(co2_cloud_t, pos, &env->cloud_head, list)
1072                 clouds[i++] = pos;
1073         qsort(clouds, n_clouds, sizeof(clouds[0]), cmp_clouds_gt);
1074
1075         for(i = 0; i < n_clouds; ++i) {
1076                 init_costs  += cloud_costs(clouds[i]);
1077
1078                 /* Process the cloud. */
1079                 process_cloud(clouds[i]);
1080
1081                 all_costs   += clouds[i]->costs;
1082                 final_costs += cloud_costs(clouds[i]);
1083
1084                 /* Dump the IFG if the user demanded it. */
1085                 if (dump_flags & DUMP_CLOUD) {
1086                         char buf[256];
1087                         FILE *f;
1088
1089                         ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_cloud_%d.dot", env->co->irg, env->co->cls->name, i);
1090                         f = fopen(buf, "wt");
1091                         if(f != NULL) {
1092                                 be_ifg_dump_dot(env->co->cenv->ifg, env->co->irg, f, &ifg_dot_cb, env);
1093                                 fclose(f);
1094                         }
1095                 }
1096         }
1097
1098         DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
1099
1100         xfree(clouds);
1101 }
1102
1103 static void writeback_colors(co2_t *env)
1104 {
1105         const arch_env_t *aenv = env->co->aenv;
1106         co2_irn_t *irn;
1107
1108         for(irn = env->touched; irn; irn = irn->touched_next) {
1109                 const arch_register_t *reg = arch_register_for_index(env->co->cls, irn->orig_col);
1110                 arch_set_irn_register(aenv, irn->irn, reg);
1111         }
1112 }
1113
1114
1115 /*
1116   ___ _____ ____   ____   ___ _____   ____                        _
1117  |_ _|  ___/ ___| |  _ \ / _ \_   _| |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
1118   | || |_ | |  _  | | | | | | || |   | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
1119   | ||  _|| |_| | | |_| | |_| || |   | |_| | |_| | | | | | | |_) | | | | | (_| |
1120  |___|_|   \____| |____/ \___/ |_|   |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
1121                                                            |_|            |___/
1122 */
1123
1124 static const char *get_dot_color_name(size_t col)
1125 {
1126         static const char *names[] = {
1127                 "blue",
1128                 "red",
1129                 "green",
1130                 "yellow",
1131                 "cyan",
1132                 "magenta",
1133                 "orange",
1134                 "chocolate",
1135                 "beige",
1136                 "navy",
1137                 "darkgreen",
1138                 "darkred",
1139                 "lightPink",
1140                 "chartreuse",
1141                 "lightskyblue",
1142                 "linen",
1143                 "pink",
1144                 "lightslateblue",
1145                 "mintcream",
1146                 "red",
1147                 "darkolivegreen",
1148                 "mediumblue",
1149                 "mistyrose",
1150                 "salmon",
1151                 "darkseagreen",
1152                 "mediumslateblue"
1153                 "moccasin",
1154                 "tomato",
1155                 "forestgreen",
1156                 "darkturquoise",
1157                 "palevioletred"
1158         };
1159
1160         return col < (sizeof(names)/sizeof(names[0])) ? names[col] : "white";
1161 }
1162
1163 static const char *get_dot_shape_name(co2_t *env, co2_irn_t *ci)
1164 {
1165         const arch_register_req_t *req;
1166
1167         req = arch_get_register_req(env->co->aenv, ci->irn, BE_OUT_POS(0));
1168         if(arch_register_req_is(req, limited))
1169                 return "diamond";
1170
1171         if(ci->fixed)
1172                 return "rectangle";
1173
1174         if(ci->tmp_fixed)
1175                 return "hexagon";
1176
1177         return "ellipse";
1178 }
1179
1180 static void ifg_dump_graph_attr(FILE *f, void *self)
1181 {
1182         (void) self;
1183         fprintf(f, "overlay=false");
1184 }
1185
1186 static int ifg_is_dump_node(void *self, ir_node *irn)
1187 {
1188         co2_t *env = self;
1189         return !arch_irn_is(env->co->aenv, irn, ignore);
1190 }
1191
1192 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
1193 {
1194         co2_t *env    = self;
1195         co2_irn_t *ci = get_co2_irn(env, irn);
1196         int peri      = 1;
1197
1198         char buf[128] = "";
1199
1200         if(ci->aff) {
1201                 co2_cloud_irn_t *cci = (void *) ci;
1202                 if (cci->cloud && cci->cloud->mst_root == cci)
1203                         peri = 2;
1204
1205                 if(cci->cloud && cci->cloud->mst_root)
1206                         ir_snprintf(buf, sizeof(buf), "%+F", cci->cloud->mst_root->inh.irn);
1207         }
1208
1209         ir_fprintf(f, "label=\"%+F%s\" style=filled peripheries=%d color=%s shape=%s", irn, buf, peri,
1210                 get_dot_color_name(get_col(env, irn)), get_dot_shape_name(env, ci));
1211 }
1212
1213 static void ifg_dump_at_end(FILE *file, void *self)
1214 {
1215         co2_t *env = self;
1216         affinity_node_t *a;
1217
1218         co_gs_foreach_aff_node(env->co, a) {
1219                 co2_cloud_irn_t *ai = get_co2_cloud_irn(env, a->irn);
1220                 int idx = get_irn_idx(a->irn);
1221                 neighb_t *n;
1222
1223                 if(ai->mst_parent != ai)
1224                         fprintf(file, "\tn%d -- n%d [style=dotted color=blue arrowhead=normal];\n", idx, get_irn_idx(ai->mst_parent->inh.irn));
1225
1226                 co_gs_foreach_neighb(a, n) {
1227                         int nidx = get_irn_idx(n->irn);
1228                         co2_cloud_irn_t *ci = get_co2_cloud_irn(env, n->irn);
1229
1230                         if(idx < nidx) {
1231                                 const char *color = get_col(env, a->irn) == get_col(env, n->irn) ? "black" : "red";
1232                                 const char *arr = "arrowhead=dot arrowtail=dot";
1233
1234                                 if(ci->mst_parent == ai)
1235                                         arr = "arrowtail=normal";
1236                                 else if(ai->mst_parent == ci)
1237                                         arr = "arrowhead=normal";
1238
1239                                 fprintf(file, "\tn%d -- n%d [label=\"%d\" %s style=dashed color=%s weight=0.01];\n", idx, nidx, n->costs, arr, color);
1240                         }
1241                 }
1242         }
1243 }
1244
1245
1246 static be_ifg_dump_dot_cb_t ifg_dot_cb = {
1247         ifg_is_dump_node,
1248         ifg_dump_graph_attr,
1249         ifg_dump_node_attr,
1250         NULL,
1251         NULL,
1252         ifg_dump_at_end
1253 };
1254
1255
1256 int co_solve_heuristic_new(copy_opt_t *co)
1257 {
1258         char  buf[256];
1259         co2_t env;
1260         FILE  *f;
1261
1262         phase_init(&env.ph, "co2", co->cenv->birg->irg, PHASE_DEFAULT_GROWTH, co2_irn_init, NULL);
1263         env.touched     = NULL;
1264         env.visited     = 0;
1265         env.co          = co;
1266         env.n_regs      = co->cls->n_regs;
1267         env.ignore_regs = bitset_alloca(co->cls->n_regs);
1268         arch_put_non_ignore_regs(co->aenv, co->cls, env.ignore_regs);
1269         bitset_flip_all(env.ignore_regs);
1270         be_abi_put_ignore_regs(co->cenv->birg->abi, co->cls, env.ignore_regs);
1271         FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
1272         INIT_LIST_HEAD(&env.cloud_head);
1273
1274         if(dump_flags & DUMP_BEFORE) {
1275                 ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_before.dot", co->irg, co->cls->name);
1276                 f = fopen(buf, "wt");
1277                 if (f != NULL) {
1278                         be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
1279                         fclose(f);
1280                 }
1281         }
1282
1283         process(&env);
1284
1285         if(dump_flags & DUMP_AFTER) {
1286                 ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_after.dot", co->irg, co->cls->name);
1287                 f = fopen(buf, "wt");
1288                 if (f != NULL) {
1289                         be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
1290                         fclose(f);
1291                 }
1292         }
1293
1294         writeback_colors(&env);
1295         phase_free(&env.ph);
1296         return 0;
1297 }