+2014-10-21 David Malcolm <dmalcolm@redhat.com>
+
+ * 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 <amacleod@redhat.com>
* loop-doloop.c: Include loop-unroll.h.
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"
}
/* In cgraph.c */
+void cgraph_c_finalize (void);
void release_function_body (tree);
cgraph_indirect_call_info *cgraph_allocate_init_indirect_info (void);
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);
/* 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<void *> reachable_call_targets;
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. */
}
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
static const char * const bt_stop[] =
{
"main",
- "toplev_main",
+ "toplev::main",
"execute_one_pass",
"compile_file",
};
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"
} dimen[10];
};
+void dwarf2out_c_finalize (void);
+
#endif /* GCC_DWARF2OUT_H */
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"
#define this_target_gcse (&default_target_gcse)
#endif
+void gcse_c_finalize (void);
+
#endif
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);
/* Current position in real source file. */
-location_t input_location;
+location_t input_location = UNKNOWN_LOCATION;
struct line_maps *line_table;
{
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;
+}
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 */
static vec<funct_state> 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
}
\f
-static void
+void
+pass_ipa_pure_const::
register_hooks (void)
{
- static bool init_p = false;
-
if (init_p)
return;
{
struct cgraph_node *node;
- register_hooks ();
+ pass_ipa_pure_const *pass = static_cast <pass_ipa_pure_const *> (current_pass);
+ pass->register_hooks ();
/* Process all of the functions.
struct lto_file_decl_data *file_data;
unsigned int j = 0;
- register_hooks ();
+ pass_ipa_pure_const *pass = static_cast <pass_ipa_pure_const *> (current_pass);
+ pass->register_hooks ();
+
while ((file_data = file_data_vec[j++]))
{
const char *data;
/* 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;
&& !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)
}
}
+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);
{
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;
+}
/* 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 */
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);
}
void
global_init_params (void)
{
+ gcc_assert (!params_finished);
+
add_params (lang_independent_params, LAST_PARAM);
targetm_common.option_default_params ();
}
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. */
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);
if (pass->tv_id)
timevar_push (pass->tv_id);
+ current_pass = pass;
ipa_pass->generate_summary ();
/* Stop timevar. */
pass_init_dump_file (pass);
+ current_pass = pass;
ipa_pass->write_summary ();
pass_fini_dump_file (pass);
pass_init_dump_file (pass);
+ current_pass = pass;
ipa_pass->write_optimization_summary ();
pass_fini_dump_file (pass);
pass_init_dump_file (pass);
+ current_pass = pass;
ipa_pass->read_summary ();
pass_fini_dump_file (pass);
pass_init_dump_file (pass);
+ current_pass = pass;
ipa_pass->read_optimization_summary ();
pass_fini_dump_file (pass);
if (pass->tv_id)
timevar_push (pass->tv_id);
+ current_pass = pass;
ipa_pass->stmt_fixup (node, stmts);
/* Stop timevar. */
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;
void
timevar_init (void)
{
+ if (timevar_enable)
+ return;
+
timevar_enable = true;
/* Zero all elapsed times. */
#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)
#include <new>
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 *);
table. */
init_ggc ();
init_stringpool ();
+ input_location = UNKNOWN_LOCATION;
line_table = ggc_alloc<line_maps> ();
linemap_init (line_table, BUILTINS_LOCATION);
line_table->reallocator = realloc_for_line_map;
/* 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)
/* 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. */
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.
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. */
/* 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 ();
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 ();
+}
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);