X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=driver%2Ffirm_opt.c;h=174a34a99757f3b5620252201efd3e3adec475ab;hb=2c26c7a7885635fc12bda81d06b334f9726a70df;hp=e3258e7d34f364dffaa29e80814ac9811edf6431;hpb=3d41888d9e918f9e883dc954de19bae38b94a4b7;p=cparser diff --git a/driver/firm_opt.c b/driver/firm_opt.c index e3258e7..174a34a 100644 --- a/driver/firm_opt.c +++ b/driver/firm_opt.c @@ -2,7 +2,7 @@ * * @file firm_opt.c -- Firm-generating back end optimizations. * - * (C) 2005-2009 Michael Beck beck@ipd.info.uni-karlsruhe.de + * (C) 2005-2010 Michael Beck beck@ipd.info.uni-karlsruhe.de * * $Id$ */ @@ -22,12 +22,6 @@ #include "firm_timing.h" #include "ast2firm.h" -#if defined(_DEBUG) || defined(FIRM_DEBUG) -#define DBG(x) dbg_printf x -#else -#define DBG(x) ((void)0) -#endif /* _DEBUG || FIRM_DEBUG */ - static ir_timer_t *t_vcg_dump; static ir_timer_t *t_verify; static ir_timer_t *t_all_opt; @@ -35,51 +29,24 @@ static bool do_irg_opt(ir_graph *irg, const char *name); /** dump all the graphs depending on cond */ -static void dump_all(const char *suffix) { - if (firm_dump.ir_graph) { - timer_push(t_vcg_dump); - if (firm_dump.no_blocks) - dump_all_ir_graphs(dump_ir_graph, suffix); - else if (firm_dump.extbb) - dump_all_ir_graphs(dump_ir_extblock_graph, suffix); - else - dump_all_ir_graphs(dump_ir_block_graph, suffix); - timer_pop(t_vcg_dump); - } -} +static void dump_all(const char *suffix) +{ + if (!firm_dump.ir_graph) + return; -/* set by the backend parameters */ -static const ir_settings_arch_dep_t *ad_param = NULL; -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; + timer_push(t_vcg_dump); + dump_all_ir_graphs(suffix); + timer_pop(t_vcg_dump); +} /* entities of runtime functions */ ir_entity_ptr rts_entities[rts_max]; -/** - * factory for setting architecture dependent parameters - */ -static const ir_settings_arch_dep_t *arch_factory(void) -{ - static const ir_settings_arch_dep_t param = { - 1, /* also use subs */ - 4, /* maximum shifts */ - 31, /* maximum shift amount */ - NULL, /* use default evaluator */ - - 1, /* allow Mulhs */ - 1, /* allow Mulus */ - 32 /* Mulh allowed up to 32 bit */ - }; - - return ad_param ? ad_param : ¶m; -} - /** * Map runtime functions. */ -static void rts_map(void) { +static void rts_map(void) +{ static const struct { ir_entity_ptr *ent; /**< address of the rts entity */ i_mapper_func func; /**< mapper function. */ @@ -183,38 +150,6 @@ static void rts_map(void) { } static int *irg_dump_no; - -static void dump_graph_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); - - timer_push(t_vcg_dump); - if (firm_dump.no_blocks) - dump_ir_graph(irg, name); - else if (firm_dump.extbb) - dump_ir_extblock_graph(irg, name); - else - dump_ir_block_graph(irg, name); - timer_pop(t_vcg_dump); -} - -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) @@ -235,11 +170,6 @@ 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); @@ -264,29 +194,14 @@ static void do_cloning(void) proc_cloning((float) firm_opt.clone_threshold); } -static void do_lower_switch(ir_graph *irg) +static void do_lower_mux(ir_graph *irg) { - lower_switch(irg, firm_opt.spare_size); + lower_mux(irg, NULL); } -static void do_lower_dw_ops(void) +static void do_vrp(ir_graph *irg) { - lwrdw_param_t init = { - 1, - 1, - 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 - }; - - if (arch_create_intrinsic) { - init.create_intrinsic = arch_create_intrinsic; - init.ctx = create_intrinsic_ctx; - } - lower_dw_ops(&init); + set_vrp_data(irg); } typedef enum opt_target { @@ -301,54 +216,64 @@ typedef enum opt_flags { OPT_FLAG_NO_VERIFY = 1 << 2, /**< don't verify after transformation */ OPT_FLAG_HIDE_OPTIONS = 1 << 3, /**< do not automatically process -foptions for this transformation */ + OPT_FLAG_ESSENTIAL = 1 << 4, /**< output won't work without this pass + so we need it even with -O0 */ } opt_flags_t; typedef void (*transform_irg_func)(ir_graph *irg); typedef void (*transform_irp_func)(void); -typedef void (*func_ptr_t)(void); typedef struct { opt_target_t target; const char *name; - func_ptr_t func; + union { + transform_irg_func transform_irg; + transform_irp_func transform_irp; + } u; const char *description; opt_flags_t flags; } opt_config_t; static opt_config_t opts[] = { - { OPT_TARGET_IRP, "rts", (func_ptr_t) rts_map, "optimization of known library functions", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "combo", (func_ptr_t) combo, "combined CCE, UCE and GVN", OPT_FLAG_NONE}, - { OPT_TARGET_IRG, "control-flow", (func_ptr_t) optimize_cf, "optimization of control-flow", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "local", (func_ptr_t) optimize_graph_df, "local graph optimizations", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRP, "remove-unused", (func_ptr_t) remove_unused_functions, "removal of unused functions", OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY }, - { OPT_TARGET_IRP, "opt-tail-rec", (func_ptr_t) opt_tail_recursion, "tail-recursion eliminiation", OPT_FLAG_NONE }, - { OPT_TARGET_IRP, "opt-func-call", (func_ptr_t) do_optimize_funccalls, "function call optimization", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "lower", (func_ptr_t) do_lower_highlevel, "lowering", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRP, "lower-const", (func_ptr_t) lower_const_code, "lowering of constant code", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY }, - { OPT_TARGET_IRP, "lower-dw", (func_ptr_t) do_lower_dw_ops, "lowering of doubleword operations", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "lower-switch", (func_ptr_t) do_lower_switch, "switch lowering", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "one-return", (func_ptr_t) normalize_one_return, "normalisation to 1 return", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY }, - { OPT_TARGET_IRG, "scalar-replace", (func_ptr_t) scalar_replacement_opt, "scalar replacement", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "reassociation", (func_ptr_t) optimize_reassociation, "reassociation", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "gcse", (func_ptr_t) do_gcse, "global common subexpression elimination", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "place", (func_ptr_t) place_code, "code placement", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "confirm", (func_ptr_t) construct_confirms, "confirm optimisation", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "opt-load-store", (func_ptr_t) optimize_load_store, "load store optimization", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "parallelize-mem", (func_ptr_t) opt_parallelize_mem, "parallelize memory", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "deconv", (func_ptr_t) conv_opt, "conv node elimination", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "thread-jumps", (func_ptr_t) opt_jumpthreading, "path-sensitive jumpthreading", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "remove-confirms", (func_ptr_t) remove_confirms, "confirm removal", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY }, - { OPT_TARGET_IRG, "gvn-pre", (func_ptr_t) do_gvn_pre, "global value numbering partial redundancy elimination", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "if-conversion", (func_ptr_t) do_if_conv, "if-conversion", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "bool", (func_ptr_t) opt_bool, "bool simplification", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "shape-blocks", (func_ptr_t) shape_blocks, "block shaping", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "ivopts", (func_ptr_t) do_stred, "induction variable strength reduction", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "remove-phi-cycles", (func_ptr_t) remove_phi_cycles, "removal of phi cycles", OPT_FLAG_HIDE_OPTIONS }, - { OPT_TARGET_IRG, "dead", (func_ptr_t) dead_node_elimination, "dead node elimination", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY }, - { OPT_TARGET_IRP, "inline", (func_ptr_t) do_inline, "inlining", OPT_FLAG_NONE }, - { OPT_TARGET_IRP, "opt-proc-clone", (func_ptr_t) do_cloning, "procedure cloning", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "invert-loops", (func_ptr_t) do_loop_inversion, "loop inversion", OPT_FLAG_NONE }, - { OPT_TARGET_IRG, "peel-loops", (func_ptr_t) do_loop_peeling, "loop peeling", OPT_FLAG_NONE }, +#define IRG(a, b, c, d) { OPT_TARGET_IRG, a, .u.transform_irg = (transform_irg_func)b, c, d } +#define IRP(a, b, c, d) { OPT_TARGET_IRP, a, .u.transform_irp = b, c, d } + IRG("bool", opt_bool, "bool simplification", OPT_FLAG_NONE), + IRG("combo", combo, "combined CCE, UCE and GVN", OPT_FLAG_NONE), + IRG("confirm", construct_confirms, "confirm optimisation", OPT_FLAG_HIDE_OPTIONS), + IRG("control-flow", optimize_cf, "optimization of control-flow", OPT_FLAG_HIDE_OPTIONS), + IRG("dead", dead_node_elimination, "dead node elimination", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY), + IRG("deconv", conv_opt, "conv node elimination", OPT_FLAG_NONE), + IRG("fp-vrp", fixpoint_vrp, "fixpoint value range propagation", OPT_FLAG_NONE), + IRG("frame", opt_frame_irg, "remove unused frame entities", OPT_FLAG_NONE), + IRG("gcse", do_gcse, "global common subexpression elimination", OPT_FLAG_NONE), + IRG("gvn-pre", do_gvn_pre, "global value numbering partial redundancy elimination", OPT_FLAG_NONE), + IRG("if-conversion", opt_if_conv, "if-conversion", OPT_FLAG_NONE), + IRG("invert-loops", do_loop_inversion, "loop inversion", OPT_FLAG_NONE), + IRG("ivopts", do_stred, "induction variable strength reduction", OPT_FLAG_NONE), + IRG("local", optimize_graph_df, "local graph optimizations", OPT_FLAG_HIDE_OPTIONS), + IRG("lower", do_lower_highlevel, "lowering", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_ESSENTIAL), + IRG("lower-mux", do_lower_mux, "mux lowering", OPT_FLAG_NONE), + IRG("opt-load-store", optimize_load_store, "load store optimization", OPT_FLAG_NONE), + IRG("opt-tail-rec", opt_tail_rec_irg, "tail-recursion eliminiation", OPT_FLAG_NONE), + IRG("parallelize-mem", opt_parallelize_mem, "parallelize memory", OPT_FLAG_NONE), + IRG("place", place_code, "code placement", OPT_FLAG_NONE), + IRG("reassociation", optimize_reassociation, "reassociation", OPT_FLAG_NONE), + IRG("remove-confirms", remove_confirms, "confirm removal", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY), + IRG("remove-phi-cycles", remove_phi_cycles, "removal of phi cycles", OPT_FLAG_HIDE_OPTIONS), + IRG("scalar-replace", scalar_replacement_opt, "scalar replacement", OPT_FLAG_NONE), + IRG("shape-blocks", shape_blocks, "block shaping", OPT_FLAG_NONE), + IRG("thread-jumps", opt_jumpthreading, "path-sensitive jumpthreading", OPT_FLAG_NONE), + IRG("unroll-loops", do_loop_unrolling, "loop unrolling", OPT_FLAG_NONE), + IRG("vrp", do_vrp, "value range propagation", OPT_FLAG_NONE), + IRP("inline", do_inline, "inlining", OPT_FLAG_NONE), + IRP("lower-const", lower_const_code, "lowering of constant code", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY | OPT_FLAG_ESSENTIAL), + IRP("target-lowering", be_lower_for_target, "lowering necessary for target architecture", OPT_FLAG_HIDE_OPTIONS | OPT_FLAG_ESSENTIAL), + IRP("opt-func-call", do_optimize_funccalls, "function call optimization", OPT_FLAG_NONE), + IRP("opt-proc-clone", do_cloning, "procedure cloning", OPT_FLAG_NONE), + IRP("remove-unused", garbage_collect_entities, "removal of unused functions/variables", OPT_FLAG_NO_DUMP | OPT_FLAG_NO_VERIFY), + IRP("rts", rts_map, "optimization of known library functions", OPT_FLAG_HIDE_OPTIONS), +#undef IRP +#undef IRG }; static const int n_opts = sizeof(opts) / sizeof(opts[0]); ir_timer_t *timers[sizeof(opts)/sizeof(opts[0])]; @@ -385,32 +310,28 @@ static bool get_opt_enabled(const char *name) */ static bool do_irg_opt(ir_graph *irg, const char *name) { - transform_irg_func func; - ir_graph *old_irg; - opt_config_t *config = get_opt(name); - size_t n = config - opts; + ir_graph *old_irg; + opt_config_t *config = get_opt(name); + size_t n = config - opts; assert(config != NULL); assert(config->target == OPT_TARGET_IRG); if (! (config->flags & OPT_FLAG_ENABLED)) return false; - old_irg = current_ir_graph; current_ir_graph = irg; - func = (transform_irg_func) config->func; - timer_push(timers[n]); - func(irg); + config->u.transform_irg(irg); timer_pop(timers[n]); if (firm_dump.all_phases && firm_dump.ir_graph) { - dump_graph_count(irg, name); + dump_ir_graph(irg, name); } if (firm_opt.check_all) { timer_push(t_verify); - irg_verify(irg, VRFY_ENFORCE_SSA); + irg_verify(irg, VERIFY_ENFORCE_SSA); timer_pop(t_verify); } @@ -420,24 +341,21 @@ static bool do_irg_opt(ir_graph *irg, const char *name) static void do_irp_opt(const char *name) { - transform_irp_func func; - opt_config_t *config = get_opt(name); - size_t n = config - opts; + opt_config_t *config = get_opt(name); + size_t n = config - opts; assert(config->target == OPT_TARGET_IRP); if (! (config->flags & OPT_FLAG_ENABLED)) return; - func = (transform_irp_func) config->func; - timer_push(timers[n]); - func(); + config->u.transform_irp(); timer_pop(timers[n]); if (firm_dump.ir_graph && firm_dump.all_phases) { int i; for (i = get_irp_n_irgs() - 1; i >= 0; --i) { ir_graph *irg = get_irp_irg(i); - dump_graph_count(irg, name); + dump_ir_graph(irg, name); } } @@ -445,7 +363,7 @@ static void do_irp_opt(const char *name) int i; timer_push(t_verify); for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - irg_verify(get_irp_irg(i), VRFY_ENFORCE_SSA); + irg_verify(get_irp_irg(i), VERIFY_ENFORCE_SSA); } timer_pop(t_verify); } @@ -472,8 +390,12 @@ static void enable_safe_defaults(void) set_opt_enabled("remove-confirms", true); set_opt_enabled("ivopts", true); set_opt_enabled("dead", true); - set_opt_enabled("lower-switch", true); set_opt_enabled("remove-phi-cycles", true); + set_opt_enabled("frame", true); + set_opt_enabled("combo", true); + set_opt_enabled("invert-loops", true); + set_opt_enabled("target-lowering", true); + set_opt_enabled("rts", true); } /** @@ -483,7 +405,7 @@ static void enable_safe_defaults(void) */ static void do_firm_optimizations(const char *input_filename) { - int i; + size_t i; unsigned aa_opt; set_opt_alias_analysis(firm_opt.alias_analysis); @@ -497,7 +419,6 @@ static void do_firm_optimizations(const char *input_filename) set_irp_memory_disambiguator_options(aa_opt); /* parameter passing code should set them directly sometime... */ - set_opt_enabled("rts", !firm_opt.freestanding); set_opt_enabled("gcse", firm_opt.gcse); set_opt_enabled("place", !firm_opt.gcse); set_opt_enabled("confirm", firm_opt.confirm); @@ -520,7 +441,10 @@ static void do_firm_optimizations(const char *input_filename) } do_irp_opt("remove-unused"); - do_irp_opt("opt-tail-rec"); + for (i = 0; i < get_irp_n_irgs(); ++i) { + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "opt-tail-rec"); + } do_irp_opt("opt-func-call"); do_irp_opt("lower-const"); @@ -529,6 +453,7 @@ static void do_firm_optimizations(const char *input_filename) do_irg_opt(irg, "scalar-replace"); do_irg_opt(irg, "invert-loops"); + do_irg_opt(irg, "unroll-loops"); do_irg_opt(irg, "local"); do_irg_opt(irg, "reassociation"); do_irg_opt(irg, "local"); @@ -541,11 +466,13 @@ static void do_firm_optimizations(const char *input_filename) */ do_irg_opt(irg, "control-flow"); do_irg_opt(irg, "confirm"); + do_irg_opt(irg, "vrp"); do_irg_opt(irg, "local"); } do_irg_opt(irg, "control-flow"); do_irg_opt(irg, "opt-load-store"); + do_irg_opt(irg, "fp-vrp"); do_irg_opt(irg, "lower"); do_irg_opt(irg, "deconv"); do_irg_opt(irg, "thread-jumps"); @@ -558,13 +485,15 @@ static void do_firm_optimizations(const char *input_filename) do_irg_opt(irg, "local"); do_irg_opt(irg, "control-flow"); } + /* this doesn't make too much sense but tests the mux destruction... */ + do_irg_opt(irg, "lower-mux"); do_irg_opt(irg, "bool"); do_irg_opt(irg, "shape-blocks"); - do_irg_opt(irg, "lower-switch"); do_irg_opt(irg, "ivopts"); do_irg_opt(irg, "local"); do_irg_opt(irg, "dead"); + do_irg_opt(irg, "frame"); } do_irp_opt("inline"); @@ -577,6 +506,13 @@ static void do_firm_optimizations(const char *input_filename) do_irg_opt(irg, "thread-jumps"); do_irg_opt(irg, "local"); do_irg_opt(irg, "control-flow"); + + if( do_irg_opt(irg, "vrp") ) { // if vrp is enabled + do_irg_opt(irg, "local"); + do_irg_opt(irg, "vrp"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "vrp"); + } } if (firm_dump.ir_graph) { @@ -585,9 +521,7 @@ static void do_firm_optimizations(const char *input_filename) construct_cf_backedges(get_irp_irg(i)); } - do_irp_opt("remove-unused"); - - dump_all("-opt"); + dump_all("opt"); if (firm_dump.statistic & STAT_AFTER_OPT) stat_dump_snapshot(input_filename, "opt"); @@ -595,187 +529,6 @@ static void do_firm_optimizations(const char *input_filename) timer_stop(t_all_opt); } -/** - * compute the size of a type (do implicit lowering) - * - * @param ty a Firm type - */ -static int compute_type_size(ir_type *ty) -{ - optimization_state_t state; - unsigned align_all = 1; - int n, size = 0, set = 0; - int i, dims, s; - - if (get_type_state(ty) == layout_fixed) { - /* do not layout already layouted types again */ - return 1; - } - - if (is_Method_type(ty) || ty == get_glob_type()) { - /* no need for size calculation for method types or the global type */ - return 1; - } - - DBG(("compute type size visiting: %s\n", get_type_name(ty))); - - switch (get_type_tpop_code(ty)) { - case tpo_class: - case tpo_struct: - for (i = 0, n = get_compound_n_members(ty); i < n; ++i) { - ir_entity *ent = get_compound_member(ty, i); - ir_type *ent_ty = get_entity_type(ent); - unsigned align, misalign; - - /* inner functions do not expand the frame */ - if (is_Method_type(ent_ty) && is_frame_type(ty)) - continue; - - /* compute member types */ - if (! compute_type_size(ent_ty)) - return 0; - - align = get_type_alignment_bytes(ent_ty); - align_all = align > align_all ? align : align_all; - misalign = (align ? size % align : 0); - size += (misalign ? align - misalign : 0); - - set_entity_offset(ent, size); - size += get_type_size_bytes(ent_ty); - - DBG((" member %s %s -> (size: %u, align: %u)\n", - get_type_name(ent_ty), get_entity_name(ent), - get_type_size_bytes(ent_ty), get_type_alignment_bytes(ent_ty))); - } - if (align_all > 0 && size % align_all) { - DBG(("align of the struct member: %u, type size: %d\n", align_all, size)); - size += align_all - (size % align_all); - DBG(("correcting type-size to %d\n", size)); - } - set_type_alignment_bytes(ty, align_all); - set = 1; - break; - - case tpo_union: - for (i = 0, n = get_union_n_members(ty); i < n; ++i) { - ir_entity *ent = get_union_member(ty, i); - - if (! compute_type_size(get_entity_type(ent))) - return 0; - s = get_type_size_bytes(get_entity_type(ent)); - - set_entity_offset(ent, 0); - size = (s > size ? s : size); - } - set = 1; - break; - - case tpo_array: - dims = get_array_n_dimensions(ty); - - if (! compute_type_size(get_array_element_type(ty))) - return 0; - - size = 1; - - 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); - ir_node *upper = get_array_upper_bound(ty, i); - ir_graph *rem = current_ir_graph; - tarval *tv_lower, *tv_upper; - long val_lower, val_upper; - - current_ir_graph = get_const_code_irg(); - local_optimize_node(lower); - local_optimize_node(upper); - current_ir_graph = rem; - - tv_lower = computed_value(lower); - tv_upper = computed_value(upper); - - if (tv_lower == tarval_bad || tv_upper == tarval_bad) { - /* - * we cannot calculate the size of this array yet, it - * even might be unknown until the end, like argv[] - */ - restore_optimization_state(&state); - return 0; - } - - val_upper = get_tarval_long(tv_upper); - val_lower = get_tarval_long(tv_lower); - size *= val_upper - val_lower; - } - restore_optimization_state(&state); - - DBG(("array %s -> (elements: %d, element type size: %d)\n", - get_type_name(ty), - size, get_type_size_bytes(get_array_element_type(ty)))); - size *= get_type_size_bytes(get_array_element_type(ty)); - set = 1; - break; - - default: - break; - } - - if (set) { - set_type_size_bytes(ty, size); - set_type_state(ty, layout_fixed); - } - - DBG(("size: %d\n", get_type_size_bytes(ty))); - - return set; -} - -/** - * layout all non-frame types of the Firm graph - */ -static void compute_type_sizes(void) -{ - int i; - ir_type *tp; - - /* all non-frame other types */ - for (i = get_irp_n_types() - 1; i >= 0; --i) { - tp = get_irp_type(i); - compute_type_size(tp); - - if (is_Method_type(tp)) { - tp = get_method_value_res_type(tp); - - if (tp) { - /* we have a value result type for this method, lower */ - compute_type_size(tp); - } - } - } -} - -/** - * 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)); - } -} - /** * do Firm lowering * @@ -785,40 +538,43 @@ static void do_firm_lowering(const char *input_filename) { int i; - do_irp_opt("lower-dw"); + /* 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) { + ir_graph *irg = get_irp_irg(i); + do_irg_opt(irg, "reassociation"); + do_irg_opt(irg, "local"); + } + + do_irp_opt("target-lowering"); if (firm_dump.statistic & STAT_AFTER_LOWER) stat_dump_snapshot(input_filename, "low"); - dump_all("-low"); - if (firm_opt.enabled) { timer_start(t_all_opt); - /* run reassociation first on all graphs BEFORE the architecture - dependent optimizations are enabled */ - for (i = get_irp_n_irgs() - 1; i >= 0; --i) { - ir_graph *irg = get_irp_irg(i); - do_irg_opt(irg, "reassociation"); - } - - /* 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) { ir_graph *irg = get_irp_irg(i); - current_ir_graph = irg; - do_irg_opt(irg, "local"); do_irg_opt(irg, "gcse"); + do_irg_opt(irg, "control-flow"); do_irg_opt(irg, "opt-load-store"); do_irg_opt(irg, "local"); do_irg_opt(irg, "control-flow"); + if (do_irg_opt(irg, "vrp")) { + do_irg_opt(irg, "local"); + do_irg_opt(irg, "control-flow"); + do_irg_opt(irg, "vrp"); + do_irg_opt(irg, "local"); + do_irg_opt(irg, "control-flow"); + } + if (do_irg_opt(irg, "if-conversion")) { do_irg_opt(irg, "local"); do_irg_opt(irg, "control-flow"); @@ -828,19 +584,14 @@ static void do_firm_lowering(const char *input_filename) } timer_stop(t_all_opt); - dump_all("-low-opt"); + do_irp_opt("remove-unused"); + + dump_all("low-opt"); } if (firm_opt.cc_opt) mark_private_methods(); - /* set the phase to low */ - for (i = get_irp_n_irgs() - 1; i >= 0; --i) - set_irg_phase_low(get_irp_irg(i)); - - /* all graphs are lowered, set the irp phase to low */ - set_irp_phase_state(phase_low); - if (firm_dump.statistic & STAT_FINAL) { stat_dump_snapshot(input_filename, "final"); } @@ -851,9 +602,8 @@ static void do_firm_lowering(const char *input_filename) */ void gen_firm_init(void) { - firm_parameter_t params; - unsigned pattern = 0; - int i; + unsigned pattern = 0; + int i; for (i = 0; i < n_opts; ++i) { timers[i] = ir_timer_new(); @@ -872,30 +622,12 @@ void gen_firm_init(void) if (firm_dump.stat_dag) pattern |= FIRMSTAT_COUNT_DAG; - memset(¶ms, 0, sizeof(params)); - params.size = sizeof(params); - params.enable_statistics = firm_dump.statistic == STAT_NONE ? 0 : - FIRMSTAT_ENABLED | FIRMSTAT_COUNT_STRONG_OP | FIRMSTAT_COUNT_CONSTS - | pattern; - params.initialize_local_func = uninitialized_local_var; - params.cc_mask = 0; /* no regparam, cdecl */ + ir_init(NULL); + firm_init_stat(firm_dump.statistic == STAT_NONE ? + 0 : FIRMSTAT_ENABLED | FIRMSTAT_COUNT_STRONG_OP + | FIRMSTAT_COUNT_CONSTS | pattern); - ir_init(¶ms); - - if (firm_be_opt.selection == BE_FIRM_BE) { - const backend_params *be_params = be_get_backend_param(); - - if (be_params->do_dw_lowering) - set_opt_enabled("lower-dw", true); - - arch_create_intrinsic = be_params->arch_create_intrinsic_fkt; - create_intrinsic_ctx = be_params->create_intrinsic_ctx; - - ad_param = be_params->dep_param; - if_conv_info = be_params->if_conv_info; - } - - edges_init_dbg(firm_opt.vrfy_edges); + edges_init_dbg(firm_opt.verify_edges); /* Sel node cannot produce NULL pointers */ set_opt_sel_based_null_check_elim(1); @@ -903,14 +635,16 @@ void gen_firm_init(void) /* dynamic dispatch works currently only if whole world scenarios */ set_opt_dyn_meth_dispatch(0); - arch_dep_init(arch_factory); - /* do not run architecture dependent optimizations in building phase */ arch_dep_set_opts(arch_dep_none); - do_node_verification((firm_verification_t) firm_opt.vrfy); - if (firm_dump.filter) - only_dump_method_with_name(new_id_from_str(firm_dump.filter)); + do_node_verification((firm_verification_t) firm_opt.verify); + if (firm_dump.filter != NULL) + ir_set_dump_filter(firm_dump.filter); + if (firm_dump.extbb) + ir_add_dump_flags(ir_dump_flag_group_extbb); + if (firm_dump.no_blocks) + ir_remove_dump_flags(ir_dump_flag_blocks_as_subgraphs); if (firm_opt.enabled) { set_optimize(1); @@ -919,15 +653,9 @@ void gen_firm_init(void) set_opt_cse(firm_opt.cse); 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 { set_optimize(0); } - - /* do not dump entity ld names */ - dump_ld_names(0); } /** @@ -939,7 +667,7 @@ void gen_firm_init(void) * @param c_mode non-zero if "C" was compiled * @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, +void gen_firm_finish(FILE *out, const char *input_filename, int new_firm_const_exists) { int i; @@ -959,23 +687,15 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, firm_dump.ir_graph = (a_byte) (firm_dump.ir_graph | firm_dump.all_phases | firm_dump.extbb); - dump_keepalive_edges(1); - dump_consts_local(1); - dump_dominator_information(1); - dump_loop_information(0); - - if (!firm_dump.edge_labels) - turn_off_edge_labels(); + ir_add_dump_flags(ir_dump_flag_keepalive_edges + | ir_dump_flag_consts_local | ir_dump_flag_dominance); + ir_remove_dump_flags(ir_dump_flag_loops | ir_dump_flag_ld_names); /* FIXME: cloning might ADD new graphs. */ irg_dump_no = calloc(get_irp_last_idx(), sizeof(*irg_dump_no)); if (firm_dump.all_types) { - dump_all_types(""); - if (! c_mode) { - dump_class_hierarchy(0, ""); - dump_class_hierarchy(1, "-with-entities"); - } + dump_ir_prog_ext(dump_typegraph, "types.vcg"); } /* finalize all graphs */ @@ -986,7 +706,7 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, dump_all(""); timer_push(t_verify); - tr_vrfy(); + tr_verify(); timer_pop(t_verify); /* all graphs are finalized, set the irp phase to high */ @@ -1001,9 +721,6 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, /* 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); @@ -1020,12 +737,9 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, 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)); + set_irg_phase_state(get_irp_irg(i), phase_low); if (firm_dump.statistic & STAT_FINAL_IR) stat_dump_snapshot(input_filename, "final-ir"); @@ -1038,6 +752,18 @@ void gen_firm_finish(FILE *out, const char *input_filename, int c_mode, stat_dump_snapshot(input_filename, "final"); } +void disable_all_opts(void) +{ + for (int i = 0; i < n_opts; ++i) { + opt_config_t *config = &opts[i]; + if (config->flags & OPT_FLAG_ESSENTIAL) { + config->flags |= OPT_FLAG_ENABLED; + } else { + config->flags &= ~OPT_FLAG_ENABLED; + } + } +} + int firm_opt_option(const char *opt) { bool enable = true;