diff --git a/gcc/ChangeLog b/gcc/ChangeLog index eece522af1a..ffa880bac65 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,75 @@ +2013-08-05 David Malcolm + + Handwritten part of conversion of passes to C++ classes. + + * Makefile.in (PASS_MANAGER_H): Add dep on pass-instances.def. + (toplev.o): Add dep on PASS_MANAGER_H. + * cgraphunit.c (cgraph_process_new_functions): Rework invocation + of early local pases to reflect this moving from a global to a + member of gcc::pass_manager. + (cgraph_add_new_function): Likewise. + * lto-cgraph.c (lto_output_node): Update for conversion of + struct ipa_opt_pass_d to a C++ subclass of opt_pass. + * passes.c (opt_pass::clone): New. + (opt_pass::gate): New. + (opt_pass::execute): New. + (opt_pass::opt_pass): New. + (pass_manager::execute_early_local_passes): New. + (pass_manager::execute_pass_mode_switching): new. + (finish_optimization_passes): Convert to... + (pass_manager::finish_optimization_passes): ...this. + (finish_optimization_passes): Update for conversion of passes to + C++ classes. + (register_dump_files_1): Use has_gate since we cannot portably + check a vtable entry against NULL. + (dump_one_pass): Likewise. + (ipa_write_summaries_2): Likewise. + (ipa_write_optimization_summaries_1): Likewise. + (ipa_read_summaries_1): Likewise. + (ipa_read_optimization_summaries_1): Likewise. + (execute_ipa_stmt_fixups): Likewise. + (pass_manager::pass_manager): Rewrite pass-creation, invoking + pass-creation functions rather than wiring up globals, and + storing the results in fields of pass_manager generated using + pass-instances.def. + (pass_manager::dump_profile_report): Update for conversion of + passes to C++ classes. + (pass_manager::execute_ipa_summary_passes): Likewise. + (execute_one_ipa_transform_pass): Likewise. + (execute_one_pass): Use has_gate and has_execute since we cannot + portably check a vtable entry against NULL. + * pass_manager.h (pass_manager::finish_optimization_passes): New. + (pass_manager): Use pass-instances.def to add fields for the + various pass instances. + * toplev.c (finalize): Update for move of + finish_optimization_passes to a method of gcc::pass_manager. + * toplev.h (finish_optimization_passes): Move to method of class + pass_manager. + * tree-pass.h (struct pass_data): New. + (opt_pass): Convert to C++ class, make it a subclass of + pass_data. + (opt_pass::gate): Convert to virtual function. + (opt_pass::~opt_pass): New. + (opt_pass::clone): New. + (opt_pass::execute): Convert to virtual function. + (opt_pass::opt_pass): New. + (opt_pass::ctxt_): new. + (gimple_opt_pass): Convert to subclass of opt_pass. + (gimple_opt_pass::gimple_opt_pass): New. + (rtl_opt_pass): Convert to subclass of opt_pass. + (rtl_opt_pass::rtl_opt_pass): New. + (ipa_opt_pass_d): Convert to subclass of opt_pass. + (ipa_opt_pass_d::ipa_opt_pass_d): New. + (simple_ipa_opt_pass): Convert to subclass of opt_pass. + (simple_ipa_opt_pass::simple_ipa_opt_pass): New. + * config/i386/i386.c (rest_of_handle_insert_vzeroupper): Rework + invocation of pass_mode_switching to reflect this moving from a + global to a member of gcc::pass_manager. + (ix86_option_override): Rework how pass_insert_vzeroupper is + added to the pass_manager to reflect autogenerated changes. + * config/i386/t-i386 (i386.o) Add deps on CONTEXT_H and + PASS_MANAGER_H. + 2013-08-05 Richard Earnshaw PR rtl-optimization/57708 diff --git a/gcc/Makefile.in b/gcc/Makefile.in index 40ad19da085..afce540eed9 100644 --- a/gcc/Makefile.in +++ b/gcc/Makefile.in @@ -987,7 +987,7 @@ PLUGIN_VERSION_H = plugin-version.h configargs.h LIBFUNCS_H = libfuncs.h $(HASHTAB_H) GRAPHITE_HTAB_H = graphite-htab.h graphite-clast-to-gimple.h $(HASH_TABLE_H) CONTEXT_H = context.h -PASS_MANAGER_H = pass_manager.h +PASS_MANAGER_H = pass_manager.h pass-instances.def # # Now figure out from those variables how to compile and link. @@ -2733,7 +2733,7 @@ toplev.o : toplev.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) \ $(OPTS_H) params.def tree-mudflap.h $(TREE_PASS_H) $(GIMPLE_H) \ tree-ssa-alias.h $(PLUGIN_H) realmpfr.h tree-diagnostic.h \ $(TREE_PRETTY_PRINT_H) opts-diagnostic.h $(COMMON_TARGET_H) \ - tsan.h diagnostic-color.h $(CONTEXT_H) + tsan.h diagnostic-color.h $(CONTEXT_H) $(PASS_MANAGER_H) hwint.o : hwint.c $(CONFIG_H) $(SYSTEM_H) $(DIAGNOSTIC_CORE_H) diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c index e308b524850..ad91117d6b1 100644 --- a/gcc/cgraphunit.c +++ b/gcc/cgraphunit.c @@ -325,7 +325,7 @@ cgraph_process_new_functions (void) push_cfun (DECL_STRUCT_FUNCTION (fndecl)); if (cgraph_state == CGRAPH_STATE_IPA_SSA && !gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) - execute_pass_list (pass_early_local_passes.pass.sub); + g->get_passes ()->execute_early_local_passes (); else if (inline_summary_vec != NULL) compute_inline_parameters (node, true); free_dominance_info (CDI_POST_DOMINATORS); @@ -509,7 +509,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); execute_pass_list (passes->all_lowering_passes); - execute_pass_list (pass_early_local_passes.pass.sub); + passes->execute_early_local_passes (); bitmap_obstack_release (NULL); pop_cfun (); @@ -534,7 +534,7 @@ cgraph_add_new_function (tree fndecl, bool lowered) gimple_register_cfg_hooks (); bitmap_obstack_initialize (NULL); if (!gimple_in_ssa_p (DECL_STRUCT_FUNCTION (fndecl))) - execute_pass_list (pass_early_local_passes.pass.sub); + g->get_passes ()->execute_early_local_passes (); bitmap_obstack_release (NULL); pop_cfun (); expand_function (node); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index df79eac71e4..cce3c9c80e8 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -62,6 +62,8 @@ along with GCC; see the file COPYING3. If not see #include "dumpfile.h" #include "tree-pass.h" #include "tree-flow.h" +#include "context.h" +#include "pass_manager.h" static rtx legitimize_dllimport_symbol (rtx, bool); static rtx legitimize_pe_coff_extern_decl (rtx, bool); @@ -2596,7 +2598,7 @@ rest_of_handle_insert_vzeroupper (void) ix86_optimize_mode_switching[AVX_U128] = 1; /* Call optimize_mode_switching. */ - pass_mode_switching.pass.execute (); + g->get_passes ()->execute_pass_mode_switching (); return 0; } @@ -4028,8 +4030,9 @@ ix86_option_override_internal (bool main_args_p) static void ix86_option_override (void) { + opt_pass *pass_insert_vzeroupper = make_pass_insert_vzeroupper (g); static struct register_pass_info insert_vzeroupper_info - = { &pass_insert_vzeroupper.pass, "reload", + = { pass_insert_vzeroupper, "reload", 1, PASS_POS_INSERT_AFTER }; diff --git a/gcc/config/i386/t-i386 b/gcc/config/i386/t-i386 index 3a77e14f5ca..f10d570c867 100644 --- a/gcc/config/i386/t-i386 +++ b/gcc/config/i386/t-i386 @@ -24,7 +24,7 @@ i386.o: $(CONFIG_H) $(SYSTEM_H) coretypes.h dumpfile.h $(TM_H) \ $(GGC_H) $(TARGET_H) $(TARGET_DEF_H) langhooks.h $(CGRAPH_H) \ $(TREE_GIMPLE_H) $(DWARF2_H) $(DF_H) tm-constrs.h $(PARAMS_H) \ i386-builtin-types.inc debug.h dwarf2out.h sbitmap.h $(FIBHEAP_H) \ - $(OPTS_H) $(DIAGNOSTIC_H) $(COMMON_TARGET_H) + $(OPTS_H) $(DIAGNOSTIC_H) $(COMMON_TARGET_H) $(CONTEXT_H) $(PIPELINE_H) i386-c.o: $(srcdir)/config/i386/i386-c.c \ $(srcdir)/config/i386/i386-protos.h $(CONFIG_H) $(SYSTEM_H) coretypes.h \ diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c index c3c393f6ec9..0dde03a7b78 100644 --- a/gcc/lto-cgraph.c +++ b/gcc/lto-cgraph.c @@ -438,7 +438,7 @@ lto_output_node (struct lto_simple_output_block *ob, struct cgraph_node *node, streamer_write_hwi_stream (ob->main_stream, node->ipa_transforms_to_apply.length ()); FOR_EACH_VEC_ELT (node->ipa_transforms_to_apply, i, pass) - streamer_write_hwi_stream (ob->main_stream, pass->pass.static_pass_number); + streamer_write_hwi_stream (ob->main_stream, pass->static_pass_number); if (tag == LTO_symtab_analyzed_node) { diff --git a/gcc/pass_manager.h b/gcc/pass_manager.h index f66cd80408f..ea078a5eb66 100644 --- a/gcc/pass_manager.h +++ b/gcc/pass_manager.h @@ -58,6 +58,12 @@ public: void dump_profile_report () const; + void finish_optimization_passes (); + + /* Access to specific passes, so that the majority can be private. */ + void execute_early_local_passes (); + unsigned int execute_pass_mode_switching (); + public: /* The root of the compilation pass tree, once constructed. */ opt_pass *all_passes; @@ -81,6 +87,37 @@ private: private: context *ctxt_; + /* References to all of the individual passes. + These fields are generated via macro expansion. + + For example: + NEXT_PASS (pass_build_cfg, 1); + within pass-instances.def means that there is a field: + opt_pass *pass_build_cfg_1; + + Similarly, the various: + NEXT_PASS (pass_copy_prop, 1); + ... + NEXT_PASS (pass_copy_prop, 8); + in pass-instances.def lead to fields: + opt_pass *pass_copy_prop_1; + ... + opt_pass *pass_copy_prop_8; */ + +#define INSERT_PASSES_AFTER(PASS) +#define PUSH_INSERT_PASSES_WITHIN(PASS) +#define POP_INSERT_PASSES() +#define NEXT_PASS(PASS, NUM) opt_pass *PASS ## _ ## NUM +#define TERMINATE_PASS_LIST() + +#include "pass-instances.def" + +#undef INSERT_PASSES_AFTER +#undef PUSH_INSERT_PASSES_WITHIN +#undef POP_INSERT_PASSES +#undef NEXT_PASS +#undef TERMINATE_PASS_LIST + }; // class pass_manager } // namespace gcc diff --git a/gcc/passes.c b/gcc/passes.c index a43a58809af..fcbd630dd88 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -82,6 +82,54 @@ struct opt_pass *current_pass; static void register_pass_name (struct opt_pass *, const char *); +/* Most passes are single-instance (within their context) and thus don't + need to implement cloning, but passes that support multiple instances + *must* provide their own implementation of the clone method. + + Handle this by providing a default implemenation, but make it a fatal + error to call it. */ + +opt_pass * +opt_pass::clone () +{ + internal_error ("pass %s does not support cloning", name); +} + +bool +opt_pass::gate () +{ + return true; +} + +unsigned int +opt_pass::execute () +{ + return 0; +} + +opt_pass::opt_pass(const pass_data &data, context *ctxt) + : pass_data(data), + sub(NULL), + next(NULL), + static_pass_number(0), + ctxt_(ctxt) +{ +} + + +void +pass_manager::execute_early_local_passes () +{ + execute_pass_list (pass_early_local_passes_1->sub); +} + +unsigned int +pass_manager::execute_pass_mode_switching () +{ + return pass_mode_switching_1->execute (); +} + + /* Call from anywhere to find out what pass this is. Useful for printing out debugging information deep inside an service routine. */ @@ -224,6 +272,7 @@ rest_of_type_compilation (tree type, int toplev) void +pass_manager:: finish_optimization_passes (void) { int i; @@ -233,16 +282,16 @@ finish_optimization_passes (void) timevar_push (TV_DUMP); if (profile_arc_flag || flag_test_coverage || flag_branch_probabilities) { - dump_start (pass_profile.pass.static_pass_number, NULL); + dump_start (pass_profile_1->static_pass_number, NULL); end_branch_prob (); - dump_finish (pass_profile.pass.static_pass_number); + dump_finish (pass_profile_1->static_pass_number); } if (optimize > 0) { - dump_start (pass_profile.pass.static_pass_number, NULL); + dump_start (pass_profile_1->static_pass_number, NULL); print_combine_total_stats (); - dump_finish (pass_profile.pass.static_pass_number); + dump_finish (pass_profile_1->static_pass_number); } /* Do whatever is necessary to finish printing the graphs. */ @@ -550,7 +599,7 @@ register_dump_files_1 (struct opt_pass *pass, int properties) /* If we have a gate, combine the properties that we could have with and without the pass being examined. */ - if (pass->gate) + if (pass->has_gate) properties &= new_properties; else properties = new_properties; @@ -679,7 +728,7 @@ dump_one_pass (struct opt_pass *pass, int pass_indent) const char *pn; bool is_on, is_really_on; - is_on = (pass->gate == NULL) ? true : pass->gate(); + is_on = pass->has_gate ? pass->gate() : true; is_really_on = override_gate_status (pass, current_function_decl, is_on); if (pass->static_pass_number <= 0) @@ -1310,12 +1359,23 @@ pass_manager::pass_manager (context *ctxt) #define PUSH_INSERT_PASSES_WITHIN(PASS) \ { \ - struct opt_pass **p = &(PASS).pass.sub; + struct opt_pass **p = &(PASS ## _1)->sub; #define POP_INSERT_PASSES() \ } -#define NEXT_PASS(PASS, NUM) (p = next_pass_1 (p, &((PASS).pass))) +#define NEXT_PASS(PASS, NUM) \ + do { \ + gcc_assert (NULL == PASS ## _ ## NUM); \ + if ((NUM) == 1) \ + PASS ## _1 = make_##PASS (ctxt_); \ + else \ + { \ + gcc_assert (PASS ## _1); \ + PASS ## _ ## NUM = PASS ## _1->clone (); \ + } \ + p = next_pass_1 (p, PASS ## _ ## NUM); \ + } while (0) #define TERMINATE_PASS_LIST() \ *p = NULL; @@ -1541,7 +1601,7 @@ pass_manager::dump_profile_report () const fprintf (stderr, " "); /* Size/time units change across gimple and RTL. */ - if (i == pass_expand.pass.static_pass_number) + if (i == pass_expand_1->static_pass_number) fprintf (stderr, "|----------"); else { @@ -1778,11 +1838,11 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass) { while (ipa_pass) { - struct opt_pass *pass = &ipa_pass->pass; + struct opt_pass *pass = ipa_pass; /* Execute all of the IPA_PASSes in the list. */ - if (ipa_pass->pass.type == IPA_PASS - && (!pass->gate || pass->gate ()) + if (ipa_pass->type == IPA_PASS + && ((!pass->has_gate) || pass->gate ()) && ipa_pass->generate_summary) { pass_init_dump_file (pass); @@ -1799,7 +1859,7 @@ execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass) pass_fini_dump_file (pass); } - ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->pass.next; + ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->next; } } @@ -1809,7 +1869,7 @@ static void execute_one_ipa_transform_pass (struct cgraph_node *node, struct ipa_opt_pass_d *ipa_pass) { - struct opt_pass *pass = &ipa_pass->pass; + struct opt_pass *pass = ipa_pass; unsigned int todo_after = 0; current_pass = pass; @@ -1933,7 +1993,7 @@ execute_one_pass (struct opt_pass *pass) /* Check whether gate check should be avoided. User controls the value of the gate through the parameter "gate_status". */ - gate_status = (pass->gate == NULL) ? true : pass->gate(); + gate_status = pass->has_gate ? pass->gate() : true; gate_status = override_gate_status (pass, current_function_decl, gate_status); /* Override gate with plugin. */ @@ -1990,7 +2050,7 @@ execute_one_pass (struct opt_pass *pass) timevar_push (pass->tv_id); /* Do it! */ - if (pass->execute) + if (pass->has_execute) { todo_after = pass->execute (); do_per_function (clear_last_verified, NULL); @@ -2066,7 +2126,7 @@ ipa_write_summaries_2 (struct opt_pass *pass, struct lto_out_decl_state *state) gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); if (pass->type == IPA_PASS && ipa_pass->write_summary - && (!pass->gate || pass->gate ())) + && ((!pass->has_gate) || pass->gate ())) { /* If a timevar is present, start it. */ if (pass->tv_id) @@ -2182,7 +2242,7 @@ ipa_write_optimization_summaries_1 (struct opt_pass *pass, struct lto_out_decl_s gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); if (pass->type == IPA_PASS && ipa_pass->write_optimization_summary - && (!pass->gate || pass->gate ())) + && ((!pass->has_gate) || pass->gate ())) { /* If a timevar is present, start it. */ if (pass->tv_id) @@ -2259,7 +2319,7 @@ ipa_read_summaries_1 (struct opt_pass *pass) gcc_assert (!cfun); gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); - if (pass->gate == NULL || pass->gate ()) + if ((!pass->has_gate) || pass->gate ()) { if (pass->type == IPA_PASS && ipa_pass->read_summary) { @@ -2310,7 +2370,7 @@ ipa_read_optimization_summaries_1 (struct opt_pass *pass) gcc_assert (!cfun); gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS); - if (pass->gate == NULL || pass->gate ()) + if ((!pass->has_gate) || pass->gate ()) { if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary) { @@ -2388,7 +2448,7 @@ execute_ipa_stmt_fixups (struct opt_pass *pass, { /* Execute all of the IPA_PASSes in the list. */ if (pass->type == IPA_PASS - && (!pass->gate || pass->gate ())) + && ((!pass->has_gate) || pass->gate ())) { struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *) pass; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index f356d55c990..387006e2e3d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2013-08-05 David Malcolm + + * g++.dg/plugin/dumb_plugin.c (plugin_init): Rework how the pass + is created and added to the pass_manager to reflect + autogenerated changes. + * g++.dg/plugin/selfassign.c (plugin_init): Likewise. + * gcc.dg/plugin/one_time_plugin.c (plugin_init): Likewise. + * gcc.dg/plugin/selfassign.c (plugin_init): Likewise. + 2013-08-04 Ed Smith-Rowland <3dw4rd@verizon.net> PR c++/58072 diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c index 0f15140068c..ab69c14294e 100644 --- a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c +++ b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c @@ -11,6 +11,7 @@ #include "intl.h" #include "toplev.h" #include "diagnostic.h" +#include "context.h" int plugin_is_GPL_compatible; @@ -124,7 +125,7 @@ plugin_init (struct plugin_name_args *plugin_info, return 1; } - pass_info.pass = &pass_dumb_plugin_example.pass; + pass_info.pass = make_pass_dumb_plugin_example (g); pass_info.reference_pass_name = ref_pass_name; pass_info.ref_pass_instance_number = ref_instance_number; pass_info.pos_op = PASS_POS_INSERT_AFTER; diff --git a/gcc/testsuite/g++.dg/plugin/selfassign.c b/gcc/testsuite/g++.dg/plugin/selfassign.c index 37a0a979cb7..3e0b38ec341 100644 --- a/gcc/testsuite/g++.dg/plugin/selfassign.c +++ b/gcc/testsuite/g++.dg/plugin/selfassign.c @@ -15,6 +15,7 @@ #include "intl.h" #include "plugin-version.h" #include "diagnostic.h" +#include "context.h" int plugin_is_GPL_compatible; @@ -309,7 +310,7 @@ plugin_init (struct plugin_name_args *plugin_info, return 1; /* Self-assign detection should happen after SSA is constructed. */ - pass_info.pass = &pass_warn_self_assign.pass; + pass_info.pass = make_pass_warn_self_assign (g); pass_info.reference_pass_name = "ssa"; pass_info.ref_pass_instance_number = 1; pass_info.pos_op = PASS_POS_INSERT_AFTER; diff --git a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c index 45e6257c070..31dfe69b1fb 100644 --- a/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c +++ b/gcc/testsuite/gcc.dg/plugin/one_time_plugin.c @@ -8,6 +8,7 @@ #include "gimple.h" #include "tree-pass.h" #include "intl.h" +#include "context.h" int plugin_is_GPL_compatible; @@ -53,7 +54,7 @@ int plugin_init (struct plugin_name_args *plugin_info, { struct register_pass_info p; - p.pass = &one_pass.pass; + p.pass = make_one_pass (g); p.reference_pass_name = "cfg"; p.ref_pass_instance_number = 1; p.pos_op = PASS_POS_INSERT_AFTER; diff --git a/gcc/testsuite/gcc.dg/plugin/selfassign.c b/gcc/testsuite/gcc.dg/plugin/selfassign.c index 37a0a979cb7..3e0b38ec341 100644 --- a/gcc/testsuite/gcc.dg/plugin/selfassign.c +++ b/gcc/testsuite/gcc.dg/plugin/selfassign.c @@ -15,6 +15,7 @@ #include "intl.h" #include "plugin-version.h" #include "diagnostic.h" +#include "context.h" int plugin_is_GPL_compatible; @@ -309,7 +310,7 @@ plugin_init (struct plugin_name_args *plugin_info, return 1; /* Self-assign detection should happen after SSA is constructed. */ - pass_info.pass = &pass_warn_self_assign.pass; + pass_info.pass = make_pass_warn_self_assign (g); pass_info.reference_pass_name = "ssa"; pass_info.ref_pass_instance_number = 1; pass_info.pos_op = PASS_POS_INSERT_AFTER; diff --git a/gcc/toplev.c b/gcc/toplev.c index 9187529119d..53f53fd95df 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -76,6 +76,7 @@ along with GCC; see the file COPYING3. If not see #include "plugin.h" #include "diagnostic-color.h" #include "context.h" +#include "pass_manager.h" #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO) #include "dbxout.h" @@ -1818,7 +1819,7 @@ finalize (bool no_backend) { statistics_fini (); - finish_optimization_passes (); + g->get_passes ()->finish_optimization_passes (); ira_finish_once (); } diff --git a/gcc/toplev.h b/gcc/toplev.h index fff452c8ba6..84ffdb0e28b 100644 --- a/gcc/toplev.h +++ b/gcc/toplev.h @@ -28,7 +28,6 @@ extern int toplev_main (int, char **); extern void rest_of_decl_compilation (tree, int, int); extern void rest_of_type_compilation (tree, int); extern void init_optimization_passes (void); -extern void finish_optimization_passes (void); extern bool enable_rtl_dump_file (void); /* In except.c. Initialize exception handling. This is used by the Ada diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 16442ed4ed2..41f7d176c40 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -34,9 +34,8 @@ enum opt_pass_type IPA_PASS }; -/* Describe one pass; this is the common part shared across different pass - types. */ -struct opt_pass +/* Metadata for a pass, non-varying across all instances of a pass. */ +struct pass_data { /* Optimization pass type. */ enum opt_pass_type type; @@ -48,23 +47,13 @@ struct opt_pass /* The -fopt-info optimization group flags as defined in dumpfile.h. */ unsigned int optinfo_flags; - /* If non-null, this pass and all sub-passes are executed only if - the function returns true. */ - bool (*gate) (void); + /* If true, this pass has its own implementation of the opt_pass::gate + method. */ + bool has_gate; - /* This is the code to run. If null, then there should be sub-passes - otherwise this pass does nothing. The return value contains - TODOs to execute in addition to those in TODO_flags_finish. */ - unsigned int (*execute) (void); - - /* A list of sub-passes to run, dependent on gate predicate. */ - struct opt_pass *sub; - - /* Next in the list of passes to run, independent of gate predicate. */ - struct opt_pass *next; - - /* Static pass number, used as a fragment of the dump file name. */ - int static_pass_number; + /* If true, this pass has its own implementation of the opt_pass::execute + method. */ + bool has_execute; /* The timevar id associated with this pass. */ /* ??? Ideally would be dynamically assigned. */ @@ -80,16 +69,72 @@ struct opt_pass unsigned int todo_flags_finish; }; -/* Description of GIMPLE pass. */ -struct gimple_opt_pass +namespace gcc { - struct opt_pass pass; + class context; +} // namespace gcc + +/* An instance of a pass. This is also "pass_data" to minimize the + changes in existing code. */ +class opt_pass : public pass_data +{ +public: + virtual ~opt_pass () { } + + /* Create a copy of this pass. + + Passes that can have multiple instances must provide their own + implementation of this, to ensure that any sharing of state between + this instance and the copy is "wired up" correctly. + + The default implementation prints an error message and aborts. */ + virtual opt_pass *clone (); + + /* If has_gate is set, this pass and all sub-passes are executed only if + the function returns true. */ + virtual bool gate (); + + /* This is the code to run. If has_execute is false, then there should + be sub-passes otherwise this pass does nothing. + The return value contains TODOs to execute in addition to those in + TODO_flags_finish. */ + virtual unsigned int execute (); + +protected: + opt_pass(const pass_data&, gcc::context *); + +public: + /* A list of sub-passes to run, dependent on gate predicate. */ + struct opt_pass *sub; + + /* Next in the list of passes to run, independent of gate predicate. */ + struct opt_pass *next; + + /* Static pass number, used as a fragment of the dump file name. */ + int static_pass_number; + +protected: + gcc::context *ctxt_; +}; + +/* Description of GIMPLE pass. */ +class gimple_opt_pass : public opt_pass +{ +protected: + gimple_opt_pass(const pass_data& data, gcc::context *ctxt) + : opt_pass(data, ctxt) + { + } }; /* Description of RTL pass. */ -struct rtl_opt_pass +class rtl_opt_pass : public opt_pass { - struct opt_pass pass; +protected: + rtl_opt_pass(const pass_data& data, gcc::context *ctxt) + : opt_pass(data, ctxt) + { + } }; struct varpool_node; @@ -98,10 +143,9 @@ struct lto_symtab_encoder_d; /* Description of IPA pass with generate summary, write, execute, read and transform stages. */ -struct ipa_opt_pass_d +class ipa_opt_pass_d : public opt_pass { - struct opt_pass pass; - +public: /* IPA passes can analyze function body and variable initializers using this hook and produce summary. */ void (*generate_summary) (void); @@ -127,13 +171,42 @@ struct ipa_opt_pass_d unsigned int function_transform_todo_flags_start; unsigned int (*function_transform) (struct cgraph_node *); void (*variable_transform) (struct varpool_node *); + +protected: + ipa_opt_pass_d(const pass_data& data, gcc::context *ctxt, + void (*generate_summary) (void), + void (*write_summary) (void), + void (*read_summary) (void), + void (*write_optimization_summary) (void), + void (*read_optimization_summary) (void), + void (*stmt_fixup) (struct cgraph_node *, gimple *), + unsigned int function_transform_todo_flags_start, + unsigned int (*function_transform) (struct cgraph_node *), + void (*variable_transform) (struct varpool_node *)) + : opt_pass(data, ctxt), + generate_summary(generate_summary), + write_summary(write_summary), + read_summary(read_summary), + write_optimization_summary(write_optimization_summary), + read_optimization_summary(read_optimization_summary), + stmt_fixup(stmt_fixup), + function_transform_todo_flags_start( + function_transform_todo_flags_start), + function_transform(function_transform), + variable_transform(variable_transform) + { + } }; /* Description of simple IPA pass. Simple IPA passes have just one execute hook. */ -struct simple_ipa_opt_pass +class simple_ipa_opt_pass : public opt_pass { - struct opt_pass pass; +protected: + simple_ipa_opt_pass(const pass_data& data, gcc::context *ctxt) + : opt_pass(data, ctxt) + { + } }; /* Pass properties. */