Added some statistics events
[libfirm] / ir / be / becopyopt.c
1 /**
2  * Author:      Daniel Grund
3  * Date:                12.04.2005
4  * Copyright:   (c) Universitaet Karlsruhe
5  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
6  */
7 #ifdef HAVE_CONFIG_H
8 #include "config.h"
9 #endif
10 #ifdef HAVE_ALLOCA_H
11 #include <alloca.h>
12 #endif
13 #ifdef HAVE_MALLOC_H
14 #include <malloc.h>
15 #endif
16
17 #include "execfreq.h"
18 #include "xmalloc.h"
19 #include "debug.h"
20 #include "pmap.h"
21 #include "irgraph.h"
22 #include "irgwalk.h"
23 #include "irprog.h"
24 #include "irloop_t.h"
25 #include "iredges_t.h"
26 #include "phiclass.h"
27 #include "irbitset.h"
28 #include "irphase_t.h"
29 #include "irprintf_t.h"
30
31
32 #include "bearch.h"
33 #include "benode_t.h"
34 #include "beutil.h"
35 #include "beifg_t.h"
36 #include "becopyopt_t.h"
37 #include "becopystat.h"
38 #include "belive_t.h"
39 #include "beinsn_t.h"
40 #include "besched_t.h"
41 #include "benodesets.h"
42 #include "bestatevent.h"
43
44 #define DUMP_BEFORE 1
45 #define DUMP_AFTER  2
46 #define DUMP_APPEL  4
47 #define DUMP_ALL    2 * DUMP_APPEL - 1
48
49 #define COST_FUNC_FREQ     1
50 #define COST_FUNC_LOOP     2
51 #define COST_FUNC_ALL_ONE  3
52
53 static int dump_flags         = 0;
54 static int style_flags        = 0;
55 static int do_stats           = 0;
56 static cost_fct_t cost_func   = co_get_costs_exec_freq;
57 static int algo               = CO_ALGO_HEUR2;
58 static int improve            = 1;
59
60 #ifdef WITH_LIBCORE
61 static const lc_opt_enum_mask_items_t dump_items[] = {
62         { "before",  DUMP_BEFORE },
63         { "after",   DUMP_AFTER  },
64         { "appel",   DUMP_APPEL  },
65         { "all",     DUMP_ALL    },
66         { NULL,      0 }
67 };
68
69 static const lc_opt_enum_mask_items_t style_items[] = {
70         { "color",   CO_IFG_DUMP_COLORS },
71         { "labels",  CO_IFG_DUMP_LABELS },
72         { "constr",  CO_IFG_DUMP_CONSTR },
73         { "shape",   CO_IFG_DUMP_SHAPE  },
74         { "full",    2 * CO_IFG_DUMP_SHAPE - 1 },
75         { NULL,      0 }
76 };
77
78 static const lc_opt_enum_mask_items_t algo_items[] = {
79         { "none",   CO_ALGO_NONE  },
80         { "heur",   CO_ALGO_HEUR  },
81         { "heur2",  CO_ALGO_HEUR2 },
82         { "heur3",  CO_ALGO_HEUR3 },
83         { "ilp",    CO_ALGO_ILP   },
84         { NULL,     0 }
85 };
86
87 static const lc_opt_enum_func_ptr_items_t cost_func_items[] = {
88         { "freq",   co_get_costs_exec_freq },
89         { "loop",   co_get_costs_loop_depth },
90         { "one",    co_get_costs_all_one },
91         { NULL,     0 }
92 };
93
94 static lc_opt_enum_mask_var_t dump_var = {
95         &dump_flags, dump_items
96 };
97
98 static lc_opt_enum_mask_var_t style_var = {
99         &style_flags, style_items
100 };
101
102 static lc_opt_enum_mask_var_t algo_var = {
103         &algo, algo_items
104 };
105
106 static lc_opt_enum_func_ptr_var_t cost_func_var = {
107         &cost_func, cost_func_items
108 };
109
110 static const lc_opt_table_entry_t options[] = {
111         LC_OPT_ENT_ENUM_INT      ("algo",    "select copy optimization algo (heur, heur2, heur3, ilp)", &algo_var),
112         LC_OPT_ENT_ENUM_FUNC_PTR ("cost",    "select a cost function (freq, loop, one)",                &cost_func_var),
113         LC_OPT_ENT_ENUM_MASK     ("dump",    "dump ifg before or after copy optimization",              &dump_var),
114         LC_OPT_ENT_ENUM_MASK     ("style",   "dump style for ifg dumping",                              &style_var),
115         LC_OPT_ENT_BOOL          ("stats",   "dump statistics after each optimization",                 &do_stats),
116         LC_OPT_ENT_BOOL          ("improve", "run heur3 before if algo can exploit start solutions",    &improve),
117         { NULL }
118 };
119
120 /* Insert additional options registration functions here. */
121 extern void be_co_ilp_register_options(lc_opt_entry_t *grp);
122 extern void be_co2_register_options(lc_opt_entry_t *grp);
123 extern void be_co3_register_options(lc_opt_entry_t *grp);
124
125 void co_register_options(lc_opt_entry_t *grp)
126 {
127         lc_opt_entry_t *co_grp = lc_opt_get_grp(grp, "co");
128         lc_opt_add_table(co_grp, options);
129
130         be_co2_register_options(co_grp);
131         be_co3_register_options(co_grp);
132 #ifdef WITH_ILP
133         be_co_ilp_register_options(co_grp);
134 #endif
135 }
136 #endif
137
138
139 #undef QUICK_AND_DIRTY_HACK
140
141 /******************************************************************************
142     _____                           _
143    / ____|                         | |
144   | |  __  ___ _ __   ___ _ __ __ _| |
145   | | |_ |/ _ \ '_ \ / _ \ '__/ _` | |
146   | |__| |  __/ | | |  __/ | | (_| | |
147    \_____|\___|_| |_|\___|_|  \__,_|_|
148
149  ******************************************************************************/
150
151 DEBUG_ONLY(static firm_dbg_module_t *dbg = NULL;)
152
153 void be_copy_opt_init(void) {
154 }
155
156 copy_opt_t *new_copy_opt(be_chordal_env_t *chordal_env, cost_fct_t get_costs)
157 {
158         const char *s1, *s2, *s3;
159         int len;
160         copy_opt_t *co;
161
162         FIRM_DBG_REGISTER(dbg, "ir.be.copyopt");
163
164         co = xcalloc(1, sizeof(*co));
165         co->cenv      = chordal_env;
166         co->aenv      = chordal_env->birg->main_env->arch_env;
167         co->irg       = chordal_env->irg;
168         co->cls       = chordal_env->cls;
169         co->get_costs = get_costs;
170
171         s1 = get_irp_prog_name();
172         s2 = get_entity_name(get_irg_entity(co->irg));
173         s3 = chordal_env->cls->name;
174         len = strlen(s1) + strlen(s2) + strlen(s3) + 5;
175         co->name = xmalloc(len);
176         snprintf(co->name, len, "%s__%s__%s", s1, s2, s3);
177
178         return co;
179 }
180
181 void free_copy_opt(copy_opt_t *co) {
182         xfree(co->name);
183         free(co);
184 }
185
186 int co_is_optimizable_root(const copy_opt_t *co, ir_node *irn) {
187         arch_register_req_t req;
188         const arch_register_t *reg;
189
190         if (arch_irn_is(co->aenv, irn, ignore))
191                 return 0;
192
193         reg = arch_get_irn_register(co->aenv, irn);
194         if (arch_register_type_is(reg, ignore))
195                 return 0;
196
197         if (is_Reg_Phi(irn) || is_Perm_Proj(co->aenv, irn) || is_2addr_code(co->aenv, irn, &req))
198                 return 1;
199
200         return 0;
201 }
202
203 int co_is_optimizable_arg(const copy_opt_t *co, ir_node *irn) {
204         const ir_edge_t *edge;
205         const arch_register_t *reg;
206
207         assert(0 && "Is buggy and obsolete. Do not use");
208
209         if (arch_irn_is(co->aenv, irn, ignore))
210                 return 0;
211
212         reg = arch_get_irn_register(co->aenv, irn);
213         if (arch_register_type_is(reg, ignore))
214                 return 0;
215
216         foreach_out_edge(irn, edge) {
217                 ir_node *n = edge->src;
218
219                 if (!nodes_interfere(co->cenv, irn, n) || irn == n) {
220                         arch_register_req_t req;
221                         arch_get_register_req(co->aenv, &req, n, -1);
222
223                         if(is_Reg_Phi(n) ||
224                            is_Perm(co->aenv, n) ||
225                            (arch_register_req_is(&req, should_be_same) && req.other_same == irn)
226                           )
227                                 return 1;
228                 }
229         }
230
231         return 0;
232 }
233
234 int co_get_costs_loop_depth(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos) {
235         int cost = 0;
236         ir_loop *loop;
237         ir_node *root_block = get_nodes_block(root);
238
239         if (is_Phi(root)) {
240                 /* for phis the copies are placed in the corresponding pred-block */
241                 loop = get_irn_loop(get_Block_cfgpred_block(root_block, pos));
242         } else {
243                 /* a perm places the copy in the same block as it resides */
244                 loop = get_irn_loop(root_block);
245         }
246         if (loop) {
247                 int d = get_loop_depth(loop);
248                 cost = d*d;
249         }
250         return 1+cost;
251 }
252
253 int co_get_costs_exec_freq(const copy_opt_t *co, ir_node *root, ir_node* arg, int pos) {
254         int res;
255         ir_node *root_bl = get_nodes_block(root);
256         ir_node *copy_bl = is_Phi(root) ? get_Block_cfgpred_block(root_bl, pos) : root_bl;
257         res = get_block_execfreq_ulong(co->cenv->exec_freq, copy_bl);
258
259         /* don't allow values smaller than one. */
260         return res < 1 ? 1 : res;
261 }
262
263
264 int co_get_costs_all_one(const copy_opt_t *co, ir_node *root, ir_node *arg, int pos) {
265         return 1;
266 }
267
268 /******************************************************************************
269    ____        _   _    _       _ _          _____ _
270   / __ \      | | | |  | |     (_) |        / ____| |
271  | |  | |_ __ | |_| |  | |_ __  _| |_ ___  | (___ | |_ ___  _ __ __ _  __ _  ___
272  | |  | | '_ \| __| |  | | '_ \| | __/ __|  \___ \| __/ _ \| '__/ _` |/ _` |/ _ \
273  | |__| | |_) | |_| |__| | | | | | |_\__ \  ____) | || (_) | | | (_| | (_| |  __/
274   \____/| .__/ \__|\____/|_| |_|_|\__|___/ |_____/ \__\___/|_|  \__,_|\__, |\___|
275         | |                                                            __/ |
276         |_|                                                           |___/
277  ******************************************************************************/
278
279 /**
280  * Determines a maximum weighted independent set with respect to
281  * the interference and conflict edges of all nodes in a qnode.
282  */
283 static int ou_max_ind_set_costs(unit_t *ou) {
284         be_chordal_env_t *chordal_env = ou->co->cenv;
285         ir_node **safe, **unsafe;
286         int i, o, safe_count, safe_costs, unsafe_count, *unsafe_costs;
287         bitset_t *curr;
288         int max, pos, curr_weight, best_weight = 0;
289
290         /* assign the nodes into two groups.
291          * safe: node has no interference, hence it is in every max stable set.
292          * unsafe: node has an interference
293          */
294         safe = alloca((ou->node_count-1) * sizeof(*safe));
295         safe_costs = 0;
296         safe_count = 0;
297         unsafe = alloca((ou->node_count-1) * sizeof(*unsafe));
298         unsafe_costs = alloca((ou->node_count-1) * sizeof(*unsafe_costs));
299         unsafe_count = 0;
300         for(i=1; i<ou->node_count; ++i) {
301                 int is_safe = 1;
302                 for(o=1; o<ou->node_count; ++o) {
303                         if (i==o)
304                                 continue;
305                         if (nodes_interfere(chordal_env, ou->nodes[i], ou->nodes[o])) {
306                                 unsafe_costs[unsafe_count] = ou->costs[i];
307                                 unsafe[unsafe_count] = ou->nodes[i];
308                                 ++unsafe_count;
309                                 is_safe = 0;
310                                 break;
311                         }
312                 }
313                 if (is_safe) {
314                         safe_costs += ou->costs[i];
315                         safe[safe_count++] = ou->nodes[i];
316                 }
317         }
318
319
320         /* now compute the best set out of the unsafe nodes*/
321         if (unsafe_count > MIS_HEUR_TRIGGER) {
322                 bitset_t *best = bitset_alloca(unsafe_count);
323                 /* Heuristik: Greedy trial and error form index 0 to unsafe_count-1 */
324                 for (i=0; i<unsafe_count; ++i) {
325                         bitset_set(best, i);
326                         /* check if it is a stable set */
327                         for (o=bitset_next_set(best, 0); o!=-1 && o<i; o=bitset_next_set(best, o+1))
328                                 if (nodes_interfere(chordal_env, unsafe[i], unsafe[o])) {
329                                         bitset_clear(best, i); /* clear the bit and try next one */
330                                         break;
331                                 }
332                 }
333                 /* compute the weight */
334                 bitset_foreach(best, pos)
335                         best_weight += unsafe_costs[pos];
336         } else {
337                 /* Exact Algorithm: Brute force */
338                 curr = bitset_alloca(unsafe_count);
339                 bitset_set_all(curr);
340                 while ((max = bitset_popcnt(curr)) != 0) {
341                         /* check if curr is a stable set */
342                         for (i=bitset_next_set(curr, 0); i!=-1; i=bitset_next_set(curr, i+1))
343                                 for (o=bitset_next_set(curr, i+1); o!=-1; o=bitset_next_set(curr, o+1)) /* !!!!! difference to qnode_max_ind_set(): NOT (curr, i) */
344                                                 if (nodes_interfere(chordal_env, unsafe[i], unsafe[o]))
345                                                         goto no_stable_set;
346
347                         /* if we arrive here, we have a stable set */
348                         /* compute the weigth of the stable set*/
349                         curr_weight = 0;
350                         bitset_foreach(curr, pos)
351                                 curr_weight += unsafe_costs[pos];
352
353                         /* any better ? */
354                         if (curr_weight > best_weight) {
355                                 best_weight = curr_weight;
356                         }
357
358         no_stable_set:
359                         bitset_minus1(curr);
360                 }
361         }
362
363         return safe_costs+best_weight;
364 }
365
366 static void co_collect_units(ir_node *irn, void *env) {
367         copy_opt_t *co = env;
368         unit_t *unit;
369         arch_register_req_t req;
370
371         if (!is_curr_reg_class(co, irn))
372                 return;
373         if (!co_is_optimizable_root(co, irn))
374                 return;
375
376         /* Init a new unit */
377         unit = xcalloc(1, sizeof(*unit));
378         unit->co = co;
379         unit->node_count = 1;
380         INIT_LIST_HEAD(&unit->queue);
381
382         /* Phi with some/all of its arguments */
383         if (is_Reg_Phi(irn)) {
384                 int i, arity;
385
386                 /* init */
387                 arity = get_irn_arity(irn);
388                 unit->nodes = xmalloc((arity+1) * sizeof(*unit->nodes));
389                 unit->costs = xmalloc((arity+1) * sizeof(*unit->costs));
390                 unit->nodes[0] = irn;
391
392                 /* fill */
393                 for (i=0; i<arity; ++i) {
394                         int o, arg_pos;
395                         ir_node *arg = get_irn_n(irn, i);
396
397                         assert(is_curr_reg_class(co, arg) && "Argument not in same register class.");
398                         if (arg == irn)
399                                 continue;
400                         if (nodes_interfere(co->cenv, irn, arg)) {
401                                 unit->inevitable_costs += co->get_costs(co, irn, arg, i);
402                                 continue;
403                         }
404
405                         /* Else insert the argument of the phi to the members of this ou */
406                         DBG((dbg, LEVEL_1, "\t   Member: %+F\n", arg));
407
408                         /* Check if arg has occurred at a prior position in the arg/list */
409                         arg_pos = 0;
410                         for (o=0; o<unit->node_count; ++o)
411                                 if (unit->nodes[o] == arg) {
412                                         arg_pos = o;
413                                         break;
414                                 }
415
416                         if (!arg_pos) { /* a new argument */
417                                 /* insert node, set costs */
418                                 unit->nodes[unit->node_count] = arg;
419                                 unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
420                                 unit->node_count++;
421                         } else { /* arg has occured before in same phi */
422                                 /* increase costs for existing arg */
423                                 unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
424                         }
425                 }
426                 unit->nodes = xrealloc(unit->nodes, unit->node_count * sizeof(*unit->nodes));
427                 unit->costs = xrealloc(unit->costs, unit->node_count * sizeof(*unit->costs));
428         } else
429
430         /* Proj of a perm with corresponding arg */
431         if (is_Perm_Proj(co->aenv, irn)) {
432                 assert(!nodes_interfere(co->cenv, irn, get_Perm_src(irn)));
433                 unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
434                 unit->costs = xmalloc(2 * sizeof(*unit->costs));
435                 unit->node_count = 2;
436                 unit->nodes[0] = irn;
437                 unit->nodes[1] = get_Perm_src(irn);
438                 unit->costs[1] = co->get_costs(co, irn, unit->nodes[1], -1);
439         } else
440
441         /* Src == Tgt of a 2-addr-code instruction */
442         if (is_2addr_code(co->aenv, irn, &req)) {
443                 ir_node *other = req.other_same;
444                 if (!nodes_interfere(co->cenv, irn, other)) {
445                         unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
446                         unit->costs = xmalloc(2 * sizeof(*unit->costs));
447                         unit->node_count = 2;
448                         unit->nodes[0] = irn;
449                         unit->nodes[1] = other;
450                         unit->costs[1] = co->get_costs(co, irn, other, -1);
451                 }
452         } else
453                 assert(0 && "This is not an optimizable node!");
454
455         /* Insert the new unit at a position according to its costs */
456         if (unit->node_count > 1) {
457                 int i;
458                 struct list_head *tmp;
459
460                 /* Determine the maximum costs this unit can cause: all_nodes_cost */
461                 for(i=1; i<unit->node_count; ++i) {
462                         unit->sort_key = MAX(unit->sort_key, unit->costs[i]);
463                         unit->all_nodes_costs += unit->costs[i];
464                 }
465
466                 /* Determine the minimal costs this unit will cause: min_nodes_costs */
467                 unit->min_nodes_costs += unit->all_nodes_costs - ou_max_ind_set_costs(unit);
468                 /* Insert the new ou according to its sort_key */
469                 tmp = &co->units;
470                 while (tmp->next != &co->units && list_entry_units(tmp->next)->sort_key > unit->sort_key)
471                         tmp = tmp->next;
472                 list_add(&unit->units, tmp);
473         } else {
474                 free(unit);
475         }
476 }
477
478 #ifdef QUICK_AND_DIRTY_HACK
479
480 static int compare_ous(const void *k1, const void *k2) {
481         const unit_t *u1 = *((const unit_t **) k1);
482         const unit_t *u2 = *((const unit_t **) k2);
483         int i, o, u1_has_constr, u2_has_constr;
484         arch_register_req_t req;
485         const arch_env_t *aenv = u1->co->aenv;
486
487         /* Units with constraints come first */
488         u1_has_constr = 0;
489         for (i=0; i<u1->node_count; ++i) {
490                 arch_get_register_req(aenv, &req, u1->nodes[i], -1);
491                 if (arch_register_req_is(&req, limited)) {
492                         u1_has_constr = 1;
493                         break;
494                 }
495         }
496
497         u2_has_constr = 0;
498         for (i=0; i<u2->node_count; ++i) {
499                 arch_get_register_req(aenv, &req, u2->nodes[i], -1);
500                 if (arch_register_req_is(&req, limited)) {
501                         u2_has_constr = 1;
502                         break;
503                 }
504         }
505
506         if (u1_has_constr != u2_has_constr)
507                 return u2_has_constr - u1_has_constr;
508
509         /* Now check, whether the two units are connected */
510 #if 0
511         for (i=0; i<u1->node_count; ++i)
512                 for (o=0; o<u2->node_count; ++o)
513                         if (u1->nodes[i] == u2->nodes[o])
514                                 return 0;
515 #endif
516
517         /* After all, the sort key decides. Greater keys come first. */
518         return u2->sort_key - u1->sort_key;
519
520 }
521
522 /**
523  * Sort the ou's according to constraints and their sort_key
524  */
525 static void co_sort_units(copy_opt_t *co) {
526         int i, count = 0, costs;
527         unit_t *ou, **ous;
528
529         /* get the number of ous, remove them form the list and fill the array */
530         list_for_each_entry(unit_t, ou, &co->units, units)
531                 count++;
532         ous = alloca(count * sizeof(*ous));
533
534         costs = co_get_max_copy_costs(co);
535
536         i = 0;
537         list_for_each_entry(unit_t, ou, &co->units, units)
538                 ous[i++] = ou;
539
540         INIT_LIST_HEAD(&co->units);
541
542         assert(count == i && list_empty(&co->units));
543
544         for (i=0; i<count; ++i)
545                 ir_printf("%+F\n", ous[i]->nodes[0]);
546
547         qsort(ous, count, sizeof(*ous), compare_ous);
548
549         ir_printf("\n\n");
550         for (i=0; i<count; ++i)
551                 ir_printf("%+F\n", ous[i]->nodes[0]);
552
553         /* reinsert into list in correct order */
554         for (i=0; i<count; ++i)
555                 list_add_tail(&ous[i]->units, &co->units);
556
557         assert(costs == co_get_max_copy_costs(co));
558 }
559 #endif
560
561 void co_build_ou_structure(copy_opt_t *co) {
562         DBG((dbg, LEVEL_1, "\tCollecting optimization units\n"));
563         INIT_LIST_HEAD(&co->units);
564         irg_walk_graph(co->irg, co_collect_units, NULL, co);
565 #ifdef QUICK_AND_DIRTY_HACK
566         co_sort_units(co);
567 #endif
568 }
569
570 void co_free_ou_structure(copy_opt_t *co) {
571         unit_t *curr, *tmp;
572         ASSERT_OU_AVAIL(co);
573         list_for_each_entry_safe(unit_t, curr, tmp, &co->units, units) {
574                 xfree(curr->nodes);
575                 xfree(curr->costs);
576                 xfree(curr);
577         }
578         co->units.next = NULL;
579 }
580
581 /* co_solve_heuristic() is implemented in becopyheur.c */
582
583 int co_get_max_copy_costs(const copy_opt_t *co) {
584         int i, res = 0;
585         unit_t *curr;
586
587         ASSERT_OU_AVAIL(co);
588
589         list_for_each_entry(unit_t, curr, &co->units, units) {
590                 res += curr->inevitable_costs;
591                 for (i=1; i<curr->node_count; ++i)
592                         res += curr->costs[i];
593         }
594         return res;
595 }
596
597 int co_get_inevit_copy_costs(const copy_opt_t *co) {
598         int res = 0;
599         unit_t *curr;
600
601         ASSERT_OU_AVAIL(co);
602
603         list_for_each_entry(unit_t, curr, &co->units, units)
604                 res += curr->inevitable_costs;
605         return res;
606 }
607
608 int co_get_copy_costs(const copy_opt_t *co) {
609         int i, res = 0;
610         unit_t *curr;
611
612         ASSERT_OU_AVAIL(co);
613
614         list_for_each_entry(unit_t, curr, &co->units, units) {
615                 int root_col = get_irn_col(co, curr->nodes[0]);
616                 DBG((dbg, LEVEL_1, "  %3d costs for root %+F color %d\n", curr->inevitable_costs, curr->nodes[0], root_col));
617                 res += curr->inevitable_costs;
618                 for (i=1; i<curr->node_count; ++i) {
619                         int arg_col = get_irn_col(co, curr->nodes[i]);
620                         if (root_col != arg_col) {
621                                 DBG((dbg, LEVEL_1, "  %3d for arg %+F color %d\n", curr->costs[i], curr->nodes[i], arg_col));
622                                 res += curr->costs[i];
623                         }
624                 }
625         }
626         return res;
627 }
628
629 int co_get_lower_bound(const copy_opt_t *co) {
630         int res = 0;
631         unit_t *curr;
632
633         ASSERT_OU_AVAIL(co);
634
635         list_for_each_entry(unit_t, curr, &co->units, units)
636                 res += curr->inevitable_costs + curr->min_nodes_costs;
637         return res;
638 }
639
640 void co_complete_stats(const copy_opt_t *co, co_complete_stats_t *stat)
641 {
642         bitset_t *seen = bitset_irg_malloc(co->irg);
643         affinity_node_t *an;
644
645         memset(stat, 0, sizeof(stat[0]));
646
647         /* count affinity edges. */
648         co_gs_foreach_aff_node(co, an) {
649                 neighb_t *neigh;
650                 stat->aff_nodes += 1;
651                 bitset_add_irn(seen, an->irn);
652                 co_gs_foreach_neighb(an, neigh) {
653                         if(!bitset_contains_irn(seen, neigh->irn)) {
654                                 stat->aff_edges += 1;
655                                 stat->max_costs += neigh->costs;
656
657                                 if(get_irn_col(co, an->irn) != get_irn_col(co, neigh->irn)) {
658                                         stat->costs += neigh->costs;
659                                         stat->unsatisfied_edges += 1;
660                                 }
661
662                                 if(nodes_interfere(co->cenv, an->irn, neigh->irn)) {
663                                         stat->aff_int += 1;
664                                         stat->inevit_costs += neigh->costs;
665                                 }
666
667                         }
668                 }
669         }
670
671         bitset_free(seen);
672 }
673
674 /******************************************************************************
675    _____                 _        _____ _
676   / ____|               | |      / ____| |
677  | |  __ _ __ __ _ _ __ | |__   | (___ | |_ ___  _ __ __ _  __ _  ___
678  | | |_ | '__/ _` | '_ \| '_ \   \___ \| __/ _ \| '__/ _` |/ _` |/ _ \
679  | |__| | | | (_| | |_) | | | |  ____) | || (_) | | | (_| | (_| |  __/
680   \_____|_|  \__,_| .__/|_| |_| |_____/ \__\___/|_|  \__,_|\__, |\___|
681                   | |                                       __/ |
682                   |_|                                      |___/
683  ******************************************************************************/
684
685 static int compare_affinity_node_t(const void *k1, const void *k2, size_t size) {
686         const affinity_node_t *n1 = k1;
687         const affinity_node_t *n2 = k2;
688
689         return (n1->irn != n2->irn);
690 }
691
692 static void add_edge(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
693         affinity_node_t new_node, *node;
694         neighb_t new_nbr, *nbr;
695         int allocnew;
696
697         new_node.irn        = n1;
698         new_node.degree     = 0;
699         new_node.neighbours = NULL;
700         node = set_insert(co->nodes, &new_node, sizeof(new_node), nodeset_hash(new_node.irn));
701
702         allocnew = 1;
703         for (nbr = node->neighbours; nbr; nbr = nbr->next)
704                 if (nbr->irn == n2) {
705                         allocnew = 0;
706                         break;
707                 }
708
709         /* if we did not find n2 in n1's neighbourhood insert it */
710         if (allocnew) {
711                 obstack_grow(&co->obst, &new_nbr, sizeof(new_nbr));
712                 nbr = obstack_finish(&co->obst);
713                 nbr->irn   = n2;
714                 nbr->costs = 0;
715                 nbr->next  = node->neighbours;
716                 node->neighbours = nbr;
717                 node->degree++;
718         }
719
720         /* now nbr points to n1's neighbour-entry of n2 */
721         nbr->costs += costs;
722 }
723
724 static INLINE void add_edges(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
725         if (! be_ifg_connected(co->cenv->ifg, n1, n2)) {
726                 add_edge(co, n1, n2, costs);
727                 add_edge(co, n2, n1, costs);
728         }
729 }
730
731 static void build_graph_walker(ir_node *irn, void *env) {
732         copy_opt_t *co = env;
733         int pos, max;
734         arch_register_req_t req;
735         const arch_register_t *reg;
736
737         if (!is_curr_reg_class(co, irn) || arch_irn_is(co->aenv, irn, ignore))
738                 return;
739
740         reg = arch_get_irn_register(co->aenv, irn);
741         if (arch_register_type_is(reg, ignore))
742                 return;
743
744         /* Phis */
745         if (is_Reg_Phi(irn))
746                 for (pos=0, max=get_irn_arity(irn); pos<max; ++pos) {
747                         ir_node *arg = get_irn_n(irn, pos);
748                         add_edges(co, irn, arg, co->get_costs(co, irn, arg, pos));
749                 }
750
751         /* Perms */
752         else if (is_Perm_Proj(co->aenv, irn)) {
753                 ir_node *arg = get_Perm_src(irn);
754                 add_edges(co, irn, arg, co->get_costs(co, irn, arg, 0));
755         }
756
757         /* 2-address code */
758         else if (is_2addr_code(co->aenv, irn, &req))
759                 add_edges(co, irn, req.other_same, co->get_costs(co, irn, req.other_same, 0));
760 }
761
762 void co_build_graph_structure(copy_opt_t *co) {
763         obstack_init(&co->obst);
764         co->nodes = new_set(compare_affinity_node_t, 32);
765
766         irg_walk_graph(co->irg, build_graph_walker, NULL, co);
767 }
768
769 void co_free_graph_structure(copy_opt_t *co) {
770         ASSERT_GS_AVAIL(co);
771
772         del_set(co->nodes);
773         obstack_free(&co->obst, NULL);
774         co->nodes = NULL;
775 }
776
777 /* co_solve_ilp1() co_solve_ilp2() are implemented in becopyilpX.c */
778
779 int co_gs_is_optimizable(copy_opt_t *co, ir_node *irn) {
780         affinity_node_t new_node, *n;
781
782         ASSERT_GS_AVAIL(co);
783
784         new_node.irn = irn;
785         n = set_find(co->nodes, &new_node, sizeof(new_node), nodeset_hash(new_node.irn));
786         if (n) {
787                 return (n->degree > 0);
788         } else
789                 return 0;
790 }
791
792 void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
793 {
794         be_ifg_t *ifg  = co->cenv->ifg;
795         int *color_map = alloca(co->cls->n_regs * sizeof(color_map[0]));
796         bitset_t *adm  = bitset_alloca(co->cls->n_regs);
797
798         ir_node *irn;
799         void *it, *nit;
800         int i, n, n_regs;
801
802         n_regs = 0;
803         for(i = 0; i < co->cls->n_regs; ++i) {
804                 const arch_register_t *reg = &co->cls->regs[i];
805                 color_map[i] = arch_register_type_is(reg, ignore) ? -1 : n_regs++;
806         }
807
808         /*
809          * n contains the first node number.
810          * the values below n are the pre-colored register nodes
811          */
812
813         it  = be_ifg_nodes_iter_alloca(ifg);
814         nit = be_ifg_neighbours_iter_alloca(ifg);
815
816         n = n_regs;
817         be_ifg_foreach_node(ifg, it, irn) {
818                 if(!arch_irn_is(co->aenv, irn, ignore))
819                         set_irn_link(irn, INT_TO_PTR(n++));
820         }
821
822         fprintf(f, "%d %d\n", n, n_regs);
823
824         be_ifg_foreach_node(ifg, it, irn) {
825                 if(!arch_irn_is(co->aenv, irn, ignore)) {
826                         int idx            = PTR_TO_INT(get_irn_link(irn));
827                         affinity_node_t *a = get_affinity_info(co, irn);
828
829                         arch_register_req_t req;
830                         ir_node *adj;
831
832                         arch_get_register_req(co->aenv, &req, irn, BE_OUT_POS(0));
833                         if(arch_register_req_is(&req, limited)) {
834                                 bitset_clear_all(adm);
835                                 req.limited(req.limited_env, adm);
836                                 for(i = 0; i < co->cls->n_regs; ++i)
837                                         if(!bitset_is_set(adm, i) && color_map[i] >= 0)
838                                                 fprintf(f, "%d %d -1\n", color_map[i], idx);
839
840                         }
841
842
843                         be_ifg_foreach_neighbour(ifg, nit, irn, adj) {
844                                 if(!arch_irn_is(co->aenv, adj, ignore)) {
845                                         int adj_idx = PTR_TO_INT(get_irn_link(adj));
846                                         if(idx < adj_idx)
847                                                 fprintf(f, "%d %d -1\n", idx, adj_idx);
848                                 }
849                         }
850
851                         if(a) {
852                                 neighb_t *n;
853
854                                 co_gs_foreach_neighb(a, n) {
855                                         if(!arch_irn_is(co->aenv, n->irn, ignore)) {
856                                                 int n_idx = PTR_TO_INT(get_irn_link(n->irn));
857                                                 if(idx < n_idx)
858                                                         fprintf(f, "%d %d %d\n", idx, n_idx, (int) n->costs);
859                                         }
860                                 }
861                         }
862                 }
863         }
864 }
865
866 typedef struct _appel_clique_walker_t {
867         phase_t ph;
868         const copy_opt_t *co;
869         int curr_nr;
870         int node_count;
871         FILE *f;
872         int dumb;
873         int *color_map;
874         struct obstack obst;
875 } appel_clique_walker_t;
876
877 typedef struct _appel_block_info_t {
878         int *live_end_nr;
879         int *live_in_nr;
880         int *phi_nr;
881         ir_node **live_end;
882         ir_node **live_in;
883         ir_node **phi;
884         int n_live_end;
885         int n_live_in;
886         int n_phi;
887 } appel_block_info_t;
888
889 static int appel_aff_weight(const appel_clique_walker_t *env, ir_node *bl)
890 {
891 #if 0
892         double freq = get_block_execfreq(env->co->cenv->execfreq, bl);
893         int res = (int) freq;
894         return res == 0 ? 1 : res;
895 #else
896         ir_loop *loop = get_irn_loop(bl);
897         if(loop) {
898                 int d = get_loop_depth(loop);
899                 return 1 + d * d;
900         }
901         return 1;
902 #endif
903 }
904
905 static void *appel_clique_walker_irn_init(phase_t *phase, ir_node *irn, void *old)
906 {
907         appel_block_info_t *res = NULL;
908
909         if(is_Block(irn)) {
910                 appel_clique_walker_t *d = (void *) phase;
911                 res = phase_alloc(phase, sizeof(res[0]));
912                 res->phi_nr      = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end_nr));
913                 res->live_end_nr = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end_nr));
914                 res->live_in_nr  = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in_nr));
915                 res->live_end    = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end));
916                 res->live_in     = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in));
917                 res->phi         = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in));
918         }
919
920         return res;
921 }
922
923 typedef struct _insn_list_t {
924         be_insn_t *insn;
925         struct list_head list;
926 } insn_list_t;
927
928 static int appel_get_live_end_nr(appel_clique_walker_t *env, ir_node *bl, ir_node *irn)
929 {
930         appel_block_info_t *bli = phase_get_irn_data(&env->ph, bl);
931         int i;
932
933         for(i = 0; i < bli->n_live_end; ++i)
934                 if(bli->live_end[i] == irn)
935                         return bli->live_end_nr[i];
936
937         return -1;
938 }
939
940 static int appel_dump_clique(appel_clique_walker_t *env, pset *live, ir_node *bl, int curr_nr, int start_nr)
941 {
942         ir_node **live_arr = alloca(env->co->cls->n_regs * sizeof(live_arr[0]));
943         ir_node *irn;
944         int n_live;
945         int j;
946
947         n_live = 0;
948         foreach_pset(live, irn)
949                 live_arr[n_live++] = irn;
950
951         /* dump the live after clique */
952         if(!env->dumb) {
953                 for(j = 0; j < n_live; ++j) {
954                         int k;
955
956                         for(k = j + 1; k < n_live; ++k) {
957                                 fprintf(env->f, "%d %d -1 ", curr_nr + j, curr_nr + k);
958                         }
959                         fprintf(env->f, "\n");
960                 }
961         }
962
963         /* dump the affinities */
964         for(j = 0; !env->dumb && j < n_live; ++j) {
965                 ir_node *irn = live_arr[j];
966                 int old_nr = PTR_TO_INT(get_irn_link(irn));
967
968                 /* if the node was already live in the last insn dump the affinity */
969                 if(old_nr > start_nr) {
970                         int weight = appel_aff_weight(env, bl);
971                         fprintf(env->f, "%d %d %d\n", old_nr, curr_nr + j, weight);
972                 }
973         }
974
975         /* set the current numbers into the link field. */
976         for(j = 0; j < n_live; ++j) {
977                 ir_node *irn = live_arr[j];
978                 set_irn_link(irn, INT_TO_PTR(curr_nr + j));
979         }
980
981         return curr_nr + n_live;
982 }
983
984 static void appel_walker(ir_node *bl, void *data)
985 {
986         appel_clique_walker_t *env = data;
987         appel_block_info_t *bli    = phase_get_or_set_irn_data(&env->ph, bl);
988         struct obstack *obst       = &env->obst;
989         void *base                 = obstack_base(obst);
990         pset *live                 = pset_new_ptr_default();
991
992         int n_insns  = 0;
993         int n_nodes  = 0;
994         int start_nr = env->curr_nr;
995         int curr_nr  = start_nr;
996
997         be_insn_env_t insn_env;
998         int i, j;
999         ir_node *irn;
1000         be_insn_t **insns;
1001
1002         insn_env.aenv = env->co->aenv;
1003         insn_env.cls  = env->co->cls;
1004         insn_env.obst = obst;
1005         insn_env.ignore_colors = env->co->cenv->ignore_colors;
1006
1007         /* Guess how many insns will be in this block. */
1008         sched_foreach(bl, irn)
1009                 n_nodes++;
1010
1011         bli->n_phi = 0;
1012         insns = malloc(n_nodes * sizeof(insns[0]));
1013
1014         /* Put all insns in an array. */
1015         irn = sched_first(bl);
1016         while(!sched_is_end(irn)) {
1017                 be_insn_t *insn;
1018                 insn = be_scan_insn(&insn_env, irn);
1019                 insns[n_insns++] = insn;
1020                 irn = insn->next_insn;
1021         }
1022
1023         DBG((env->co->cenv->dbg, LEVEL_2, "%+F\n", bl));
1024         be_liveness_end_of_block(env->co->cenv->lv, env->co->aenv, env->co->cls, bl, live);
1025
1026         /* Generate the bad and ugly. */
1027         for(i = n_insns - 1; i >= 0; --i) {
1028                 be_insn_t *insn = insns[i];
1029
1030                 /* The first live set has to be saved in the block border set. */
1031                 if(i == n_insns - 1) {
1032                         j = 0;
1033                         foreach_pset(live, irn) {
1034                                 bli->live_end[j]    = irn;
1035                                 bli->live_end_nr[j] = curr_nr + j;
1036                                 ++j;
1037                         }
1038                         bli->n_live_end = j;
1039                 }
1040
1041                 if(!env->dumb) {
1042                         for(j = 0; j < insn->use_start; ++j) {
1043                                 ir_node *op   = insn->ops[j].carrier;
1044                                 bitset_t *adm = insn->ops[j].regs;
1045                                 int k;
1046                                 int nr;
1047
1048                                 if(!insn->ops[j].has_constraints)
1049                                         continue;
1050
1051                                 nr = 0;
1052                                 foreach_pset(live, irn) {
1053                                         if(irn == op) {
1054                                                 pset_break(live);
1055                                                 break;
1056                                         }
1057                                         ++nr;
1058                                 }
1059
1060                                 assert(nr < pset_count(live));
1061
1062                                 for(k = 0; k < env->co->cls->n_regs; ++k) {
1063                                         int mapped_col = env->color_map[k];
1064                                         if(mapped_col >= 0 && !bitset_is_set(adm, k) && !bitset_is_set(env->co->cenv->ignore_colors, k))
1065                                                 fprintf(env->f, "%d %d -1\n", curr_nr + nr, mapped_col);
1066                                 }
1067                         }
1068                 }
1069
1070                 /* dump the clique and update the stuff. */
1071                 curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
1072
1073                 /* remove all defs. */
1074                 for(j = 0; j < insn->use_start; ++j)
1075                         pset_remove_ptr(live, insn->ops[j].carrier);
1076
1077                 if(is_Phi(insn->irn) && arch_irn_consider_in_reg_alloc(env->co->aenv, env->co->cls, insn->irn)) {
1078                         bli->phi[bli->n_phi]    = insn->irn;
1079                         bli->phi_nr[bli->n_phi] = PTR_TO_INT(get_irn_link(insn->irn));
1080                         bli->n_phi++;
1081                 }
1082
1083                 /* add all uses */
1084                 else
1085                         for(j = insn->use_start; j < insn->n_ops; ++j)
1086                                 pset_insert_ptr(live, insn->ops[j].carrier);
1087         }
1088
1089         /* print the start clique. */
1090         curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
1091
1092         i = 0;
1093         foreach_pset(live, irn) {
1094                 bli->live_in[i]    = irn;
1095                 bli->live_in_nr[i] = PTR_TO_INT(get_irn_link(irn));
1096                 ++i;
1097         }
1098         bli->n_live_in = i;
1099
1100         del_pset(live);
1101         free(insns);
1102         obstack_free(obst, base);
1103         env->curr_nr = curr_nr;
1104 }
1105
1106 static void appel_inter_block_aff(ir_node *bl, void *data)
1107 {
1108         appel_clique_walker_t *env = data;
1109         appel_block_info_t *bli    = phase_get_irn_data(&env->ph, bl);
1110
1111         int i, j, n;
1112
1113         for(i = 0; i < bli->n_live_in; ++i) {
1114                 ir_node *irn = bli->live_in[i];
1115
1116                 for(j = 0, n = get_Block_n_cfgpreds(bl); j < n; ++j) {
1117                         ir_node *pred  = get_Block_cfgpred_block(bl, j);
1118
1119                         int nr = appel_get_live_end_nr(env, pred, irn);
1120                         assert(nr >= 0);
1121                         fprintf(env->f, "%d %d 1\n", bli->live_in_nr[i], nr);
1122                 }
1123         }
1124
1125         for(i = 0; i < bli->n_phi; ++i) {
1126                 ir_node *irn = bli->phi[i];
1127
1128                 for(j = 0, n = get_Block_n_cfgpreds(bl); j < n; ++j) {
1129                         ir_node *pred  = get_Block_cfgpred_block(bl, j);
1130                         ir_node *op = get_irn_n(irn, j);
1131
1132                         int nr = appel_get_live_end_nr(env, pred, op);
1133                         assert(nr >= 0);
1134                         fprintf(env->f, "%d %d 1\n", bli->phi_nr[i], nr);
1135                 }
1136         }
1137
1138 }
1139
1140 void co_dump_appel_graph_cliques(const copy_opt_t *co, FILE *f)
1141 {
1142         int i;
1143         int n_colors;
1144         appel_clique_walker_t env;
1145         bitset_t *adm = bitset_alloca(co->cls->n_regs);
1146
1147         be_liveness_recompute(co->cenv->lv);
1148         obstack_init(&env.obst);
1149         phase_init(&env.ph, "appel_clique_dumper", co->irg, PHASE_DEFAULT_GROWTH, appel_clique_walker_irn_init);
1150         env.curr_nr = co->cls->n_regs;
1151         env.co = co;
1152         env.f = f;
1153
1154         bitset_copy(adm, co->cenv->ignore_colors);
1155         bitset_flip_all(adm);
1156
1157         /* Make color map. */
1158         env.color_map = alloca(co->cls->n_regs * sizeof(env.color_map[0]));
1159         for(i = 0, n_colors = 0; i < co->cls->n_regs; ++i) {
1160                 const arch_register_t *reg = &co->cls->regs[i];
1161                 env.color_map[i] = arch_register_type_is(reg, ignore) ? -1 : n_colors++;
1162         }
1163
1164         env.dumb = 1;
1165         env.curr_nr = n_colors;
1166         irg_block_walk_graph(co->irg, firm_clear_link, NULL, NULL);
1167         irg_block_walk_graph(co->irg, appel_walker, NULL, &env);
1168
1169         fprintf(f, "%d %d\n", env.curr_nr, n_colors);
1170
1171         /* make the first k nodes interfere */
1172         for(i = 0; i < n_colors; ++i) {
1173                 int j;
1174                 for(j = i + 1; j < n_colors; ++j)
1175                         fprintf(f, "%d %d -1 ", i, j);
1176                 fprintf(f, "\n");
1177         }
1178
1179         env.dumb = 0;
1180         env.curr_nr = n_colors;
1181         irg_block_walk_graph(co->irg, firm_clear_link, NULL, NULL);
1182         irg_block_walk_graph(co->irg, appel_walker, NULL, &env);
1183         irg_block_walk_graph(co->irg, appel_inter_block_aff, NULL, &env);
1184         obstack_free(&env.obst, NULL);
1185 }
1186
1187 /*
1188          ___ _____ ____   ____   ___ _____   ____                        _
1189         |_ _|  ___/ ___| |  _ \ / _ \_   _| |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
1190          | || |_ | |  _  | | | | | | || |   | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
1191          | ||  _|| |_| | | |_| | |_| || |   | |_| | |_| | | | | | | |_) | | | | | (_| |
1192         |___|_|   \____| |____/ \___/ |_|   |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
1193                                                                   |_|            |___/
1194 */
1195
1196 static const char *get_dot_color_name(int col)
1197 {
1198         static const char *names[] = {
1199                 "blue",
1200                 "red",
1201                 "green",
1202                 "yellow",
1203                 "cyan",
1204                 "magenta",
1205                 "orange",
1206                 "chocolate",
1207                 "beige",
1208                 "navy",
1209                 "darkgreen",
1210                 "darkred",
1211                 "lightPink",
1212                 "chartreuse",
1213                 "lightskyblue",
1214                 "linen",
1215                 "pink",
1216                 "lightslateblue",
1217                 "mintcream",
1218                 "red",
1219                 "darkolivegreen",
1220                 "mediumblue",
1221                 "mistyrose",
1222                 "salmon",
1223                 "darkseagreen",
1224                 "mediumslateblue"
1225                 "moccasin",
1226                 "tomato",
1227                 "forestgreen",
1228                 "darkturquoise",
1229                 "palevioletred"
1230         };
1231
1232         return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
1233 }
1234
1235 typedef struct _co_ifg_dump_t {
1236         const copy_opt_t *co;
1237         unsigned flags;
1238 } co_ifg_dump_t;
1239
1240 static void ifg_dump_graph_attr(FILE *f, void *self)
1241 {
1242         fprintf(f, "overlap=scale");
1243 }
1244
1245 static int ifg_is_dump_node(void *self, ir_node *irn)
1246 {
1247         co_ifg_dump_t *cod = self;
1248         return !arch_irn_is(cod->co->aenv, irn, ignore);
1249 }
1250
1251 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
1252 {
1253         co_ifg_dump_t *env         = self;
1254         const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
1255         arch_register_req_t req;
1256         int limited;
1257
1258         arch_get_register_req(env->co->aenv, &req, irn, BE_OUT_POS(0));
1259         limited = arch_register_req_is(&req, limited);
1260
1261         if(env->flags & CO_IFG_DUMP_LABELS) {
1262                 ir_fprintf(f, "label=\"%+F", irn);
1263
1264                 if((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
1265                         bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
1266                         req.limited(req.limited_env, bs);
1267                         ir_fprintf(f, "\\n%B", bs);
1268                 }
1269                 ir_fprintf(f, "\" ");
1270         }
1271
1272         else
1273                 fprintf(f, "label=\"\" shape=point " );
1274
1275         if(env->flags & CO_IFG_DUMP_SHAPE)
1276                 fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
1277
1278         if(env->flags & CO_IFG_DUMP_COLORS)
1279                 fprintf(f, "style=filled color=%s ", get_dot_color_name(reg->index));
1280 }
1281
1282 static void ifg_dump_at_end(FILE *file, void *self)
1283 {
1284         co_ifg_dump_t *env = self;
1285         affinity_node_t *a;
1286
1287         co_gs_foreach_aff_node(env->co, a) {
1288                 const arch_register_t *ar = arch_get_irn_register(env->co->aenv, a->irn);
1289                 unsigned aidx = get_irn_idx(a->irn);
1290                 neighb_t *n;
1291
1292                 co_gs_foreach_neighb(a, n) {
1293                         const arch_register_t *nr = arch_get_irn_register(env->co->aenv, n->irn);
1294                         unsigned nidx = get_irn_idx(n->irn);
1295
1296                         if(aidx < nidx) {
1297                                 const char *color = nr == ar ? "blue" : "red";
1298                                 fprintf(file, "\tn%d -- n%d [weight=0.01 ", aidx, nidx);
1299                                 if(env->flags & CO_IFG_DUMP_LABELS)
1300                                         fprintf(file, "label=\"%d\" ", n->costs);
1301                                 if(env->flags & CO_IFG_DUMP_COLORS)
1302                                         fprintf(file, "color=%s ", color);
1303                                 else
1304                                         fprintf(file, "style=dotted");
1305                                 fprintf(file, "];\n");
1306                         }
1307                 }
1308         }
1309 }
1310
1311
1312 static be_ifg_dump_dot_cb_t ifg_dot_cb = {
1313         ifg_is_dump_node,
1314         ifg_dump_graph_attr,
1315         ifg_dump_node_attr,
1316         NULL,
1317         NULL,
1318         ifg_dump_at_end
1319 };
1320
1321
1322
1323 void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags)
1324 {
1325         co_ifg_dump_t cod;
1326
1327         cod.co    = co;
1328         cod.flags = flags;
1329         be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &cod);
1330 }
1331
1332
1333 void co_solve_park_moon(copy_opt_t *opt)
1334 {
1335
1336 }
1337
1338 static int void_algo(copy_opt_t *co)
1339 {
1340         return 0;
1341 }
1342
1343 /*
1344                 _    _                  _ _   _
1345            / \  | | __ _  ___  _ __(_) |_| |__  _ __ ___  ___
1346           / _ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \/ __|
1347          / ___ \| | (_| | (_) | |  | | |_| | | | | | | | \__ \
1348         /_/   \_\_|\__, |\___/|_|  |_|\__|_| |_|_| |_| |_|___/
1349                            |___/
1350 */
1351
1352 typedef struct {
1353         co_algo_t *algo;
1354         const char *name;
1355         int can_improve_existing;
1356 } co_algo_info_t;
1357
1358 static co_algo_info_t algos[] = {
1359         { void_algo,                "none",  0 },
1360         { co_solve_heuristic,       "heur1", 0 },
1361         { co_solve_heuristic_new,   "heur2", 0 },
1362         { co_solve_heuristic_java,  "heur3", 0 },
1363 #ifdef WITH_ILP
1364         { co_solve_ilp2,            "ilp",   1 },
1365 #endif
1366         { NULL,                     "",      0 }
1367 };
1368
1369 /*
1370     __  __       _         ____       _
1371    |  \/  | __ _(_)_ __   |  _ \ _ __(_)_   _____ _ __
1372    | |\/| |/ _` | | '_ \  | | | | '__| \ \ / / _ \ '__|
1373    | |  | | (_| | | | | | | |_| | |  | |\ V /  __/ |
1374    |_|  |_|\__,_|_|_| |_| |____/|_|  |_| \_/ \___|_|
1375
1376 */
1377
1378 void co_driver(be_chordal_env_t *cenv)
1379 {
1380         co_complete_stats_t before, after;
1381         copy_opt_t *co;
1382         co_algo_t  *algo_func;
1383         int was_optimal = 0;
1384
1385         if(algo < 0 || algo >= CO_ALGO_LAST)
1386                 return;
1387
1388         co = new_copy_opt(cenv, cost_func);
1389         co_build_ou_structure(co);
1390         co_build_graph_structure(co);
1391
1392         co_complete_stats(co, &before);
1393
1394         be_stat_ev("co_aff_nodes",    before.aff_nodes);
1395         be_stat_ev("co_aff_edges",    before.aff_edges);
1396         be_stat_ev("co_max_costs",    before.max_costs);
1397         be_stat_ev("co_inevit_costs", before.inevit_costs);
1398         be_stat_ev("co_aff_int",      before.aff_int);
1399
1400         be_stat_ev("co_init_costs",   before.costs);
1401         be_stat_ev("co_init_unsat",   before.unsatisfied_edges);
1402
1403         /* Dump the interference graph in Appel's format. */
1404         if(dump_flags & DUMP_APPEL) {
1405                 FILE *f = be_chordal_open(cenv, "", ".apl");
1406                 co_dump_appel_graph(co, f);
1407                 fclose(f);
1408         }
1409
1410         if(dump_flags & DUMP_BEFORE) {
1411                 FILE *f = be_chordal_open(cenv, "", "-before.dot");
1412                 co_dump_ifg_dot(co, f, style_flags);
1413                 fclose(f);
1414         }
1415
1416         /* if the algo can improve results, provide an initial solution with heur3 */
1417         if(improve && algos[algo].can_improve_existing) {
1418                 co_complete_stats_t stats;
1419
1420                 /* produce a heuristical solution */
1421                 co_solve_heuristic_java(co);
1422
1423                 /* do the stats and provide the current costs */
1424                 co_complete_stats(co, &stats);
1425                 be_stat_ev("co_prepare_costs", stats.costs);
1426         }
1427
1428         algo_func = algos[algo].algo;
1429         was_optimal = algo_func(co);
1430         be_stat_ev("co_optimal", was_optimal);
1431
1432         if(dump_flags & DUMP_AFTER) {
1433                 FILE *f = be_chordal_open(cenv, "", "-after.dot");
1434                 co_dump_ifg_dot(co, f, style_flags);
1435                 fclose(f);
1436         }
1437
1438         co_complete_stats(co, &after);
1439
1440         if(do_stats) {
1441                 int optimizable_costs = after.max_costs - after.inevit_costs;
1442                 int evitable          = after.costs     - after.inevit_costs;
1443
1444                 ir_printf("%30F %10s %10d%10d%10d", cenv->irg, cenv->cls->name, after.max_costs, before.costs, after.inevit_costs);
1445
1446                 if(optimizable_costs > 0)
1447                         printf("%10d %5.2f\n", after.costs, (evitable * 100.0) / optimizable_costs);
1448                 else
1449                         printf("%10d %5s\n", after.costs, "-");
1450         }
1451
1452         be_stat_ev("co_after_costs", after.costs);
1453         be_stat_ev("co_after_unsat", after.unsatisfied_edges);
1454
1455         co_free_graph_structure(co);
1456         co_free_ou_structure(co);
1457         free_copy_opt(co);
1458 }