X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=driver%2Ffirm_opt.c;h=7b0e3a6be6bd8e6689e6ecd08b81426dbe709195;hb=02f47f268839c472e23095ac0025e5ccbb5ed70a;hp=3eff5f03ee62b1f72d8af6079b37acf0ccde4449;hpb=098ba001486fc4336ad43e8364aa74adc0fae9a1;p=cparser diff --git a/driver/firm_opt.c b/driver/firm_opt.c index 3eff5f0..7b0e3a6 100644 --- a/driver/firm_opt.c +++ b/driver/firm_opt.c @@ -6,19 +6,20 @@ * * $Id$ */ +#include #include #include +#include +#include #include - -#ifdef FIRM_BACKEND #include -#endif /* FIRM_BACKEND */ #include "firm_opt.h" #include "firm_codegen.h" #include "firm_cmdline.h" #include "firm_timing.h" +#include "ast2firm.h" #ifdef _WIN32 #define snprintf _snprintf @@ -112,6 +113,8 @@ static create_intrinsic_fkt *arch_create_intrinsic = NULL; static void *create_intrinsic_ctx = NULL; static const ir_settings_if_conv_t *if_conv_info = NULL; +ir_mode *firm_imm_fp_mode = NULL; + /* entities of runtime functions */ ir_entity_ptr rts_entities[rts_max]; @@ -243,12 +246,14 @@ static void dump_graph_count(ir_graph *const irg, const char *const suffix) DUMP_ONE(1, irg, name); } +#if 0 static void dump_graph_cfg_count(ir_graph *const irg, const char *const suffix) { char name[64]; snprintf(name, sizeof(name), "-%02d_%s", irg_dump_no[get_irg_idx(irg)]++, suffix); DUMP_ONE_CFG(1, irg, name); } +#endif static void dump_all_count(const char *const suffix) { @@ -280,283 +285,308 @@ static void dump_all_count(const char *const suffix) } \ } while (0) -/** - * run all the Firm optimizations - * - * @param input_filename the name of the (main) source file - * @param firm_const_exists non-zero, if the const attribute was used on functions - */ -static void do_firm_optimizations(const char *input_filename, int firm_const_exists) +static void remove_unused_functions(void) { - int i; - ir_graph *irg; - unsigned aa_opt; + ir_entity **keep_methods; + int arr_len; - /* FIXME: cloning might ADD new graphs. */ - irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no)); + /* Analysis that finds the free methods, + i.e. methods that are dereferenced. + Optimizes polymorphic calls :-). */ + cgana(&arr_len, &keep_methods); - set_opt_strength_red(firm_opt.strength_red); - set_opt_scalar_replacement(firm_opt.scalar_replace); - set_opt_auto_create_sync(firm_opt.auto_sync); - set_opt_alias_analysis(firm_opt.alias_analysis); + /* Remove methods that are never called. */ + gc_irgs(arr_len, keep_methods); + free(keep_methods); +} - /* Overflow unsafe transformation can be enabled here if OSR is disabled, else - must be disabled until OSR finished. */ - set_opt_overflow_unsafe_transform(firm_opt.strength_red == FALSE); +static int firm_const_exists; - aa_opt = aa_opt_no_opt; - if (firm_opt.strict_alias) - aa_opt |= aa_opt_type_based | aa_opt_byte_type_may_alias; - if (firm_opt.no_alias) - aa_opt = aa_opt_no_alias; +static void do_optimize_funccalls(void) +{ + optimize_funccalls(firm_const_exists, NULL); +} - set_irp_memory_disambiguator_options(aa_opt); +static void do_gcse(ir_graph *irg) +{ + set_opt_global_cse(1); + optimize_graph_df(irg); + place_code(irg); + set_opt_global_cse(0); +} - timer_start(TV_ALL_OPT); +static void do_lower_highlevel(ir_graph *irg) +{ + lower_highlevel_graph(irg, firm_opt.lower_bitfields); +} - if (firm_opt.remove_unused) { - ir_entity **keep_methods; - int arr_len; +static void do_if_conv(ir_graph *irg) +{ + opt_if_conv(irg, if_conv_info); +} - /* Analysis that finds the free methods, - i.e. methods that are dereferenced. - Optimizes polymorphic calls :-). */ - cgana(&arr_len, &keep_methods); +static void do_stred(ir_graph *irg) +{ + opt_osr(irg, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift); +} - /* Remove methods that are never called. */ - gc_irgs(arr_len, keep_methods); +static void do_inline(void) +{ + inline_functions(firm_opt.inline_maxsize, firm_opt.inline_threshold); +} - free(keep_methods); - } +static void do_cloning(void) +{ + proc_cloning((float) firm_opt.clone_threshold); +} - if (! firm_opt.freestanding) { - rts_map(); - DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "rts"); - CHECK_ALL(firm_opt.check_all); - } +static void do_lower_switch(ir_graph *irg) +{ + lower_switch(irg, firm_opt.spare_size); +} - if (firm_opt.tail_rec) { - timer_push(TV_TAIL_REC); - opt_tail_recursion(); - timer_pop(); +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, "shape-blocks",(func_ptr_t) shape_blocks, true, true, true, TV_END_MELT }, + { 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; + } - DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "tail_rec"); - CHECK_ALL(firm_opt.check_all); - } + assert(0); + return NULL; +} - if (firm_opt.func_calls) { - timer_push(TV_REAL_FUNC_CALL); - optimize_funccalls(firm_const_exists, NULL); - timer_pop(); - DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "func_call"); - CHECK_ALL(firm_opt.check_all); - } +static void set_opt_enabled(const char *name, bool enabled) +{ + opt_config_t *config = get_opt(name); + config->enabled = enabled; +} - if (firm_opt.do_inline) { - timer_push(TV_INLINE); - inline_leave_functions(500, 80, 30, FALSE); - timer_pop(); - DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "inl"); - CHECK_ALL(firm_opt.check_all); - } +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; - /* do lowering on the const code irg */ - lower_const_code(); + if (config->timer != -1) + timer_push(config->timer); - for (i = 0; i < get_irp_n_irgs(); i++) { - irg = current_ir_graph = get_irp_irg(i); + old_irg = current_ir_graph; + current_ir_graph = irg; + func = (transform_irg_func) config->func; + func(irg); -#ifdef FIRM_EXT_GRS - /* If SIMD optimization is on, make sure we have only 1 return */ - if (firm_ext_grs.create_pattern || firm_ext_grs.simd_opt) - normalize_one_return(irg); -#endif + 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); -#if 0 - if (firm_opt.modes) { - /* convert all modes into integer if possible */ - arch_mode_conversion(irg, predefs.mode_uint); - } -#endif - timer_push(TV_SCALAR_REPLACE); - scalar_replacement_opt(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "scalar"); - CHECK_ONE(firm_opt.check_all, irg); + current_ir_graph = old_irg; +} - timer_push(TV_LOCAL_OPT); - optimize_graph_df(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt"); - CHECK_ONE(firm_opt.check_all, 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; - timer_push(TV_REASSOCIATION); - optimize_reassociation(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "reassoc"); - CHECK_ONE(firm_opt.check_all, irg); + if (config->timer != -1) + timer_push(config->timer); - if (firm_opt.confirm) { - /* Confirm construction currently can only handle blocks with only one control - flow predecessor. Calling optimize_cf here removes Bad predecessors and help - the optimization of switch constructs. */ - timer_push(TV_CF_OPT); - optimize_cf(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt"); - CHECK_ONE(firm_opt.check_all, irg); - timer_push(TV_CONFIRM_CREATE); - construct_confirms(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "confirms"); - CHECK_ONE(firm_opt.check_all, irg); - } + func = (transform_irp_func) config->func; + func(); - timer_push(TV_LOCAL_OPT); - optimize_graph_df(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt"); - CHECK_ONE(firm_opt.check_all, irg); - - compute_doms(irg); - CHECK_ONE(firm_opt.check_all, irg); - - if (firm_opt.code_place) { - timer_push(TV_CODE_PLACE); - set_opt_global_cse(1); - optimize_graph_df(irg); - place_code(irg); - set_opt_global_cse(0); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "place"); - CHECK_ONE(firm_opt.check_all, irg); - } + DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, config->name); + CHECK_ALL(firm_opt.check_all); - if (firm_opt.luffig) { - opt_ldst2(irg); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst2"); - CHECK_ONE(firm_opt.check_all, irg); - } + if (config->timer != -1) + timer_pop(); +} - timer_push(TV_CF_OPT); - optimize_cf(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt"); - CHECK_ONE(firm_opt.check_all, irg); +/** + * run all the Firm optimizations + * + * @param input_filename the name of the (main) source file + */ +static void do_firm_optimizations(const char *input_filename) +{ + int i; + unsigned aa_opt; - /* should we really remove the Confirm here? */ - if (firm_opt.confirm) { - timer_push(TV_CONFIRM_CREATE); - remove_confirms(irg); - timer_pop(); - } + /* FIXME: cloning might ADD new graphs. */ + irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no)); - irg_verify(irg, VRFY_ENFORCE_SSA); - if (firm_opt.gvn_pre) { - do_gvn_pre(irg); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "pre"); - CHECK_ONE(firm_opt.check_all, irg); - irg_verify(irg, VRFY_ENFORCE_SSA); - } + set_opt_strength_red(firm_opt.strength_red); + set_opt_scalar_replacement(firm_opt.scalar_replace); + set_opt_auto_create_sync(firm_opt.auto_sync); + set_opt_alias_analysis(firm_opt.alias_analysis); + set_opt_combo(firm_opt.combo); - if (firm_opt.loop_unrolling) { - timer_push(TV_LOOP_UNROLL); - optimize_loop_unrolling(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "loop"); - CHECK_ONE(firm_opt.check_all, irg); - } + aa_opt = aa_opt_no_opt; + if (firm_opt.strict_alias) + aa_opt |= aa_opt_type_based | aa_opt_byte_type_may_alias; + if (firm_opt.no_alias) + aa_opt = aa_opt_no_alias; - if (firm_opt.load_store) { - timer_push(TV_LOAD_STORE); - optimize_load_store(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "ldst"); - CHECK_ONE(firm_opt.check_all, irg); - } + set_irp_memory_disambiguator_options(aa_opt); - lower_highlevel_graph(irg, firm_opt.lower_bitfields); + /* parameter passing code should set them directly sometime... */ + set_opt_enabled("rts", firm_opt.freestanding); + set_opt_enabled("gc_irgs", firm_opt.remove_unused); + set_opt_enabled("tailrec", firm_opt.tail_rec); + set_opt_enabled("funccalls", firm_opt.func_calls); + set_opt_enabled("gcse", firm_opt.gcse); + set_opt_enabled("place", !firm_opt.gcse); + set_opt_enabled("confirm", firm_opt.confirm); + set_opt_enabled("remove_confirms", firm_opt.confirm); + set_opt_enabled("sync", firm_opt.sync); + set_opt_enabled("ldst", firm_opt.load_store); + set_opt_enabled("deconv", firm_opt.deconv); + set_opt_enabled("condeval", firm_opt.cond_eval); + set_opt_enabled("gvnpre", firm_opt.gvn_pre); + set_opt_enabled("ifconv", firm_opt.if_conversion); + set_opt_enabled("bool", firm_opt.bool_opt); + set_opt_enabled("shape-blocks", firm_opt.shape_blocks); + set_opt_enabled("inline", firm_opt.do_inline); + set_opt_enabled("clone", firm_opt.cloning); + set_opt_enabled("combo", firm_opt.combo); - if (firm_opt.deconv) { - timer_push(TV_DECONV); - conv_opt(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "deconv"); - CHECK_ONE(firm_opt.check_all, irg); - } + timer_start(TV_ALL_OPT); - if (firm_opt.cond_eval) { - timer_push(TV_COND_EVAL); - opt_cond_eval(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cond_eval"); - CHECK_ONE(firm_opt.check_all, irg); - } + do_irp_opt("rts"); - compute_doms(irg); - compute_postdoms(irg); - DUMP_ONE_CFG_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "dom"); - CHECK_ONE(firm_opt.check_all, irg); + /* first step: kill dead code */ + if (firm_opt.combo) { + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "combo"); + } + } else { + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); + } + } - construct_backedges(irg); + do_irp_opt("gc_irgs"); + do_irp_opt("tailrec"); + do_irp_opt("funccalls"); + do_irp_opt("lowerconst"); - timer_push(TV_CF_OPT); - optimize_cf(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "cfopt"); - CHECK_ONE(firm_opt.check_all, irg); + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_graph *irg = get_irp_irg(i); - if (firm_opt.if_conversion) { - timer_push(TV_IF_CONV); - opt_if_conv(current_ir_graph, if_conv_info); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "if"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - - timer_push(TV_LOCAL_OPT); - optimize_graph_df(current_ir_graph); - timer_pop(); - timer_push(TV_CF_OPT); - optimize_cf(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "after_if"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - } + do_irg_opt(irg, "scalar"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "reassoc"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "gcse"); - if (firm_opt.bool_opt) { - opt_bool(irg); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "bool"); - CHECK_ONE(firm_opt.check_all, irg); + if (firm_opt.confirm) { + /* Confirm construction currently can only handle blocks with only one control + flow predecessor. Calling optimize_cf here removes Bad predecessors and help + the optimization of switch constructs. */ + do_irg_opt(irg, "controlflow"); + do_irg_opt(irg, "confirm"); + do_irg_opt(irg, "local"); } - timer_push(TV_OSR); - opt_osr(current_ir_graph, osr_flag_default | osr_flag_keep_reg_pressure | osr_flag_ignore_x86_shift); - /* now it is safe to enable overflow unsafe transformations */ - set_opt_overflow_unsafe_transform(1); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "stred"); - CHECK_ONE(firm_opt.check_all, irg); + do_irg_opt(irg, "controlflow"); + do_irg_opt(irg, "ldst"); + do_irg_opt(irg, "lower"); + do_irg_opt(irg, "deconv"); + do_irg_opt(irg, "condeval"); + do_irg_opt(irg, "remove_confirms"); + do_irg_opt(irg, "gvnpre"); + do_irg_opt(irg, "place"); + do_irg_opt(irg, "controlflow"); - timer_push(TV_LOCAL_OPT); - optimize_graph_df(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "lopt"); - CHECK_ONE(firm_opt.check_all, irg); + if (firm_opt.if_conversion) { + do_irg_opt(irg, "ifconv"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); + } - edges_deactivate(irg); - timer_push(TV_DEAD_NODE); - dead_node_elimination(irg); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, irg, "dead"); - CHECK_ONE(firm_opt.check_all, irg); + do_irg_opt(irg, "bool"); + do_irg_opt(irg, "shape-blocks"); + do_irg_opt(irg, "lower_switch"); + do_irg_opt(irg, "stred"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "dead"); } - if (firm_opt.cloning) { - proc_cloning((float)firm_opt.clone_threshold); - DUMP_ALL_C(firm_dump.ir_graph && firm_dump.all_phases, "clone"); - CHECK_ALL(firm_opt.check_all); + do_irp_opt("inline"); + do_irp_opt("clone"); + + for (i = 0; i < get_irp_n_irgs(); i++) { + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); + do_irg_opt(irg, "condeval"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); } if (firm_dump.ir_graph) { @@ -565,27 +595,14 @@ static void do_firm_optimizations(const char *input_filename, int firm_const_exi construct_cf_backedges(get_irp_irg(i)); } - if (firm_opt.remove_unused) { - 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); - } - + do_irp_opt("gc_irgs"); DUMP_ALL(firm_dump.ir_graph, "-opt"); - /* verify optimized graphs */ - for (i = get_irp_n_irgs() - 1; i >= 0; --i) - irg_verify(get_irp_irg(i), VRFY_ENFORCE_SSA); + for (i = get_irp_n_irgs() - 1; i >= 0; --i) { + ir_graph *irg = get_irp_irg(i); + irg_verify(irg, VRFY_ENFORCE_SSA); + } if (firm_dump.statistic & STAT_AFTER_OPT) stat_dump_snapshot(input_filename, "opt"); @@ -675,6 +692,7 @@ static int compute_type_size(ir_type *ty) save_optimization_state(&state); set_optimize(1); set_opt_constant_folding(1); + set_opt_algebraic_simplification(1); for (i = 0; i < dims; ++i) { ir_node *lower = get_array_lower_bound(ty, i); @@ -728,24 +746,14 @@ static int compute_type_size(ir_type *ty) } /* compute_type_size */ /** - * layout all types of the Firm graph + * layout all non-frame types of the Firm graph */ static void compute_type_sizes(void) { int i; ir_type *tp; - ir_graph *irg; - - /* all frame types */ - for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - irg = get_irp_irg(i); - /* do not optimize away variables in debug mode */ - if (firm_opt.debug_mode == DBG_MODE_NONE) - opt_frame_irg(irg); - compute_type_size(get_irg_frame_type(irg)); - } - /* all other types */ + /* all non-frame other types */ for (i = get_irp_n_types() - 1; i >= 0; --i) { tp = get_irp_type(i); compute_type_size(tp); @@ -761,6 +769,24 @@ static void compute_type_sizes(void) } } /* compute_type_sizes */ +/** + * layout all frame-types of the Firm graph + */ +static void compute_frame_type_sizes(void) +{ + int i; + ir_graph *irg; + + /* all frame types */ + for (i = get_irp_n_irgs() - 1; i >= 0; --i) { + irg = get_irp_irg(i); + /* do not optimize away variables in debug mode */ + if (firm_opt.debug_mode == DBG_MODE_NONE) + opt_frame_irg(irg); + compute_type_size(get_irg_frame_type(irg)); + } +} /* compute_frame_type_sizes */ + /** * do Firm lowering * @@ -770,21 +796,14 @@ static void do_firm_lowering(const char *input_filename) { int i; - /* do class lowering and vtbl creation */ -// lower_classes_to_struct("vtbl", "m"); - -#if 0 - timer_push(TV_LOWER); - lower_highlevel(); - timer_pop(); -#endif - if (firm_opt.lower_ll) { lwrdw_param_t init = { 1, 1, - mode_Ls, mode_Lu, - mode_Is, mode_Iu, + get_atomic_mode(ATOMIC_TYPE_LONGLONG), + get_atomic_mode(ATOMIC_TYPE_ULONGLONG), + get_atomic_mode(ATOMIC_TYPE_INT), + get_atomic_mode(ATOMIC_TYPE_UINT), def_create_intrinsic_fkt, NULL }; @@ -796,7 +815,6 @@ static void do_firm_lowering(const char *input_filename) } timer_push(TV_DW_LOWER); lower_dw_ops(&init); - DUMP_ALL(firm_dump.ir_graph, "-dw"); timer_pop(); } @@ -817,72 +835,34 @@ static void do_firm_lowering(const char *input_filename) /* run reassociation first on all graphs BEFORE the architecture dependent optimizations are enabled */ for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - current_ir_graph = get_irp_irg(i); + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "reassoc"); + } - timer_push(TV_REASSOCIATION); - optimize_reassociation(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "reassoc"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - } + /* enable architecture dependent optimizations */ + arch_dep_set_opts((arch_dep_opts_t) + ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) | + (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) | + (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) )); for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - current_ir_graph = get_irp_irg(i); - - if (firm_opt.code_place) - set_opt_global_cse(1); - - timer_push(TV_LOCAL_OPT); - optimize_graph_df(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "lopt"); - if (! firm_opt.code_place) - CHECK_ONE(firm_opt.check_all, current_ir_graph); - - if (firm_opt.code_place) { - timer_push(TV_CODE_PLACE); - place_code(current_ir_graph); - set_opt_global_cse(0); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "place"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - } + ir_graph *irg = get_irp_irg(i); -// set_opt_global_cse(0); - timer_push(TV_LOAD_STORE); - optimize_load_store(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "ldst"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); + current_ir_graph = irg; - - timer_push(TV_LOCAL_OPT); - optimize_graph_df(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "lopt"); - - timer_push(TV_CF_OPT); - optimize_cf(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "cf"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "gcse"); + do_irg_opt(irg, "ldst"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); if (firm_opt.if_conversion) { - timer_push(TV_IF_CONV); - opt_if_conv(current_ir_graph, if_conv_info); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "if"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - - timer_push(TV_LOCAL_OPT); - optimize_graph_df(current_ir_graph); - timer_pop(); - timer_push(TV_CF_OPT); - optimize_cf(current_ir_graph); - timer_pop(); - DUMP_ONE_C(firm_dump.ir_graph && firm_dump.all_phases, current_ir_graph, "after_if"); - CHECK_ONE(firm_opt.check_all, current_ir_graph); - } + do_irg_opt(irg, "ifconv"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "controlflow"); + } + + do_irg_opt(current_ir_graph, "sync"); } timer_stop(TV_ALL_OPT); @@ -910,7 +890,6 @@ static void do_firm_lowering(const char *input_filename) void gen_firm_init(void) { firm_parameter_t params; - char *dump_filter; unsigned pattern = 0; /* the automatic state is only set if inlining is enabled */ @@ -930,9 +909,10 @@ void gen_firm_init(void) params.cc_mask = 0; /* no regparam, cdecl */ params.builtin_dbg = NULL; -#ifdef FIRM_BACKEND + init_firm(¶ms); + if (firm_be_opt.selection == BE_FIRM_BE) { - const backend_params *be_params = be_init(); + const backend_params *be_params = be_get_backend_param(); firm_opt.lower_ll = (a_byte) be_params->do_dw_lowering; params.arch_op_settings = be_params->arch_op_settings; @@ -942,24 +922,20 @@ void gen_firm_init(void) ad_param = be_params->dep_param; if_conv_info = be_params->if_conv_info; - } -#endif /* FIRM_BACKEND */ -#ifdef FIRM_EXT_GRS - /* Activate Graph rewriting if SIMD optimization is turned on */ - /* This has to be done before init_firm() is called! */ - if (firm_ext_grs.simd_opt) - ext_grs_activate(); -#endif + if (be_params->has_imm_fp_mode) + firm_imm_fp_mode = be_params->imm_fp_mode; + } - init_firm(¶ms); dbg_init(NULL, NULL, dbg_snprint); edges_init_dbg(firm_opt.vrfy_edges); - //cbackend_set_debug_retrieve(dbg_retrieve); set_opt_precise_exc_context(firm_opt.precise_exc); set_opt_fragile_ops(firm_opt.fragile_ops); + /* Sel node cannot produce NULL pointers */ + set_opt_sel_based_null_check_elim(1); + /* dynamic dispatch works currently only if whole world scenarios */ set_opt_dyn_meth_dispatch(0); @@ -975,28 +951,19 @@ void gen_firm_init(void) if (firm_opt.enabled) { set_optimize(1); set_opt_constant_folding(firm_opt.const_folding); + set_opt_algebraic_simplification(firm_opt.const_folding); set_opt_cse(firm_opt.cse); - set_opt_global_cse (0); + set_opt_global_cse(0); set_opt_unreachable_code(1); set_opt_control_flow(firm_opt.control_flow); set_opt_control_flow_weak_simplification(1); set_opt_control_flow_strong_simplification(1); - } - else + } else { set_optimize(0); - - dump_filter = getenv("FIRM_DUMP_FILTER"); - if (dump_filter) - only_dump_method_with_name(new_id_from_str(dump_filter)); + } /* do not dump entity ld names */ dump_ld_names(0); - -#if 0 - /* init the ycomp debugger extension */ - if (firm_opt.ycomp_dbg) - firm_init_ycomp_debugger(firm_opt.ycomp_host, firm_opt.ycomp_port); -#endif } /* gen_firm_init */ /** @@ -1006,12 +973,14 @@ void gen_firm_init(void) * @param out a file handle for the output, may be NULL * @param input_filename the name of the (main) source file * @param c_mode non-zero if "C" was compiled - * @param firm_const_exists non-zero, if the const attribute was used on functions + * @param new_firm_const_exists non-zero, if the const attribute was used on functions */ -void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm_const_exists) +void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int new_firm_const_exists) { int i; + firm_const_exists = new_firm_const_exists; + /* the general for dumping option must be set, or the others will not work */ firm_dump.ir_graph = (a_byte) (firm_dump.ir_graph | firm_dump.all_phases | firm_dump.extbb); @@ -1052,18 +1021,30 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm /* all graphs are finalized, set the irp phase to high */ set_irp_phase_state(phase_high); + /* BEWARE: kill unreachable code before doing compound lowering */ + for (i = get_irp_n_irgs() - 1; i >= 0; --i) { + ir_graph *irg = get_irp_irg(i); + optimize_cf(irg); + } + /* lower all compound call return values */ lower_compound_params(); /* computes the sizes of all types that are still not computed */ compute_type_sizes(); + /* lower copyb nodes */ + for (i = get_irp_n_irgs() - 1; i >= 0; --i) { + ir_graph *irg = get_irp_irg(i); + lower_CopyB(irg, 128, 4); + } + if (firm_dump.statistic & STAT_BEFORE_OPT) { stat_dump_snapshot(input_filename, "noopt"); } if (firm_opt.enabled) - do_firm_optimizations(input_filename, firm_const_exists); + do_firm_optimizations(input_filename); if (firm_dump.gen_firm_asm) { timer_push(TV_FIRM_ASM); @@ -1075,34 +1056,13 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm if (firm_opt.lower) do_firm_lowering(input_filename); + /* computes the sizes of all frame types */ + compute_frame_type_sizes(); + /* set the phase to low */ for (i = get_irp_n_irgs() - 1; i >= 0; --i) set_irg_phase_low(get_irp_irg(i)); - -#ifdef FIRM_EXT_GRS - /** SIMD Optimization Extensions **/ - - /* Pattern creation step. No code has to be generated, so - exit after pattern creation */ - if (firm_ext_grs.create_pattern) { - ext_grs_create_pattern(); - exit(0); - } - - /* SIMD optimization step. Uses graph patterns to find - rich instructions and rewrite */ - if (firm_ext_grs.simd_opt) - ext_grs_simd_opt(); -#endif - - /* enable architecture dependent optimizations */ - arch_dep_set_opts((arch_dep_opts_t) - ((firm_opt.muls ? arch_dep_mul_to_shift : arch_dep_none) | - (firm_opt.divs ? arch_dep_div_by_const : arch_dep_none) | - (firm_opt.mods ? arch_dep_mod_by_const : arch_dep_none) )); - - if (firm_dump.statistic & STAT_FINAL_IR) stat_dump_snapshot(input_filename, "final-ir"); @@ -1112,20 +1072,14 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, int firm if (firm_dump.statistic & STAT_FINAL) stat_dump_snapshot(input_filename, "final"); - -#if 0 - if (firm_opt.ycomp_dbg) - firm_finish_ycomp_debugger(); -#endif -} /* gen_firm_finish */ +} /** * Do very early initializations */ -void firm_early_init(void) { -#ifdef FIRM_BACKEND +void firm_early_init(void) +{ /* arg: need this here for command line options */ be_opt_register(); -#endif firm_init_options(NULL, 0, NULL); -} /* firm_early_init */ +}