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