X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fbe%2Fbemain.c;h=c476f88b4c8589f7593a4df2afa917476985504a;hb=4ed245f5007168dab7850942a7ee6b6b29a19817;hp=d40367a174707da6384f8fefe65a585da127cb2e;hpb=ee8287263ba35574833e8078b4f3106529823f98;p=libfirm diff --git a/ir/be/bemain.c b/ir/be/bemain.c index d40367a17..c476f88b4 100644 --- a/ir/be/bemain.c +++ b/ir/be/bemain.c @@ -28,6 +28,7 @@ #include "iredges_t.h" #include "irloop_t.h" #include "irtools.h" +#include "irvrfy.h" #include "return.h" #include "firmstat.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(); @@ -363,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 */ @@ -387,7 +418,7 @@ static void be_main_loop(FILE *file_handle) 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)); @@ -414,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"); @@ -445,33 +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_codegen); - /* Schedule the graphs. */ + /* let backend prepare scheduling */ + BE_TIMER_PUSH(t_codegen); arch_code_generator_before_sched(birg.cg); + BE_TIMER_POP(t_codegen); - BE_TIMER_POP(); + /* schedule the irg */ BE_TIMER_PUSH(t_sched); + list_sched(&birg, &be_options); + BE_TIMER_POP(t_sched); - list_sched(&birg, be_enable_mris); dump(DUMP_SCHED, irg, "-sched", dump_ir_block_graph_sched); - BE_TIMER_POP(); - BE_TIMER_PUSH(t_verify); - /* 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); @@ -480,68 +510,88 @@ 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_POP(); + 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); - BE_TIMER_PUSH(t_verify); /* check schedule */ + BE_TIMER_PUSH(t_verify); be_sched_vrfy(birg.irg, vrfy_option); - BE_TIMER_POP(); + BE_TIMER_POP(t_verify); - BE_TIMER_PUSH(t_codegen); /* 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_ONLY(lc_timer_start(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); - 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"); + /* 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); - BE_TIMER_POP(); - BE_TIMER_PUSH(t_verify); + BE_TIMER_PUSH(t_finish); + arch_code_generator_finish(birg.cg); + BE_TIMER_POP(t_finish); - /* check schedule */ - be_sched_vrfy(birg.irg, vrfy_option); + 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(); + 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"); restore_optimization_state(&state); BE_TIMER_ONLY(num_nodes_a = get_num_reachable_nodes(irg)); - - /* switched off due to statistics (statistic module needs all irgs) */ - if (! stat_is_active()) - free_ir_graph(irg); - BE_TIMER_POP(); + BE_TIMER_POP(t_other); #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) @@ -559,6 +609,7 @@ static void be_main_loop(FILE *file_handle) 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); @@ -572,6 +623,11 @@ static void be_main_loop(FILE *file_handle) 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);