X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbemain.c;h=c476f88b4c8589f7593a4df2afa917476985504a;hb=4ed245f5007168dab7850942a7ee6b6b29a19817;hp=4c8e8875b0b52203a157227e4cc1c27dc4bfd73b;hpb=6161a76604293595d3467597e036d9f02ac66e20;p=libfirm diff --git a/ir/be/bemain.c b/ir/be/bemain.c index 4c8e8875b..c476f88b4 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -28,7 +28,9 @@ #include "iredges_t.h" #include "irloop_t.h" #include "irtools.h" +#include "irvrfy.h" #include "return.h" +#include "firmstat.h" #include "bearch.h" #include "firm/bearch_firm.h" @@ -45,7 +47,6 @@ #include "besched_t.h" #include "belistsched.h" #include "belive_t.h" -#include "bespillilp.h" #include "bespillbelady.h" #include "bera.h" #include "beraextern.h" @@ -65,6 +66,8 @@ static be_options_t be_options = { DUMP_NONE, /* dump options */ BE_TIME_OFF, /* no timing */ + BE_SCHED_SELECT_HEUR, /* mueller heuristic selector */ + 0, /* disable mris */ "i44pc52.info.uni-karlsruhe.de", /* ilp server */ "cplex" /* ilp solver */ }; @@ -73,7 +76,7 @@ static be_options_t be_options = { static unsigned dump_flags = 0; /* verify options */ -static unsigned vrfy_option = BE_VRFY_WARN; +static int vrfy_option = BE_VRFY_WARN; /* register allocator to use. */ static const be_ra_t *ra = &be_ra_chordal_allocator; @@ -81,9 +84,6 @@ static const be_ra_t *ra = &be_ra_chordal_allocator; /* back end instruction set architecture to use */ static const arch_isa_if_t *isa_if = &ia32_isa_if; -/* mris option */ -static int be_enable_mris = 0; - #ifdef WITH_LIBCORE static lc_opt_entry_t *be_grp_root = NULL; @@ -128,6 +128,15 @@ static const lc_opt_enum_int_items_t vrfy_items[] = { { NULL, 0 } }; +/* schedule selector options. */ +static const lc_opt_enum_int_items_t sched_select_items[] = { + { "isa", BE_SCHED_SELECT_ISA }, + { "muchnik", BE_SCHED_SELECT_MUCHNIK }, + { "heur", BE_SCHED_SELECT_HEUR }, + { "hmuchnik", BE_SCHED_SELECT_HMUCHNIK }, + { NULL, 0 } +}; + static lc_opt_enum_mask_var_t dump_var = { &dump_flags, dump_items }; @@ -144,14 +153,19 @@ static lc_opt_enum_int_var_t vrfy_var = { &vrfy_option, vrfy_items }; +static lc_opt_enum_int_var_t sched_select_var = { + &be_options.sched_select, sched_select_items +}; + static const lc_opt_table_entry_t be_main_options[] = { - LC_OPT_ENT_ENUM_MASK("dump", "dump irg on several occasions", &dump_var), - LC_OPT_ENT_ENUM_PTR ("ra", "register allocator", &ra_var), - LC_OPT_ENT_ENUM_PTR ("isa", "the instruction set architecture", &isa_var), - LC_OPT_ENT_NEGBOOL ("noomitfp", "do not omit frame pointer", &be_omit_fp), - LC_OPT_ENT_BOOL ("mris", "enable mris schedule preparation", &be_enable_mris), - LC_OPT_ENT_ENUM_PTR ("vrfy", "verify the backend irg (off, warn, assert)", &vrfy_var), - LC_OPT_ENT_BOOL ("time", "get backend timing statistics", &be_options.timing), + LC_OPT_ENT_ENUM_MASK("dump", "dump irg on several occasions", &dump_var), + LC_OPT_ENT_ENUM_PTR ("ra", "register allocator", &ra_var), + LC_OPT_ENT_ENUM_PTR ("isa", "the instruction set architecture", &isa_var), + LC_OPT_ENT_NEGBOOL ("noomitfp", "do not omit frame pointer", &be_omit_fp), + LC_OPT_ENT_ENUM_PTR ("vrfy", "verify the backend irg (off, warn, assert)", &vrfy_var), + LC_OPT_ENT_BOOL ("time", "get backend timing statistics", &be_options.timing), + LC_OPT_ENT_BOOL ("sched.mris", "enable mris schedule preparation", &be_options.mris), + LC_OPT_ENT_ENUM_PTR ("sched.select", "schedule node selector (isa, muchnik, heur, hmuchnik)",&sched_select_var), #ifdef WITH_ILP LC_OPT_ENT_STR ("ilp.server", "the ilp server name", be_options.ilp_server, sizeof(be_options.ilp_server)), @@ -228,7 +242,6 @@ const backend_params *be_init(void) be_opt_register(); be_sched_init(); - be_liveness_init(); be_numbering_init(); be_copy_opt_init(); copystat_init(); @@ -340,15 +353,7 @@ static void be_main_loop(FILE *file_handle) unsigned num_nodes_b = 0; unsigned num_nodes_a = 0; unsigned num_nodes_r = 0; - unsigned ra_prolog = 0; - unsigned ra_epilog = 0; - unsigned ra_live = 0; - unsigned ra_spill = 0; - unsigned ra_color = 0; - unsigned ra_ifg = 0; - unsigned ra_copymin = 0; - unsigned ra_ssa = 0; - lc_timer_t *t_prolog, *t_abi, *t_codegen, *t_sched, *t_constr, *t_regalloc, *t_finish, *t_emit, *t_other; + lc_timer_t *t_prolog, *t_abi, *t_codegen, *t_sched, *t_constr, *t_regalloc, *t_finish, *t_emit, *t_other, *t_verify; be_ra_timer_t *ra_timer; if (be_options.timing == BE_TIME_ON) { @@ -360,6 +365,7 @@ static void be_main_loop(FILE *file_handle) t_regalloc = lc_timer_register("regalloc", "register allocation"); t_finish = lc_timer_register("finish", "graph finish"); t_emit = lc_timer_register("emiter", "code emiter"); + t_verify = lc_timer_register("verify", "graph verification"); t_other = lc_timer_register("other", "other"); } @@ -370,8 +376,26 @@ static void be_main_loop(FILE *file_handle) /* for debugging, anchors helps */ // dump_all_anchors(1); -#define BE_TIMER_PUSH(timer) if (be_options.timing == BE_TIME_ON) lc_timer_push(timer) -#define BE_TIMER_POP() if (be_options.timing == BE_TIME_ON) lc_timer_pop() +#define BE_TIMER_PUSH(timer) \ + if (be_options.timing == BE_TIME_ON) { \ + int res = lc_timer_push(timer); \ + if (vrfy_option == BE_VRFY_ASSERT) \ + assert(res && "Timer already on stack, cannot be pushed twice."); \ + else if (vrfy_option == BE_VRFY_WARN && ! res) \ + fprintf(stderr, "Timer %s already on stack, cannot be pushed twice.\n", \ + lc_timer_get_name(timer)); \ + } +#define BE_TIMER_POP(timer) \ + if (be_options.timing == BE_TIME_ON) { \ + lc_timer_t *tmp = lc_timer_pop(); \ + if (vrfy_option == BE_VRFY_ASSERT) \ + assert(tmp == timer && "Attempt to pop wrong timer."); \ + else if (vrfy_option == BE_VRFY_WARN && tmp != timer) \ + fprintf(stderr, "Attempt to pop wrong timer. %s is on stack, trying to pop %s.\n", \ + lc_timer_get_name(tmp), lc_timer_get_name(timer)); \ + timer = tmp; \ + } + #define BE_TIMER_ONLY(code) if (be_options.timing == BE_TIME_ON) do { code; } while(0) /* For all graphs */ @@ -391,9 +415,10 @@ static void be_main_loop(FILE *file_handle) LC_STOP_AND_RESET_TIMER(t_regalloc); LC_STOP_AND_RESET_TIMER(t_finish); LC_STOP_AND_RESET_TIMER(t_emit); + LC_STOP_AND_RESET_TIMER(t_verify); LC_STOP_AND_RESET_TIMER(t_other); } - BE_TIMER_PUSH(t_other); + BE_TIMER_PUSH(t_other); /* t_other */ BE_TIMER_ONLY(num_nodes_b = get_num_reachable_nodes(irg)); @@ -420,23 +445,25 @@ static void be_main_loop(FILE *file_handle) /* create the code generator and generate code. */ prepare_graph(&birg); + BE_TIMER_POP(t_prolog); + /* some transformations need to be done before abi introduce */ + BE_TIMER_PUSH(t_codegen); arch_code_generator_before_abi(birg.cg); - - BE_TIMER_POP(); - BE_TIMER_PUSH(t_abi); + BE_TIMER_POP(t_codegen); /* implement the ABI conventions. */ + BE_TIMER_PUSH(t_abi); birg.abi = be_abi_introduce(&birg); - dump(DUMP_ABI, irg, "-abi", dump_ir_block_graph); + BE_TIMER_POP(t_abi); + dump(DUMP_ABI, irg, "-abi", dump_ir_block_graph); be_do_stat_nodes(irg, "02 Abi"); - BE_TIMER_POP(); - BE_TIMER_PUSH(t_codegen); - /* generate code */ + BE_TIMER_PUSH(t_codegen); arch_code_generator_prepare_graph(birg.cg); + BE_TIMER_POP(t_codegen); be_do_stat_nodes(irg, "03 Prepare"); @@ -451,26 +478,30 @@ static void be_main_loop(FILE *file_handle) /* Compute loop nesting information (for weighting copies) */ construct_cf_backedges(irg); - dump(DUMP_PREPARED, irg, "-prepared", dump_ir_block_graph); - - BE_TIMER_POP(); BE_TIMER_ONLY(num_nodes_r = get_num_reachable_nodes(irg)); - BE_TIMER_PUSH(t_sched); - /* Schedule the graphs. */ + /* let backend prepare scheduling */ + BE_TIMER_PUSH(t_codegen); arch_code_generator_before_sched(birg.cg); - list_sched(&birg, be_enable_mris); + BE_TIMER_POP(t_codegen); + + /* schedule the irg */ + BE_TIMER_PUSH(t_sched); + list_sched(&birg, &be_options); + BE_TIMER_POP(t_sched); + dump(DUMP_SCHED, irg, "-sched", dump_ir_block_graph_sched); /* check schedule */ + BE_TIMER_PUSH(t_verify); be_sched_vrfy(birg.irg, vrfy_option); + BE_TIMER_POP(t_verify); be_do_stat_nodes(irg, "04 Schedule"); - BE_TIMER_POP(); + /* introduce patterns to assure constraints */ BE_TIMER_PUSH(t_constr); - /* we switch off optimizations here, because they might cause trouble */ save_optimization_state(&state); set_optimize(0); @@ -479,73 +510,91 @@ static void be_main_loop(FILE *file_handle) /* add Keeps for should_be_different constrained nodes */ /* beware: needs schedule due to usage of be_ssa_constr */ assure_constraints(&birg); - dump(DUMP_SCHED, irg, "-assured", dump_ir_block_graph_sched); + BE_TIMER_POP(t_constr); + dump(DUMP_SCHED, irg, "-assured", dump_ir_block_graph_sched); be_do_stat_nodes(irg, "05 Constraints"); /* connect all stack modifying nodes together (see beabi.c) */ - be_abi_fix_stack_nodes(birg.abi); + BE_TIMER_PUSH(t_abi); + be_abi_fix_stack_nodes(birg.abi, NULL); + BE_TIMER_POP(t_abi); + dump(DUMP_SCHED, irg, "-fix_stack", dump_ir_block_graph_sched); /* check schedule */ + BE_TIMER_PUSH(t_verify); be_sched_vrfy(birg.irg, vrfy_option); + BE_TIMER_POP(t_verify); /* do some statistics */ be_do_stat_reg_pressure(&birg); /* stuff needs to be done after scheduling but before register allocation */ + BE_TIMER_PUSH(t_codegen); arch_code_generator_before_ra(birg.cg); - - BE_TIMER_POP(); - BE_TIMER_PUSH(t_regalloc); + BE_TIMER_POP(t_codegen); /* Do register allocation */ + BE_TIMER_ONLY(lc_timer_start(t_regalloc)); ra_timer = ra->allocate(&birg); - dump(DUMP_RA, irg, "-ra", dump_ir_block_graph_sched); - - if (be_options.timing == BE_TIME_ON && ra_timer) { - ra_prolog = lc_timer_elapsed_msec(ra_timer->t_prolog); - ra_epilog = lc_timer_elapsed_msec(ra_timer->t_epilog); - ra_live = lc_timer_elapsed_msec(ra_timer->t_live); - ra_spill = lc_timer_elapsed_msec(ra_timer->t_spill); - ra_color = lc_timer_elapsed_msec(ra_timer->t_color); - ra_copymin = lc_timer_elapsed_msec(ra_timer->t_copymin); - ra_ssa = lc_timer_elapsed_msec(ra_timer->t_ssa); - ra_ifg = lc_timer_elapsed_msec(ra_timer->t_ifg); - } + BE_TIMER_ONLY(lc_timer_stop(t_regalloc)); + dump(DUMP_RA, irg, "-ra", dump_ir_block_graph_sched); be_do_stat_nodes(irg, "06 Register Allocation"); - BE_TIMER_POP(); + /* let the codegenerator prepare the graph for emitter */ BE_TIMER_PUSH(t_finish); - arch_code_generator_after_ra(birg.cg); + BE_TIMER_POP(t_finish); + + /* fix stack offsets */ + BE_TIMER_PUSH(t_abi); be_abi_fix_stack_bias(birg.abi); + BE_TIMER_POP(t_abi); - /* check schedule */ - be_sched_vrfy(birg.irg, vrfy_option); + BE_TIMER_PUSH(t_finish); + arch_code_generator_finish(birg.cg); + BE_TIMER_POP(t_finish); + + dump(DUMP_FINAL, irg, "-finish", dump_ir_block_graph_sched); + + /* check schedule and register allocation */ + BE_TIMER_PUSH(t_verify); + if (vrfy_option == BE_VRFY_WARN) { + //irg_verify(birg.irg, VRFY_ENFORCE_SSA); + be_check_dominance(birg.irg); + be_verify_schedule(birg.irg); + be_verify_register_allocation(env.arch_env, birg.irg); + } + else if (vrfy_option == BE_VRFY_ASSERT) { + //assert(irg_verify(birg.irg, VRFY_ENFORCE_SSA) && "irg verification failed"); + assert(be_check_dominance(birg.irg) && "Dominance verification failed"); + assert(be_verify_schedule(birg.irg) && "Schedule verification failed"); + assert(be_verify_register_allocation(env.arch_env, birg.irg) + && "register allocation verification failed"); + } + BE_TIMER_POP(t_verify); - BE_TIMER_POP(); + /* emit assembler code */ BE_TIMER_PUSH(t_emit); - arch_code_generator_done(birg.cg); + BE_TIMER_POP(t_emit); + dump(DUMP_FINAL, irg, "-end", dump_ir_extblock_graph_sched); + + BE_TIMER_PUSH(t_abi); be_abi_free(birg.abi); + BE_TIMER_POP(t_abi); be_do_stat_nodes(irg, "07 Final"); - - BE_TIMER_POP(); - restore_optimization_state(&state); BE_TIMER_ONLY(num_nodes_a = get_num_reachable_nodes(irg)); + BE_TIMER_POP(t_other); - /* switched off due to statistics (statistic module needs all irgs) */ - // free_ir_graph(irg); - BE_TIMER_POP(); - -#define LC_EMIT(timer) printf("%-20s: %u msec\n", lc_timer_get_description(timer), lc_timer_elapsed_msec(timer)) -#define EMIT_RA_TIME(n, t) printf("%-20s: %u msec\n", n, t) +#define LC_EMIT(timer) printf("%-20s: %.3lf msec\n", lc_timer_get_description(timer), (double)lc_timer_elapsed_usec(timer) / 1000.0) +#define LC_EMIT_RA(timer) printf("\t%-20s: %.3lf msec\n", lc_timer_get_description(timer), (double)lc_timer_elapsed_usec(timer) / 1000.0) if (be_options.timing == BE_TIME_ON) { printf("==>> IRG %s <<==\n", get_entity_name(get_irg_entity(irg))); printf("# nodes at begin: %u\n", num_nodes_b); @@ -557,25 +606,34 @@ static void be_main_loop(FILE *file_handle) LC_EMIT(t_sched); LC_EMIT(t_constr); LC_EMIT(t_regalloc); - EMIT_RA_TIME("prolog", ra_prolog); - EMIT_RA_TIME("liveness", ra_live); - EMIT_RA_TIME("spilling", ra_spill); - EMIT_RA_TIME("coloring", ra_color); - EMIT_RA_TIME("ifg build", ra_ifg); - EMIT_RA_TIME("copymin", ra_copymin); - EMIT_RA_TIME("ssa destr", ra_ssa); - EMIT_RA_TIME("epilog", ra_epilog); + LC_EMIT_RA(ra_timer->t_prolog); + LC_EMIT_RA(ra_timer->t_live); + LC_EMIT_RA(ra_timer->t_spill); + LC_EMIT_RA(ra_timer->t_spillslots); + LC_EMIT_RA(ra_timer->t_color); + LC_EMIT_RA(ra_timer->t_ifg); + LC_EMIT_RA(ra_timer->t_copymin); + LC_EMIT_RA(ra_timer->t_ssa); + LC_EMIT_RA(ra_timer->t_epilog); + LC_EMIT_RA(ra_timer->t_verify); + LC_EMIT_RA(ra_timer->t_other); LC_EMIT(t_finish); LC_EMIT(t_emit); + LC_EMIT(t_verify); LC_EMIT(t_other); } #undef LC_EMIT + + /* switched off due to statistics (statistic module needs all irgs) */ + if (! stat_is_active()) + free_ir_graph(irg); + } be_done_env(&env); -#undef BE_TIME_START -#undef BE_TIME_STOP -#undef BE_TIME_ONLY +#undef BE_TIMER_POP +#undef BE_TIMER_PUSH +#undef BE_TIMER_ONLY } /* Main interface to the frontend. */