I'm looking into using LTO to pass information between compilers for different targets, for the OpenACC implementation. This area of the compiler seems somewhat obfuscated by overengineering, and I'd like to simplify it first to make it easier to work with.
lto_gimple_out and lto_finish_out aren't real passes, only their write_summary methods are nonnull. The only thing we really do to emit LTO is just to make two function calls, to lto_output and produce_asm_for_decls, but this is wrapped in a lot of pass_manager boilerplate to confuse the reader. Other downsides are bogus empty dump files left behind, and plain dead code like ipa_read_optimization_summaries_1 (passes->all_lto_gen_passes); The following patch simplifies this by getting rid of all_lto_gen_passes. We could simplify a little further if we decided we really don't need two different timevars for different steps of LTO output. Bootstrapped and tested on x86_64-linux, ok? Bernd
* cgraphunit.c (ipa_passes): Don't execute all_lto_gen_passes. * lto-streamer-out.c (lto_output, produce_asm_for_decls): No longer static. (pass_data_ipa_lto_gimple_out, pass_ipa_lto_gimple_out, make_pass_ipa_lto_gimple_out, pass_data_ipa_lto_finish_out, pass_ipa_lto_finish_out, make_pass_ipa_lto_finish_out): Remove. * lto-streamer.h (lto_output, produce_asm_for_decls): Declare. * pass-manager.h (GCC_PASS_LISTS, class pass_manager): Remove all_to_gen_passes. * passes.c (pass_manager::dump_passes): Remove its use. (pass_manager::register_pass): Likewise. (ipa_read_summaries, ipa_read_optimization_summaries): Likewise. (pass_manager::pass_manager): Don't initialize or use it. (write_lto): New static function. (ipa_write_summaries_1, ipa_write_optimization_summaries): Use it instead of using all_lto_gen_passes. * passes.def (all_to_gen_passes, pass_ipa_lto_gimple_out, pass_ipa_lto_finish_out): Delete. * tree-pass.h (make_pass_ipa_lto_gimple_out, make_pass_ipa_lto_finish_out): Don't declare. diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index 8ab274b..e815be0 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -2018,9 +2018,6 @@ ipa_passes (void) if (flag_generate_lto) targetm.asm_out.lto_start (); - execute_ipa_summary_passes ((struct ipa_opt_pass_d *) - passes->all_lto_gen_passes); - if (!in_lto_p) ipa_write_summaries (); diff --git a/gcc/lto-streamer-out.c b/gcc/lto-streamer-out.c index 9a00230..5176e35 100644 --- a/gcc/lto-streamer-out.c +++ b/gcc/lto-streamer-out.c @@ -1966,7 +1966,7 @@ copy_function (struct cgraph_node *node) /* Main entry point from the pass manager. */ -static void +void lto_output (void) { struct lto_out_decl_state *decl_state; @@ -2016,53 +2016,6 @@ lto_output (void) #endif } -namespace { - -const pass_data pass_data_ipa_lto_gimple_out = -{ - IPA_PASS, /* type */ - "lto_gimple_out", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - false, /* has_execute */ - TV_IPA_LTO_GIMPLE_OUT, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_ipa_lto_gimple_out : public ipa_opt_pass_d -{ -public: - pass_ipa_lto_gimple_out (gcc::context *ctxt) - : ipa_opt_pass_d (pass_data_ipa_lto_gimple_out, ctxt, - NULL, /* generate_summary */ - lto_output, /* write_summary */ - NULL, /* read_summary */ - lto_output, /* write_optimization_summary */ - NULL, /* read_optimization_summary */ - NULL, /* stmt_fixup */ - 0, /* function_transform_todo_flags_start */ - NULL, /* function_transform */ - NULL) /* variable_transform */ - {} - - /* opt_pass methods: */ - bool gate () { return gate_lto_out (); } - -}; // class pass_ipa_lto_gimple_out - -} // anon namespace - -ipa_opt_pass_d * -make_pass_ipa_lto_gimple_out (gcc::context *ctxt) -{ - return new pass_ipa_lto_gimple_out (ctxt); -} - - /* Write each node in encoded by ENCODER to OB, as well as those reachable from it and required for correct representation of its semantics. Each node in ENCODER must be a global declaration or a type. A node @@ -2382,7 +2335,7 @@ produce_symtab (struct output_block *ob) this file to be written in to a section that can then be read in to recover these on other side. */ -static void +void produce_asm_for_decls (void) { struct lto_out_decl_state *out_state; @@ -2486,50 +2439,3 @@ produce_asm_for_decls (void) lto_function_decl_states.release (); destroy_output_block (ob); } - - -namespace { - -const pass_data pass_data_ipa_lto_finish_out = -{ - IPA_PASS, /* type */ - "lto_decls_out", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - true, /* has_gate */ - false, /* has_execute */ - TV_IPA_LTO_DECL_OUT, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_ipa_lto_finish_out : public ipa_opt_pass_d -{ -public: - pass_ipa_lto_finish_out (gcc::context *ctxt) - : ipa_opt_pass_d (pass_data_ipa_lto_finish_out, ctxt, - NULL, /* generate_summary */ - produce_asm_for_decls, /* write_summary */ - NULL, /* read_summary */ - produce_asm_for_decls, /* write_optimization_summary */ - NULL, /* read_optimization_summary */ - NULL, /* stmt_fixup */ - 0, /* function_transform_todo_flags_start */ - NULL, /* function_transform */ - NULL) /* variable_transform */ - {} - - /* opt_pass methods: */ - bool gate () { return gate_lto_out (); } - -}; // class pass_ipa_lto_finish_out - -} // anon namespace - -ipa_opt_pass_d * -make_pass_ipa_lto_finish_out (gcc::context *ctxt) -{ - return new pass_ipa_lto_finish_out (ctxt); -} diff --git a/gcc/lto-streamer.h b/gcc/lto-streamer.h index 797e92e..9dac7c9 100644 --- a/gcc/lto-streamer.h +++ b/gcc/lto-streamer.h @@ -862,6 +862,8 @@ extern void destroy_output_block (struct output_block *); extern void lto_output_tree (struct output_block *, tree, bool, bool); extern void lto_output_toplevel_asms (void); extern void produce_asm (struct output_block *ob, tree fn); +extern void lto_output (); +extern void produce_asm_for_decls (); void lto_output_decl_state_streams (struct output_block *, struct lto_out_decl_state *); void lto_output_decl_state_refs (struct output_block *, diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h index 77d78eb..9a71e9c 100644 --- a/gcc/pass_manager.h +++ b/gcc/pass_manager.h @@ -29,7 +29,6 @@ struct register_pass_info; DEF_PASS_LIST (all_lowering_passes) \ DEF_PASS_LIST (all_small_ipa_passes) \ DEF_PASS_LIST (all_regular_ipa_passes) \ - DEF_PASS_LIST (all_lto_gen_passes) \ DEF_PASS_LIST (all_passes) #define DEF_PASS_LIST(LIST) PASS_LIST_NO_##LIST, @@ -82,7 +81,6 @@ public: opt_pass *all_small_ipa_passes; opt_pass *all_lowering_passes; opt_pass *all_regular_ipa_passes; - opt_pass *all_lto_gen_passes; opt_pass *all_late_ipa_passes; /* A map from static pass id to optimization pass. */ diff --git a/gcc/passes.c b/gcc/passes.c index f45ed0a..55ec70f 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -907,7 +907,6 @@ pass_manager::dump_passes () const dump_pass_list (all_lowering_passes, 1); dump_pass_list (all_small_ipa_passes, 1); dump_pass_list (all_regular_ipa_passes, 1); - dump_pass_list (all_lto_gen_passes, 1); dump_pass_list (all_late_ipa_passes, 1); dump_pass_list (all_passes, 1); @@ -1426,8 +1425,6 @@ pass_manager::register_pass (struct register_pass_info *pass_info) if (!success || all_instances) success |= position_pass (pass_info, &all_regular_ipa_passes); if (!success || all_instances) - success |= position_pass (pass_info, &all_lto_gen_passes); - if (!success || all_instances) success |= position_pass (pass_info, &all_late_ipa_passes); if (!success || all_instances) success |= position_pass (pass_info, &all_passes); @@ -1498,7 +1495,7 @@ pass_manager::operator new (size_t sz) pass_manager::pass_manager (context *ctxt) : all_passes (NULL), all_small_ipa_passes (NULL), all_lowering_passes (NULL), - all_regular_ipa_passes (NULL), all_lto_gen_passes (NULL), + all_regular_ipa_passes (NULL), all_late_ipa_passes (NULL), passes_by_id (NULL), passes_by_id_size (0), m_ctxt (ctxt) { @@ -1553,9 +1550,6 @@ pass_manager::pass_manager (context *ctxt) register_dump_files (all_regular_ipa_passes, PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg); - register_dump_files (all_lto_gen_passes, - PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh - | PROP_cfg); register_dump_files (all_late_ipa_passes, PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh | PROP_cfg); @@ -2274,6 +2268,18 @@ execute_pass_list (struct opt_pass *pass) while (pass); } +/* Write out all LTO data. */ +static void +write_lto (void) +{ + timevar_push (TV_IPA_LTO_GIMPLE_OUT); + lto_output (); + timevar_pop (TV_IPA_LTO_GIMPLE_OUT); + timevar_push (TV_IPA_LTO_DECL_OUT); + produce_asm_for_decls (); + timevar_pop (TV_IPA_LTO_DECL_OUT); +} + /* Same as execute_pass_list but assume that subpasses of IPA passes are local passes. If SET is not NULL, write out summaries of only those node in SET. */ @@ -2328,7 +2334,8 @@ ipa_write_summaries_1 (lto_symtab_encoder_t encoder) gcc_assert (!flag_wpa); ipa_write_summaries_2 (passes->all_regular_ipa_passes, state); - ipa_write_summaries_2 (passes->all_lto_gen_passes, state); + + write_lto (); gcc_assert (lto_get_out_decl_state () == state); lto_pop_out_decl_state (); @@ -2461,7 +2468,8 @@ ipa_write_optimization_summaries (lto_symtab_encoder_t encoder) gcc_assert (flag_wpa); pass_manager *passes = g->get_passes (); ipa_write_optimization_summaries_1 (passes->all_regular_ipa_passes, state); - ipa_write_optimization_summaries_1 (passes->all_lto_gen_passes, state); + + write_lto (); gcc_assert (lto_get_out_decl_state () == state); lto_pop_out_decl_state (); @@ -2509,14 +2517,13 @@ ipa_read_summaries_1 (struct opt_pass *pass) } -/* Read all the summaries for all_regular_ipa_passes and all_lto_gen_passes. */ +/* Read all the summaries for all_regular_ipa_passes. */ void ipa_read_summaries (void) { pass_manager *passes = g->get_passes (); ipa_read_summaries_1 (passes->all_regular_ipa_passes); - ipa_read_summaries_1 (passes->all_lto_gen_passes); } /* Same as execute_pass_list but assume that subpasses of IPA passes @@ -2559,14 +2566,13 @@ ipa_read_optimization_summaries_1 (struct opt_pass *pass) } } -/* Read all the summaries for all_regular_ipa_passes and all_lto_gen_passes. */ +/* Read all the summaries for all_regular_ipa_passes. */ void ipa_read_optimization_summaries (void) { pass_manager *passes = g->get_passes (); ipa_read_optimization_summaries_1 (passes->all_regular_ipa_passes); - ipa_read_optimization_summaries_1 (passes->all_lto_gen_passes); } /* Same as execute_pass_list but assume that subpasses of IPA passes diff --git a/gcc/passes.def b/gcc/passes.def index 8d8dd80..a6efbb4 100644 --- a/gcc/passes.def +++ b/gcc/passes.def @@ -111,11 +111,6 @@ along with GCC; see the file COPYING3. If not see NEXT_PASS (pass_ipa_reference); TERMINATE_PASS_LIST () - INSERT_PASSES_AFTER (all_lto_gen_passes) - NEXT_PASS (pass_ipa_lto_gimple_out); - NEXT_PASS (pass_ipa_lto_finish_out); /* This must be the last LTO pass. */ - TERMINATE_PASS_LIST () - /* Simple IPA passes executed after the regular passes. In WHOPR mode the passes are executed after partitioning and thus see just parts of the compiled unit. */ diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 9efee1e..77abd94 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -458,7 +458,6 @@ extern simple_ipa_opt_pass *make_pass_early_local_passes (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_whole_program_visibility (gcc::context *ctxt); -extern ipa_opt_pass_d *make_pass_ipa_lto_gimple_out (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_increase_alignment (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_inline (gcc::context *ctxt); @@ -470,7 +469,6 @@ extern ipa_opt_pass_d *make_pass_ipa_devirt (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_reference (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_pure_const (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_pta (gcc::context *ctxt); -extern ipa_opt_pass_d *make_pass_ipa_lto_finish_out (gcc::context *ctxt); extern simple_ipa_opt_pass *make_pass_ipa_tm (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_profile (gcc::context *ctxt); extern ipa_opt_pass_d *make_pass_ipa_cdtor_merge (gcc::context *ctxt);