allow character mode constants
[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                         /* Check if arg has occurred at a prior position in the arg/list */
424                         arg_pos = 0;
425                         for (o=0; o<unit->node_count; ++o)
426                                 if (unit->nodes[o] == arg) {
427                                         arg_pos = o;
428                                         break;
429                                 }
430
431                         if (!arg_pos) { /* a new argument */
432                                 /* insert node, set costs */
433                                 unit->nodes[unit->node_count] = arg;
434                                 unit->costs[unit->node_count] = co->get_costs(co, irn, arg, i);
435                                 unit->node_count++;
436                         } else { /* arg has occured before in same phi */
437                                 /* increase costs for existing arg */
438                                 unit->costs[arg_pos] += co->get_costs(co, irn, arg, i);
439                         }
440                 }
441                 unit->nodes = xrealloc(unit->nodes, unit->node_count * sizeof(*unit->nodes));
442                 unit->costs = xrealloc(unit->costs, unit->node_count * sizeof(*unit->costs));
443         } else
444
445         /* Proj of a perm with corresponding arg */
446         if (is_Perm_Proj(co->aenv, irn)) {
447                 assert(!nodes_interfere(co->cenv, irn, get_Perm_src(irn)));
448                 unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
449                 unit->costs = xmalloc(2 * sizeof(*unit->costs));
450                 unit->node_count = 2;
451                 unit->nodes[0] = irn;
452                 unit->nodes[1] = get_Perm_src(irn);
453                 unit->costs[1] = co->get_costs(co, irn, unit->nodes[1], -1);
454         } else {
455                 const arch_register_req_t *req =
456                         arch_get_register_req(co->aenv, irn, -1);
457
458                 /* Src == Tgt of a 2-addr-code instruction */
459                 if (is_2addr_code(req)) {
460                         ir_node *other = get_irn_n(irn, req->other_same);
461                         if (!arch_irn_is(co->aenv, other, ignore) &&
462                                         !nodes_interfere(co->cenv, irn, other)) {
463                                 unit->nodes = xmalloc(2 * sizeof(*unit->nodes));
464                                 unit->costs = xmalloc(2 * sizeof(*unit->costs));
465                                 unit->node_count = 2;
466                                 unit->nodes[0] = irn;
467                                 unit->nodes[1] = other;
468                                 unit->costs[1] = co->get_costs(co, irn, other, -1);
469                         }
470                 } else {
471                         assert(0 && "This is not an optimizable node!");
472                 }
473         }
474
475         /* Insert the new unit at a position according to its costs */
476         if (unit->node_count > 1) {
477                 int i;
478                 struct list_head *tmp;
479
480                 /* Determine the maximum costs this unit can cause: all_nodes_cost */
481                 for(i=1; i<unit->node_count; ++i) {
482                         unit->sort_key = MAX(unit->sort_key, unit->costs[i]);
483                         unit->all_nodes_costs += unit->costs[i];
484                 }
485
486                 /* Determine the minimal costs this unit will cause: min_nodes_costs */
487                 unit->min_nodes_costs += unit->all_nodes_costs - ou_max_ind_set_costs(unit);
488                 /* Insert the new ou according to its sort_key */
489                 tmp = &co->units;
490                 while (tmp->next != &co->units && list_entry_units(tmp->next)->sort_key > unit->sort_key)
491                         tmp = tmp->next;
492                 list_add(&unit->units, tmp);
493         } else {
494                 free(unit);
495         }
496 }
497
498 #ifdef QUICK_AND_DIRTY_HACK
499
500 static int compare_ous(const void *k1, const void *k2) {
501         const unit_t *u1 = *((const unit_t **) k1);
502         const unit_t *u2 = *((const unit_t **) k2);
503         int i, o, u1_has_constr, u2_has_constr;
504         arch_register_req_t req;
505         const arch_env_t *aenv = u1->co->aenv;
506
507         /* Units with constraints come first */
508         u1_has_constr = 0;
509         for (i=0; i<u1->node_count; ++i) {
510                 arch_get_register_req(aenv, &req, u1->nodes[i], -1);
511                 if (arch_register_req_is(&req, limited)) {
512                         u1_has_constr = 1;
513                         break;
514                 }
515         }
516
517         u2_has_constr = 0;
518         for (i=0; i<u2->node_count; ++i) {
519                 arch_get_register_req(aenv, &req, u2->nodes[i], -1);
520                 if (arch_register_req_is(&req, limited)) {
521                         u2_has_constr = 1;
522                         break;
523                 }
524         }
525
526         if (u1_has_constr != u2_has_constr)
527                 return u2_has_constr - u1_has_constr;
528
529         /* Now check, whether the two units are connected */
530 #if 0
531         for (i=0; i<u1->node_count; ++i)
532                 for (o=0; o<u2->node_count; ++o)
533                         if (u1->nodes[i] == u2->nodes[o])
534                                 return 0;
535 #endif
536
537         /* After all, the sort key decides. Greater keys come first. */
538         return u2->sort_key - u1->sort_key;
539
540 }
541
542 /**
543  * Sort the ou's according to constraints and their sort_key
544  */
545 static void co_sort_units(copy_opt_t *co) {
546         int i, count = 0, costs;
547         unit_t *ou, **ous;
548
549         /* get the number of ous, remove them form the list and fill the array */
550         list_for_each_entry(unit_t, ou, &co->units, units)
551                 count++;
552         ous = alloca(count * sizeof(*ous));
553
554         costs = co_get_max_copy_costs(co);
555
556         i = 0;
557         list_for_each_entry(unit_t, ou, &co->units, units)
558                 ous[i++] = ou;
559
560         INIT_LIST_HEAD(&co->units);
561
562         assert(count == i && list_empty(&co->units));
563
564         for (i=0; i<count; ++i)
565                 ir_printf("%+F\n", ous[i]->nodes[0]);
566
567         qsort(ous, count, sizeof(*ous), compare_ous);
568
569         ir_printf("\n\n");
570         for (i=0; i<count; ++i)
571                 ir_printf("%+F\n", ous[i]->nodes[0]);
572
573         /* reinsert into list in correct order */
574         for (i=0; i<count; ++i)
575                 list_add_tail(&ous[i]->units, &co->units);
576
577         assert(costs == co_get_max_copy_costs(co));
578 }
579 #endif
580
581 void co_build_ou_structure(copy_opt_t *co) {
582         DBG((dbg, LEVEL_1, "\tCollecting optimization units\n"));
583         INIT_LIST_HEAD(&co->units);
584         irg_walk_graph(co->irg, co_collect_units, NULL, co);
585 #ifdef QUICK_AND_DIRTY_HACK
586         co_sort_units(co);
587 #endif
588 }
589
590 void co_free_ou_structure(copy_opt_t *co) {
591         unit_t *curr, *tmp;
592         ASSERT_OU_AVAIL(co);
593         list_for_each_entry_safe(unit_t, curr, tmp, &co->units, units) {
594                 xfree(curr->nodes);
595                 xfree(curr->costs);
596                 xfree(curr);
597         }
598         co->units.next = NULL;
599 }
600
601 /* co_solve_heuristic() is implemented in becopyheur.c */
602
603 int co_get_max_copy_costs(const copy_opt_t *co) {
604         int i, res = 0;
605         unit_t *curr;
606
607         ASSERT_OU_AVAIL(co);
608
609         list_for_each_entry(unit_t, curr, &co->units, units) {
610                 res += curr->inevitable_costs;
611                 for (i=1; i<curr->node_count; ++i)
612                         res += curr->costs[i];
613         }
614         return res;
615 }
616
617 int co_get_inevit_copy_costs(const copy_opt_t *co) {
618         int res = 0;
619         unit_t *curr;
620
621         ASSERT_OU_AVAIL(co);
622
623         list_for_each_entry(unit_t, curr, &co->units, units)
624                 res += curr->inevitable_costs;
625         return res;
626 }
627
628 int co_get_copy_costs(const copy_opt_t *co) {
629         int i, res = 0;
630         unit_t *curr;
631
632         ASSERT_OU_AVAIL(co);
633
634         list_for_each_entry(unit_t, curr, &co->units, units) {
635                 int root_col = get_irn_col(co, curr->nodes[0]);
636                 DBG((dbg, LEVEL_1, "  %3d costs for root %+F color %d\n", curr->inevitable_costs, curr->nodes[0], root_col));
637                 res += curr->inevitable_costs;
638                 for (i=1; i<curr->node_count; ++i) {
639                         int arg_col = get_irn_col(co, curr->nodes[i]);
640                         if (root_col != arg_col) {
641                                 DBG((dbg, LEVEL_1, "  %3d for arg %+F color %d\n", curr->costs[i], curr->nodes[i], arg_col));
642                                 res += curr->costs[i];
643                         }
644                 }
645         }
646         return res;
647 }
648
649 int co_get_lower_bound(const copy_opt_t *co) {
650         int res = 0;
651         unit_t *curr;
652
653         ASSERT_OU_AVAIL(co);
654
655         list_for_each_entry(unit_t, curr, &co->units, units)
656                 res += curr->inevitable_costs + curr->min_nodes_costs;
657         return res;
658 }
659
660 void co_complete_stats(const copy_opt_t *co, co_complete_stats_t *stat)
661 {
662         bitset_t *seen = bitset_irg_malloc(co->irg);
663         affinity_node_t *an;
664
665         memset(stat, 0, sizeof(stat[0]));
666
667         /* count affinity edges. */
668         co_gs_foreach_aff_node(co, an) {
669                 neighb_t *neigh;
670                 stat->aff_nodes += 1;
671                 bitset_add_irn(seen, an->irn);
672                 co_gs_foreach_neighb(an, neigh) {
673                         if(!bitset_contains_irn(seen, neigh->irn)) {
674                                 stat->aff_edges += 1;
675                                 stat->max_costs += neigh->costs;
676
677                                 if(get_irn_col(co, an->irn) != get_irn_col(co, neigh->irn)) {
678                                         stat->costs += neigh->costs;
679                                         stat->unsatisfied_edges += 1;
680                                 }
681
682                                 if(nodes_interfere(co->cenv, an->irn, neigh->irn)) {
683                                         stat->aff_int += 1;
684                                         stat->inevit_costs += neigh->costs;
685                                 }
686
687                         }
688                 }
689         }
690
691         bitset_free(seen);
692 }
693
694 /******************************************************************************
695    _____                 _        _____ _
696   / ____|               | |      / ____| |
697  | |  __ _ __ __ _ _ __ | |__   | (___ | |_ ___  _ __ __ _  __ _  ___
698  | | |_ | '__/ _` | '_ \| '_ \   \___ \| __/ _ \| '__/ _` |/ _` |/ _ \
699  | |__| | | | (_| | |_) | | | |  ____) | || (_) | | | (_| | (_| |  __/
700   \_____|_|  \__,_| .__/|_| |_| |_____/ \__\___/|_|  \__,_|\__, |\___|
701                   | |                                       __/ |
702                   |_|                                      |___/
703  ******************************************************************************/
704
705 static int compare_affinity_node_t(const void *k1, const void *k2, size_t size) {
706         const affinity_node_t *n1 = k1;
707         const affinity_node_t *n2 = k2;
708
709         return (n1->irn != n2->irn);
710 }
711
712 static void add_edge(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
713         affinity_node_t new_node, *node;
714         neighb_t new_nbr, *nbr;
715         int allocnew;
716
717         new_node.irn        = n1;
718         new_node.degree     = 0;
719         new_node.neighbours = NULL;
720         node = set_insert(co->nodes, &new_node, sizeof(new_node), nodeset_hash(new_node.irn));
721
722         allocnew = 1;
723         for (nbr = node->neighbours; nbr; nbr = nbr->next)
724                 if (nbr->irn == n2) {
725                         allocnew = 0;
726                         break;
727                 }
728
729         /* if we did not find n2 in n1's neighbourhood insert it */
730         if (allocnew) {
731                 obstack_grow(&co->obst, &new_nbr, sizeof(new_nbr));
732                 nbr = obstack_finish(&co->obst);
733                 nbr->irn   = n2;
734                 nbr->costs = 0;
735                 nbr->next  = node->neighbours;
736                 node->neighbours = nbr;
737                 node->degree++;
738         }
739
740         /* now nbr points to n1's neighbour-entry of n2 */
741         nbr->costs += costs;
742 }
743
744 static INLINE void add_edges(copy_opt_t *co, ir_node *n1, ir_node *n2, int costs) {
745         if (! be_ifg_connected(co->cenv->ifg, n1, n2)) {
746                 add_edge(co, n1, n2, costs);
747                 add_edge(co, n2, n1, costs);
748         }
749 }
750
751 static void build_graph_walker(ir_node *irn, void *env) {
752         copy_opt_t *co = env;
753         int pos, max;
754         const arch_register_t *reg;
755
756         if (!is_curr_reg_class(co, irn) || arch_irn_is(co->aenv, irn, ignore))
757                 return;
758
759         reg = arch_get_irn_register(co->aenv, irn);
760         if (arch_register_type_is(reg, ignore))
761                 return;
762
763         /* Phis */
764         if (is_Reg_Phi(irn))
765                 for (pos=0, max=get_irn_arity(irn); pos<max; ++pos) {
766                         ir_node *arg = get_irn_n(irn, pos);
767                         add_edges(co, irn, arg, co->get_costs(co, irn, arg, pos));
768                 }
769
770         /* Perms */
771         else if (is_Perm_Proj(co->aenv, irn)) {
772                 ir_node *arg = get_Perm_src(irn);
773                 add_edges(co, irn, arg, co->get_costs(co, irn, arg, 0));
774         }
775
776         /* 2-address code */
777         else {
778                 const arch_register_req_t *req =
779                         arch_get_register_req(co->aenv, irn, -1);
780                 if (is_2addr_code(req)) {
781                         ir_node *other = get_irn_n(irn, req->other_same);
782                         if(!arch_irn_is(co->aenv, other, ignore))
783                                 add_edges(co, irn, other, co->get_costs(co, irn, other, 0));
784                 }
785         }
786 }
787
788 void co_build_graph_structure(copy_opt_t *co) {
789         obstack_init(&co->obst);
790         co->nodes = new_set(compare_affinity_node_t, 32);
791
792         irg_walk_graph(co->irg, build_graph_walker, NULL, co);
793 }
794
795 void co_free_graph_structure(copy_opt_t *co) {
796         ASSERT_GS_AVAIL(co);
797
798         del_set(co->nodes);
799         obstack_free(&co->obst, NULL);
800         co->nodes = NULL;
801 }
802
803 /* co_solve_ilp1() co_solve_ilp2() are implemented in becopyilpX.c */
804
805 int co_gs_is_optimizable(copy_opt_t *co, ir_node *irn) {
806         affinity_node_t new_node, *n;
807
808         ASSERT_GS_AVAIL(co);
809
810         new_node.irn = irn;
811         n = set_find(co->nodes, &new_node, sizeof(new_node), nodeset_hash(new_node.irn));
812         if (n) {
813                 return (n->degree > 0);
814         } else
815                 return 0;
816 }
817
818 void co_dump_appel_graph(const copy_opt_t *co, FILE *f)
819 {
820         be_ifg_t *ifg  = co->cenv->ifg;
821         int *color_map = alloca(co->cls->n_regs * sizeof(color_map[0]));
822
823         ir_node *irn;
824         void *it, *nit;
825         int i, n, n_regs;
826
827         n_regs = 0;
828         for(i = 0; i < co->cls->n_regs; ++i) {
829                 const arch_register_t *reg = &co->cls->regs[i];
830                 color_map[i] = arch_register_type_is(reg, ignore) ? -1 : n_regs++;
831         }
832
833         /*
834          * n contains the first node number.
835          * the values below n are the pre-colored register nodes
836          */
837
838         it  = be_ifg_nodes_iter_alloca(ifg);
839         nit = be_ifg_neighbours_iter_alloca(ifg);
840
841         n = n_regs;
842         be_ifg_foreach_node(ifg, it, irn) {
843                 if(!arch_irn_is(co->aenv, irn, ignore))
844                         set_irn_link(irn, INT_TO_PTR(n++));
845         }
846
847         fprintf(f, "%d %d\n", n, n_regs);
848
849         be_ifg_foreach_node(ifg, it, irn) {
850                 if(!arch_irn_is(co->aenv, irn, ignore)) {
851                         int idx            = PTR_TO_INT(get_irn_link(irn));
852                         affinity_node_t *a = get_affinity_info(co, irn);
853
854                         const arch_register_req_t *req;
855                         ir_node *adj;
856
857                         req = arch_get_register_req(co->aenv, irn, BE_OUT_POS(0));
858                         if(arch_register_req_is(req, limited)) {
859                                 for(i = 0; i < co->cls->n_regs; ++i) {
860                                         if(!rbitset_is_set(req->limited, i) && color_map[i] >= 0)
861                                                 fprintf(f, "%d %d -1\n", color_map[i], idx);
862                                 }
863                         }
864
865
866                         be_ifg_foreach_neighbour(ifg, nit, irn, adj) {
867                                 if(!arch_irn_is(co->aenv, adj, ignore)) {
868                                         int adj_idx = PTR_TO_INT(get_irn_link(adj));
869                                         if(idx < adj_idx)
870                                                 fprintf(f, "%d %d -1\n", idx, adj_idx);
871                                 }
872                         }
873
874                         if(a) {
875                                 neighb_t *n;
876
877                                 co_gs_foreach_neighb(a, n) {
878                                         if(!arch_irn_is(co->aenv, n->irn, ignore)) {
879                                                 int n_idx = PTR_TO_INT(get_irn_link(n->irn));
880                                                 if(idx < n_idx)
881                                                         fprintf(f, "%d %d %d\n", idx, n_idx, (int) n->costs);
882                                         }
883                                 }
884                         }
885                 }
886         }
887 }
888
889 typedef struct _appel_clique_walker_t {
890         ir_phase ph;
891         const copy_opt_t *co;
892         int curr_nr;
893         int node_count;
894         FILE *f;
895         int dumb;
896         int *color_map;
897         struct obstack obst;
898 } appel_clique_walker_t;
899
900 typedef struct _appel_block_info_t {
901         int *live_end_nr;
902         int *live_in_nr;
903         int *phi_nr;
904         ir_node **live_end;
905         ir_node **live_in;
906         ir_node **phi;
907         int n_live_end;
908         int n_live_in;
909         int n_phi;
910 } appel_block_info_t;
911
912 static int appel_aff_weight(const appel_clique_walker_t *env, ir_node *bl)
913 {
914 #if 0
915         double freq = get_block_execfreq(env->co->cenv->execfreq, bl);
916         int res = (int) freq;
917         return res == 0 ? 1 : res;
918 #else
919         ir_loop *loop = get_irn_loop(bl);
920         if(loop) {
921                 int d = get_loop_depth(loop);
922                 return 1 + d * d;
923         }
924         return 1;
925 #endif
926 }
927
928 static void *appel_clique_walker_irn_init(ir_phase *phase, ir_node *irn, void *old)
929 {
930         appel_block_info_t *res = NULL;
931
932         if(is_Block(irn)) {
933                 appel_clique_walker_t *d = (void *) phase;
934                 res = phase_alloc(phase, sizeof(res[0]));
935                 res->phi_nr      = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end_nr));
936                 res->live_end_nr = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end_nr));
937                 res->live_in_nr  = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in_nr));
938                 res->live_end    = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_end));
939                 res->live_in     = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in));
940                 res->phi         = phase_alloc(phase, d->co->cls->n_regs * sizeof(res->live_in));
941         }
942
943         return res;
944 }
945
946 typedef struct _insn_list_t {
947         be_insn_t *insn;
948         struct list_head list;
949 } insn_list_t;
950
951 static int appel_get_live_end_nr(appel_clique_walker_t *env, ir_node *bl, ir_node *irn)
952 {
953         appel_block_info_t *bli = phase_get_irn_data(&env->ph, bl);
954         int i;
955
956         for(i = 0; i < bli->n_live_end; ++i)
957                 if(bli->live_end[i] == irn)
958                         return bli->live_end_nr[i];
959
960         return -1;
961 }
962
963 static int appel_dump_clique(appel_clique_walker_t *env, pset *live, ir_node *bl, int curr_nr, int start_nr)
964 {
965         ir_node **live_arr = alloca(env->co->cls->n_regs * sizeof(live_arr[0]));
966         ir_node *irn;
967         int n_live;
968         int j;
969
970         n_live = 0;
971         foreach_pset(live, irn)
972                 live_arr[n_live++] = irn;
973
974         /* dump the live after clique */
975         if(!env->dumb) {
976                 for(j = 0; j < n_live; ++j) {
977                         int k;
978
979                         for(k = j + 1; k < n_live; ++k) {
980                                 fprintf(env->f, "%d %d -1 ", curr_nr + j, curr_nr + k);
981                         }
982                         fprintf(env->f, "\n");
983                 }
984         }
985
986         /* dump the affinities */
987         for(j = 0; !env->dumb && j < n_live; ++j) {
988                 ir_node *irn = live_arr[j];
989                 int old_nr = PTR_TO_INT(get_irn_link(irn));
990
991                 /* if the node was already live in the last insn dump the affinity */
992                 if(old_nr > start_nr) {
993                         int weight = appel_aff_weight(env, bl);
994                         fprintf(env->f, "%d %d %d\n", old_nr, curr_nr + j, weight);
995                 }
996         }
997
998         /* set the current numbers into the link field. */
999         for(j = 0; j < n_live; ++j) {
1000                 ir_node *irn = live_arr[j];
1001                 set_irn_link(irn, INT_TO_PTR(curr_nr + j));
1002         }
1003
1004         return curr_nr + n_live;
1005 }
1006
1007 static void appel_walker(ir_node *bl, void *data)
1008 {
1009         appel_clique_walker_t *env = data;
1010         appel_block_info_t *bli    = phase_get_or_set_irn_data(&env->ph, bl);
1011         struct obstack *obst       = &env->obst;
1012         void *base                 = obstack_base(obst);
1013         pset *live                 = pset_new_ptr_default();
1014         be_lv_t *lv                = env->co->cenv->birg->lv;
1015
1016         int n_insns  = 0;
1017         int n_nodes  = 0;
1018         int start_nr = env->curr_nr;
1019         int curr_nr  = start_nr;
1020
1021         be_insn_env_t insn_env;
1022         int i, j;
1023         ir_node *irn;
1024         be_insn_t **insns;
1025
1026         insn_env.aenv = env->co->aenv;
1027         insn_env.cls  = env->co->cls;
1028         insn_env.obst = obst;
1029         insn_env.ignore_colors = env->co->cenv->ignore_colors;
1030
1031         /* Guess how many insns will be in this block. */
1032         sched_foreach(bl, irn)
1033                 n_nodes++;
1034
1035         bli->n_phi = 0;
1036         insns = malloc(n_nodes * sizeof(insns[0]));
1037
1038         /* Put all insns in an array. */
1039         irn = sched_first(bl);
1040         while(!sched_is_end(irn)) {
1041                 be_insn_t *insn;
1042                 insn = be_scan_insn(&insn_env, irn);
1043                 insns[n_insns++] = insn;
1044                 irn = insn->next_insn;
1045         }
1046
1047         DBG((dbg, LEVEL_2, "%+F\n", bl));
1048         be_liveness_end_of_block(lv, env->co->aenv, env->co->cls, bl, live);
1049
1050         /* Generate the bad and ugly. */
1051         for(i = n_insns - 1; i >= 0; --i) {
1052                 be_insn_t *insn = insns[i];
1053
1054                 /* The first live set has to be saved in the block border set. */
1055                 if(i == n_insns - 1) {
1056                         j = 0;
1057                         foreach_pset(live, irn) {
1058                                 bli->live_end[j]    = irn;
1059                                 bli->live_end_nr[j] = curr_nr + j;
1060                                 ++j;
1061                         }
1062                         bli->n_live_end = j;
1063                 }
1064
1065                 if(!env->dumb) {
1066                         for(j = 0; j < insn->use_start; ++j) {
1067                                 ir_node *op   = insn->ops[j].carrier;
1068                                 bitset_t *adm = insn->ops[j].regs;
1069                                 int k;
1070                                 int nr;
1071
1072                                 if(!insn->ops[j].has_constraints)
1073                                         continue;
1074
1075                                 nr = 0;
1076                                 foreach_pset(live, irn) {
1077                                         if(irn == op) {
1078                                                 pset_break(live);
1079                                                 break;
1080                                         }
1081                                         ++nr;
1082                                 }
1083
1084                                 assert(nr < pset_count(live));
1085
1086                                 for(k = 0; k < env->co->cls->n_regs; ++k) {
1087                                         int mapped_col = env->color_map[k];
1088                                         if(mapped_col >= 0 && !bitset_is_set(adm, k) && !bitset_is_set(env->co->cenv->ignore_colors, k))
1089                                                 fprintf(env->f, "%d %d -1\n", curr_nr + nr, mapped_col);
1090                                 }
1091                         }
1092                 }
1093
1094                 /* dump the clique and update the stuff. */
1095                 curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
1096
1097                 /* remove all defs. */
1098                 for(j = 0; j < insn->use_start; ++j)
1099                         pset_remove_ptr(live, insn->ops[j].carrier);
1100
1101                 if(is_Phi(insn->irn) && arch_irn_consider_in_reg_alloc(env->co->aenv, env->co->cls, insn->irn)) {
1102                         bli->phi[bli->n_phi]    = insn->irn;
1103                         bli->phi_nr[bli->n_phi] = PTR_TO_INT(get_irn_link(insn->irn));
1104                         bli->n_phi++;
1105                 }
1106
1107                 /* add all uses */
1108                 else
1109                         for(j = insn->use_start; j < insn->n_ops; ++j)
1110                                 pset_insert_ptr(live, insn->ops[j].carrier);
1111         }
1112
1113         /* print the start clique. */
1114         curr_nr = appel_dump_clique(env, live, bl, curr_nr, start_nr);
1115
1116         i = 0;
1117         foreach_pset(live, irn) {
1118                 bli->live_in[i]    = irn;
1119                 bli->live_in_nr[i] = PTR_TO_INT(get_irn_link(irn));
1120                 ++i;
1121         }
1122         bli->n_live_in = i;
1123
1124         del_pset(live);
1125         free(insns);
1126         obstack_free(obst, base);
1127         env->curr_nr = curr_nr;
1128 }
1129
1130 static void appel_inter_block_aff(ir_node *bl, void *data)
1131 {
1132         appel_clique_walker_t *env = data;
1133         appel_block_info_t *bli    = phase_get_irn_data(&env->ph, bl);
1134
1135         int i, j, n;
1136
1137         for(i = 0; i < bli->n_live_in; ++i) {
1138                 ir_node *irn = bli->live_in[i];
1139
1140                 for(j = 0, n = get_Block_n_cfgpreds(bl); j < n; ++j) {
1141                         ir_node *pred  = get_Block_cfgpred_block(bl, j);
1142
1143                         int nr = appel_get_live_end_nr(env, pred, irn);
1144                         assert(nr >= 0);
1145                         fprintf(env->f, "%d %d 1\n", bli->live_in_nr[i], nr);
1146                 }
1147         }
1148
1149         for(i = 0; i < bli->n_phi; ++i) {
1150                 ir_node *irn = bli->phi[i];
1151
1152                 for(j = 0, n = get_Block_n_cfgpreds(bl); j < n; ++j) {
1153                         ir_node *pred  = get_Block_cfgpred_block(bl, j);
1154                         ir_node *op = get_irn_n(irn, j);
1155
1156                         int nr = appel_get_live_end_nr(env, pred, op);
1157                         assert(nr >= 0);
1158                         fprintf(env->f, "%d %d 1\n", bli->phi_nr[i], nr);
1159                 }
1160         }
1161
1162 }
1163
1164 void co_dump_appel_graph_cliques(const copy_opt_t *co, FILE *f)
1165 {
1166         int i;
1167         int n_colors;
1168         appel_clique_walker_t env;
1169         bitset_t *adm = bitset_alloca(co->cls->n_regs);
1170         be_lv_t *lv = co->cenv->birg->lv;
1171
1172         be_liveness_recompute(lv);
1173         obstack_init(&env.obst);
1174         phase_init(&env.ph, "appel_clique_dumper", co->irg, PHASE_DEFAULT_GROWTH, appel_clique_walker_irn_init, NULL);
1175         env.curr_nr = co->cls->n_regs;
1176         env.co = co;
1177         env.f = f;
1178
1179         bitset_copy(adm, co->cenv->ignore_colors);
1180         bitset_flip_all(adm);
1181
1182         /* Make color map. */
1183         env.color_map = alloca(co->cls->n_regs * sizeof(env.color_map[0]));
1184         for(i = 0, n_colors = 0; i < co->cls->n_regs; ++i) {
1185                 const arch_register_t *reg = &co->cls->regs[i];
1186                 env.color_map[i] = arch_register_type_is(reg, ignore) ? -1 : n_colors++;
1187         }
1188
1189         env.dumb = 1;
1190         env.curr_nr = n_colors;
1191         irg_block_walk_graph(co->irg, firm_clear_link, NULL, NULL);
1192         irg_block_walk_graph(co->irg, appel_walker, NULL, &env);
1193
1194         fprintf(f, "%d %d\n", env.curr_nr, n_colors);
1195
1196         /* make the first k nodes interfere */
1197         for(i = 0; i < n_colors; ++i) {
1198                 int j;
1199                 for(j = i + 1; j < n_colors; ++j)
1200                         fprintf(f, "%d %d -1 ", i, j);
1201                 fprintf(f, "\n");
1202         }
1203
1204         env.dumb = 0;
1205         env.curr_nr = n_colors;
1206         irg_block_walk_graph(co->irg, firm_clear_link, NULL, NULL);
1207         irg_block_walk_graph(co->irg, appel_walker, NULL, &env);
1208         irg_block_walk_graph(co->irg, appel_inter_block_aff, NULL, &env);
1209         obstack_free(&env.obst, NULL);
1210 }
1211
1212 /*
1213          ___ _____ ____   ____   ___ _____   ____                        _
1214         |_ _|  ___/ ___| |  _ \ / _ \_   _| |  _ \ _   _ _ __ ___  _ __ (_)_ __   __ _
1215          | || |_ | |  _  | | | | | | || |   | | | | | | | '_ ` _ \| '_ \| | '_ \ / _` |
1216          | ||  _|| |_| | | |_| | |_| || |   | |_| | |_| | | | | | | |_) | | | | | (_| |
1217         |___|_|   \____| |____/ \___/ |_|   |____/ \__,_|_| |_| |_| .__/|_|_| |_|\__, |
1218                                                                   |_|            |___/
1219 */
1220
1221 static const char *get_dot_color_name(int col)
1222 {
1223         static const char *names[] = {
1224                 "blue",
1225                 "red",
1226                 "green",
1227                 "yellow",
1228                 "cyan",
1229                 "magenta",
1230                 "orange",
1231                 "chocolate",
1232                 "beige",
1233                 "navy",
1234                 "darkgreen",
1235                 "darkred",
1236                 "lightPink",
1237                 "chartreuse",
1238                 "lightskyblue",
1239                 "linen",
1240                 "pink",
1241                 "lightslateblue",
1242                 "mintcream",
1243                 "red",
1244                 "darkolivegreen",
1245                 "mediumblue",
1246                 "mistyrose",
1247                 "salmon",
1248                 "darkseagreen",
1249                 "mediumslateblue"
1250                 "moccasin",
1251                 "tomato",
1252                 "forestgreen",
1253                 "darkturquoise",
1254                 "palevioletred"
1255         };
1256
1257         return col < sizeof(names)/sizeof(names[0]) ? names[col] : "white";
1258 }
1259
1260 typedef struct _co_ifg_dump_t {
1261         const copy_opt_t *co;
1262         unsigned flags;
1263 } co_ifg_dump_t;
1264
1265 static void ifg_dump_graph_attr(FILE *f, void *self)
1266 {
1267         fprintf(f, "overlap=scale");
1268 }
1269
1270 static int ifg_is_dump_node(void *self, ir_node *irn)
1271 {
1272         co_ifg_dump_t *cod = self;
1273         return !arch_irn_is(cod->co->aenv, irn, ignore);
1274 }
1275
1276 static void ifg_dump_node_attr(FILE *f, void *self, ir_node *irn)
1277 {
1278         co_ifg_dump_t *env         = self;
1279         const arch_register_t *reg = arch_get_irn_register(env->co->aenv, irn);
1280         const arch_register_req_t *req;
1281         int limited;
1282
1283         req = arch_get_register_req(env->co->aenv, irn, BE_OUT_POS(0));
1284         limited = arch_register_req_is(req, limited);
1285
1286         if(env->flags & CO_IFG_DUMP_LABELS) {
1287                 ir_fprintf(f, "label=\"%+F", irn);
1288
1289 #if 0
1290                 // TODO fix this...
1291                 if((env->flags & CO_IFG_DUMP_CONSTR) && limited) {
1292                         bitset_t *bs = bitset_alloca(env->co->cls->n_regs);
1293                         req.limited(req.limited_env, bs);
1294                         ir_fprintf(f, "\\n%B", bs);
1295                 }
1296 #endif
1297                 ir_fprintf(f, "\" ");
1298         } else {
1299                 fprintf(f, "label=\"\" shape=point " );
1300         }
1301
1302         if(env->flags & CO_IFG_DUMP_SHAPE)
1303                 fprintf(f, "shape=%s ", limited ? "diamond" : "ellipse");
1304
1305         if(env->flags & CO_IFG_DUMP_COLORS)
1306                 fprintf(f, "style=filled color=%s ", get_dot_color_name(reg->index));
1307 }
1308
1309 static void ifg_dump_at_end(FILE *file, void *self)
1310 {
1311         co_ifg_dump_t *env = self;
1312         affinity_node_t *a;
1313
1314         co_gs_foreach_aff_node(env->co, a) {
1315                 const arch_register_t *ar = arch_get_irn_register(env->co->aenv, a->irn);
1316                 unsigned aidx = get_irn_idx(a->irn);
1317                 neighb_t *n;
1318
1319                 co_gs_foreach_neighb(a, n) {
1320                         const arch_register_t *nr = arch_get_irn_register(env->co->aenv, n->irn);
1321                         unsigned nidx = get_irn_idx(n->irn);
1322
1323                         if(aidx < nidx) {
1324                                 const char *color = nr == ar ? "blue" : "red";
1325                                 fprintf(file, "\tn%d -- n%d [weight=0.01 ", aidx, nidx);
1326                                 if(env->flags & CO_IFG_DUMP_LABELS)
1327                                         fprintf(file, "label=\"%d\" ", n->costs);
1328                                 if(env->flags & CO_IFG_DUMP_COLORS)
1329                                         fprintf(file, "color=%s ", color);
1330                                 else
1331                                         fprintf(file, "style=dotted");
1332                                 fprintf(file, "];\n");
1333                         }
1334                 }
1335         }
1336 }
1337
1338
1339 static be_ifg_dump_dot_cb_t ifg_dot_cb = {
1340         ifg_is_dump_node,
1341         ifg_dump_graph_attr,
1342         ifg_dump_node_attr,
1343         NULL,
1344         NULL,
1345         ifg_dump_at_end
1346 };
1347
1348
1349
1350 void co_dump_ifg_dot(const copy_opt_t *co, FILE *f, unsigned flags)
1351 {
1352         co_ifg_dump_t cod;
1353
1354         cod.co    = co;
1355         cod.flags = flags;
1356         be_ifg_dump_dot(co->cenv->ifg, co->irg, f, &ifg_dot_cb, &cod);
1357 }
1358
1359
1360 void co_solve_park_moon(copy_opt_t *opt)
1361 {
1362
1363 }
1364
1365 static int void_algo(copy_opt_t *co)
1366 {
1367         return 0;
1368 }
1369
1370 /*
1371                 _    _                  _ _   _
1372            / \  | | __ _  ___  _ __(_) |_| |__  _ __ ___  ___
1373           / _ \ | |/ _` |/ _ \| '__| | __| '_ \| '_ ` _ \/ __|
1374          / ___ \| | (_| | (_) | |  | | |_| | | | | | | | \__ \
1375         /_/   \_\_|\__, |\___/|_|  |_|\__|_| |_|_| |_| |_|___/
1376                            |___/
1377 */
1378
1379 typedef struct {
1380         co_algo_t  *algo;
1381         const char *name;
1382         int        can_improve_existing;
1383 } co_algo_info_t;
1384
1385 static co_algo_info_t algos[] = {
1386         { void_algo,               "none",  0 },
1387         { co_solve_heuristic,      "heur1", 0 },
1388         { co_solve_heuristic_new,  "heur2", 0 },
1389         { co_solve_heuristic_java, "heur3", 0 },
1390         { co_solve_heuristic_mst,  "heur4", 0 },
1391 #ifdef WITH_ILP
1392         { co_solve_ilp2,           "ilp",   1 },
1393 #endif
1394         { NULL,                    "",      0 }
1395 };
1396
1397 /*
1398     __  __       _         ____       _
1399    |  \/  | __ _(_)_ __   |  _ \ _ __(_)_   _____ _ __
1400    | |\/| |/ _` | | '_ \  | | | | '__| \ \ / / _ \ '__|
1401    | |  | | (_| | | | | | | |_| | |  | |\ V /  __/ |
1402    |_|  |_|\__,_|_|_| |_| |____/|_|  |_| \_/ \___|_|
1403
1404 */
1405
1406 static FILE *my_open(const be_chordal_env_t *env, const char *prefix, const char *suffix)
1407 {
1408         FILE *result;
1409         char buf[1024];
1410
1411         ir_snprintf(buf, sizeof(buf), "%s%F_%s%s", prefix, env->irg, env->cls->name, suffix);
1412         result = fopen(buf, "wt");
1413         if(result == NULL) {
1414                 panic("Couldn't open '%s' for writing.", buf);
1415         }
1416
1417         return result;
1418 }
1419
1420 void co_driver(be_chordal_env_t *cenv)
1421 {
1422         lc_timer_t          *timer = lc_timer_register("firm.be.copyopt", "runtime");
1423         co_complete_stats_t before, after;
1424         copy_opt_t          *co;
1425         co_algo_t           *algo_func;
1426         int                 was_optimal = 0;
1427
1428         if (algo < 0 || algo >= CO_ALGO_LAST)
1429                 return;
1430
1431         co = new_copy_opt(cenv, cost_func);
1432         co_build_ou_structure(co);
1433         co_build_graph_structure(co);
1434
1435         co_complete_stats(co, &before);
1436
1437         be_stat_ev_ull("co_aff_nodes",    before.aff_nodes);
1438         be_stat_ev_ull("co_aff_edges",    before.aff_edges);
1439         be_stat_ev_ull("co_max_costs",    before.max_costs);
1440         be_stat_ev_ull("co_inevit_costs", before.inevit_costs);
1441         be_stat_ev_ull("co_aff_int",      before.aff_int);
1442
1443         be_stat_ev_ull("co_init_costs",   before.costs);
1444         be_stat_ev_ull("co_init_unsat",   before.unsatisfied_edges);
1445
1446         /* Dump the interference graph in Appel's format. */
1447         if (dump_flags & DUMP_APPEL) {
1448                 FILE *f = my_open(cenv, "", ".apl");
1449                 co_dump_appel_graph(co, f);
1450                 fclose(f);
1451         }
1452
1453         if (dump_flags & DUMP_BEFORE) {
1454                 FILE *f = my_open(cenv, "", "-before.dot");
1455                 co_dump_ifg_dot(co, f, style_flags);
1456                 fclose(f);
1457         }
1458
1459         /* if the algo can improve results, provide an initial solution with heur3 */
1460         if (improve && algos[algo].can_improve_existing) {
1461                 co_complete_stats_t stats;
1462
1463                 /* produce a heuristic solution */
1464 #ifdef WITH_JVM
1465                 co_solve_heuristic_java(co);
1466 #else
1467                 co_solve_heuristic(co);
1468 #endif /* WITH_JVM */
1469
1470                 /* do the stats and provide the current costs */
1471                 co_complete_stats(co, &stats);
1472                 be_stat_ev_ull("co_prepare_costs", stats.costs);
1473         }
1474
1475 #ifdef WITH_JVM
1476         /* start the JVM here so that it does not tamper the timing. */
1477         if (algo == CO_ALGO_HEUR3)
1478                 be_java_coal_start_jvm();
1479 #endif /* WITH_JVM */
1480
1481         algo_func = algos[algo].algo;
1482
1483         /* perform actual copy minimization */
1484         lc_timer_reset_and_start(timer);
1485         was_optimal = algo_func(co);
1486         lc_timer_stop(timer);
1487
1488         be_stat_ev("co_time", lc_timer_elapsed_msec(timer));
1489         be_stat_ev_ull("co_optimal", was_optimal);
1490
1491         if (dump_flags & DUMP_AFTER) {
1492                 FILE *f = my_open(cenv, "", "-after.dot");
1493                 co_dump_ifg_dot(co, f, style_flags);
1494                 fclose(f);
1495         }
1496
1497         co_complete_stats(co, &after);
1498
1499         if (do_stats) {
1500                 ulong64 optimizable_costs = after.max_costs - after.inevit_costs;
1501                 ulong64 evitable          = after.costs     - after.inevit_costs;
1502
1503                 ir_printf("%30F ", cenv->irg);
1504                 printf("%10s %10" ULL_FMT "%10" ULL_FMT "%10" ULL_FMT, cenv->cls->name, after.max_costs, before.costs, after.inevit_costs);
1505
1506                 if(optimizable_costs > 0)
1507                         printf("%10" ULL_FMT " %5.2f\n", after.costs, (evitable * 100.0) / optimizable_costs);
1508                 else
1509                         printf("%10" ULL_FMT " %5s\n", after.costs, "-");
1510         }
1511
1512         be_stat_ev_ull("co_after_costs", after.costs);
1513         be_stat_ev_ull("co_after_unsat", after.unsatisfied_edges);
1514
1515         co_free_graph_structure(co);
1516         co_free_ou_structure(co);
1517         free_copy_opt(co);
1518 }