initial checkin
[libfirm] / ir / be / becopyheur2.c
1
2 /**
3  * More experiments on coalescing.
4  * @author Sebastian Hack
5  * @date   14.04.2006
6  */
7
8 #include <stdlib.h>
9 #include <limits.h>
10
11 #include "list.h"
12 #include "pdeq.h"
13 #include "bitset.h"
14
15 #include "debug.h"
16 #include "bitfiddle.h"
17
18 #include "irphase_t.h"
19 #include "irgraph_t.h"
20 #include "irnode_t.h"
21 #include "irprintf.h"
22
23 #include "beabi.h"
24 #include "benode_t.h"
25 #include "becopyopt.h"
26 #include "becopyopt_t.h"
27 #include "bechordal_t.h"
28
29 #define INFEASIBLE(cost) ((cost) == INT_MAX)
30
31 static be_ifg_dump_dot_cb_t ifg_dot_cb;
32
33 typedef unsigned col_t;
34
35 typedef struct _co2_irn_t   co2_irn_t;
36 typedef struct _co2_cloud_t co2_cloud_t;
37
38 typedef struct {
39         phase_t     ph;
40         copy_opt_t *co;
41         bitset_t   *ignore_regs;
42         co2_irn_t  *touched;
43         int         visited;
44         int         n_regs;
45         struct list_head cloud_head;
46         DEBUG_ONLY(firm_dbg_module_t *dbg;)
47 } co2_t;
48
49 struct _co2_irn_t {
50         ir_node         *irn;
51         co2_cloud_t     *cloud;
52         co2_irn_t       *touched_next;
53         affinity_node_t *aff;
54         int              costs;
55         col_t            tmp_col;
56         col_t            orig_col;
57         int              visited;
58         int              fixed_index;
59         int                              last_color_change;
60         unsigned         fixed     : 1;
61         unsigned         tmp_fixed : 1;
62         struct list_head changed_list;
63         struct list_head cloud_list;
64 };
65
66 struct _co2_cloud_t {
67         co2_t      *env;
68         int         costs;
69         int         inevit;
70         int         best_costs;
71         int         n_memb;
72         int         max_degree;
73         int                     ticks;
74         co2_irn_t  *master;
75         co2_irn_t **seq;
76         col_t      *best_cols;
77         int       **failrure_matrix;
78         struct list_head members_head;
79         struct list_head list;
80 };
81
82 #define NEIGHBOR_FIXED   1
83 #define NEIGHBOR_CONSTR  2
84 #define SELF_CONSTR      4
85 #define DONT_WANT        8
86
87 typedef struct {
88         col_t col;
89         int costs;
90         unsigned flags;
91 } col_cost_pair_t;
92
93 #define get_co2_irn(co2, irn)   ((co2_irn_t *) phase_get_or_set_irn_data(&co2->ph, irn))
94
95 static void *co2_irn_init(phase_t *ph, ir_node *irn, void *data)
96 {
97         co2_t *env    = (co2_t *) ph;
98         co2_irn_t *ci = data ? data : phase_alloc(ph, sizeof(ci[0]));
99
100         memset(ci, 0, sizeof(ci[0]));
101         INIT_LIST_HEAD(&ci->changed_list);
102         INIT_LIST_HEAD(&ci->cloud_list);
103         ci->irn          = irn;
104         ci->touched_next = env->touched;
105         ci->orig_col     = get_irn_col(env->co, irn);
106         ci->aff          = get_affinity_info(env->co, (ir_node *)irn);
107         env->touched     = ci;
108         return ci;
109 }
110
111
112 static int co2_irn_cmp(const void *a, const void *b)
113 {
114         const co2_irn_t **p = a;
115         const co2_irn_t **q = b;
116         return (*q)->costs - (*p)->costs;
117 }
118
119 static int cmp_clouds(const void *a, const void *b)
120 {
121         const co2_cloud_t **p = a;
122         const co2_cloud_t **q = b;
123         return (*q)->costs - (*p)->costs;
124 }
125
126 /**
127  * An order on color/costs pairs.
128  * If the costs are equal, we use the color as a kind of normalization.
129  */
130 static int col_cost_pair_lt(const void *a, const void *b)
131 {
132         const col_cost_pair_t *p = a;
133         const col_cost_pair_t *q = b;
134         int c = p->costs;
135         int d = q->costs;
136
137         return (c > d) - (c < d);
138 }
139
140 const char *flag_str(unsigned int fl)
141 {
142         static char buf[10];
143
144         buf[0] = fl & NEIGHBOR_CONSTR ? 'c' : '-';
145         buf[1] = fl & NEIGHBOR_FIXED  ? 'n' : '-';
146         buf[2] = fl & SELF_CONSTR     ? 'C' : '-';
147         buf[3] = fl & DONT_WANT       ? 'd' : '-';
148         buf[4] = '\0';
149         return buf;
150 }
151
152 static col_t get_col(co2_t *env, ir_node *irn)
153 {
154         co2_irn_t *ci = get_co2_irn(env, irn);
155         return ci->tmp_fixed ? ci->tmp_col : ci->orig_col;
156 }
157
158 static INLINE int color_is_fix(co2_t *env, ir_node *irn)
159 {
160         co2_irn_t *ci = get_co2_irn(env, irn);
161         return ci->fixed || ci->tmp_fixed;
162 }
163
164 static bitset_t *admissible_colors(co2_t *env, co2_irn_t *ci, bitset_t *bs)
165 {
166         arch_register_req_t req;
167
168         arch_get_register_req(env->co->aenv, &req, ci->irn, BE_OUT_POS(0));
169         if(arch_register_req_is(&req, limited))
170                 req.limited(req.limited_env, bs);
171         else {
172                 bitset_copy(bs, env->ignore_regs);
173                 bitset_flip_all(bs);
174         }
175
176         return bs;
177 }
178
179 static int is_color_admissible(co2_t *env, co2_irn_t *ci, col_t col)
180 {
181         bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
182         admissible_colors(env, ci, bs);
183         return bitset_is_set(bs, col);
184 }
185
186 static void incur_constraint_costs(co2_t *env, ir_node *irn, col_cost_pair_t *col_costs, int costs)
187 {
188         bitset_t *aux = bitset_alloca(env->co->cls->n_regs);
189         arch_register_req_t req;
190
191         arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
192
193         if(arch_register_req_is(&req, limited)) {
194                 bitset_pos_t elm;
195                 int n_constr;
196
197                 req.limited(req.limited_env, aux);
198                 n_constr = bitset_popcnt(aux);
199                 bitset_foreach(aux, elm) {
200                         col_costs[elm].costs  = add_saturated(col_costs[elm].costs, costs / n_constr);
201                         col_costs[elm].flags |= NEIGHBOR_CONSTR;
202                 }
203         }
204 }
205
206 /**
207  * Determine costs which shall indicate how cheap/expensive it is to try
208  * to assign a node some color.
209  * The costs are computed for all colors. INT_MAX means that it is impossible
210  * to give the node that specific color.
211  *
212  * @param env       The co2 this pointer.
213  * @param irn       The node.
214  * @param col_costs An array of colors x costs where the costs are written to.
215  */
216 static void determine_color_costs(co2_t *env, co2_irn_t *ci, col_cost_pair_t *col_costs)
217 {
218         ir_node *irn       = ci->irn;
219         be_ifg_t *ifg      = env->co->cenv->ifg;
220         int n_regs         = env->co->cls->n_regs;
221         bitset_t *forb     = bitset_alloca(n_regs);
222         affinity_node_t *a = get_affinity_info(env->co, irn);
223
224         bitset_pos_t elm;
225         ir_node *pos;
226         void *it;
227         int i;
228
229 #if 0
230         if(get_irn_node_nr(irn) == 2040) {
231                 printf("Hallo");
232         }
233 #endif
234
235         /* Put all forbidden colors into the aux bitset. */
236         admissible_colors(env, ci, forb);
237         bitset_flip_all(forb);
238
239         for(i = 0; i < n_regs; ++i) {
240                 col_costs[i].col   = i;
241                 col_costs[i].costs = 0;
242                 col_costs[i].flags = 0;
243         }
244
245         if(a) {
246                 neighb_t *n;
247
248                 co_gs_foreach_neighb(a, n) {
249                         if(color_is_fix(env, n->irn)) {
250                                 col_t col = get_col(env, n->irn);
251                                 col_costs[col].costs = add_saturated(col_costs[col].costs, -n->costs * 128);
252                         }
253
254                         incur_constraint_costs(env, n->irn, col_costs, -n->costs);
255                 }
256         }
257
258         it = be_ifg_neighbours_iter_alloca(ifg);
259         be_ifg_foreach_neighbour(ifg, it, irn, pos) {
260                 col_t col = get_col(env, pos);
261                 if(color_is_fix(env, pos)) {
262                         col_costs[col].costs  = INT_MAX;
263                         col_costs[col].flags |= NEIGHBOR_FIXED;
264                 }
265                 else {
266                         incur_constraint_costs(env, pos, col_costs, INT_MAX);
267                         col_costs[col].costs = add_saturated(col_costs[col].costs, 8 * be_ifg_degree(ifg, pos));
268                 }
269         }
270
271         /* Set the costs to infinity for each color which is not allowed at this node. */
272         bitset_foreach(forb, elm) {
273                 col_costs[elm].costs  = INT_MAX;
274                 col_costs[elm].flags |= SELF_CONSTR;
275         }
276
277 }
278
279 static void single_color_cost(co2_t *env, col_t col, col_cost_pair_t *seq)
280 {
281         int n_regs = env->co->cls->n_regs;
282         int i;
283
284         for(i = 0; i < n_regs; ++i) {
285                 seq[i].col   = i;
286                 seq[i].costs = INT_MAX;
287                 seq[i].flags = 0;
288                 seq[i].flags = DONT_WANT;
289         }
290
291         seq[col].col = 0;
292         seq[0].col   = col;
293         seq[0].costs = 0;
294         seq[0].flags = 0;
295 }
296
297 static int curr_costs(co2_t *env, affinity_node_t *a)
298 {
299         col_t a_col = get_col(env, a->irn);
300         int costs   = 0;
301         neighb_t *n;
302
303         co_gs_foreach_neighb(a, n) {
304                 col_t n_col = get_col(env, n->irn);
305                 costs += n_col != a_col ? n->costs : 0;
306         }
307
308         return costs;
309 }
310
311 static int cloud_costs(co2_t *env, co2_cloud_t *cloud)
312 {
313         int costs = 0;
314         co2_irn_t *ci;
315
316         list_for_each_entry(co2_irn_t, ci, &cloud->members_head, cloud_list) {
317                 affinity_node_t *a = get_affinity_info(env->co, ci->irn);
318                 costs += curr_costs(env, a);
319         }
320
321         return costs;
322 }
323
324 static void reject_coloring(struct list_head *h)
325 {
326         co2_irn_t *pos;
327
328         list_for_each_entry(co2_irn_t, pos, h, changed_list)
329                 pos->tmp_fixed = 0;
330 }
331
332 static void materialize_coloring(struct list_head *h)
333 {
334         co2_irn_t *pos;
335
336         list_for_each_entry(co2_irn_t, pos, h, changed_list) {
337                 pos->orig_col = pos->tmp_col;
338                 pos->tmp_fixed = 0;
339         }
340 }
341
342 typedef struct {
343         co2_irn_t *ci;
344         col_t col;
345 } col_entry_t;
346
347 static col_entry_t *save_coloring(struct obstack *obst, struct list_head *changed)
348 {
349         co2_irn_t *pos;
350         col_entry_t ent;
351
352         list_for_each_entry(co2_irn_t, pos, changed, changed_list) {
353                 ent.ci  = pos;
354                 ent.col = pos->tmp_col;
355                 pos->tmp_col = 0;
356                 obstack_grow(obst, &ent, sizeof(ent));
357         }
358         memset(&ent, 0, sizeof(ent));
359         obstack_grow(obst, &ent, sizeof(ent));
360         return obstack_finish(obst);
361 }
362
363 static int change_color_not(co2_t *env, ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth);
364 static int change_color_single(co2_t *env, ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth);
365
366 static int recolor(co2_t *env, ir_node *irn, col_cost_pair_t *col_list, struct list_head *parent_changed, int depth)
367 {
368         int n_regs         = env->co->cls->n_regs;
369         be_ifg_t *ifg      = env->co->cenv->ifg;
370         co2_irn_t *ci      = get_co2_irn(env, irn);
371         int res            = 0;
372         int n_aff          = 0;
373
374         int i;
375
376         for(i = 0; i < n_regs; ++i) {
377                 col_t tgt_col  = col_list[i].col;
378                 unsigned costs = col_list[i].costs;
379                 int neigh_ok   = 1;
380
381                 struct list_head changed;
382                 ir_node *n;
383                 void *it;
384
385                 DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying color %d(%d) on %+F\n", depth, tgt_col, costs, irn));
386
387                 /* If the costs for that color (and all successive) are infinite, bail out we won't make it anyway. */
388                 if(INFEASIBLE(costs)) {
389                         DB((env->dbg, LEVEL_4, "\t\t%2{firm:indent}color %d infeasible due to %s\n", depth, tgt_col, flag_str(col_list[i].flags)));
390                         ci->tmp_fixed = 0;
391                         return 0;
392                 }
393
394                 /* Set the new color of the node and mark the node as temporarily fixed. */
395                 ci->tmp_col     = tgt_col;
396                 ci->tmp_fixed   = 1;
397
398                 /*
399                 If that color has costs > 0, there's at least one neighbor having that color,
400                 so we will try to change the neighbors' colors, too.
401                 */
402                 INIT_LIST_HEAD(&changed);
403                 list_add(&ci->changed_list, &changed);
404
405                 it = be_ifg_neighbours_iter_alloca(ifg);
406                 be_ifg_foreach_neighbour(ifg, it, irn, n) {
407
408                         /* try to re-color the neighbor if it has the target color. */
409                         if(get_col(env, n) == tgt_col) {
410                                 struct list_head tmp;
411
412                                 /*
413                                 Try to change the color of the neighbor and record all nodes which
414                                 get changed in the tmp list. Add this list to the "changed" list for
415                                 that color. If we did not succeed to change the color of the neighbor,
416                                 we bail out and try the next color.
417                                 */
418                                 INIT_LIST_HEAD(&tmp);
419                                 neigh_ok = change_color_not(env, n, tgt_col, &tmp, depth + 1);
420                                 list_splice(&tmp, &changed);
421                                 if(!neigh_ok)
422                                         break;
423                         }
424                 }
425
426                 /*
427                 We managed to assign the target color to all neighbors, so from the perspective
428                 of the current node, every thing was ok and we can return safely.
429                 */
430                 if(neigh_ok) {
431                         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d(%d) was ok\n", depth, tgt_col, costs));
432                         list_splice(&changed, parent_changed);
433                         res = 1;
434                         break;
435                 }
436
437                 /*
438                 If not, that color did not succeed and we unfix all nodes we touched
439                 by traversing the changed list and setting tmp_fixed to 0 for these nodes.
440                 */
441                 else
442                         reject_coloring(&changed);
443         }
444
445         return res;
446 }
447
448 static int change_color_not(co2_t *env, ir_node *irn, col_t not_col, struct list_head *parent_changed, int depth)
449 {
450         co2_irn_t *ci = get_co2_irn(env, irn);
451         int res       = 0;
452         col_t col     = get_col(env, irn);
453
454         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}clearing %+F(%d) of color %d\n", depth, irn, col, not_col));
455
456         /* the node does not have to forbidden color. That's fine, mark it as visited and return. */
457         if(col != not_col) {
458                 if(!ci->tmp_fixed) {
459                         ci->tmp_col     = col;
460                         ci->tmp_fixed   = 1;
461                 }
462
463                 list_add(&ci->changed_list, parent_changed);
464                 return 1;
465         }
466
467         /* The node has the color it should not have _and_ has not been visited yet. */
468         if(!color_is_fix(env, irn)) {
469                 int n_regs            = env->co->cls->n_regs;
470                 col_cost_pair_t *csts = alloca(n_regs * sizeof(csts[0]));
471
472                 /* Get the costs for giving the node a specific color. */
473                 determine_color_costs(env, ci, csts);
474
475                 /* Since the node must not have the not_col, set the costs for that color to "infinity" */
476                 csts[not_col].costs = INT_MAX;
477
478                 /* sort the colors according costs, cheapest first. */
479                 qsort(csts, n_regs, sizeof(csts[0]), col_cost_pair_lt);
480
481                 /* Try recoloring the node using the color list. */
482                 res = recolor(env, irn, csts, parent_changed, depth);
483         }
484
485         /* If we came here, everything went ok. */
486         return res;
487 }
488
489 static int change_color_single(co2_t *env, ir_node *irn, col_t tgt_col, struct list_head *parent_changed, int depth)
490 {
491         co2_irn_t *ci = get_co2_irn(env, irn);
492         col_t col     = get_col(env, irn);
493         int res       = 0;
494
495         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}trying to set %+F(%d) to color %d\n", depth, irn, col, tgt_col));
496
497         /* the node has the wanted color. That's fine, mark it as visited and return. */
498         if(col == tgt_col) {
499                 if(!ci->tmp_fixed) {
500                         ci->tmp_col     = col;
501                         ci->tmp_fixed   = 1;
502                         list_add(&ci->changed_list, parent_changed);
503                 }
504
505                 DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}ok\n", depth));
506                 return 1;
507         }
508
509         if(!color_is_fix(env, irn)) {
510                 int n_regs           = env->co->cls->n_regs;
511                 col_cost_pair_t *seq = alloca(n_regs * sizeof(seq[0]));
512
513                 /* Get the costs for giving the node a specific color. */
514                 single_color_cost(env, tgt_col, seq);
515
516                 /* Try recoloring the node using the color list. */
517                 res = recolor(env, irn, seq, parent_changed, depth);
518
519                 DB((env->dbg, LEVEL_3, "\t\t%2{firm:indent}color %d %s for %+F\n", depth, tgt_col, res ? "was ok" : "failed", irn));
520         }
521
522         return res;
523 }
524
525 static void examine_cloud_coloring(co2_t *env, co2_cloud_t *cloud)
526 {
527         int costs = cloud_costs(env, cloud);
528
529         if(costs < cloud->best_costs) {
530                 int i;
531
532                 for(i = 0; i < cloud->n_memb; ++i)
533                         cloud->best_cols[i] = get_col(env, cloud->seq[i]->irn);
534
535                 cloud->best_costs = costs;
536         }
537 }
538
539 static int color_change_balance(co2_t *env, co2_irn_t *ci, bitset_t *tried_colors, int depth)
540 {
541         col_t col   = get_col(env, ci->irn);
542         int balance = 0;
543         neighb_t *n;
544
545         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}node %+F has color %d\n", depth, ci->irn, col));
546         co_gs_foreach_neighb(ci->aff, n) {
547                 col_t nc  = get_col(env, n->irn);
548                 int fixed = color_is_fix(env, n->irn);
549
550 #if 0
551                 if(fixed) {
552                         if(nc == col)
553                                 balance -= n->costs;
554                         else if(!bitset_is_set(tried_colors, nc))
555                                 balance += n->costs;
556                 }
557
558                 else
559                         balance += n->costs;
560
561 #else
562                 if(nc == col) {
563                         balance -= n->costs;
564                         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}neighbor %+F has the same color, bonus %d\n", depth, n->irn, -n->costs));
565                 }
566                 else if(!fixed) {
567                         balance += n->costs;
568                         DBG((env->dbg, LEVEL_3, "\t\t%2{firm:indent}non fixed neighbor %+F has different color %d, malus %d\n", depth, n->irn, nc, n->costs));
569                 }
570 #endif
571         }
572
573         return balance;
574 }
575
576 static void adjust_start_colors(co2_t *env, co2_cloud_t *cloud, col_cost_pair_t *seq)
577 {
578         int n_regs    = env->co->cls->n_regs;
579         bitset_t *adm = bitset_alloca(n_regs);
580         bitset_pos_t col;
581         int i;
582
583         for(i = 0; i < cloud->n_memb; ++i) {
584                 co2_irn_t *ci = cloud->seq[i];
585                 int n_constr;
586
587                 /* Prefer precolored neighbors. */
588                 bitset_clear_all(adm);
589                 admissible_colors(env, ci, adm);
590                 n_constr = bitset_popcnt(adm);
591
592                 bitset_foreach(adm, col) {
593                         seq[col].costs = add_saturated(seq[col].costs, -128 * (n_regs - n_constr));
594                 }
595
596                 bitset_foreach_clear(adm, col) {
597                         seq[col].costs = add_saturated(seq[col].costs, 128);
598                 }
599         }
600
601         admissible_colors(env, cloud->master, adm);
602         bitset_flip_all(adm);
603
604         bitset_foreach(adm, col)
605                 seq[col].costs = INT_MAX;
606 }
607
608 static int process_node(co2_t *env, co2_cloud_t *cloud, int index)
609 {
610         struct list_head changed;
611         int res = 0;
612
613         if(index < cloud->n_memb) {
614                 co2_irn_t *ci           = cloud->seq[index];
615                 int n_regs              = env->co->cls->n_regs;
616                 col_cost_pair_t *seq    = alloca(n_regs * sizeof(seq[0]));
617                 bitset_t *cols_tried    = bitset_alloca(n_regs);
618                 int done                = 0;
619                 int n_new_fixed         = 0;
620                 int n_fixed             = 0;
621
622                 neighb_t *n;
623                 int i;
624
625                 /*
626                 Investigate if one of the fixed neighbors of this node has changed
627                 its color since this node changed its color. If so we will
628                 consider changing this node's color again.
629                 */
630
631                 co_gs_foreach_neighb(ci->aff, n) {
632                         co2_irn_t *ni = get_co2_irn(env, n->irn);
633                         n_fixed += ni->fixed;
634                         n_new_fixed += ni->fixed && ni->last_color_change > ci->last_color_change;
635                 }
636
637                 if(n_fixed > 0 && n_new_fixed == 0)
638                         return process_node(env, cloud, index + 1);
639
640                 determine_color_costs(env, ci, seq);
641
642                 /* If this is the first node, adjust the sequence of the coloring. */
643                 if(index == 0)
644                         adjust_start_colors(env, cloud, seq);
645
646                 qsort(seq, n_regs, sizeof(seq[0]), col_cost_pair_lt);
647
648                 for(i = 0; i < n_regs && !done; ++i) {
649                         col_t col = seq[i].col;
650                         int costs = seq[i].costs;
651                         int ok;
652
653                         /*
654                                 if all affinity neighbors fixed,
655                                 try only color changes to affinity colors.
656                                 all other colors do no good.
657                         */
658
659                         DB((env->dbg, LEVEL_2, "\t%2{firm:indent}trying %+F index %d for color %d\n", index, ci->irn, index, col));
660                         if(INFEASIBLE(costs)) {
661                                 DBG((env->dbg, LEVEL_2, "\t%2{firm:indent}-> color is infeasible due to %s\n", index, flag_str(seq[i].flags)));
662                                 break;
663                         }
664
665                         bitset_set(cols_tried, col);
666                         INIT_LIST_HEAD(&changed);
667                         cloud->ticks++;
668                         ok = change_color_single(env, ci->irn, col, &changed, index);
669                         DB((env->dbg, LEVEL_2, "\t%2{firm:indent}-> %s\n", index, ok ? "ok" : "failed"));
670
671                         /* if we succeeded changing the color, we will figure out the next node. */
672                         if(ok) {
673                                 int balance;
674                                 int finish;
675
676                                 /* Mark the time of the last color change */
677                                 ci->last_color_change = cloud->ticks;
678
679                                 /* materialize the coloring and fix the node's color. */
680                                 ci->fixed = 1;
681
682                                 /* process the next nodes. if the function returns one, we found an optimal coloring already, so get out. */
683                                 finish = process_node(env, cloud, index + 1);
684
685                                 /* if this is the last node in the coloring sequence, examine the coloring */
686                                 if(index == cloud->n_memb - 1) {
687                                         examine_cloud_coloring(env, cloud);
688                                         DB((env->dbg, LEVEL_2, "\t%2{firm:indent}-> current best coloring %d\n", index, cloud->best_costs));
689                                         if(cloud->best_costs == cloud->inevit)
690                                                 finish = 1;
691                                 }
692
693                                 /* Compute the recoloring balance for this solution. */
694                                 balance = color_change_balance(env, ci, cols_tried, index);
695                                 DBG((env->dbg, LEVEL_3, "\t%2{firm:indent}balance for further color changing: %d\n", index, balance));
696
697                                 /* unfix the node. */
698                                 reject_coloring(&changed);
699                                 ci->fixed = 0;
700
701                                 if(finish || balance <= 0) {
702                                         res  = finish;
703                                         done = 1;
704                                 }
705                         }
706                 }
707         }
708
709         return res;
710 }
711
712 static co2_irn_t **get_neighb_arr(co2_t *env, co2_irn_t *ci, co2_irn_t **nbs)
713 {
714         int i;
715         neighb_t *n;
716
717         i = 0;
718         co_gs_foreach_neighb(ci->aff, n) {
719                 nbs[i++] = get_co2_irn(env, n->irn);
720         }
721
722         qsort(nbs, ci->aff->degree, sizeof(nbs[0]), co2_irn_cmp);
723         return nbs;
724 }
725
726 static void determine_coloring_sequence(co2_t *env, co2_cloud_t *cloud)
727 {
728         pdeq *q         = new_pdeq1(cloud->master);
729         bitset_t *seen  = bitset_malloc(get_irg_last_idx(env->co->irg));
730         co2_irn_t **nbs = alloca(cloud->max_degree * sizeof(nbs[0]));
731         int i, j;
732
733         j = 0;
734         bitset_set(seen, get_irn_idx(cloud->master->irn));
735         while(!pdeq_empty(q)) {
736                 co2_irn_t *curr = pdeq_getl(q);
737
738                 cloud->seq[j++] = curr;
739                 get_neighb_arr(env, curr, nbs);
740
741                 for(i = 0; i < curr->aff->degree; ++i) {
742                         co2_irn_t *ni = nbs[i];
743                         int idx       = get_irn_idx(ni->irn);
744                         if(!bitset_is_set(seen, idx)) {
745                                 pdeq_putr(q, ni);
746                                 bitset_set(seen, idx);
747                         }
748                 }
749         }
750
751         del_pdeq(q);
752         bitset_free(seen);
753 }
754
755 static void populate_cloud(co2_t *env, co2_cloud_t *cloud, affinity_node_t *a, int curr_costs)
756 {
757         be_ifg_t *ifg = env->co->cenv->ifg;
758         co2_irn_t *ci = get_co2_irn(env, a->irn);
759         int costs     = 0;
760         neighb_t *n;
761
762         if(ci->visited >= env->visited)
763                 return;
764
765         /* mark the node as visited and add it to the cloud. */
766         ci->visited = env->visited;
767         ci->cloud   = cloud;
768         list_add(&ci->cloud_list, &cloud->members_head);
769
770         DB((env->dbg, LEVEL_3, "%+F\n", ci->irn));
771
772         /* determine the nodes costs */
773         co_gs_foreach_neighb(a, n) {
774                 costs += n->costs;
775                 DB((env->dbg, LEVEL_3, "\t%+F\n", n->irn));
776                 if(be_ifg_connected(ifg, a->irn, n->irn))
777                         cloud->inevit += n->costs;
778         }
779
780         /* add the node's cost to the total costs of the cloud. */
781         ci->costs          = costs;
782         cloud->costs      += costs;
783         cloud->max_degree  = MAX(cloud->max_degree, ci->aff->degree);
784         cloud->n_memb++;
785
786         /* If this is the heaviest node in the cloud, set it as the cloud's master. */
787         if(costs >= curr_costs) {
788                 cloud->master = ci;
789                 curr_costs    = costs;
790         }
791
792         /* add all the neighbors of the node to the cloud. */
793         co_gs_foreach_neighb(a, n) {
794                 affinity_node_t *an = get_affinity_info(env->co, n->irn);
795                 assert(an);
796                 populate_cloud(env, cloud, an, curr_costs);
797         }
798 }
799
800 static co2_cloud_t *new_cloud(co2_t *env, affinity_node_t *a)
801 {
802         co2_cloud_t *cloud = phase_alloc(&env->ph, sizeof(cloud[0]));
803         memset(cloud, 0, sizeof(cloud[0]));
804         INIT_LIST_HEAD(&cloud->members_head);
805         INIT_LIST_HEAD(&cloud->list);
806         list_add(&cloud->list, &env->cloud_head);
807         cloud->best_costs = INT_MAX;
808         cloud->env = env;
809         env->visited++;
810         populate_cloud(env, cloud, a, 0);
811
812         /* Allocate space for the best colors array, where the best coloring is saved. */
813         cloud->best_cols = phase_alloc(&env->ph, cloud->n_memb * sizeof(cloud->best_cols[0]));
814
815         /* Also allocate space for the node sequence and compute that sequence. */
816         cloud->seq    = phase_alloc(&env->ph, cloud->n_memb * sizeof(cloud->seq[0]));
817         cloud->seq[0] = cloud->master;
818         env->visited++;
819         determine_coloring_sequence(env, cloud);
820
821 #if 0
822         /* Allocate the failure matrix. */
823         cloud->failrure_matrix = phase_alloc(&env->ph, cloud->n_memb * sizeof(cloud->failrure_matrix[0]));
824         for(i = 0; i < env->n_regs; ++i) {
825                 cloud->failrure_matrix[i] = phase_alloc(&env->ph, env->n_regs * sizeof(cloud->failrure_matrix[i][0]));
826                 memset(cloud->failrure_matrix[i], 0, env->n_regs * sizeof(cloud->failrure_matrix[i][0]));
827         }
828 #endif
829         return cloud;
830 }
831
832 static void process_cloud(co2_t *env, co2_cloud_t *cloud, int nr)
833 {
834         struct list_head changed;
835         int i;
836
837         /* initialize the best coloring. */
838         examine_cloud_coloring(env, cloud);
839
840         DB((env->dbg, LEVEL_1, "\nnew cloud\nall costs %d, initial costs %d, inevit %d\n", cloud->costs, cloud->best_costs, cloud->inevit));
841         for(i = 0; i < cloud->n_memb; ++i) {
842                 co2_irn_t *ci = cloud->seq[i];
843                 DB((env->dbg, LEVEL_1, "\tmember %+F cost %d col %d\n", ci->irn, ci->costs, get_col(env, ci->irn)));
844         }
845
846         process_node(env, cloud, 0);
847         DB((env->dbg, LEVEL_1, "final coloring costs %d\n", cloud->best_costs));
848
849         /* re-try the best coloring. */
850         INIT_LIST_HEAD(&changed);
851         for(i = 0; i < cloud->n_memb; ++i) {
852                 co2_irn_t *ci = cloud->seq[i];
853                 col_t col     = cloud->best_cols[i];
854
855                 int ok;
856
857                 DB((env->dbg, LEVEL_2, "\tsetting %+F to %d\n", ci->irn, col));
858                 ok = change_color_single(env, ci->irn, col, &changed, 0);
859                 assert(ok);
860                 ci->fixed = 1;
861         }
862         materialize_coloring(&changed);
863
864         {
865                 co2_irn_t *ci;
866                 int some_fixed = 0;
867                 for(ci = env->touched; ci; ci = ci->touched_next) {
868                         if(ci->tmp_fixed) {
869                                 some_fixed = 1;
870                                 ir_printf("%+F is still temp fixed\n", ci->irn);
871                         }
872                 }
873                 assert(!some_fixed);
874         }
875
876         {
877                 char buf[256];
878                 FILE *f;
879
880                 ir_snprintf(buf, sizeof(buf), "ifg_%F_%s_cloud_%d.dot", env->co->irg, env->co->cls->name, nr);
881                 if(f = fopen(buf, "wt")) {
882                         be_ifg_dump_dot(env->co->cenv->ifg, env->co->irg, f, &ifg_dot_cb, env);
883                         fclose(f);
884                 }
885         }
886
887 }
888
889 static void process(co2_t *env)
890 {
891         affinity_node_t *a;
892         co2_cloud_t *pos;
893         co2_cloud_t **clouds;
894         int n_clouds;
895         int i;
896         int init_costs  = 0;
897         int all_costs   = 0;
898         int final_costs = 0;
899
900         n_clouds = 0;
901         co_gs_foreach_aff_node(env->co, a) {
902                 co2_irn_t *ci = get_co2_irn(env, a->irn);
903
904                 if(!ci->cloud) {
905                         co2_cloud_t *cloud = new_cloud(env, a);
906                         n_clouds++;
907                 }
908         }
909
910         i = 0;
911         clouds = xmalloc(n_clouds * sizeof(clouds[0]));
912         list_for_each_entry(co2_cloud_t, pos, &env->cloud_head, list)
913                 clouds[i++] = pos;
914         qsort(clouds, n_clouds, sizeof(clouds[0]), cmp_clouds);
915
916         for(i = 0; i < n_clouds; ++i) {
917                 init_costs  += cloud_costs(env, clouds[i]);
918                 process_cloud(env, clouds[i], i);
919                 all_costs   += clouds[i]->costs;
920                 final_costs += clouds[i]->best_costs;
921         }
922
923         DB((env->dbg, LEVEL_1, "all costs: %d, init costs: %d, final costs: %d\n", all_costs, init_costs, final_costs));
924
925         xfree(clouds);
926 }
927
928 static void writeback_colors(co2_t *env)
929 {
930         const arch_env_t *aenv = env->co->aenv;
931         co2_irn_t *irn;
932
933         for(irn = env->touched; irn; irn = irn->touched_next) {
934                 const arch_register_t *reg = arch_register_for_index(env->co->cls, irn->orig_col);
935                 arch_set_irn_register(aenv, irn->irn, reg);
936         }
937 }
938
939 /*
940   ___ _____ ____   ____   ___ _____   ____                        _
941  |_ _|  ___/ ___| |  _ \ / _ \_   _| |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
942   | || |_ | |  _  | | | | | | || |   | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
943   | ||  _|| |_| | | |_| | |_| || |   | |_| | |_| | | | | | | |_) | | | | | (_| |
944  |___|_|   \____| |____/ \___/ |_|   |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
945                                                            |_|            |___/
946 */
947
948 static const char *get_dot_color_name(int col)
949 {
950         static const char *names[] = {
951                 "blue",
952                 "red",
953                 "green",
954                 "yellow",
955                 "cyan",
956                 "magenta",
957                 "orange",
958                 "chocolate",
959                 "beige",
960                 "navy",
961                 "darkgreen",
962                 "darkred",
963                 "lightPink",
964                 "chartreuse",
965                 "lightskyblue",
966                 "linen",
967                 "pink",
968                 "lightslateblue",
969                 "mintcream",
970                 "red",
971                 "darkolivegreen",
972                 "mediumblue",
973                 "mistyrose",
974                 "salmon",
975                 "darkseagreen",
976                 "mediumslateblue"
977                 "moccasin",
978                 "tomato",
979                 "forestgreen",
980                 "darkturquoise",
981                 "palevioletred"
982         };
983
984         return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
985 }
986
987 static const char *get_dot_shape_name(co2_t *env, co2_irn_t *ci)
988 {
989         arch_register_req_t req;
990
991         arch_get_register_req(env->co->aenv, &req, ci->irn, BE_OUT_POS(0));
992         if(arch_register_req_is(&req, limited))
993                 return "diamond";
994
995         if(ci->fixed)
996                 return "rectangle";
997
998         if(ci->tmp_fixed)
999                 return "hexagon";
1000
1001         return "ellipse";
1002 }
1003
1004 static void ifg_dump_graph_attr(FILE *f, void *self)
1005 {
1006         fprintf(f, "overlay=false");
1007 }
1008
1009 static int ifg_is_dump_node(void *self, ir_node *irn)
1010 {
1011         co2_t *env = self;
1012         return !arch_irn_is(env->co->aenv, irn, ignore);
1013 }
1014
1015 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
1016 {
1017         co2_t *env    = self;
1018         co2_irn_t *ci = get_co2_irn(env, irn);
1019
1020         ir_fprintf(f, "label=\"%+F,%d\" style=filled color=%s shape=%s", irn, ci->costs,
1021                 get_dot_color_name(get_col(env, irn)), get_dot_shape_name(env, ci));
1022 }
1023
1024 static void ifg_dump_at_end(FILE *file, void *self)
1025 {
1026         co2_t *env = self;
1027         affinity_node_t *a;
1028
1029         co_gs_foreach_aff_node(env->co, a) {
1030                 int idx = get_irn_idx(a->irn);
1031                 neighb_t *n;
1032
1033                 co_gs_foreach_neighb(a, n) {
1034                         int nidx = get_irn_idx(n->irn);
1035
1036                         if(idx < nidx) {
1037                                 const char *style = get_col(env, a->irn) == get_col(env, n->irn) ? "dashed" : "dotted";
1038                                 fprintf(file, "\tn%d -- n%d [label=\"%d\" style=%s weight=0.01];\n", idx, nidx, n->costs, style);
1039                         }
1040                 }
1041         }
1042
1043 }
1044
1045 static be_ifg_dump_dot_cb_t ifg_dot_cb = {
1046         ifg_is_dump_node,
1047         ifg_dump_graph_attr,
1048         ifg_dump_node_attr,
1049         NULL,
1050         NULL,
1051         ifg_dump_at_end
1052 };
1053
1054 void co_solve_heuristic_new(copy_opt_t *co)
1055 {
1056         co2_t env;
1057         FILE *f;
1058
1059         phase_init(&env.ph, "co2", co->cenv->birg->irg, PHASE_DEFAULT_GROWTH, co2_irn_init);
1060         env.touched     = NULL;
1061         env.visited     = 0;
1062         env.co          = co;
1063         env.ignore_regs = bitset_alloca(co->cls->n_regs);
1064         arch_put_non_ignore_regs(co->aenv, co->cls, env.ignore_regs);
1065         bitset_flip_all(env.ignore_regs);
1066         be_abi_put_ignore_regs(co->cenv->birg->abi, co->cls, env.ignore_regs);
1067         FIRM_DBG_REGISTER(env.dbg, "firm.be.co2");
1068         INIT_LIST_HEAD(&env.cloud_head);
1069
1070         if(f = be_chordal_open(co->cenv, "ifg_before_", "dot")) {
1071                 be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
1072                 fclose(f);
1073         }
1074
1075         process(&env);
1076
1077         if(f = be_chordal_open(co->cenv, "ifg_after_", "dot")) {
1078                 be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &env);
1079                 fclose(f);
1080         }
1081
1082         writeback_colors(&env);
1083         phase_free(&env.ph);
1084 }