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