added space
[libfirm] / ir / be / bechordal_main.c
1 /**
2  * @file   bechordal_main.c
3  * @date   29.11.2005
4  * @author Sebastian Hack
5  * @cvs-id $Id$
6  *
7  * Copyright (C) 2005-2006 Universitaet Karlsruhe
8  * Released under the GPL
9  *
10  * Driver for the chordal register allocator.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #include <time.h>
17
18 #include "obst.h"
19 #include "pset.h"
20 #include "list.h"
21 #include "bitset.h"
22 #include "iterator.h"
23 #include "firm_config.h"
24
25 #ifdef WITH_LIBCORE
26 #include <libcore/lc_opts.h>
27 #include <libcore/lc_opts_enum.h>
28 #include <libcore/lc_timing.h>
29 #endif /* WITH_LIBCORE */
30
31 #include "ircons_t.h"
32 #include "irmode_t.h"
33 #include "irgraph_t.h"
34 #include "irprintf_t.h"
35 #include "irgwalk.h"
36 #include "ircons.h"
37 #include "irdump.h"
38 #include "irdom.h"
39 #include "ircons.h"
40 #include "irbitset.h"
41 #include "irnode.h"
42 #include "ircons.h"
43 #include "debug.h"
44 #include "xmalloc.h"
45 #include "execfreq.h"
46
47 #include "bechordal_t.h"
48 #include "beabi.h"
49 #include "bejavacoal.h"
50 #include "beutil.h"
51 #include "besched.h"
52 #include "besched_t.h"
53 #include "belive_t.h"
54 #include "bearch.h"
55 #include "beifg_t.h"
56 #include "beifg_impl.h"
57 #include "benode_t.h"
58 #include "bestatevent.h"
59 #include "bestat.h"
60
61 #include "bespillbelady.h"
62 #include "bespillmorgan.h"
63 #include "bespillslots.h"
64 #include "bespilloptions.h"
65 #include "belower.h"
66
67 #ifdef WITH_ILP
68 #include "bespillremat.h"
69 #endif /* WITH_ILP */
70
71 #include "bejavacoal.h"
72 #include "becopystat.h"
73 #include "becopyopt.h"
74 #include "bessadestr.h"
75 #include "beverify.h"
76 #include "benode_t.h"
77
78 static be_ra_chordal_opts_t options = {
79         BE_CH_DUMP_NONE,
80         BE_CH_SPILL_BELADY,
81         BE_CH_IFG_STD,
82         BE_CH_LOWER_PERM_SWAP,
83         BE_CH_VRFY_WARN,
84 };
85
86 /** Enable extreme live range splitting. */
87 static int be_elr_split = 0;
88
89 /** Assumed loop iteration count for execution frequency estimation. */
90 static int be_loop_weight = 9;
91
92 #ifdef WITH_LIBCORE
93 static be_ra_timer_t ra_timer = {
94         NULL,
95         NULL,
96         NULL,
97         NULL,
98         NULL,
99         NULL,
100         NULL,
101         NULL,
102         NULL,
103         NULL,
104         NULL,
105 };
106
107 static const lc_opt_enum_int_items_t spill_items[] = {
108         { "morgan", BE_CH_SPILL_MORGAN },
109         { "belady", BE_CH_SPILL_BELADY },
110 #ifdef WITH_ILP
111         { "remat",  BE_CH_SPILL_REMAT },
112 #endif /* WITH_ILP */
113         { NULL, 0 }
114 };
115
116 static const lc_opt_enum_int_items_t ifg_flavor_items[] = {
117         { "std",     BE_CH_IFG_STD     },
118         { "fast",    BE_CH_IFG_FAST    },
119         { "clique",  BE_CH_IFG_CLIQUE  },
120         { "pointer", BE_CH_IFG_POINTER },
121         { "list",    BE_CH_IFG_LIST    },
122         { "check",   BE_CH_IFG_CHECK   },
123         { NULL,      0                 }
124 };
125
126 static const lc_opt_enum_int_items_t lower_perm_items[] = {
127         { "copy", BE_CH_LOWER_PERM_COPY },
128         { "swap", BE_CH_LOWER_PERM_SWAP },
129         { NULL, 0 }
130 };
131
132 static const lc_opt_enum_int_items_t lower_perm_stat_items[] = {
133         { NULL, 0 }
134 };
135
136 static const lc_opt_enum_int_items_t dump_items[] = {
137         { "spill",      BE_CH_DUMP_SPILL      },
138         { "live",       BE_CH_DUMP_LIVE       },
139         { "color",      BE_CH_DUMP_COLOR      },
140         { "copymin",    BE_CH_DUMP_COPYMIN    },
141         { "ssadestr",   BE_CH_DUMP_SSADESTR   },
142         { "tree",       BE_CH_DUMP_TREE_INTV  },
143         { "constr",     BE_CH_DUMP_CONSTR     },
144         { "lower",      BE_CH_DUMP_LOWER      },
145         { "spillslots", BE_CH_DUMP_SPILLSLOTS },
146         { "appel",      BE_CH_DUMP_APPEL      },
147         { "all",        BE_CH_DUMP_ALL        },
148         { NULL, 0 }
149 };
150
151 static const lc_opt_enum_int_items_t be_ch_vrfy_items[] = {
152         { "off",    BE_CH_VRFY_OFF    },
153         { "warn",   BE_CH_VRFY_WARN   },
154         { "assert", BE_CH_VRFY_ASSERT },
155         { NULL, 0 }
156 };
157
158 static lc_opt_enum_int_var_t spill_var = {
159         &options.spill_method, spill_items
160 };
161
162 static lc_opt_enum_int_var_t ifg_flavor_var = {
163         &options.ifg_flavor, ifg_flavor_items
164 };
165
166 static lc_opt_enum_int_var_t lower_perm_var = {
167         &options.lower_perm_opt, lower_perm_items
168 };
169
170 static lc_opt_enum_int_var_t dump_var = {
171         &options.dump_flags, dump_items
172 };
173
174 static lc_opt_enum_int_var_t be_ch_vrfy_var = {
175         &options.vrfy_option, be_ch_vrfy_items
176 };
177
178 static const lc_opt_table_entry_t be_chordal_options[] = {
179         LC_OPT_ENT_ENUM_INT ("spill",         "spill method", &spill_var),
180         LC_OPT_ENT_ENUM_PTR ("ifg",           "interference graph flavour", &ifg_flavor_var),
181         LC_OPT_ENT_ENUM_PTR ("perm",          "perm lowering options", &lower_perm_var),
182         LC_OPT_ENT_ENUM_MASK("dump",          "select dump phases", &dump_var),
183         LC_OPT_ENT_ENUM_PTR ("vrfy",          "verify options", &be_ch_vrfy_var),
184         LC_OPT_ENT_BOOL     ("elrsplit",      "enable extreme live range splitting", &be_elr_split),
185         LC_OPT_ENT_INT      ("loop_weight",   "assumed amount of loop iterations for guessing the execution frequency", &be_loop_weight),
186         { NULL }
187 };
188
189 typedef struct _post_spill_env_t {
190         be_chordal_env_t cenv;
191         double           pre_spill_cost;
192 } post_spill_env_t;
193
194 extern void be_spill_remat_register_options(lc_opt_entry_t *ent);
195
196 void be_ra_chordal_check(be_chordal_env_t *chordal_env) {
197         const arch_env_t *arch_env = chordal_env->birg->main_env->arch_env;
198         struct obstack ob;
199         pmap_entry *pme;
200         ir_node **nodes, *n1, *n2;
201         int i, o;
202         be_lv_t *lv = chordal_env->birg->lv;
203         DEBUG_ONLY(firm_dbg_module_t *dbg = chordal_env->dbg;)
204
205         /* Collect all irns */
206         obstack_init(&ob);
207         pmap_foreach(chordal_env->border_heads, pme) {
208                 border_t *curr;
209                 struct list_head *head = pme->value;
210                 list_for_each_entry(border_t, curr, head, list)
211                         if (curr->is_def && curr->is_real)
212                                 if (arch_get_irn_reg_class(arch_env, curr->irn, -1) == chordal_env->cls)
213                                         obstack_ptr_grow(&ob, curr->irn);
214         }
215         obstack_ptr_grow(&ob, NULL);
216         nodes = (ir_node **) obstack_finish(&ob);
217
218         /* Check them */
219         for (i = 0, n1 = nodes[i]; n1; n1 = nodes[++i]) {
220                 const arch_register_t *n1_reg, *n2_reg;
221
222                 n1_reg = arch_get_irn_register(arch_env, n1);
223                 if (!arch_reg_is_allocatable(arch_env, n1, -1, n1_reg)) {
224                         DBG((dbg, 0, "Register %s assigned to %+F is not allowed\n", n1_reg->name, n1));
225                         assert(0 && "Register constraint does not hold");
226                 }
227                 for (o = i+1, n2 = nodes[o]; n2; n2 = nodes[++o]) {
228                         n2_reg = arch_get_irn_register(arch_env, n2);
229                         if (values_interfere(lv, n1, n2) && n1_reg == n2_reg) {
230                                 DBG((dbg, 0, "Values %+F and %+F interfere and have the same register assigned: %s\n", n1, n2, n1_reg->name));
231                                 assert(0 && "Interfering values have the same color!");
232                         }
233                 }
234         }
235         obstack_free(&ob, NULL);
236 }
237
238 int nodes_interfere(const be_chordal_env_t *env, const ir_node *a, const ir_node *b)
239 {
240         if(env->ifg)
241                 return be_ifg_connected(env->ifg, a, b);
242         else
243                 return values_interfere(env->birg->lv, a, b);
244 }
245
246 static void be_ra_chordal_register_options(lc_opt_entry_t *grp)
247 {
248         static int run_once = 0;
249         lc_opt_entry_t *chordal_grp;
250
251         if (! run_once) {
252                 run_once    = 1;
253                 chordal_grp = lc_opt_get_grp(grp, "chordal");
254
255                 lc_opt_add_table(chordal_grp, be_chordal_options);
256
257                 co_register_options(chordal_grp);
258 #ifdef WITH_JVM
259                 be_java_coal_register_options(chordal_grp);
260 #endif
261 #ifdef WITH_ILP
262                 be_spill_remat_register_options(chordal_grp);
263 #endif
264                 be_spill_register_options(chordal_grp);
265         }
266 }
267 #endif /* WITH_LIBCORE */
268
269 static void dump(unsigned mask, ir_graph *irg,
270                                  const arch_register_class_t *cls,
271                                  const char *suffix,
272                                  void (*dump_func)(ir_graph *, const char *))
273 {
274         if((options.dump_flags & mask) == mask) {
275                 if (cls) {
276                         char buf[256];
277                         snprintf(buf, sizeof(buf), "-%s%s", cls->name, suffix);
278                         be_dump(irg, buf, dump_func);
279                 }
280                 else
281                         be_dump(irg, suffix, dump_func);
282         }
283 }
284
285 static void put_ignore_colors(be_chordal_env_t *chordal_env)
286 {
287         int n_colors = chordal_env->cls->n_regs;
288         int i;
289
290         bitset_clear_all(chordal_env->ignore_colors);
291         be_abi_put_ignore_regs(chordal_env->birg->abi, chordal_env->cls, chordal_env->ignore_colors);
292         for(i = 0; i < n_colors; ++i)
293                 if(arch_register_type_is(&chordal_env->cls->regs[i], ignore))
294                         bitset_set(chordal_env->ignore_colors, i);
295 }
296
297 FILE *be_chordal_open(const be_chordal_env_t *env, const char *prefix, const char *suffix)
298 {
299         char buf[1024];
300
301         ir_snprintf(buf, sizeof(buf), "%s%F_%s%s", prefix, env->irg, env->cls->name, suffix);
302         return fopen(buf, "wt");
303 }
304
305 void check_ifg_implementations(be_chordal_env_t *chordal_env)
306 {
307         FILE *f;
308
309         f = be_chordal_open(chordal_env, "std", ".log");
310         chordal_env->ifg = be_ifg_std_new(chordal_env);
311         be_ifg_check_sorted_to_file(chordal_env->ifg, f);
312         fclose(f);
313
314         f = be_chordal_open(chordal_env, "list", ".log");
315         be_ifg_free(chordal_env->ifg);
316         chordal_env->ifg = be_ifg_list_new(chordal_env);
317         be_ifg_check_sorted_to_file(chordal_env->ifg, f);
318         fclose(f);
319
320         f = be_chordal_open(chordal_env, "clique", ".log");
321         be_ifg_free(chordal_env->ifg);
322         chordal_env->ifg = be_ifg_clique_new(chordal_env);
323         be_ifg_check_sorted_to_file(chordal_env->ifg, f);
324         fclose(f);
325
326         f = be_chordal_open(chordal_env, "pointer", ".log");
327         be_ifg_free(chordal_env->ifg);
328         chordal_env->ifg = be_ifg_pointer_new(chordal_env);
329         be_ifg_check_sorted_to_file(chordal_env->ifg, f);
330         fclose(f);
331
332         chordal_env->ifg = NULL;
333 };
334
335 /**
336  * Checks for every reload if it's user can perform the load on itself.
337  */
338 static void memory_operand_walker(ir_node *irn, void *env) {
339         be_chordal_env_t *cenv = env;
340         const arch_env_t *aenv = cenv->birg->main_env->arch_env;
341         const ir_edge_t  *edge, *ne;
342         ir_node          *block;
343         ir_node          *spill;
344
345         if (! be_is_Reload(irn))
346                 return;
347
348         /* always use addressmode, it's good for x86 */
349 #if 0
350         /* only use memory operands, if the reload is only used by 1 node */
351         if(get_irn_n_edges(irn) > 1)
352                 return;
353 #endif
354
355         spill = be_get_Reload_mem(irn);
356         block = get_nodes_block(irn);
357
358         foreach_out_edge_safe(irn, edge, ne) {
359                 ir_node *src = get_edge_src_irn(edge);
360                 int     pos  = get_edge_src_pos(edge);
361
362                 assert(src && "outedges broken!");
363
364                 if (get_nodes_block(src) == block && arch_possible_memory_operand(aenv, src, pos)) {
365                         DBG((cenv->dbg, LEVEL_3, "performing memory operand %+F at %+F\n", irn, src));
366                         //arch_perform_memory_operand(aenv, src, spill, pos);
367                 }
368         }
369
370         /* kill the Reload */
371         if (get_irn_n_edges(irn) == 0) {
372                 sched_remove(irn);
373                 set_irn_n(irn, 0, new_Bad());
374                 set_irn_n(irn, 1, new_Bad());
375         }
376 }
377
378 /**
379  * Starts a walk for memory operands if supported by the backend.
380  */
381 static INLINE void check_for_memory_operands(be_chordal_env_t *chordal_env) {
382         irg_walk_graph(chordal_env->irg, NULL, memory_operand_walker, chordal_env);
383 }
384
385 /**
386  * Sorry for doing stats again...
387  */
388 typedef struct _node_stat_t {
389         unsigned int n_phis;      /**< Phis of the current register class. */
390         unsigned int n_mem_phis;  /**< Memory Phis (Phis with spill operands). */
391         unsigned int n_copies;    /**< Copies */
392         unsigned int n_perms;     /**< Perms */
393         unsigned int n_spills;    /**< Spill nodes */
394         unsigned int n_reloads;   /**< Reloads */
395 } node_stat_t;
396
397 struct node_stat_walker {
398         node_stat_t *stat;
399         const be_chordal_env_t *cenv;
400         bitset_t *mem_phis;
401 };
402
403 static void node_stat_walker(ir_node *irn, void *data)
404 {
405         struct node_stat_walker *env = data;
406         const arch_env_t *aenv       = env->cenv->birg->main_env->arch_env;
407
408         if(arch_irn_consider_in_reg_alloc(aenv, env->cenv->cls, irn)) {
409
410                 /* if the node is a normal phi */
411                 if(is_Phi(irn))
412                         env->stat->n_phis++;
413
414                 else if(arch_irn_classify(aenv, irn) & arch_irn_class_spill)
415                         ++env->stat->n_spills;
416
417                 else if(arch_irn_classify(aenv, irn) & arch_irn_class_reload)
418                         ++env->stat->n_reloads;
419
420                 else if(arch_irn_classify(aenv, irn) & arch_irn_class_copy)
421                         ++env->stat->n_copies;
422
423                 else if(arch_irn_classify(aenv, irn) & arch_irn_class_perm)
424                         ++env->stat->n_perms;
425         }
426
427         /* a mem phi is a PhiM with a mem phi operand or a Spill operand */
428         else if(is_Phi(irn) && get_irn_mode(irn) == mode_M) {
429                 int i;
430
431                 for(i = get_irn_arity(irn) - 1; i >= 0; --i) {
432                         ir_node *op = get_irn_n(irn, i);
433
434                         if((is_Phi(op) && bitset_contains_irn(env->mem_phis, op)) || (arch_irn_classify(aenv, op) & arch_irn_class_spill)) {
435                                 bitset_add_irn(env->mem_phis, irn);
436                                 env->stat->n_mem_phis++;
437                                 break;
438                         }
439                 }
440         }
441 }
442
443 static void node_stats(const be_chordal_env_t *cenv, node_stat_t *stat)
444 {
445         struct node_stat_walker env;
446
447         memset(stat, 0, sizeof(stat[0]));
448         env.cenv     = cenv;
449         env.mem_phis = bitset_irg_malloc(cenv->irg);
450         env.stat     = stat;
451         irg_walk_graph(cenv->irg, NULL, node_stat_walker, &env);
452         bitset_free(env.mem_phis);
453 }
454
455 static void insn_count_walker(ir_node *irn, void *data)
456 {
457         int *cnt = data;
458
459         switch(get_irn_opcode(irn)) {
460         case iro_Proj:
461         case iro_Phi:
462         case iro_Start:
463         case iro_End:
464                 break;
465         default:
466                 (*cnt)++;
467         }
468 }
469
470 static unsigned int count_insns(ir_graph *irg)
471 {
472         int cnt = 0;
473         irg_walk_graph(irg, insn_count_walker, NULL, &cnt);
474         return cnt;
475 }
476
477 #ifdef WITH_LIBCORE
478 /**
479  * Initialize all timers.
480  */
481 static void be_init_timer(be_options_t *main_opts)
482 {
483         if (main_opts->timing == BE_TIME_ON) {
484                 ra_timer.t_prolog     = lc_timer_register("ra_prolog",     "regalloc prolog");
485                 ra_timer.t_epilog     = lc_timer_register("ra_epilog",     "regalloc epilog");
486                 ra_timer.t_live       = lc_timer_register("ra_liveness",   "be liveness");
487                 ra_timer.t_spill      = lc_timer_register("ra_spill",      "spiller");
488                 ra_timer.t_spillslots = lc_timer_register("ra_spillslots", "spillslots");
489                 ra_timer.t_color      = lc_timer_register("ra_color",      "graph coloring");
490                 ra_timer.t_ifg        = lc_timer_register("ra_ifg",        "interference graph");
491                 ra_timer.t_copymin    = lc_timer_register("ra_copymin",    "copy minimization");
492                 ra_timer.t_ssa        = lc_timer_register("ra_ssadestr",   "ssa destruction");
493                 ra_timer.t_verify     = lc_timer_register("ra_verify",     "graph verification");
494                 ra_timer.t_other      = lc_timer_register("ra_other",      "other time");
495
496                 LC_STOP_AND_RESET_TIMER(ra_timer.t_prolog);
497                 LC_STOP_AND_RESET_TIMER(ra_timer.t_epilog);
498                 LC_STOP_AND_RESET_TIMER(ra_timer.t_live);
499                 LC_STOP_AND_RESET_TIMER(ra_timer.t_spill);
500                 LC_STOP_AND_RESET_TIMER(ra_timer.t_spillslots);
501                 LC_STOP_AND_RESET_TIMER(ra_timer.t_color);
502                 LC_STOP_AND_RESET_TIMER(ra_timer.t_ifg);
503                 LC_STOP_AND_RESET_TIMER(ra_timer.t_copymin);
504                 LC_STOP_AND_RESET_TIMER(ra_timer.t_ssa);
505                 LC_STOP_AND_RESET_TIMER(ra_timer.t_verify);
506                 LC_STOP_AND_RESET_TIMER(ra_timer.t_other);
507         }
508 }
509
510 #define BE_TIMER_INIT(main_opts)        be_init_timer(main_opts)
511
512 #define BE_TIMER_PUSH(timer)                                                            \
513         if (main_opts->timing == BE_TIME_ON) {                                              \
514                 if (! lc_timer_push(timer)) {                                                   \
515                         if (options.vrfy_option == BE_CH_VRFY_ASSERT)                               \
516                                 assert(!"Timer already on stack, cannot be pushed twice.");             \
517                         else if (options.vrfy_option == BE_CH_VRFY_WARN)                            \
518                                 fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \
519                                         lc_timer_get_name(timer));                                          \
520                 }                                                                               \
521         }
522 #define BE_TIMER_POP(timer)                                                                    \
523         if (main_opts->timing == BE_TIME_ON) {                                                     \
524                 lc_timer_t *tmp = lc_timer_pop();                                                      \
525                 if (options.vrfy_option == BE_CH_VRFY_ASSERT)                                          \
526                         assert(tmp == timer && "Attempt to pop wrong timer.");                             \
527                 else if (options.vrfy_option == BE_CH_VRFY_WARN && tmp != timer)                       \
528                         fprintf(stderr, "Attempt to pop wrong timer. %s is on stack, trying to pop %s.\n", \
529                                 lc_timer_get_name(tmp), lc_timer_get_name(timer));                             \
530                 timer = tmp;                                                                           \
531         }
532 #else
533
534 #define BE_TIMER_INIT(main_opts)
535 #define BE_TIMER_PUSH(timer)
536 #define BE_TIMER_POP(timer)
537
538 #endif /* WITH_LIBCORE */
539
540 /**
541  * Perform things which need to be done per register class before spilling.
542  */
543 static void pre_spill(const arch_isa_t *isa, int cls_idx, post_spill_env_t *pse) {
544         be_chordal_env_t *chordal_env = &pse->cenv;
545         node_stat_t      node_stat;
546
547         chordal_env->cls           = arch_isa_get_reg_class(isa, cls_idx);
548         chordal_env->border_heads  = pmap_create();
549         chordal_env->ignore_colors = bitset_malloc(chordal_env->cls->n_regs);
550
551 #ifdef FIRM_STATISTICS
552         if (be_stat_ev_is_active()) {
553                 be_stat_tags[STAT_TAG_CLS] = chordal_env->cls->name;
554                 be_stat_ev_push(be_stat_tags, STAT_TAG_LAST, be_stat_file);
555
556                 /* perform some node statistics. */
557                 node_stats(chordal_env, &node_stat);
558                 be_stat_ev("phis_before_spill", node_stat.n_phis);
559         }
560 #endif /* FIRM_STATISTICS */
561
562         /* put all ignore registers into the ignore register set. */
563         put_ignore_colors(chordal_env);
564
565         be_pre_spill_prepare_constr(chordal_env);
566         dump(BE_CH_DUMP_CONSTR, chordal_env->irg, chordal_env->cls, "-constr-pre", dump_ir_block_graph_sched);
567
568 #ifdef FIRM_STATISTICS
569         if (be_stat_ev_is_active()) {
570                 pse->pre_spill_cost = be_estimate_irg_costs(chordal_env->irg,
571                         chordal_env->birg->main_env->arch_env, chordal_env->birg->exec_freq);
572         }
573 #endif /* FIRM_STATISTICS */
574 }
575
576 /**
577  * Perform things which need to be done per register class after spilling.
578  */
579 static void post_spill(post_spill_env_t *pse) {
580         be_chordal_env_t    *chordal_env = &pse->cenv;
581         ir_graph            *irg         = chordal_env->irg;
582         be_irg_t            *birg        = chordal_env->birg;
583         const be_main_env_t *main_env    = birg->main_env;
584         be_options_t        *main_opts   = main_env->options;
585         static int          splitted     = 0;
586         node_stat_t         node_stat;
587
588 #ifdef FIRM_STATISTICS
589         if (be_stat_ev_is_active()) {
590                 double spillcosts = be_estimate_irg_costs(irg, main_env->arch_env, birg->exec_freq) - pse->pre_spill_cost;
591
592                 be_stat_ev_l("spillcosts", (long) spillcosts);
593
594                 node_stats(chordal_env, &node_stat);
595                 be_stat_ev("phis_after_spill", node_stat.n_phis);
596                 be_stat_ev("mem_phis", node_stat.n_mem_phis);
597                 be_stat_ev("reloads", node_stat.n_reloads);
598                 be_stat_ev("spills", node_stat.n_spills);
599         }
600 #endif /* FIRM_STATISTICS */
601
602         check_for_memory_operands(chordal_env);
603
604         be_abi_fix_stack_nodes(birg->abi, birg->lv);
605
606         BE_TIMER_PUSH(ra_timer.t_verify);
607
608         /* verify schedule and register pressure */
609         if (chordal_env->opts->vrfy_option == BE_CH_VRFY_WARN) {
610                 be_verify_schedule(irg);
611                 be_verify_register_pressure(chordal_env->birg, chordal_env->cls, irg);
612         }
613         else if (chordal_env->opts->vrfy_option == BE_CH_VRFY_ASSERT) {
614                 assert(be_verify_schedule(irg) && "Schedule verification failed");
615                 assert(be_verify_register_pressure(chordal_env->birg, chordal_env->cls, irg)
616                         && "Register pressure verification failed");
617         }
618         BE_TIMER_POP(ra_timer.t_verify);
619
620         if (be_elr_split && ! splitted) {
621                 extreme_liverange_splitting(chordal_env);
622                 splitted = 1;
623         }
624
625         /* Color the graph. */
626         BE_TIMER_PUSH(ra_timer.t_color);
627         be_ra_chordal_color(chordal_env);
628         BE_TIMER_POP(ra_timer.t_color);
629
630         dump(BE_CH_DUMP_CONSTR, irg, chordal_env->cls, "-color", dump_ir_block_graph_sched);
631
632         /* Create the ifg with the selected flavor */
633         BE_TIMER_PUSH(ra_timer.t_ifg);
634         switch (chordal_env->opts->ifg_flavor) {
635                 default:
636                         fprintf(stderr, "no valid ifg flavour selected. falling back to std\n");
637                 case BE_CH_IFG_STD:
638                 case BE_CH_IFG_FAST:
639                         chordal_env->ifg = be_ifg_std_new(chordal_env);
640                         break;
641                 case BE_CH_IFG_CLIQUE:
642                         chordal_env->ifg = be_ifg_clique_new(chordal_env);
643                         break;
644                 case BE_CH_IFG_POINTER:
645                         chordal_env->ifg = be_ifg_pointer_new(chordal_env);
646                         break;
647                 case BE_CH_IFG_LIST:
648                         chordal_env->ifg = be_ifg_list_new(chordal_env);
649                         break;
650                 case BE_CH_IFG_CHECK:
651                         check_ifg_implementations(chordal_env);
652                         /* Build the interference graph. */
653                         chordal_env->ifg = be_ifg_std_new(chordal_env);
654                         break;
655         }
656         BE_TIMER_POP(ra_timer.t_ifg);
657
658 #ifdef FIRM_STATISTICS
659         if (be_stat_ev_is_active()) {
660                 be_ifg_stat_t stat;
661                 be_ifg_stat(chordal_env, &stat);
662                 be_stat_ev("ifg_nodes", stat.n_nodes);
663                 be_stat_ev("ifg_edges", stat.n_edges);
664                 be_stat_ev("ifg_comps", stat.n_comps);
665
666                 node_stats(chordal_env, &node_stat);
667                 be_stat_ev("perms_before_coal", node_stat.n_perms);
668                 be_stat_ev("copies_before_coal", node_stat.n_copies);
669         }
670 #endif /* FIRM_STATISTICS */
671
672         /* copy minimization */
673         BE_TIMER_PUSH(ra_timer.t_copymin);
674         co_driver(chordal_env);
675         BE_TIMER_POP(ra_timer.t_copymin);
676
677         dump(BE_CH_DUMP_COPYMIN, irg, chordal_env->cls, "-copymin", dump_ir_block_graph_sched);
678
679         BE_TIMER_PUSH(ra_timer.t_ssa);
680
681         /* ssa destruction */
682         be_ssa_destruction(chordal_env);
683
684         BE_TIMER_POP(ra_timer.t_ssa);
685
686         dump(BE_CH_DUMP_SSADESTR, irg, chordal_env->cls, "-ssadestr", dump_ir_block_graph_sched);
687
688         BE_TIMER_PUSH(ra_timer.t_verify);
689         if (chordal_env->opts->vrfy_option != BE_CH_VRFY_OFF) {
690                 be_ssa_destruction_check(chordal_env);
691         }
692         BE_TIMER_POP(ra_timer.t_verify);
693
694         be_ifg_free(chordal_env->ifg);
695         pmap_destroy(chordal_env->border_heads);
696         bitset_free(chordal_env->ignore_colors);
697
698 #ifdef FIRM_STATISTICS
699         if (be_stat_ev_is_active()) {
700                 node_stats(chordal_env, &node_stat);
701                 be_stat_ev("perms_after_coal", node_stat.n_perms);
702                 be_stat_ev("copies_after_coal", node_stat.n_copies);
703                 be_stat_ev_pop();
704         }
705 #endif /* FIRM_STATISTICS */
706 }
707
708 /**
709  * Performs chordal register allocation for each register class on given irg.
710  *
711  * @param birg  Backend irg object
712  * @return Structure containing timer for the single phases or NULL if no timing requested.
713  */
714 static be_ra_timer_t *be_ra_chordal_main(be_irg_t *birg)
715 {
716         const be_main_env_t *main_env  = birg->main_env;
717         const arch_isa_t    *isa       = arch_env_get_isa(main_env->arch_env);
718         ir_graph            *irg       = birg->irg;
719         be_options_t        *main_opts = main_env->options;
720         int                 j, m;
721         be_chordal_env_t    chordal_env;
722
723         BE_TIMER_INIT(main_opts);
724         BE_TIMER_PUSH(ra_timer.t_other);
725         BE_TIMER_PUSH(ra_timer.t_prolog);
726
727         be_assure_dom_front(birg);
728         be_assure_liveness(birg);
729
730         chordal_env.opts      = &options;
731         chordal_env.irg       = irg;
732         chordal_env.birg      = birg;
733         FIRM_DBG_REGISTER(chordal_env.dbg, "firm.be.chordal");
734
735         obstack_init(&chordal_env.obst);
736
737         BE_TIMER_POP(ra_timer.t_prolog);
738
739         be_stat_ev("insns_before", count_insns(irg));
740
741         if (! arch_code_generator_has_spiller(birg->cg)) {
742                 /* use one of the generic spiller */
743
744                 /* Perform the following for each register class. */
745                 for (j = 0, m = arch_isa_get_n_reg_class(isa); j < m; ++j) {
746                         post_spill_env_t pse;
747
748                         memcpy(&pse.cenv, &chordal_env, sizeof(chordal_env));
749                         pre_spill(isa, j, &pse);
750
751                         BE_TIMER_PUSH(ra_timer.t_spill);
752                         /* spilling */
753                         switch(options.spill_method) {
754                         case BE_CH_SPILL_MORGAN:
755                                 be_spill_morgan(&chordal_env);
756                                 break;
757                         case BE_CH_SPILL_BELADY:
758                                 be_spill_belady(&chordal_env);
759                                 break;
760         #ifdef WITH_ILP
761                         case BE_CH_SPILL_REMAT:
762                                 be_spill_remat(&chordal_env);
763                                 break;
764         #endif /* WITH_ILP */
765                         default:
766                                 fprintf(stderr, "no valid spiller selected. falling back to belady\n");
767                                 be_spill_belady(&chordal_env);
768                         }
769                         BE_TIMER_POP(ra_timer.t_spill);
770
771                         dump(BE_CH_DUMP_SPILL, irg, chordal_env.cls, "-spill", dump_ir_block_graph_sched);
772
773                         post_spill(&pse);
774                 }
775         }
776         else {
777                 post_spill_env_t *pse;
778
779                 /* the backend has it's own spiller */
780                 m = arch_isa_get_n_reg_class(isa);
781
782                 pse = alloca(m * sizeof(pse[0]));
783
784                 for (j = 0; j < m; ++j) {
785                         memcpy(&pse[j].cenv, &chordal_env, sizeof(chordal_env));
786                         pre_spill(isa, j, &pse[j]);
787                 }
788
789                 BE_TIMER_PUSH(ra_timer.t_spill);
790                 arch_code_generator_spill(birg->cg, &chordal_env);
791                 BE_TIMER_POP(ra_timer.t_spill);
792                 dump(BE_CH_DUMP_SPILL, irg, NULL, "-spill", dump_ir_block_graph_sched);
793
794                 for (j = 0; j < m; ++j) {
795                         post_spill(&pse[j]);
796                 }
797         }
798
799         BE_TIMER_PUSH(ra_timer.t_spillslots);
800
801         be_coalesce_spillslots(&chordal_env);
802         dump(BE_CH_DUMP_SPILLSLOTS, irg, NULL, "-spillslots", dump_ir_block_graph_sched);
803
804         BE_TIMER_POP(ra_timer.t_spillslots);
805
806         BE_TIMER_PUSH(ra_timer.t_verify);
807         /* verify spillslots */
808         if (options.vrfy_option == BE_CH_VRFY_WARN) {
809                 be_verify_spillslots(main_env->arch_env, irg);
810         }
811         else if (options.vrfy_option == BE_CH_VRFY_ASSERT) {
812                 assert(be_verify_spillslots(main_env->arch_env, irg) && "Spillslot verification failed");
813         }
814         BE_TIMER_POP(ra_timer.t_verify);
815
816         BE_TIMER_PUSH(ra_timer.t_epilog);
817         dump(BE_CH_DUMP_LOWER, irg, NULL, "-spilloff", dump_ir_block_graph_sched);
818
819         lower_nodes_after_ra(&chordal_env, options.lower_perm_opt & BE_CH_LOWER_PERM_COPY ? 1 : 0);
820         dump(BE_CH_DUMP_LOWER, irg, NULL, "-belower-after-ra", dump_ir_block_graph_sched);
821
822         obstack_free(&chordal_env.obst, NULL);
823         BE_TIMER_POP(ra_timer.t_epilog);
824
825         BE_TIMER_POP(ra_timer.t_other);
826
827         be_stat_ev("insns_after", count_insns(irg));
828
829 #ifdef WITH_LIBCORE
830         return main_opts->timing == BE_TIME_ON ? &ra_timer : NULL;
831 #endif /* WITH_LIBCORE */
832         return NULL;
833 }
834
835 const be_ra_t be_ra_chordal_allocator = {
836 #ifdef WITH_LIBCORE
837         be_ra_chordal_register_options,
838 #else
839         NULL,
840 #endif
841         be_ra_chordal_main,
842 };