bc76a28af402277c98558f9e3d3ea95d173e3e1b
[cparser] / driver / firm_opt.c
1 /**
2  *
3  * @file firm_opt.c -- Firm-generating back end optimizations.
4  *
5  * (C) 2005-2009  Michael Beck   beck@ipd.info.uni-karlsruhe.de
6  *
7  * $Id$
8  */
9
10 #include <config.h>
11
12 #include <stdbool.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <stdbool.h>
16 #include <assert.h>
17 #include <libfirm/firm.h>
18 #include <libfirm/be.h>
19
20
21 #include "firm_opt.h"
22 #include "firm_codegen.h"
23 #include "firm_cmdline.h"
24 #include "firm_timing.h"
25 #include "ast2firm.h"
26
27 #if defined(_DEBUG) || defined(FIRM_DEBUG)
28 #define DBG(x)  dbg_printf x
29 #else
30 #define DBG(x) ((void)0)
31 #endif /* _DEBUG || FIRM_DEBUG */
32
33 static bool do_irg_opt(ir_graph *irg, const char *name);
34
35 /** dump all the graphs depending on cond */
36 #define DUMP_ALL(cond, suffix)                             \
37   do {                                                     \
38     if (cond) {                                            \
39       timer_push(TV_VCG_DUMP);                             \
40       if (firm_dump.no_blocks)                             \
41         dump_all_ir_graphs(dump_ir_graph, suffix);         \
42       else if (firm_dump.extbb)                            \
43         dump_all_ir_graphs(dump_ir_extblock_graph, suffix);\
44       else                                                 \
45         dump_all_ir_graphs(dump_ir_block_graph, suffix);   \
46       timer_pop();                                         \
47     }                                                      \
48   } while (0)
49
50 /** dump all control flow graphs depending on cond */
51 #define DUMP_ALL_CFG(cond, suffix)                      \
52   do {                                                  \
53     if (cond) {                                         \
54       timer_push(TV_VCG_DUMP);                          \
55         dump_all_ir_graphs(dump_cfg, suffix);           \
56       timer_pop();                                      \
57     }                                                   \
58   } while (0)
59
60 /** check all graphs depending on cond */
61 #define CHECK_ALL(cond)                                 \
62   do {                                                  \
63     if (cond) {                                         \
64       int ii;                                           \
65       timer_push(TV_VERIFY);                            \
66       for (ii = get_irp_n_irgs() - 1; ii >= 0; --ii)    \
67         irg_verify(get_irp_irg(ii), VRFY_ENFORCE_SSA);  \
68       timer_pop();                                      \
69     }                                                   \
70   } while (0)
71
72
73
74 /** dump graphs irg depending on cond */
75 #define DUMP_ONE(cond, irg, suffix)                     \
76   do {                                                  \
77     if (cond) {                                         \
78       timer_push(TV_VCG_DUMP);                          \
79       if (firm_dump.no_blocks)                          \
80         dump_ir_graph(irg, suffix);                     \
81       else if (firm_dump.extbb)                         \
82         dump_ir_extblock_graph(irg, suffix);            \
83       else                                              \
84         dump_ir_block_graph(irg, suffix);               \
85       timer_pop();                                      \
86     }                                                   \
87   } while (0)
88
89 /** dump control flow graph irg depending on cond */
90 #define DUMP_ONE_CFG(cond, irg, suffix)                 \
91   do {                                                  \
92     if (cond) {                                         \
93       timer_push(TV_VCG_DUMP);                          \
94       dump_cfg(irg, suffix);                            \
95       timer_pop();                                      \
96     }                                                   \
97   } while (0)
98
99 /** check a graph irg depending on cond */
100 #define CHECK_ONE(cond, irg)                            \
101   do {                                                  \
102     if (cond) {                                         \
103       timer_push(TV_VERIFY);                            \
104         irg_verify(irg, VRFY_ENFORCE_SSA);              \
105       timer_pop();                                      \
106     }                                                   \
107   } while (0)
108
109
110 /* set by the backend parameters */
111 static const ir_settings_arch_dep_t *ad_param = NULL;
112 static create_intrinsic_fkt *arch_create_intrinsic = NULL;
113 static void *create_intrinsic_ctx = NULL;
114 static const ir_settings_if_conv_t *if_conv_info = NULL;
115
116 /* entities of runtime functions */
117 ir_entity_ptr rts_entities[rts_max];
118
119 /**
120  * factory for setting architecture dependent parameters
121  */
122 static const ir_settings_arch_dep_t *arch_factory(void)
123 {
124   static const ir_settings_arch_dep_t param = {
125       1,   /* also use subs */
126       4,   /* maximum shifts */
127      31,   /* maximum shift amount */
128      NULL, /* use default evaluator */
129
130       1, /* allow Mulhs */
131       1, /* allow Mulus */
132      32  /* Mulh allowed up to 32 bit */
133   };
134
135   return ad_param ? ad_param : &param;
136 }
137
138 /**
139  * Map runtime functions.
140  */
141 static void rts_map(void) {
142   static const struct {
143     ir_entity_ptr *ent; /**< address of the rts entity */
144     i_mapper_func func; /**< mapper function. */
145   } mapper[] = {
146     /* integer */
147     { &rts_entities[rts_abs],     i_mapper_abs },
148     { &rts_entities[rts_labs],    i_mapper_abs },
149     { &rts_entities[rts_llabs],   i_mapper_abs },
150     { &rts_entities[rts_imaxabs], i_mapper_abs },
151
152     /* double -> double */
153     { &rts_entities[rts_fabs],    i_mapper_abs },
154     { &rts_entities[rts_sqrt],    i_mapper_sqrt },
155     { &rts_entities[rts_cbrt],    i_mapper_cbrt },
156     { &rts_entities[rts_pow],     i_mapper_pow },
157     { &rts_entities[rts_exp],     i_mapper_exp },
158     { &rts_entities[rts_exp2],    i_mapper_exp },
159     { &rts_entities[rts_exp10],   i_mapper_exp },
160     { &rts_entities[rts_log],     i_mapper_log },
161     { &rts_entities[rts_log2],    i_mapper_log2 },
162     { &rts_entities[rts_log10],   i_mapper_log10 },
163     { &rts_entities[rts_sin],     i_mapper_sin },
164     { &rts_entities[rts_cos],     i_mapper_cos },
165     { &rts_entities[rts_tan],     i_mapper_tan },
166     { &rts_entities[rts_asin],    i_mapper_asin },
167     { &rts_entities[rts_acos],    i_mapper_acos },
168     { &rts_entities[rts_atan],    i_mapper_atan },
169     { &rts_entities[rts_sinh],    i_mapper_sinh },
170     { &rts_entities[rts_cosh],    i_mapper_cosh },
171     { &rts_entities[rts_tanh],    i_mapper_tanh },
172
173     /* float -> float */
174     { &rts_entities[rts_fabsf],   i_mapper_abs },
175     { &rts_entities[rts_sqrtf],   i_mapper_sqrt },
176     { &rts_entities[rts_cbrtf],   i_mapper_cbrt },
177     { &rts_entities[rts_powf],    i_mapper_pow },
178     { &rts_entities[rts_expf],    i_mapper_exp },
179     { &rts_entities[rts_exp2f],   i_mapper_exp },
180     { &rts_entities[rts_exp10f],  i_mapper_exp },
181     { &rts_entities[rts_logf],    i_mapper_log },
182     { &rts_entities[rts_log2f],   i_mapper_log2 },
183     { &rts_entities[rts_log10f],  i_mapper_log10 },
184     { &rts_entities[rts_sinf],    i_mapper_sin },
185     { &rts_entities[rts_cosf],    i_mapper_cos },
186     { &rts_entities[rts_tanf],    i_mapper_tan },
187     { &rts_entities[rts_asinf],   i_mapper_asin },
188     { &rts_entities[rts_acosf],   i_mapper_acos },
189     { &rts_entities[rts_atanf],   i_mapper_atan },
190     { &rts_entities[rts_sinhf],   i_mapper_sinh },
191     { &rts_entities[rts_coshf],   i_mapper_cosh },
192     { &rts_entities[rts_tanhf],   i_mapper_tanh },
193
194     /* long double -> long double */
195     { &rts_entities[rts_fabsl],   i_mapper_abs },
196     { &rts_entities[rts_sqrtl],   i_mapper_sqrt },
197     { &rts_entities[rts_cbrtl],   i_mapper_cbrt },
198     { &rts_entities[rts_powl],    i_mapper_pow },
199     { &rts_entities[rts_expl],    i_mapper_exp },
200     { &rts_entities[rts_exp2l],   i_mapper_exp },
201     { &rts_entities[rts_exp10l],  i_mapper_exp },
202     { &rts_entities[rts_logl],    i_mapper_log },
203     { &rts_entities[rts_log2l],   i_mapper_log2 },
204     { &rts_entities[rts_log10l],  i_mapper_log10 },
205     { &rts_entities[rts_sinl],    i_mapper_sin },
206     { &rts_entities[rts_cosl],    i_mapper_cos },
207     { &rts_entities[rts_tanl],    i_mapper_tan },
208     { &rts_entities[rts_asinl],   i_mapper_asin },
209     { &rts_entities[rts_acosl],   i_mapper_acos },
210     { &rts_entities[rts_atanl],   i_mapper_atan },
211     { &rts_entities[rts_sinhl],   i_mapper_sinh },
212     { &rts_entities[rts_coshl],   i_mapper_cosh },
213     { &rts_entities[rts_tanhl],   i_mapper_tanh },
214
215     /* string */
216     { &rts_entities[rts_strcmp],  i_mapper_strcmp },
217     { &rts_entities[rts_strncmp], i_mapper_strncmp },
218     { &rts_entities[rts_strcpy],  i_mapper_strcpy },
219     { &rts_entities[rts_strlen],  i_mapper_strlen },
220     { &rts_entities[rts_memcpy],  i_mapper_memcpy },
221     { &rts_entities[rts_mempcpy], i_mapper_mempcpy },
222     { &rts_entities[rts_memmove], i_mapper_memmove },
223     { &rts_entities[rts_memset],  i_mapper_memset },
224     { &rts_entities[rts_memcmp],  i_mapper_memcmp }
225   };
226   i_record rec[sizeof(mapper)/sizeof(mapper[0])];
227   unsigned i, n_map;
228
229   for (i = n_map = 0; i < sizeof(mapper)/sizeof(mapper[0]); ++i)
230     if (*mapper[i].ent != NULL) {
231       rec[n_map].i_call.kind     = INTRINSIC_CALL;
232       rec[n_map].i_call.i_ent    = *mapper[i].ent;
233       rec[n_map].i_call.i_mapper = mapper[i].func;
234       rec[n_map].i_call.ctx      = NULL;
235       rec[n_map].i_call.link     = NULL;
236       ++n_map;
237   }  /* if */
238   if (n_map > 0)
239     lower_intrinsics(rec, n_map, /* part_block_used=*/0);
240 }  /* rts_map */
241
242 static int *irg_dump_no;
243
244 static void dump_graph_count(ir_graph *const irg, const char *const suffix)
245 {
246   char name[64];
247   snprintf(name, sizeof(name), "-%02d_%s", irg_dump_no[get_irg_idx(irg)]++, suffix);
248   DUMP_ONE(1, irg, name);
249 }
250
251 static void dump_all_count(const char *const suffix)
252 {
253   const int n_irgs = get_irp_n_irgs();
254   int i;
255
256   for (i = 0; i < n_irgs; ++i)
257     dump_graph_count(get_irp_irg(i), suffix);
258 }
259
260 #define DUMP_ONE_C(cond, irg, suffix)    \
261   do {                                   \
262     if (cond) {                          \
263       dump_graph_count((irg), (suffix)); \
264     }                                    \
265   } while (0)
266
267 #define DUMP_ALL_C(cond, suffix) \
268   do {                           \
269     if (cond) {                  \
270       dump_all_count((suffix));  \
271     }                            \
272   } while (0)
273
274 static void remove_unused_functions(void)
275 {
276         ir_entity **keep_methods;
277         int         arr_len;
278
279         /* Analysis that finds the free methods,
280            i.e. methods that are dereferenced.
281            Optimizes polymorphic calls :-). */
282         cgana(&arr_len, &keep_methods);
283
284         /* Remove methods that are never called. */
285         gc_irgs(arr_len, keep_methods);
286         free(keep_methods);
287 }
288
289 static int firm_const_exists;
290
291 static void do_optimize_funccalls(void)
292 {
293         optimize_funccalls(firm_const_exists, NULL);
294 }
295
296 static void do_gcse(ir_graph *irg)
297 {
298         set_opt_global_cse(1);
299         optimize_graph_df(irg);
300         place_code(irg);
301         set_opt_global_cse(0);
302 }
303
304 static void do_lower_highlevel(ir_graph *irg)
305 {
306         lower_highlevel_graph(irg, firm_opt.lower_bitfields);
307 }
308
309 static void do_if_conv(ir_graph *irg)
310 {
311         opt_if_conv(irg, if_conv_info);
312 }
313
314 static void do_stred(ir_graph *irg)
315 {
316         opt_osr(irg, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift);
317 }
318
319 static void after_inline_opt(ir_graph *irg)
320 {
321         do_irg_opt(irg, "scalar-replace");
322         do_irg_opt(irg, "local");
323         do_irg_opt(irg, "control-flow");
324         do_irg_opt(irg, "combo");
325 }
326
327 static void do_inline(void)
328 {
329         inline_functions(firm_opt.inline_maxsize, firm_opt.inline_threshold,
330                          after_inline_opt);
331 }
332
333 static void do_cloning(void)
334 {
335         proc_cloning((float) firm_opt.clone_threshold);
336 }
337
338 static void do_lower_switch(ir_graph *irg)
339 {
340         lower_switch(irg, firm_opt.spare_size);
341 }
342
343 typedef enum opt_target {
344         OPT_TARGET_IRG, /**< optimization function works on a single graph */
345         OPT_TARGET_IRP  /**< optimization function works on the complete program */
346 } opt_target_t;
347
348 typedef enum opt_flags {
349         OPT_FLAG_NONE         = 0,
350         OPT_FLAG_ENABLED      = 1 << 0, /**< enable the optimization */
351         OPT_FLAG_NO_DUMP      = 1 << 1, /**< don't dump after transformation */
352         OPT_FLAG_NO_VERIFY    = 1 << 2, /**< don't verify after transformation */
353         OPT_FLAG_HIDE_OPTIONS = 1 << 3, /**< do not automatically process
354                                              -foptions for this transformation */
355 } opt_flags_t;
356
357 typedef void (*transform_irg_func)(ir_graph *irg);
358 typedef void (*transform_irp_func)(void);
359 typedef void (*func_ptr_t)(void);
360
361 typedef struct {
362         opt_target_t  target;
363         const char   *name;
364         func_ptr_t    func;
365         int           timer;
366         const char   *description;
367         opt_flags_t   flags;
368 } opt_config_t;
369
370 static opt_config_t opts[] = {
371         { OPT_TARGET_IRP, "rts",             (func_ptr_t) rts_map,                 TV_RTS,            "optimization of known library functions", OPT_FLAG_HIDE_OPTIONS },
372         { OPT_TARGET_IRG, "combo",           (func_ptr_t) combo,                   TV_COMBO,          "combined CCE, UCE and GVN",               OPT_FLAG_NONE},
373         { OPT_TARGET_IRG, "control-flow",    (func_ptr_t) optimize_cf,             TV_CF_OPT,         "optimization of control-flow",            OPT_FLAG_HIDE_OPTIONS },
374         { OPT_TARGET_IRG, "local",           (func_ptr_t) optimize_graph_df,       TV_LOCAL_OPT,      "local graph optimizations",               OPT_FLAG_HIDE_OPTIONS },
375         { OPT_TARGET_IRP, "remove-unused",   (func_ptr_t) remove_unused_functions, TV_CGANA,          "removal of unused functions",             OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
376         { OPT_TARGET_IRP, "opt-tail-rec",    (func_ptr_t) opt_tail_recursion,      TV_TAIL_REC,       "tail-recursion eliminiation",             OPT_FLAG_NONE },
377         { OPT_TARGET_IRP, "opt-func-call",   (func_ptr_t) do_optimize_funccalls,   TV_REAL_FUNC_CALL, "function call optimization",              OPT_FLAG_NONE },
378         { OPT_TARGET_IRP, "lower-const",     (func_ptr_t) lower_const_code,        TV_LOWER,          "lowering of constant code",               OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
379         { OPT_TARGET_IRG, "one-return",      (func_ptr_t) normalize_one_return,    TV_ONERETURN,      "normalisation to 1 return",               OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
380         { OPT_TARGET_IRG, "scalar-replace",  (func_ptr_t) scalar_replacement_opt,  TV_SCALAR_REPLACE, "scalar replacement",                      OPT_FLAG_NONE },
381         { OPT_TARGET_IRG, "reassociation",   (func_ptr_t) optimize_reassociation,  TV_REASSOCIATION,  "reassociation",                           OPT_FLAG_NONE },
382         { OPT_TARGET_IRG, "gcse",            (func_ptr_t) do_gcse,                 TV_CODE_PLACE,     "global common subexpression elimination", OPT_FLAG_NONE },
383         { OPT_TARGET_IRG, "place",           (func_ptr_t) place_code,              TV_CODE_PLACE,     "code placement",                          OPT_FLAG_NONE },
384         { OPT_TARGET_IRG, "confirm",         (func_ptr_t) construct_confirms,      TV_CONFIRM_CREATE, "confirm optimisation",                    OPT_FLAG_HIDE_OPTIONS },
385         { OPT_TARGET_IRG, "opt-load-store",  (func_ptr_t) optimize_load_store,     TV_LOAD_STORE,     "load store optimization",                 OPT_FLAG_NONE },
386         { OPT_TARGET_IRG, "sync",            (func_ptr_t) opt_sync,                TV_SYNC,           "automatic sync-node creation",            OPT_FLAG_NONE },
387         { OPT_TARGET_IRG, "lower",           (func_ptr_t) do_lower_highlevel,      TV_LOWER,          "lowering",                                OPT_FLAG_HIDE_OPTIONS },
388         { OPT_TARGET_IRG, "deconv",          (func_ptr_t) conv_opt,                TV_DECONV,         "conv node elimination",                   OPT_FLAG_NONE },
389         { OPT_TARGET_IRG, "thread-jumps",    (func_ptr_t) opt_jumpthreading,       TV_JUMPTHREADING,  "path-sensitive jumpthreading",            OPT_FLAG_NONE },
390         { OPT_TARGET_IRG, "remove-confirms", (func_ptr_t) remove_confirms,         TV_CONFIRM_CREATE, "confirm removal",                         OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
391         { OPT_TARGET_IRG, "gvn-pre",         (func_ptr_t) do_gvn_pre,              TV_GVNPRE,         "global value numbering partial redundancy elimination", OPT_FLAG_NONE },
392         { OPT_TARGET_IRG, "if-conversion",   (func_ptr_t) do_if_conv,              TV_IF_CONV,        "if-conversion",                           OPT_FLAG_NONE },
393         { OPT_TARGET_IRG, "bool",            (func_ptr_t) opt_bool,                TV_BOOLOPT,        "bool simplification",                     OPT_FLAG_NONE },
394         { OPT_TARGET_IRG, "shape-blocks",    (func_ptr_t) shape_blocks,            TV_END_MELT,       "block shaping",                           OPT_FLAG_NONE },
395         { OPT_TARGET_IRG, "ivopts",          (func_ptr_t) do_stred,                TV_OSR,            "induction variable strength reduction",   OPT_FLAG_NONE },
396         { OPT_TARGET_IRG, "remove-phi-cycles", (func_ptr_t) remove_phi_cycles,     TV_OSR,            "removal of phi cycles",                   OPT_FLAG_HIDE_OPTIONS },
397         { OPT_TARGET_IRG, "dead",            (func_ptr_t) dead_node_elimination,   TV_DEAD_NODE,      "dead node elimination",                   OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY },
398         { OPT_TARGET_IRP, "inline",          (func_ptr_t) do_inline,               TV_INLINE,         "inlining",                                OPT_FLAG_NONE },
399         { OPT_TARGET_IRP, "opt-proc-clone",  (func_ptr_t) do_cloning,              TV_CLONE,          "procedure cloning",                       OPT_FLAG_NONE },
400         { OPT_TARGET_IRG, "lower-switch",    (func_ptr_t) do_lower_switch,         TV_LOWER,          "switch lowering",                         OPT_FLAG_HIDE_OPTIONS },
401         { OPT_TARGET_IRG, "invert-loops",    (func_ptr_t) do_loop_inversion,       TV_LOOP_INVERSION, "loop inversion",                          OPT_FLAG_NONE },
402         { OPT_TARGET_IRG, "peel-loops",      (func_ptr_t) do_loop_peeling,         TV_LOOP_PEELING,   "loop peeling",                            OPT_FLAG_NONE },
403 };
404 static const int n_opts = sizeof(opts) / sizeof(opts[0]);
405
406 static opt_config_t *get_opt(const char *name)
407 {
408         int i;
409         for (i = 0; i < n_opts; ++i) {
410                 opt_config_t *config = &opts[i];
411                 if (strcmp(config->name, name) == 0)
412                         return config;
413         }
414
415         return NULL;
416 }
417
418 static void set_opt_enabled(const char *name, bool enabled)
419 {
420         opt_config_t *config = get_opt(name);
421         config->flags = (config->flags & ~OPT_FLAG_ENABLED)
422                 | (enabled ? OPT_FLAG_ENABLED : 0);
423 }
424
425 static bool get_opt_enabled(const char *name)
426 {
427         opt_config_t *config = get_opt(name);
428         return (config->flags & OPT_FLAG_ENABLED) != 0;
429 }
430
431 /**
432  * perform an optimisation on a single graph
433  *
434  * @return  true if something changed, false otherwise
435  */
436 static bool do_irg_opt(ir_graph *irg, const char *name)
437 {
438         transform_irg_func  func;
439         ir_graph           *old_irg;
440         opt_config_t       *config = get_opt(name);
441         assert(config->target == OPT_TARGET_IRG);
442         if (! (config->flags & OPT_FLAG_ENABLED))
443                 return false;
444
445         if (config->timer != -1)
446                 timer_push(config->timer);
447
448         old_irg          = current_ir_graph;
449         current_ir_graph = irg;
450
451         func = (transform_irg_func) config->func;
452         func(irg);
453
454         if (config->timer != -1)
455                 timer_pop();
456
457         DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, config->name);
458         CHECK_ONE(firm_opt.check_all, irg);
459
460         current_ir_graph = old_irg;
461         return true;
462 }
463
464 static void do_irp_opt(const char *name)
465 {
466         transform_irp_func  func;
467         opt_config_t       *config = get_opt(name);
468         assert(config->target == OPT_TARGET_IRP);
469         if (! (config->flags & OPT_FLAG_ENABLED))
470                 return;
471
472         if (config->timer != -1)
473                 timer_push(config->timer);
474
475         func = (transform_irp_func) config->func;
476         func();
477
478         DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, config->name);
479         CHECK_ALL(firm_opt.check_all);
480
481         if (config->timer != -1)
482                 timer_pop();
483 }
484
485 /**
486  * Enable transformations which should be always safe (and cheap) to perform
487  */
488 static void enable_safe_defaults(void)
489 {
490         set_opt_enabled("remove-unused", true);
491         set_opt_enabled("opt-tail-rec", true);
492         set_opt_enabled("opt-func-call", true);
493         set_opt_enabled("reassociation", true);
494         set_opt_enabled("control-flow", true);
495         set_opt_enabled("local", true);
496         set_opt_enabled("lower-const", true);
497         set_opt_enabled("scalar-replace", true);
498         set_opt_enabled("place", true);
499         set_opt_enabled("confirm", true);
500         set_opt_enabled("opt-load-store", true);
501         set_opt_enabled("lower", true);
502         set_opt_enabled("deconv", true);
503         set_opt_enabled("remove-confirms", true);
504         set_opt_enabled("ivopts", true);
505         set_opt_enabled("dead", true);
506         set_opt_enabled("lower-switch", true);
507         set_opt_enabled("remove-phi-cycles", true);
508 }
509
510 /**
511  * run all the Firm optimizations
512  *
513  * @param input_filename     the name of the (main) source file
514  */
515 static void do_firm_optimizations(const char *input_filename)
516 {
517   int      i;
518   unsigned aa_opt;
519
520   /* FIXME: cloning might ADD new graphs. */
521   irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no));
522
523   set_opt_alias_analysis(firm_opt.alias_analysis);
524
525   aa_opt = aa_opt_no_opt;
526   if (firm_opt.strict_alias)
527     aa_opt |= aa_opt_type_based | aa_opt_byte_type_may_alias;
528   if (firm_opt.no_alias)
529     aa_opt = aa_opt_no_alias;
530
531   set_irp_memory_disambiguator_options(aa_opt);
532
533   /* parameter passing code should set them directly sometime... */
534   set_opt_enabled("rts", !firm_opt.freestanding);
535   set_opt_enabled("gcse", firm_opt.gcse);
536   set_opt_enabled("place", !firm_opt.gcse);
537   set_opt_enabled("confirm", firm_opt.confirm);
538   set_opt_enabled("remove-confirms", firm_opt.confirm);
539
540   /* osr supersedes remove_phi_cycles */
541   if (get_opt_enabled("ivopts"))
542           set_opt_enabled("remove-phi-cycles", false);
543
544   timer_start(TV_ALL_OPT);
545
546   do_irp_opt("rts");
547
548   /* first step: kill dead code */
549   for (i = 0; i < get_irp_n_irgs(); i++) {
550     ir_graph *irg = get_irp_irg(i);
551     do_irg_opt(irg, "combo");
552     do_irg_opt(irg, "local");
553     do_irg_opt(irg, "control-flow");
554   }
555
556   do_irp_opt("remove-unused");
557   do_irp_opt("opt-tail-rec");
558   do_irp_opt("opt-func-call");
559   do_irp_opt("lower-const");
560
561   for (i = 0; i < get_irp_n_irgs(); i++) {
562     ir_graph *irg = get_irp_irg(i);
563
564     do_irg_opt(irg, "scalar-replace");
565     do_irg_opt(irg, "invert-loops");
566     do_irg_opt(irg, "local");
567     do_irg_opt(irg, "reassociation");
568     do_irg_opt(irg, "local");
569     do_irg_opt(irg, "gcse");
570
571     if (firm_opt.confirm) {
572       /* Confirm construction currently can only handle blocks with only one
573          control flow predecessor. Calling optimize_cf here removes Bad
574          predecessors and help the optimization of switch constructs. */
575       do_irg_opt(irg, "control-flow");
576       do_irg_opt(irg, "confirm");
577       do_irg_opt(irg, "local");
578     }
579
580     do_irg_opt(irg, "control-flow");
581     do_irg_opt(irg, "opt-load-store");
582     do_irg_opt(irg, "lower");
583     do_irg_opt(irg, "deconv");
584     do_irg_opt(irg, "thread-jumps");
585     do_irg_opt(irg, "remove-confirms");
586     do_irg_opt(irg, "gvn-pre");
587     do_irg_opt(irg, "place");
588     do_irg_opt(irg, "control-flow");
589
590     if (do_irg_opt(irg, "if-conversion")) {
591       do_irg_opt(irg, "local");
592       do_irg_opt(irg, "control-flow");
593     }
594
595     do_irg_opt(irg, "bool");
596     do_irg_opt(irg, "shape-blocks");
597     do_irg_opt(irg, "lower-switch");
598     do_irg_opt(irg, "ivopts");
599     do_irg_opt(irg, "local");
600     do_irg_opt(irg, "dead");
601   }
602
603   do_irp_opt("inline");
604   do_irp_opt("opt-proc-clone");
605
606   for (i = 0; i < get_irp_n_irgs(); i++) {
607     ir_graph *irg = get_irp_irg(i);
608     do_irg_opt(irg, "local");
609     do_irg_opt(irg, "control-flow");
610     do_irg_opt(irg, "thread-jumps");
611     do_irg_opt(irg, "local");
612     do_irg_opt(irg, "control-flow");
613   }
614
615   if (firm_dump.ir_graph) {
616     /* recompute backedges for nicer dumps */
617     for (i = 0; i < get_irp_n_irgs(); i++)
618       construct_cf_backedges(get_irp_irg(i));
619   }
620
621   do_irp_opt("remove-unused");
622
623   DUMP_ALL(firm_dump.ir_graph, "-opt");
624   /* verify optimized graphs */
625   CHECK_ALL(firm_opt.check_all);
626
627   if (firm_dump.statistic & STAT_AFTER_OPT)
628     stat_dump_snapshot(input_filename, "opt");
629
630   timer_stop(TV_ALL_OPT);
631 }  /* do_firm_optimizations */
632
633 /**
634  * compute the size of a type (do implicit lowering)
635  *
636  * @param ty   a Firm type
637  */
638 static int compute_type_size(ir_type *ty)
639 {
640   optimization_state_t state;
641   unsigned             align_all = 1;
642   int                  n, size = 0, set = 0;
643   int                  i, dims, s;
644
645   if (get_type_state(ty) == layout_fixed) {
646     /* do not layout already layouted types again */
647     return 1;
648   }
649
650   if (is_Method_type(ty) || ty == get_glob_type()) {
651     /* no need for size calculation for method types or the global type */
652     return 1;
653   }
654
655   DBG(("compute type size visiting: %s\n", get_type_name(ty)));
656
657   switch (get_type_tpop_code(ty)) {
658   case tpo_class:
659   case tpo_struct:
660     for (i = 0, n = get_compound_n_members(ty); i < n; ++i) {
661       ir_entity *ent  = get_compound_member(ty, i);
662       ir_type *ent_ty = get_entity_type(ent);
663       unsigned align, misalign;
664
665       /* inner functions do not expand the frame */
666       if (is_Method_type(ent_ty) && is_frame_type(ty))
667         continue;
668
669       /* compute member types */
670       if (! compute_type_size(ent_ty))
671         return 0;
672
673       align     = get_type_alignment_bytes(ent_ty);
674       align_all = align > align_all ? align : align_all;
675       misalign  = (align ? size % align : 0);
676       size     += (misalign ? align - misalign : 0);
677
678       set_entity_offset(ent, size);
679       size += get_type_size_bytes(ent_ty);
680
681       DBG(("  member %s %s -> (size: %u, align: %u)\n",
682             get_type_name(ent_ty), get_entity_name(ent),
683             get_type_size_bytes(ent_ty), get_type_alignment_bytes(ent_ty)));
684     }
685     if (align_all > 0 && size % align_all) {
686        DBG(("align of the struct member: %u, type size: %d\n", align_all, size));
687        size += align_all - (size % align_all);
688        DBG(("correcting type-size to %d\n", size));
689     }
690     set_type_alignment_bytes(ty, align_all);
691     set = 1;
692     break;
693
694   case tpo_union:
695     for (i = 0, n = get_union_n_members(ty); i < n; ++i) {
696       ir_entity *ent = get_union_member(ty, i);
697
698       if (! compute_type_size(get_entity_type(ent)))
699         return 0;
700       s = get_type_size_bytes(get_entity_type(ent));
701
702       set_entity_offset(ent, 0);
703       size = (s > size ? s : size);
704     }
705     set = 1;
706     break;
707
708   case tpo_array:
709     dims = get_array_n_dimensions(ty);
710
711     if (! compute_type_size(get_array_element_type(ty)))
712       return 0;
713
714     size = 1;
715
716     save_optimization_state(&state);
717     set_optimize(1);
718     set_opt_constant_folding(1);
719         set_opt_algebraic_simplification(1);
720
721     for (i = 0; i < dims; ++i) {
722       ir_node *lower   = get_array_lower_bound(ty, i);
723       ir_node *upper   = get_array_upper_bound(ty, i);
724       ir_graph *rem    = current_ir_graph;
725       tarval  *tv_lower, *tv_upper;
726       long     val_lower, val_upper;
727
728       current_ir_graph = get_const_code_irg();
729       local_optimize_node(lower);
730       local_optimize_node(upper);
731       current_ir_graph = rem;
732
733       tv_lower = computed_value(lower);
734       tv_upper = computed_value(upper);
735
736       if (tv_lower == tarval_bad || tv_upper == tarval_bad) {
737         /*
738          * we cannot calculate the size of this array yet, it
739          * even might be unknown until the end, like argv[]
740          */
741         restore_optimization_state(&state);
742         return 0;
743       }
744
745       val_upper = get_tarval_long(tv_upper);
746       val_lower = get_tarval_long(tv_lower);
747       size     *= val_upper - val_lower;
748     }
749     restore_optimization_state(&state);
750
751     DBG(("array %s -> (elements: %d, element type size: %d)\n",
752           get_type_name(ty),
753           size, get_type_size_bytes(get_array_element_type(ty))));
754     size *= get_type_size_bytes(get_array_element_type(ty));
755     set = 1;
756     break;
757
758   default:
759     break;
760   }
761
762   if (set) {
763     set_type_size_bytes(ty, size);
764     set_type_state(ty, layout_fixed);
765   }
766
767   DBG(("size: %d\n", get_type_size_bytes(ty)));
768
769   return set;
770 }  /* compute_type_size */
771
772 /**
773  * layout all non-frame types of the Firm graph
774  */
775 static void compute_type_sizes(void)
776 {
777   int i;
778   ir_type *tp;
779
780   /* all non-frame other types */
781   for (i = get_irp_n_types() - 1; i >= 0; --i) {
782     tp = get_irp_type(i);
783     compute_type_size(tp);
784
785     if (is_Method_type(tp)) {
786       tp = get_method_value_res_type(tp);
787
788       if (tp) {
789         /* we have a value result type for this method, lower */
790         compute_type_size(tp);
791       }
792     }
793   }
794 }  /* compute_type_sizes */
795
796 /**
797  * layout all frame-types of the Firm graph
798  */
799 static void compute_frame_type_sizes(void)
800 {
801   int i;
802   ir_graph *irg;
803
804   /* all frame types */
805   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
806     irg = get_irp_irg(i);
807     /* do not optimize away variables in debug mode */
808     if (firm_opt.debug_mode == DBG_MODE_NONE)
809       opt_frame_irg(irg);
810     compute_type_size(get_irg_frame_type(irg));
811   }
812 }  /* compute_frame_type_sizes */
813
814 /**
815  * do Firm lowering
816  *
817  * @param input_filename  the name of the (main) source file
818  */
819 static void do_firm_lowering(const char *input_filename)
820 {
821   int i;
822
823   if (firm_opt.lower_ll) {
824     lwrdw_param_t init = {
825       1,
826       1,
827       get_atomic_mode(ATOMIC_TYPE_LONGLONG),
828       get_atomic_mode(ATOMIC_TYPE_ULONGLONG),
829       get_atomic_mode(ATOMIC_TYPE_INT),
830       get_atomic_mode(ATOMIC_TYPE_UINT),
831       def_create_intrinsic_fkt,
832       NULL
833     };
834
835
836     if (arch_create_intrinsic) {
837       init.create_intrinsic = arch_create_intrinsic;
838       init.ctx              = create_intrinsic_ctx;
839     }
840     timer_push(TV_DW_LOWER);
841       lower_dw_ops(&init);
842     timer_pop();
843   }
844
845   if (firm_dump.statistic & STAT_AFTER_LOWER)
846     stat_dump_snapshot(input_filename, "low");
847
848   /* verify lowered graphs */
849   CHECK_ALL(firm_opt.check_all);
850
851   DUMP_ALL(firm_dump.ir_graph, "-low");
852
853   if (firm_opt.enabled) {
854     timer_start(TV_ALL_OPT);
855
856     /* run reassociation first on all graphs BEFORE the architecture dependent optimizations
857        are enabled */
858     for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
859       ir_graph *irg = get_irp_irg(i);
860           do_irg_opt(irg, "reassociation");
861         }
862
863     /* enable architecture dependent optimizations */
864     arch_dep_set_opts((arch_dep_opts_t)
865                       ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) |
866                       (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) |
867                       (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) ));
868
869     for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
870       ir_graph *irg = get_irp_irg(i);
871
872       current_ir_graph = irg;
873
874       do_irg_opt(irg, "local");
875       do_irg_opt(irg, "gcse");
876       do_irg_opt(irg, "opt-load-store");
877       do_irg_opt(irg, "local");
878       do_irg_opt(irg, "control-flow");
879
880       if (do_irg_opt(irg, "if-conversion")) {
881         do_irg_opt(irg, "local");
882         do_irg_opt(irg, "control-flow");
883       }
884
885       do_irg_opt(current_ir_graph, "sync");
886     }
887     timer_stop(TV_ALL_OPT);
888
889     DUMP_ALL(firm_dump.ir_graph, "-low-opt");
890   }
891
892   if (firm_opt.cc_opt)
893     mark_private_methods();
894
895   /* set the phase to low */
896   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
897     set_irg_phase_low(get_irp_irg(i));
898
899   /* all graphs are lowered, set the irp phase to low */
900   set_irp_phase_state(phase_low);
901
902   if (firm_dump.statistic & STAT_FINAL) {
903     stat_dump_snapshot(input_filename, "final");
904   }
905 }  /* do_firm_lowering */
906
907 /**
908  * Initialize for the Firm-generating back end.
909  */
910 void gen_firm_init(void)
911 {
912   firm_parameter_t params;
913   unsigned         pattern = 0;
914
915   if (firm_dump.stat_pattern)
916     pattern |= FIRMSTAT_PATTERN_ENABLED;
917
918   if (firm_dump.stat_dag)
919     pattern |= FIRMSTAT_COUNT_DAG;
920
921   memset(&params, 0, sizeof(params));
922   params.size                  = sizeof(params);
923   params.enable_statistics     = firm_dump.statistic == STAT_NONE ? 0 :
924     FIRMSTAT_ENABLED | FIRMSTAT_COUNT_STRONG_OP | FIRMSTAT_COUNT_CONSTS | pattern;
925   params.initialize_local_func = uninitialized_local_var;
926   params.cc_mask               = 0; /* no regparam, cdecl */
927   params.builtin_dbg           = NULL;
928
929   ir_init(&params);
930
931   if (firm_be_opt.selection == BE_FIRM_BE) {
932     const backend_params *be_params = be_get_backend_param();
933
934     firm_opt.lower_ll       = (a_byte) be_params->do_dw_lowering;
935
936     arch_create_intrinsic   = be_params->arch_create_intrinsic_fkt;
937     create_intrinsic_ctx    = be_params->create_intrinsic_ctx;
938
939     ad_param                = be_params->dep_param;
940     if_conv_info            = be_params->if_conv_info;
941   }
942
943   dbg_init(NULL, NULL, dbg_snprint);
944   edges_init_dbg(firm_opt.vrfy_edges);
945
946   /* Sel node cannot produce NULL pointers */
947   set_opt_sel_based_null_check_elim(1);
948
949   /* dynamic dispatch works currently only if whole world scenarios */
950   set_opt_dyn_meth_dispatch(0);
951
952   arch_dep_init(arch_factory);
953
954   /* do not run architecture dependent optimizations in building phase */
955   arch_dep_set_opts(arch_dep_none);
956
957   do_node_verification((firm_verification_t) firm_opt.vrfy);
958   if (firm_dump.filter)
959     only_dump_method_with_name(new_id_from_str(firm_dump.filter));
960
961   if (firm_opt.enabled) {
962     set_optimize(1);
963     set_opt_constant_folding(firm_opt.const_folding);
964     set_opt_algebraic_simplification(firm_opt.const_folding);
965     set_opt_cse(firm_opt.cse);
966     set_opt_global_cse(0);
967     set_opt_unreachable_code(1);
968     set_opt_control_flow(firm_opt.control_flow);
969     set_opt_control_flow_weak_simplification(1);
970     set_opt_control_flow_strong_simplification(1);
971   } else {
972     set_optimize(0);
973   }
974
975   /* do not dump entity ld names */
976   dump_ld_names(0);
977 }  /* gen_firm_init */
978
979 /**
980  * Called, after the Firm generation is completed,
981  * do all optimizations and backend call here.
982  *
983  * @param out                a file handle for the output, may be NULL
984  * @param input_filename     the name of the (main) source file
985  * @param c_mode             non-zero if "C" was compiled
986  * @param new_firm_const_exists  non-zero, if the const attribute was used on functions
987  */
988 void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int new_firm_const_exists)
989 {
990   int i;
991
992 #if 0
993   if (firm_opt.enable_statev) {
994           char buf[1024];
995           snprintf(buf, sizeof(buf), "%s.ev", input_filename);
996           ir_stat_ev_begin(input_filename, firm_opt.statev_filter);
997           ir_stat_ev_compilation_unit(input_filename);
998   }
999 #endif
1000
1001   firm_const_exists = new_firm_const_exists;
1002
1003   /* the general for dumping option must be set, or the others will not work */
1004   firm_dump.ir_graph
1005       = (a_byte) (firm_dump.ir_graph | firm_dump.all_phases | firm_dump.extbb);
1006
1007   dump_keepalive_edges(1);
1008   dump_consts_local(1);
1009   dump_dominator_information(1);
1010   dump_loop_information(0);
1011
1012   if (!firm_dump.edge_labels)
1013     turn_off_edge_labels();
1014
1015   if (firm_dump.all_types) {
1016     dump_all_types("");
1017     if (! c_mode) {
1018       dump_class_hierarchy(0, "");
1019       dump_class_hierarchy(1, "-with-entities");
1020     }
1021   }
1022
1023   /* finalize all graphs */
1024   timer_push(TV_CONSTRUCT);
1025   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
1026     ir_graph *irg = get_irp_irg(i);
1027
1028     irg_finalize_cons(irg);
1029     DUMP_ONE(firm_dump.ir_graph, irg, "");
1030
1031     /* verify the graph */
1032     CHECK_ONE(firm_opt.check_all, irg);
1033   }
1034   timer_pop();
1035
1036   timer_push(TV_VERIFY);
1037     tr_vrfy();
1038   timer_pop();
1039
1040   /* all graphs are finalized, set the irp phase to high */
1041   set_irp_phase_state(phase_high);
1042
1043   /* BEWARE: kill unreachable code before doing compound lowering */
1044   timer_push(TV_CF_OPT);
1045   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
1046     ir_graph *irg = get_irp_irg(i);
1047     optimize_cf(irg);
1048   }
1049   timer_pop();
1050
1051   /* lower all compound call return values */
1052   lower_compound_params();
1053
1054   /* computes the sizes of all types that are still not computed */
1055   compute_type_sizes();
1056
1057   /* lower copyb nodes */
1058   for (i = get_irp_n_irgs() - 1; i >= 0; --i) {
1059     ir_graph *irg = get_irp_irg(i);
1060     lower_CopyB(irg, 128, 4);
1061   }
1062
1063   if (firm_dump.statistic & STAT_BEFORE_OPT) {
1064     stat_dump_snapshot(input_filename, "noopt");
1065   }
1066
1067   if (firm_opt.enabled)
1068     do_firm_optimizations(input_filename);
1069
1070   if (firm_dump.gen_firm_asm) {
1071     timer_push(TV_FIRM_ASM);
1072       gen_Firm_assembler(input_filename);
1073     timer_pop();
1074     return;
1075   }
1076
1077   if (firm_opt.lower)
1078     do_firm_lowering(input_filename);
1079
1080   /* computes the sizes of all frame types */
1081   compute_frame_type_sizes();
1082
1083   /* set the phase to low */
1084   for (i = get_irp_n_irgs() - 1; i >= 0; --i)
1085     set_irg_phase_low(get_irp_irg(i));
1086
1087   if (firm_dump.statistic & STAT_FINAL_IR)
1088     stat_dump_snapshot(input_filename, "final-ir");
1089
1090   /* run the code generator */
1091   if (firm_be_opt.selection != BE_NONE)
1092     do_codegen(out, input_filename);
1093
1094   if (firm_dump.statistic & STAT_FINAL)
1095     stat_dump_snapshot(input_filename, "final");
1096 }
1097
1098 int firm_opt_option(const char *opt)
1099 {
1100         bool enable = true;
1101         if (strncmp(opt, "no-", 3) == 0) {
1102                 enable = false;
1103                 opt = opt + 3;
1104         }
1105
1106         opt_config_t *config = get_opt(opt);
1107         if (config == NULL || (config->flags & OPT_FLAG_HIDE_OPTIONS))
1108                 return 0;
1109
1110         config->flags &= ~OPT_FLAG_ENABLED;
1111         config->flags |= enable ? OPT_FLAG_ENABLED : 0;
1112         return 1;
1113 }
1114
1115 void firm_opt_option_help(void)
1116 {
1117         int i;
1118
1119         for (i = 0; i < n_opts; ++i) {
1120                 char buf[1024];
1121                 char buf2[1024];
1122
1123                 const opt_config_t *config = &opts[i];
1124                 if (config->flags & OPT_FLAG_HIDE_OPTIONS)
1125                         continue;
1126
1127                 snprintf(buf2, sizeof(buf2), "firm: enable %s", config->description);
1128                 print_option_help(config->name, buf2);
1129                 snprintf(buf, sizeof(buf), "no-%s", config->name);
1130                 snprintf(buf2, sizeof(buf2), "firm: disable %s", config->description);
1131                 print_option_help(buf, buf2);
1132         }
1133 }
1134
1135 /**
1136  * Do very early initializations
1137  */
1138 void firm_early_init(void)
1139 {
1140   /* arg: need this here for command line options */
1141   be_opt_register();
1142
1143   enable_safe_defaults();
1144 }