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