+static void remove_unused_functions(void)
+{
+ ir_entity **keep_methods;
+ int arr_len;
+
+ /* Analysis that finds the free methods,
+ i.e. methods that are dereferenced.
+ Optimizes polymorphic calls :-). */
+ cgana(&arr_len, &keep_methods);
+
+ /* Remove methods that are never called. */
+ gc_irgs(arr_len, keep_methods);
+ free(keep_methods);
+}
+
+static int firm_const_exists;
+
+static void do_optimize_funccalls(void)
+{
+ optimize_funccalls(firm_const_exists, NULL);
+}
+
+static void do_gcse(ir_graph *irg)
+{
+ set_opt_global_cse(1);
+ place_code(irg);
+ set_opt_global_cse(0);
+}
+
+static void do_lower_highlevel(ir_graph *irg)
+{
+ lower_highlevel_graph(irg, firm_opt.lower_bitfields);
+}
+
+static void do_if_conv(ir_graph *irg)
+{
+ opt_if_conv(irg, if_conv_info);
+}
+
+static void do_stred(ir_graph *irg)
+{
+ opt_osr(irg, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift);
+}
+
+static void do_inline(void)
+{
+ inline_functions(500, 50);
+}
+
+static void do_cloning(void)
+{
+ proc_cloning((float) firm_opt.clone_threshold);
+}
+
+static void do_lower_switch(ir_graph *irg)
+{
+ lower_switch(irg, firm_opt.spare_size);
+}
+
+typedef enum opt_target {
+ OPT_TARGET_IRG,
+ OPT_TARGET_IRP
+} opt_target;
+
+typedef void (*transform_irg_func)(ir_graph *irg);
+typedef void (*transform_irp_func)(void);
+typedef void (*func_ptr_t)(void);
+
+typedef struct {
+ opt_target target;
+ const char *name;
+ func_ptr_t func;
+ bool enabled;
+ bool dump;
+ bool verify;
+ int timer;
+} opt_config_t;
+
+static opt_config_t opts[] = {
+ { OPT_TARGET_IRP, "rts", (func_ptr_t) rts_map, true, true, true, -1 },
+ { OPT_TARGET_IRG, "combo", (func_ptr_t) combo, true, true, true, TV_COMBO },
+ { OPT_TARGET_IRG, "controlflow", (func_ptr_t) optimize_cf, true, true, true, TV_CF_OPT },
+ { OPT_TARGET_IRG, "local", (func_ptr_t) optimize_graph_df, true, true, true, TV_LOCAL_OPT },
+ { OPT_TARGET_IRP, "gc_irgs", (func_ptr_t) remove_unused_functions, true, false, false, TV_CGANA },
+ { OPT_TARGET_IRP, "tailrec", (func_ptr_t) opt_tail_recursion, true, true, true, TV_TAIL_REC },
+ { OPT_TARGET_IRP, "funccalls", (func_ptr_t) do_optimize_funccalls, true, true, true, TV_REAL_FUNC_CALL },
+ { OPT_TARGET_IRP, "lowerconst", (func_ptr_t) lower_const_code, true, false, false, -1 },
+ { OPT_TARGET_IRG, "onereturn", (func_ptr_t) normalize_one_return, true, false, false, -1 },
+ { OPT_TARGET_IRG, "scalar", (func_ptr_t) scalar_replacement_opt, true, true, true, TV_SCALAR_REPLACE },
+ { OPT_TARGET_IRG, "reassoc", (func_ptr_t) optimize_reassociation, true, true, true, TV_REASSOCIATION },
+ { OPT_TARGET_IRG, "gcse", (func_ptr_t) do_gcse, true, true, true, TV_CODE_PLACE },
+ { OPT_TARGET_IRG, "place", (func_ptr_t) place_code, true, true, true, TV_CODE_PLACE },
+ { OPT_TARGET_IRG, "confirm", (func_ptr_t) construct_confirms, true, true, true, TV_CONFIRM_CREATE },
+ { OPT_TARGET_IRG, "ldst", (func_ptr_t) optimize_load_store, true, true, true, TV_LOAD_STORE },
+ { OPT_TARGET_IRG, "sync", (func_ptr_t) opt_sync, true, true, true, -1 },
+ { OPT_TARGET_IRG, "lower", (func_ptr_t) do_lower_highlevel, true, true, true, -1 },
+ { OPT_TARGET_IRG, "deconv", (func_ptr_t) conv_opt, true, true, true, TV_DECONV },
+ { OPT_TARGET_IRG, "condeval", (func_ptr_t) opt_cond_eval, true, true, true, TV_COND_EVAL },
+ { OPT_TARGET_IRG, "remove_confirms", (func_ptr_t) remove_confirms, true, false, false, TV_CONFIRM_CREATE },
+ { OPT_TARGET_IRG, "gvnpre", (func_ptr_t) do_gvn_pre, true, true, true, -1 },
+ { OPT_TARGET_IRG, "ifconv", (func_ptr_t) do_if_conv, true, true, true, TV_IF_CONV },
+ { OPT_TARGET_IRG, "bool", (func_ptr_t) opt_bool, true, true, true, -1 },
+ { OPT_TARGET_IRG, "stred", (func_ptr_t) do_stred, true, true, true, TV_OSR },
+ { OPT_TARGET_IRG, "dead", (func_ptr_t) dead_node_elimination, true, false, true, TV_DEAD_NODE },
+ { OPT_TARGET_IRP, "inline", (func_ptr_t) do_inline, true, true, true, -1 },
+ { OPT_TARGET_IRP, "clone", (func_ptr_t) do_cloning, true, true, true, -1 },
+ { OPT_TARGET_IRG, "lower_switch", (func_ptr_t) do_lower_switch, true, true, true, -1 },
+};
+static const int n_opts = sizeof(opts) / sizeof(opts[0]);
+
+static opt_config_t *get_opt(const char *name)
+{
+ int i;
+ for (i = 0; i < n_opts; ++i) {
+ opt_config_t *config = &opts[i];
+ if (strcmp(config->name, name) == 0)
+ return config;
+ }
+
+ assert(0);
+ return NULL;
+}
+
+static void set_opt_enabled(const char *name, bool enabled)
+{
+ opt_config_t *config = get_opt(name);
+ config->enabled = enabled;
+}
+
+static void do_irg_opt(ir_graph *irg, const char *name)
+{
+ transform_irg_func func;
+ ir_graph *old_irg;
+ opt_config_t *config = get_opt(name);
+ assert(config->target == OPT_TARGET_IRG);
+ if (!config->enabled)
+ return;
+
+ if (config->timer != -1)
+ timer_push(config->timer);
+
+ old_irg = current_ir_graph;
+ current_ir_graph = irg;
+
+ func = (transform_irg_func) config->func;
+ func(irg);
+
+ if (config->timer != -1)
+ timer_pop();
+
+ DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, config->name);
+ CHECK_ONE(firm_opt.check_all, irg);
+
+ current_ir_graph = old_irg;
+}
+
+static void do_irp_opt(const char *name)
+{
+ transform_irp_func func;
+ opt_config_t *config = get_opt(name);
+ assert(config->target == OPT_TARGET_IRP);
+ if (!config->enabled)
+ return;
+
+ if (config->timer != -1)
+ timer_push(config->timer);
+
+ func = (transform_irp_func) config->func;
+ func();
+
+ DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, config->name);
+ CHECK_ALL(firm_opt.check_all);
+
+ if (config->timer != -1)
+ timer_pop();
+}
+