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