From 3edf64aa919b9bf725672bd0ad91bfd30c6a31df Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Tue, 21 Oct 2014 16:55:38 +0000 Subject: [PATCH] State cleanups from jit branch gcc/ChangeLog: * cgraph.c (cgraph_c_finalize): New function. * cgraph.h (cgraph_c_finalize): New prototype. (cgraphunit_c_finalize): New prototype. * cgraphunit.c (first_analyzed): Move from analyze_functions to file-scope. (first_analyzed_var): Likewise. (analyze_functions): Move static variables into file-scope. (cgraphunit_c_finalize): New function. * diagnostic.c (diagnostic_finish): Free the memory for context->classify_diagnostic and context->printer, running the destructor for the latter. (bt_stop): Use toplev::main. * dwarf2out.c (dwarf2out_finalize): New function. * dwarf2out.h (dwarf2out_c_finalize): New prototype. * gcse.c (gcse_c_finalize): New function. * gcse.h (gcse_c_finalize): New prototype. * ggc-page.c (init_ggc): Make idempotent. * input.c (input_location): Initialize to UNKNOWN_LOCATION. * ipa-cp.c (ipa_cp_c_finalize): New function. * ipa-prop.h (ipa_cp_c_finalize): New prototype. * ipa-pure-const.c (function_insertion_hook_holder): Move to be a field of class pass_ipa_pure_const. (node_duplication_hook_holder): Likewise. (node_removal_hook_holder): Likewise. (register_hooks): Convert to method... (pass_ipa_pure_const::register_hooks): ...here, converting static variable init_p into... (pass_ipa_pure_const::init_p): ...new field. (pure_const_generate_summary): Update invocation of register_hooks to invoke as a method of current_pass. (pure_const_read_summary): Likewise. (propagate): Convert to... (pass_ipa_pure_const::execute): ...method. * ipa-reference.c (ipa_init): Move static bool init_p from here to... (ipa_init_p): New file-scope variable, so that it can be reset when repeatedly invoking the compiler within one process by... (ipa_reference_c_finalize): New function. * ipa-reference.h (ipa_reference_c_finalize): New. * main.c (main): Replace invocation of toplev_main with construction of a toplev instance, and call its "main" method. * params.c (global_init_params): Add an assert that params_finished is false. (params_c_finalize): New. * params.h (params_c_finalize): New. * passes.c (execute_ipa_summary_passes): Set "current_pass" before invoking generate_summary, for the benefit of pass_ipa_pure_const. (ipa_write_summaries_2): Assign "pass" to "current_pass" global before calling write_summary hook. (ipa_write_optimization_summaries_1): Likewise when calling write_optimization_summary hook. (ipa_read_summaries_1): Likewise for read_summary hook. (ipa_read_optimization_summaries_1): Likewise for read_optimization_summary hook. (execute_ipa_stmt_fixups): Likewise. * stringpool.c (init_stringpool): Clean up if we're called more than once. * timevar.c (timevar_init): Ignore repeated calls. * toplev.c: Include "dwarf2out.h", "ipa-reference.h", "gcse.h", "ipa-prop.h". (general_init): Reset "input_location" to UNKNOWN_LOCATION. (initialize_rtl): Move static local "initialized_once" into file scope, and rename to... (rtl_initialized): New variable. (do_compile): Move timevar initialization from here to toplev::start_timevars. (toplev::toplev, toplev::~toplev, toplev::start_timevars, toplev::finalize): New functions. (toplev_main): Rename to... (toplev::main): ...this. * toplev.h (class toplev): New class. From-SVN: r216522 --- gcc/ChangeLog | 74 ++++++++++++++++++++++++++++ gcc/cgraph.c | 14 ++++++ gcc/cgraph.h | 3 ++ gcc/cgraphunit.c | 20 +++++++- gcc/diagnostic.c | 11 ++++- gcc/dwarf2out.c | 86 ++++++++++++++++++++++++++++++++ gcc/dwarf2out.h | 2 + gcc/gcse.c | 9 ++++ gcc/gcse.h | 2 + gcc/ggc-page.c | 5 ++ gcc/input.c | 2 +- gcc/ipa-cp.c | 12 +++++ gcc/ipa-prop.h | 3 ++ gcc/ipa-pure-const.c | 113 +++++++++++++++++++++++++------------------ gcc/ipa-reference.c | 17 +++++-- gcc/ipa-reference.h | 1 + gcc/main.c | 6 ++- gcc/params.c | 14 ++++++ gcc/params.h | 4 ++ gcc/passes.c | 6 +++ gcc/stringpool.c | 5 ++ gcc/timevar.c | 3 ++ gcc/toplev.c | 68 ++++++++++++++++++++------ gcc/toplev.h | 19 +++++++- 24 files changed, 425 insertions(+), 74 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f29decfb566..bce5f7010eb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,77 @@ +2014-10-21 David Malcolm + + * cgraph.c (cgraph_c_finalize): New function. + * cgraph.h (cgraph_c_finalize): New prototype. + (cgraphunit_c_finalize): New prototype. + * cgraphunit.c (first_analyzed): Move from analyze_functions + to file-scope. + (first_analyzed_var): Likewise. + (analyze_functions): Move static variables into file-scope. + (cgraphunit_c_finalize): New function. + * diagnostic.c (diagnostic_finish): Free the memory for + context->classify_diagnostic and context->printer, running the + destructor for the latter. + (bt_stop): Use toplev::main. + * dwarf2out.c (dwarf2out_finalize): New function. + * dwarf2out.h (dwarf2out_c_finalize): New prototype. + * gcse.c (gcse_c_finalize): New function. + * gcse.h (gcse_c_finalize): New prototype. + * ggc-page.c (init_ggc): Make idempotent. + * input.c (input_location): Initialize to UNKNOWN_LOCATION. + * ipa-cp.c (ipa_cp_c_finalize): New function. + * ipa-prop.h (ipa_cp_c_finalize): New prototype. + * ipa-pure-const.c (function_insertion_hook_holder): Move to be + a field of class pass_ipa_pure_const. + (node_duplication_hook_holder): Likewise. + (node_removal_hook_holder): Likewise. + (register_hooks): Convert to method... + (pass_ipa_pure_const::register_hooks): ...here, converting + static variable init_p into... + (pass_ipa_pure_const::init_p): ...new field. + (pure_const_generate_summary): Update invocation of + register_hooks to invoke as a method of current_pass. + (pure_const_read_summary): Likewise. + (propagate): Convert to... + (pass_ipa_pure_const::execute): ...method. + * ipa-reference.c (ipa_init): Move static bool init_p from here + to... + (ipa_init_p): New file-scope variable, so that it can be reset + when repeatedly invoking the compiler within one process by... + (ipa_reference_c_finalize): New function. + * ipa-reference.h (ipa_reference_c_finalize): New. + * main.c (main): Replace invocation of toplev_main with + construction of a toplev instance, and call its "main" method. + * params.c (global_init_params): Add an assert that + params_finished is false. + (params_c_finalize): New. + * params.h (params_c_finalize): New. + * passes.c (execute_ipa_summary_passes): Set "current_pass" before + invoking generate_summary, for the benefit of pass_ipa_pure_const. + (ipa_write_summaries_2): Assign "pass" to "current_pass" global + before calling write_summary hook. + (ipa_write_optimization_summaries_1): Likewise when calling + write_optimization_summary hook. + (ipa_read_summaries_1): Likewise for read_summary hook. + (ipa_read_optimization_summaries_1): Likewise for + read_optimization_summary hook. + (execute_ipa_stmt_fixups): Likewise. + * stringpool.c (init_stringpool): Clean up if we're called more + than once. + * timevar.c (timevar_init): Ignore repeated calls. + * toplev.c: Include "dwarf2out.h", "ipa-reference.h", "gcse.h", + "ipa-prop.h". + (general_init): Reset "input_location" to UNKNOWN_LOCATION. + (initialize_rtl): Move static local "initialized_once" + into file scope, and rename to... + (rtl_initialized): New variable. + (do_compile): Move timevar initialization from here to + toplev::start_timevars. + (toplev::toplev, toplev::~toplev, toplev::start_timevars, + toplev::finalize): New functions. + (toplev_main): Rename to... + (toplev::main): ...this. + * toplev.h (class toplev): New class. + 2014-10-21 Andrew MacLeod * loop-doloop.c: Include loop-unroll.h. diff --git a/gcc/cgraph.c b/gcc/cgraph.c index f472ec53159..6536233430d 100644 --- a/gcc/cgraph.c +++ b/gcc/cgraph.c @@ -3097,4 +3097,18 @@ gimple_check_call_matching_types (gimple call_stmt, tree callee, return true; } +/* Reset all state within cgraph.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +cgraph_c_finalize (void) +{ + symtab = NULL; + + x_cgraph_nodes_queue = NULL; + + cgraph_fnver_htab = NULL; + version_info_node = NULL; +} + #include "gt-cgraph.h" diff --git a/gcc/cgraph.h b/gcc/cgraph.h index aa28414e851..2a55e171f98 100644 --- a/gcc/cgraph.h +++ b/gcc/cgraph.h @@ -2108,6 +2108,7 @@ asmname_hasher::pch_nx (symtab_node *&n, gt_pointer_operator op, void *cookie) } /* In cgraph.c */ +void cgraph_c_finalize (void); void release_function_body (tree); cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void); @@ -2121,6 +2122,8 @@ bool resolution_used_from_other_file_p (enum ld_plugin_symbol_resolution); extern bool gimple_check_call_matching_types (gimple, tree, bool); /* In cgraphunit.c */ +void cgraphunit_c_finalize (void); + /* Initialize datastructures so DECL is a function in lowered gimple form. IN_SSA is true if the gimple is in SSA. */ basic_block init_lowered_empty_function (tree, bool); diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index c558a000c62..e84c70089c1 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -884,15 +884,15 @@ walk_polymorphic_call_targets (hash_set *reachable_call_targets, /* Discover all functions and variables that are trivially needed, analyze them as well as all functions and variables referred by them */ +static cgraph_node *first_analyzed; +static varpool_node *first_analyzed_var; static void analyze_functions (void) { /* Keep track of already processed nodes when called multiple times for intermodule optimization. */ - static cgraph_node *first_analyzed; cgraph_node *first_handled = first_analyzed; - static varpool_node *first_analyzed_var; varpool_node *first_handled_var = first_analyzed_var; hash_set reachable_call_targets; @@ -2292,6 +2292,22 @@ symbol_table::finalize_compilation_unit (void) timevar_pop (TV_CGRAPH); } +/* Reset all state within cgraphunit.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +cgraphunit_c_finalize (void) +{ + gcc_assert (cgraph_new_nodes.length () == 0); + cgraph_new_nodes.truncate (0); + + vtable_entry_type = NULL; + queued_nodes = &symtab_terminator; + + first_analyzed = NULL; + first_analyzed_var = NULL; +} + /* Creates a wrapper from cgraph_node to TARGET node. Thunk is used for this kind of wrapper method. */ diff --git a/gcc/diagnostic.c b/gcc/diagnostic.c index 881da0b8045..642cbe38b9a 100644 --- a/gcc/diagnostic.c +++ b/gcc/diagnostic.c @@ -177,6 +177,15 @@ diagnostic_finish (diagnostic_context *context) } diagnostic_file_cache_fini (); + + XDELETEVEC (context->classify_diagnostic); + context->classify_diagnostic = NULL; + + /* diagnostic_initialize allocates context->printer using XNEW + and placement-new. */ + context->printer->~pretty_printer (); + XDELETE (context->printer); + context->printer = NULL; } /* Initialize DIAGNOSTIC, where the message MSG has already been @@ -342,7 +351,7 @@ diagnostic_show_locus (diagnostic_context * context, static const char * const bt_stop[] = { "main", - "toplev_main", + "toplev::main", "execute_one_pass", "compile_file", }; diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 8c651766f0b..a87f9c0997e 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -24619,4 +24619,90 @@ dwarf2out_finish (const char *filename) output_indirect_strings (); } +/* Reset all state within dwarf2out.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +dwarf2out_c_finalize (void) +{ + last_var_location_insn = NULL; + cached_next_real_insn = NULL; + used_rtx_array = NULL; + incomplete_types = NULL; + decl_scope_table = NULL; + debug_info_section = NULL; + debug_skeleton_info_section = NULL; + debug_abbrev_section = NULL; + debug_skeleton_abbrev_section = NULL; + debug_aranges_section = NULL; + debug_addr_section = NULL; + debug_macinfo_section = NULL; + debug_line_section = NULL; + debug_skeleton_line_section = NULL; + debug_loc_section = NULL; + debug_pubnames_section = NULL; + debug_pubtypes_section = NULL; + debug_str_section = NULL; + debug_str_dwo_section = NULL; + debug_str_offsets_section = NULL; + debug_ranges_section = NULL; + debug_frame_section = NULL; + fde_vec = NULL; + debug_str_hash = NULL; + skeleton_debug_str_hash = NULL; + dw2_string_counter = 0; + have_multiple_function_sections = false; + text_section_used = false; + cold_text_section_used = false; + cold_text_section = NULL; + current_unit_personality = NULL; + + deferred_locations_list = NULL; + + next_die_offset = 0; + single_comp_unit_die = NULL; + comdat_type_list = NULL; + limbo_die_list = NULL; + deferred_asm_name = NULL; + file_table = NULL; + decl_die_table = NULL; + common_block_die_table = NULL; + decl_loc_table = NULL; + call_arg_locations = NULL; + call_arg_loc_last = NULL; + call_site_count = -1; + tail_call_site_count = -1; + //block_map = NULL; + cached_dw_loc_list_table = NULL; + abbrev_die_table = NULL; + abbrev_die_table_allocated = 0; + abbrev_die_table_in_use = 0; + line_info_label_num = 0; + cur_line_info_table = NULL; + text_section_line_info = NULL; + cold_text_section_line_info = NULL; + separate_line_info = NULL; + info_section_emitted = false; + pubname_table = NULL; + pubtype_table = NULL; + macinfo_table = NULL; + ranges_table = NULL; + ranges_table_allocated = 0; + ranges_table_in_use = 0; + ranges_by_label = 0; + ranges_by_label_allocated = 0; + ranges_by_label_in_use = 0; + have_location_lists = false; + loclabel_num = 0; + poc_label_num = 0; + last_emitted_file = NULL; + label_num = 0; + file_table_last_lookup = NULL; + tmpl_value_parm_die_table = NULL; + generic_type_instances = NULL; + frame_pointer_fb_offset = 0; + frame_pointer_fb_offset_valid = false; + base_types.release (); +} + #include "gt-dwarf2out.h" diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 7843e0a7eac..c30d81f0d6e 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -277,4 +277,6 @@ struct array_descr_info } dimen[10]; }; +void dwarf2out_c_finalize (void); + #endif /* GCC_DWARF2OUT_H */ diff --git a/gcc/gcse.c b/gcc/gcse.c index b6e3cf801b1..9c62f8b3bb1 100644 --- a/gcc/gcse.c +++ b/gcc/gcse.c @@ -4293,4 +4293,13 @@ make_pass_rtl_hoist (gcc::context *ctxt) return new pass_rtl_hoist (ctxt); } +/* Reset all state within gcse.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +gcse_c_finalize (void) +{ + test_insn = NULL; +} + #include "gt-gcse.h" diff --git a/gcc/gcse.h b/gcc/gcse.h index 1b8c1c65a2b..8e6820f79fe 100644 --- a/gcc/gcse.h +++ b/gcc/gcse.h @@ -39,4 +39,6 @@ extern struct target_gcse *this_target_gcse; #define this_target_gcse (&default_target_gcse) #endif +void gcse_c_finalize (void); + #endif diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 85b1ce9f284..2236a3a7d2f 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -1697,8 +1697,13 @@ compute_inverse (unsigned order) void init_ggc (void) { + static bool init_p = false; unsigned order; + if (init_p) + return; + init_p = true; + G.pagesize = getpagesize (); G.lg_pagesize = exact_log2 (G.pagesize); diff --git a/gcc/input.c b/gcc/input.c index 7a88e2e29ac..8d6356a014d 100644 --- a/gcc/input.c +++ b/gcc/input.c @@ -105,7 +105,7 @@ struct fcache /* Current position in real source file. */ -location_t input_location; +location_t input_location = UNKNOWN_LOCATION; struct line_maps *line_table; diff --git a/gcc/ipa-cp.c b/gcc/ipa-cp.c index a3be16f8bf4..a6269755036 100644 --- a/gcc/ipa-cp.c +++ b/gcc/ipa-cp.c @@ -3827,3 +3827,15 @@ make_pass_ipa_cp (gcc::context *ctxt) { return new pass_ipa_cp (ctxt); } + +/* Reset all state within ipa-cp.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +ipa_cp_c_finalize (void) +{ + max_count = 0; + overall_size = 0; + max_new_size = 0; + values_topo = NULL; +} diff --git a/gcc/ipa-prop.h b/gcc/ipa-prop.h index 7a06af9958b..d2f0c675846 100644 --- a/gcc/ipa-prop.h +++ b/gcc/ipa-prop.h @@ -732,4 +732,7 @@ ipa_parm_adjustment *ipa_get_adjustment_candidate (tree **, bool *, tree build_ref_for_offset (location_t, tree, HOST_WIDE_INT, tree, gimple_stmt_iterator *, bool); +/* In ipa-cp.c */ +void ipa_cp_c_finalize (void); + #endif /* IPA_PROP_H */ diff --git a/gcc/ipa-pure-const.c b/gcc/ipa-pure-const.c index b5ded3e73ed..c221cd0a3ba 100644 --- a/gcc/ipa-pure-const.c +++ b/gcc/ipa-pure-const.c @@ -115,10 +115,45 @@ typedef struct funct_state_d * funct_state; static vec funct_state_vec; -/* Holders of ipa cgraph hooks: */ -static struct cgraph_node_hook_list *function_insertion_hook_holder; -static struct cgraph_2node_hook_list *node_duplication_hook_holder; -static struct cgraph_node_hook_list *node_removal_hook_holder; +static bool gate_pure_const (void); + +namespace { + +const pass_data pass_data_ipa_pure_const = +{ + IPA_PASS, /* type */ + "pure-const", /* name */ + OPTGROUP_NONE, /* optinfo_flags */ + TV_IPA_PURE_CONST, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + 0, /* todo_flags_finish */ +}; + +class pass_ipa_pure_const : public ipa_opt_pass_d +{ +public: + pass_ipa_pure_const(gcc::context *ctxt); + + /* opt_pass methods: */ + bool gate (function *) { return gate_pure_const (); } + unsigned int execute (function *fun); + + void register_hooks (void); + +private: + bool init_p; + + /* Holders of ipa cgraph hooks: */ + struct cgraph_node_hook_list *function_insertion_hook_holder; + struct cgraph_2node_hook_list *node_duplication_hook_holder; + struct cgraph_node_hook_list *node_removal_hook_holder; + +}; // class pass_ipa_pure_const + +} // anon namespace /* Try to guess if function body will always be visible to compiler when compiling the call and whether compiler will be able @@ -881,11 +916,10 @@ remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED) } -static void +void +pass_ipa_pure_const:: register_hooks (void) { - static bool init_p = false; - if (init_p) return; @@ -908,7 +942,8 @@ pure_const_generate_summary (void) { struct cgraph_node *node; - register_hooks (); + pass_ipa_pure_const *pass = static_cast (current_pass); + pass->register_hooks (); /* Process all of the functions. @@ -989,7 +1024,9 @@ pure_const_read_summary (void) struct lto_file_decl_data *file_data; unsigned int j = 0; - register_hooks (); + pass_ipa_pure_const *pass = static_cast (current_pass); + pass->register_hooks (); + while ((file_data = file_data_vec[j++])) { const char *data; @@ -1470,8 +1507,9 @@ propagate_nothrow (void) /* Produce the global information by preforming a transitive closure on the local information that was produced by generate_summary. */ -static unsigned int -propagate (void) +unsigned int +pass_ipa_pure_const:: +execute (function *) { struct cgraph_node *node; @@ -1500,44 +1538,23 @@ gate_pure_const (void) && !seen_error ()); } -namespace { - -const pass_data pass_data_ipa_pure_const = +pass_ipa_pure_const::pass_ipa_pure_const(gcc::context *ctxt) + : ipa_opt_pass_d(pass_data_ipa_pure_const, ctxt, + pure_const_generate_summary, /* generate_summary */ + pure_const_write_summary, /* write_summary */ + pure_const_read_summary, /* read_summary */ + NULL, /* write_optimization_summary */ + NULL, /* read_optimization_summary */ + NULL, /* stmt_fixup */ + 0, /* function_transform_todo_flags_start */ + NULL, /* function_transform */ + NULL), /* variable_transform */ + init_p(false), + function_insertion_hook_holder(NULL), + node_duplication_hook_holder(NULL), + node_removal_hook_holder(NULL) { - IPA_PASS, /* type */ - "pure-const", /* name */ - OPTGROUP_NONE, /* optinfo_flags */ - TV_IPA_PURE_CONST, /* tv_id */ - 0, /* properties_required */ - 0, /* properties_provided */ - 0, /* properties_destroyed */ - 0, /* todo_flags_start */ - 0, /* todo_flags_finish */ -}; - -class pass_ipa_pure_const : public ipa_opt_pass_d -{ -public: - pass_ipa_pure_const (gcc::context *ctxt) - : ipa_opt_pass_d (pass_data_ipa_pure_const, ctxt, - pure_const_generate_summary, /* generate_summary */ - pure_const_write_summary, /* write_summary */ - pure_const_read_summary, /* read_summary */ - NULL, /* 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: */ - virtual bool gate (function *) { return gate_pure_const (); } - virtual unsigned int execute (function *) { return propagate (); } - -}; // class pass_ipa_pure_const - -} // anon namespace +} ipa_opt_pass_d * make_pass_ipa_pure_const (gcc::context *ctxt) diff --git a/gcc/ipa-reference.c b/gcc/ipa-reference.c index 9767eabaddf..f3af47ae832 100644 --- a/gcc/ipa-reference.c +++ b/gcc/ipa-reference.c @@ -399,17 +399,17 @@ propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x } } +static bool ipa_init_p = false; + /* The init routine for analyzing global static variable usage. See comments at top for description. */ static void ipa_init (void) { - static bool init_p = false; - - if (init_p) + if (ipa_init_p) return; - init_p = true; + ipa_init_p = true; if (dump_file) reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0); @@ -1173,3 +1173,12 @@ make_pass_ipa_reference (gcc::context *ctxt) { return new pass_ipa_reference (ctxt); } + +/* Reset all state within ipa-reference.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +ipa_reference_c_finalize (void) +{ + ipa_init_p = false; +} diff --git a/gcc/ipa-reference.h b/gcc/ipa-reference.h index c840024e4b4..3e7dc731980 100644 --- a/gcc/ipa-reference.h +++ b/gcc/ipa-reference.h @@ -26,6 +26,7 @@ along with GCC; see the file COPYING3. If not see /* In ipa-reference.c */ bitmap ipa_reference_get_not_read_global (struct cgraph_node *fn); bitmap ipa_reference_get_not_written_global (struct cgraph_node *fn); +void ipa_reference_c_finalize (void); #endif /* GCC_IPA_REFERENCE_H */ diff --git a/gcc/main.c b/gcc/main.c index 241d15144f2..4bba0415ab3 100644 --- a/gcc/main.c +++ b/gcc/main.c @@ -26,12 +26,14 @@ along with GCC; see the file COPYING3. If not see int main (int argc, char **argv); -/* We define main() to call toplev_main(), which is defined in toplev.c. +/* We define main() to call toplev::main(), which is defined in toplev.c. We do this in a separate file in order to allow the language front-end to define a different main(), if it so desires. */ int main (int argc, char **argv) { - return toplev_main (argc, argv); + toplev toplev (true); + + return toplev.main (argc, argv); } diff --git a/gcc/params.c b/gcc/params.c index 3ae5ccd5cbe..7aa96e2c8f3 100644 --- a/gcc/params.c +++ b/gcc/params.c @@ -69,6 +69,8 @@ add_params (const param_info params[], size_t n) void global_init_params (void) { + gcc_assert (!params_finished); + add_params (lang_independent_params, LAST_PARAM); targetm_common.option_default_params (); } @@ -82,6 +84,18 @@ finish_params (void) params_finished = true; } +/* Reset all state within params.c so that we can rerun the compiler + within the same process. For use by toplev::finalize. */ + +void +params_c_finalize (void) +{ + XDELETEVEC (compiler_params); + compiler_params = NULL; + num_compiler_params = 0; + params_finished = false; +} + /* Set the value of the parameter given by NUM to VALUE in PARAMS and PARAMS_SET. If EXPLICIT_P, this is being set by the user; otherwise it is being set implicitly by the compiler. */ diff --git a/gcc/params.h b/gcc/params.h index d488e32ebfe..4779e17da33 100644 --- a/gcc/params.h +++ b/gcc/params.h @@ -113,6 +113,10 @@ extern void global_init_params (void); set. */ extern void finish_params (void); +/* Reset all state in params.c */ + +extern void params_c_finalize (void); + /* Return the default value of parameter NUM. */ extern int default_param_value (compiler_param num); diff --git a/gcc/passes.c b/gcc/passes.c index 68de5d62d32..428c79792b7 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -1948,6 +1948,7 @@ execute_ipa_summary_passes (ipa_opt_pass_d *ipa_pass) if (pass->tv_id) timevar_push (pass->tv_id); + current_pass = pass; ipa_pass->generate_summary (); /* Stop timevar. */ @@ -2259,6 +2260,7 @@ ipa_write_summaries_2 (opt_pass *pass, struct lto_out_decl_state *state) pass_init_dump_file (pass); + current_pass = pass; ipa_pass->write_summary (); pass_fini_dump_file (pass); @@ -2377,6 +2379,7 @@ ipa_write_optimization_summaries_1 (opt_pass *pass, pass_init_dump_file (pass); + current_pass = pass; ipa_pass->write_optimization_summary (); pass_fini_dump_file (pass); @@ -2457,6 +2460,7 @@ ipa_read_summaries_1 (opt_pass *pass) pass_init_dump_file (pass); + current_pass = pass; ipa_pass->read_summary (); pass_fini_dump_file (pass); @@ -2507,6 +2511,7 @@ ipa_read_optimization_summaries_1 (opt_pass *pass) pass_init_dump_file (pass); + current_pass = pass; ipa_pass->read_optimization_summary (); pass_fini_dump_file (pass); @@ -2586,6 +2591,7 @@ execute_ipa_stmt_fixups (opt_pass *pass, if (pass->tv_id) timevar_push (pass->tv_id); + current_pass = pass; ipa_pass->stmt_fixup (node, stmts); /* Stop timevar. */ diff --git a/gcc/stringpool.c b/gcc/stringpool.c index c880cb1e678..330df6c1d35 100644 --- a/gcc/stringpool.c +++ b/gcc/stringpool.c @@ -61,6 +61,11 @@ stringpool_ggc_alloc (size_t x) void init_stringpool (void) { + /* Clean up if we're called more than once. + (We can't make this idempotent since identifiers contain state) */ + if (ident_hash) + ht_destroy (ident_hash); + /* Create with 16K (2^14) entries. */ ident_hash = ht_create (14); ident_hash->alloc_node = alloc_node; diff --git a/gcc/timevar.c b/gcc/timevar.c index c111e983cbd..0e56a23e23c 100644 --- a/gcc/timevar.c +++ b/gcc/timevar.c @@ -223,6 +223,9 @@ timevar_accumulate (struct timevar_time_def *timer, void timevar_init (void) { + if (timevar_enable) + return; + timevar_enable = true; /* Zero all elapsed times. */ diff --git a/gcc/toplev.c b/gcc/toplev.c index 7df9cc79004..a87ff9a2ff8 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -83,6 +83,10 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-color.h" #include "context.h" #include "pass_manager.h" +#include "dwarf2out.h" +#include "ipa-reference.h" +#include "ipa-prop.h" +#include "gcse.h" #include "optabs.h" #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) @@ -101,7 +105,7 @@ along with GCC; see the file COPYING3. If not see #include static void general_init (const char *); -static void do_compile (void); +static void do_compile (); static void process_options (void); static void backend_init (void); static int lang_dependent_init (const char *); @@ -1161,6 +1165,7 @@ general_init (const char *argv0) table. */ init_ggc (); init_stringpool (); + input_location = UNKNOWN_LOCATION; line_table = ggc_alloc (); linemap_init (line_table, BUILTINS_LOCATION); line_table->reallocator = realloc_for_line_map; @@ -1708,16 +1713,16 @@ lang_dependent_init_target (void) /* Perform initializations that are lang-dependent or target-dependent. but matters only for late optimizations and RTL generation. */ +static int rtl_initialized; + void initialize_rtl (void) { - static int initialized_once; - /* Initialization done just once per compilation, but delayed till code generation. */ - if (!initialized_once) + if (!rtl_initialized) ira_init_once (); - initialized_once = true; + rtl_initialized = true; /* Target specific RTL backend initialization. */ if (!this_target_rtl->target_specific_initialized) @@ -1922,14 +1927,8 @@ standard_type_bitsize (int bitsize) /* Initialize the compiler, and compile the input file. */ static void -do_compile (void) +do_compile () { - /* Initialize timing first. The C front ends read the main file in - the post_options hook, and C++ does file timings. */ - if (time_report || !quiet_flag || flag_detailed_statistics) - timevar_init (); - timevar_start (TV_TOTAL); - process_options (); /* Don't do any more if an error has already occurred. */ @@ -1987,12 +1986,30 @@ do_compile (void) timevar_stop (TV_PHASE_FINALIZE); } +} - /* Stop timing and print the times. */ +toplev::toplev (bool use_TV_TOTAL) + : m_use_TV_TOTAL (use_TV_TOTAL) +{ + if (!m_use_TV_TOTAL) + start_timevars (); +} + +toplev::~toplev () +{ timevar_stop (TV_TOTAL); timevar_print (stderr); } +void +toplev::start_timevars () +{ + if (time_report || !quiet_flag || flag_detailed_statistics) + timevar_init (); + + timevar_start (TV_TOTAL); +} + /* Entry point of cc1, cc1plus, jc1, f771, etc. Exit code is FATAL_EXIT_CODE if can't open files or if there were any errors, or SUCCESS_EXIT_CODE if compilation succeeded. @@ -2000,7 +2017,7 @@ do_compile (void) It is not safe to call this function more than once. */ int -toplev_main (int argc, char **argv) +toplev::main (int argc, char **argv) { /* Parsing and gimplification sometimes need quite large stack. Increase stack size limits if possible. */ @@ -2050,7 +2067,11 @@ toplev_main (int argc, char **argv) /* Exit early if we can (e.g. -help). */ if (!exit_after_options) - do_compile (); + { + if (m_use_TV_TOTAL) + start_timevars (); + do_compile (); + } if (warningcount || errorcount || werrorcount) print_ignored_options (); @@ -2068,3 +2089,20 @@ toplev_main (int argc, char **argv) return (SUCCESS_EXIT_CODE); } + +/* For those that want to, this function aims to clean up enough state that + you can call toplev::main again. */ +void +toplev::finalize (void) +{ + rtl_initialized = false; + this_target_rtl->target_specific_initialized = false; + + cgraph_c_finalize (); + cgraphunit_c_finalize (); + dwarf2out_c_finalize (); + gcse_c_finalize (); + ipa_cp_c_finalize (); + ipa_reference_c_finalize (); + params_c_finalize (); +} diff --git a/gcc/toplev.h b/gcc/toplev.h index 1b5457823b8..b845843307a 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -24,7 +24,24 @@ along with GCC; see the file COPYING3. If not see extern struct cl_decoded_option *save_decoded_options; extern unsigned int save_decoded_options_count; -extern int toplev_main (int, char **); +/* Invoking the compiler. */ +class toplev +{ +public: + toplev (bool use_TV_TOTAL); + ~toplev (); + + int main (int argc, char **argv); + + void finalize (); + +private: + + void start_timevars (); + + bool m_use_TV_TOTAL; +}; + extern void rest_of_decl_compilation (tree, int, int); extern void rest_of_type_compilation (tree, int); extern void init_optimization_passes (void); -- 2.30.2