Patchwork [4/6] Handwritten part of conversion of passes to instances of C++ classes

login
register
mail settings
Submitter David Malcolm
Date April 20, 2013, 1:23 a.m.
Message ID <1366420982-1546-5-git-send-email-dmalcolm@redhat.com>
Download mbox | patch
Permalink /patch/238134/
State New
Headers show

Comments

David Malcolm - April 20, 2013, 1:23 a.m.
This is the hand-written part of the patch; it is required for the
	preceding auto-generated patch to make sense.

	* context.h: New file: introducing a context class to hold global
	state, with a "the_ctxt" singleton.
	* pipeline.h: New file: defines a new "class pipeline", to hold the
	pass hierarchy, with a field per pass, and with fields to replace
	various globals within passes.c as listed below
	* toplev.c (the_ctxt): define the singleton the_ctxt in this file
	* passes.def (NEXT_PASS_IDX): introduce new macro NEXT_PASS_IDX for
	use any time a pass is reused, giving a unique index, so that the
	fields in the pipeline class have unique names.
	* tree-pass.h (required): add helper struct so that various property
	and todo flags can be self-documenting
	(provided): likewise
	(destroyed): likewise
	(start): likewise
	(finish): likewise
	(pass_properties): introduce a new struct pass_properties to group
	the three fields required, provided, destroyed within opt_pass
	(pass_todo_flags): similarly for the todo_start, todo_finish fields
	(opt_pass): convert struct opt_pass to a class opt_pass.  Replace
	the gate and execute callbacks with pairs of C++ virtual functions:
	one to check for the presence of a hook, and another to implement
	the hook, since there are numerous places in the existing code
	guarded by a test against the function pointer being non-NULL.  Add
	a reference to the context instance as member data to the opt_pass,
	to make it easier to have multiple sets of global GCC state within
	a process.
	(gimple_opt_pass): convert struct gimple_opt_pass into a C++ class,
	derived from opt_pass
	(rtl_opt_pass): ditto
	(simple_ipa_opt_pass): ditto
	(ipa_opt_pass_d): ditto, splitting the various function pointer
	hooks into has_ and impl_ virtual functions as per opt_pass
	(gcc_pass_lists): eliminate this global
	(get_pass_for_id): eliminate this function in favor of a member
	function of class pipeline with the same name
	(passes_by_id): eliminate this function in favor of a field of class
	pipeline with the same name
	(passes_by_id_size): ditto
	(all_passes): remove this global, it is now a field within class
	pipeline
	(all_small_ipa_passes): ditto
	(all_lowering_passes): ditto
	(all_regular_ipa_passes): ditto
	(all_late_ipa_passes): ditto
	(all_lto_gen_passes): ditto
	* passes.c (init_optimization_passes): Create the_ctxt.passes.
	Redefine the pass-creation macros for passes.def so that they
	populate the fields of the_ctxt.passes, rather than setting global
	variables; use the_ctxt.passes when accessing the pass lists.
	(dump_passes): Get at the pass lists as fields of the_ctxt.passes
	instance of "pipeline", rather than them being globals
	(register_pass): ditto
	(ipa_write_optimization_summaries): ditto
	(ipa_write_summaries_1): ditto
	(ipa_read_summaries): ditto
	(ipa_read_optimization_summaries): ditto
	(execute_all_ipa_stmt_fixups): ditto
	(finish_optimization_passes): no longer need to access
	.pass to get at static_pass_number; lookup passes by the_ctxt.passes
	(all_passes): remove this global, it is now a field within class
	pipeline
	(all_small_ipa_passes): ditto
	(all_lowering_passes): ditto
	(all_regular_ipa_passes): ditto
	(all_late_ipa_passes): ditto
	(all_lto_gen_passes): ditto
	(gcc_pass_lists): eliminate this global
	(passes_by_id): remove this global, it is now a field within class
	pipeline
	(passes_by_id_size): ditto
	(set_pass_for_id): rename to pipeline::set_pass_for_id
	(get_pass_for_id): rename to pipeline::get_pass_for_id
	(register_one_dump_file): set_pass_for_id is now a method of
	pipeline
	(register_dump_files_1): update for change from pass->properties_*
	fields to pass->props struct and for pass->gate != NULL to
	pass->has_gate ()
	(register_dump_files): update for change from pass->properties_*
	fields to pass->props struct
	(create_pass_tab): passes_by_id_size is now a field of class
	pipeline
	(dump_one_pass): opt_pass->gate is now a C++ member function
	(make_pass_instance): replace todo_flags_* with fields of
	todo_flags struct
	(position_pass): ditto
	(check_profile_consistency): passes_by_id_size is now a field of
	class pipeline
	(dump_profile_report): ditto; likewise for passes_by_id; access
	pass_expand via the_ctxt.passes rather than as a global; no longer
	need to access .pass to get at static_pass_number
	(update_properties_after_pass): update for change from
	pass->properties_* fields to pass->props struct
	(execute_ipa_summary_passes): no longer need to access .pass to
	cast to an opt_pass; eliminate redundant !pass->gate test; convert
	ipa_pass->generate_summary test to call to
	ipa_pass->has_generate_summary(); convert ipa_pass->generate_summary
	call to ipa_pass->impl_generate_summary
	(execute_one_ipa_transform_pass): no longer need to access .pass to
	cast to an opt_pass; replace ipa_pass->function_transform test with
	call to ipa_pass->has_function_transform; replace call to
	ipa_pass->generate_summary with one to
	ipa_pass->impl_generate_summary
	(execute_one_pass): remove redundant test against pass->gate;
	replace todo_flags_* with fields of todo_flags struct; update for
	change from pass->properties_* fields to pass->props struct;
	replace test against pass->execute != NULL with call to
	pass->has_execute; replace call to pass->execute with call to
	impl_execute
	(ipa_write_summaries_2): replace call to ipa_pass->write_summary
	with call to ipa_pass->impl_write_summary
	(ipa_write_optimization_summaries_1): replace call to
	ipa_pass->write_optimization_summary with call to
	ipa_pass->impl_write_optimization_summary
	(ipa_read_summaries_1): eliminate redundant pass->gate == NULL test;
	convert ipa_pass->read_summary != NULL test into a call to
	ipa_pass->has_read_summary; convert call to ipa_pass->read_summary
	into ipa_pass->impl_read_summary
	(ipa_read_optimization_summaries_1): likewise for
	"read_optimization_summary"
	(execute_ipa_stmt_fixups): likewise for "stmt_fixup"
	* cgraphunit.c (cgraph_process_new_functions): Use the_ctxt.passes
	when accessing the pass lists.
	(cgraph_add_new_function): likewise
	(cgraph_analyze_function): likewise
	(expand_function): likewise
	(ipa_passes): likewise
	(compile): likewise
	* config/i386/i386.c (rest_of_handle_insert_vzeroupper): Use
	the_ctxt.passes when locating pass_mode_switching
	(ix86_option_override): Invoke factory function to make an instance
	of pass_insert_vzeroupper.
	* lto-cgraph.c (lto_output_node): now that passes are C++ classes
	we no longer need to access .pass to get at static_pass_number
	(input_node): Use the_ctxt.passes when looking up a pass by id
	* lto/lto.c (read_cgraph_and_symbols): Use
	the_ctxt.passes when locating pass_ipa_inline
	(do_whole_program_analysis): Use
	the_ctxt.passes when locating all_regular_ipa_passes
	* statistics.c (statistics_fini): get_pass_for_id is now a method of
	class pipeline
	* testsuite/g++.dg/plugin/dumb_plugin.c (plugin_init): Update pass
	registration to reflect the automated refactor.py patch, so that it
	calls the pass creation function (rather than relying on a single
	global instance of the pass).
	* testsuite/g++.dg/plugin/selfassign.c (plugin_init): likewise
	* testsuite/gcc.dg/plugin/one_time_plugin.c (plugin_init): likewise
	* testsuite/gcc.dg/plugin/selfassign.c (plugin_init): likewise
---
 gcc/ChangeLog                                 | 153 ++++++++++++++++
 gcc/cgraphunit.c                              |  32 ++--
 gcc/config/i386/i386.c                        |  10 +-
 gcc/context.h                                 |  35 ++++
 gcc/lto-cgraph.c                              |   9 +-
 gcc/lto/lto.c                                 |   6 +-
 gcc/passes.c                                  | 222 +++++++++++++----------
 gcc/passes.def                                | 165 ++++++++---------
 gcc/pipeline.h                                |  71 ++++++++
 gcc/statistics.c                              |   8 +-
 gcc/testsuite/g++.dg/plugin/dumb_plugin.c     |   3 +-
 gcc/testsuite/g++.dg/plugin/selfassign.c      |   3 +-
 gcc/testsuite/gcc.dg/plugin/one_time_plugin.c |   3 +-
 gcc/testsuite/gcc.dg/plugin/selfassign.c      |   3 +-
 gcc/toplev.c                                  |   4 +
 gcc/tree-pass.h                               | 249 +++++++++++++++++++++-----
 16 files changed, 724 insertions(+), 252 deletions(-)
 create mode 100644 gcc/context.h
 create mode 100644 gcc/pipeline.h
David Malcolm - April 26, 2013, 4:04 p.m.
On Fri, 2013-04-19 at 21:23 -0400, David Malcolm wrote:
> 	This is the hand-written part of the patch; it is required for the
> 	preceding auto-generated patch to make sense.

[Answering my own patch]

This patch isn't yet good enough as-is: upon investigating test case
failures I found that the patch wasn't properly handling instances of
passes, leading to the symptom of:
  cc1plus: error: unrecognized command line option '-fdump-tree-fre1'
which was because both of the instances of "fre" were erroneously
getting the dump switch '-fdump-tree-fre' (i.e. missing the trailing
instance number).

This highlighted a deeper issue with converting the passes to C++
classes: register_pass expects a pre-allocated pass, but potentially
needs to create multiple copies of the pass if it's going to be inserted
in multiple places, and gcc/passes.c:make_pass_instance creates these
instances using a memcpy with a fixed size (based on the pass type).  If
we're going to support hanging extra data off of a pass instance, it
means a small reorganization here.

I'm working on a revised patch series which respects the status quo as
per -fdump- option names, and which changes register_pass so that you
pass in a callback for creating passes, rather than creating the pass
yourself.

Dave

Patch

diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 397f535..84eff8b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,5 +1,158 @@ 
 2013-04-19  David Malcolm  <dmalcolm@redhat.com>
 
+	This is the hand-written part of the patch; it is required for the
+	preceding auto-generated patch to make sense.
+
+	* context.h: New file: introducing a context class to hold global
+	state, with a "the_ctxt" singleton.
+	* pipeline.h: New file: defines a new "class pipeline", to hold the
+	pass hierarchy, with a field per pass, and with fields to replace
+	various globals within passes.c as listed below
+	* toplev.c (the_ctxt): define the singleton the_ctxt in this file
+	* passes.def (NEXT_PASS_IDX): introduce new macro NEXT_PASS_IDX for
+	use any time a pass is reused, giving a unique index, so that the
+	fields in the pipeline class have unique names.
+	* tree-pass.h (required): add helper struct so that various property
+	and todo flags can be self-documenting
+	(provided): likewise
+	(destroyed): likewise
+	(start): likewise
+	(finish): likewise
+	(pass_properties): introduce a new struct pass_properties to group
+	the three fields required, provided, destroyed within opt_pass
+	(pass_todo_flags): similarly for the todo_start, todo_finish fields
+	(opt_pass): convert struct opt_pass to a class opt_pass.  Replace
+	the gate and execute callbacks with pairs of C++ virtual functions:
+	one to check for the presence of a hook, and another to implement
+	the hook, since there are numerous places in the existing code
+	guarded by a test against the function pointer being non-NULL.  Add
+	a reference to the context instance as member data to the opt_pass,
+	to make it easier to have multiple sets of global GCC state within
+	a process.
+	(gimple_opt_pass): convert struct gimple_opt_pass into a C++ class,
+	derived from opt_pass
+	(rtl_opt_pass): ditto
+	(simple_ipa_opt_pass): ditto
+	(ipa_opt_pass_d): ditto, splitting the various function pointer
+	hooks into has_ and impl_ virtual functions as per opt_pass
+	(gcc_pass_lists): eliminate this global
+	(get_pass_for_id): eliminate this function in favor of a member
+	function of class pipeline with the same name
+	(passes_by_id): eliminate this function in favor of a field of class
+	pipeline with the same name
+	(passes_by_id_size): ditto
+	(all_passes): remove this global, it is now a field within class
+	pipeline
+	(all_small_ipa_passes): ditto
+	(all_lowering_passes): ditto
+	(all_regular_ipa_passes): ditto
+	(all_late_ipa_passes): ditto
+	(all_lto_gen_passes): ditto
+	* passes.c (init_optimization_passes): Create the_ctxt.passes.
+	Redefine the pass-creation macros for passes.def so that they
+	populate the fields of the_ctxt.passes, rather than setting global
+	variables; use the_ctxt.passes when accessing the pass lists.
+	(dump_passes): Get at the pass lists as fields of the_ctxt.passes
+	instance of "pipeline", rather than them being globals
+	(register_pass): ditto
+	(ipa_write_optimization_summaries): ditto
+	(ipa_write_summaries_1): ditto
+	(ipa_read_summaries): ditto
+	(ipa_read_optimization_summaries): ditto
+	(execute_all_ipa_stmt_fixups): ditto
+	(finish_optimization_passes): no longer need to access
+	.pass to get at static_pass_number; lookup passes by the_ctxt.passes
+	(all_passes): remove this global, it is now a field within class
+	pipeline
+	(all_small_ipa_passes): ditto
+	(all_lowering_passes): ditto
+	(all_regular_ipa_passes): ditto
+	(all_late_ipa_passes): ditto
+	(all_lto_gen_passes): ditto
+	(gcc_pass_lists): eliminate this global
+	(passes_by_id): remove this global, it is now a field within class
+	pipeline
+	(passes_by_id_size): ditto
+	(set_pass_for_id): rename to pipeline::set_pass_for_id
+	(get_pass_for_id): rename to pipeline::get_pass_for_id
+	(register_one_dump_file): set_pass_for_id is now a method of
+	pipeline
+	(register_dump_files_1): update for change from pass->properties_*
+	fields to pass->props struct and for pass->gate != NULL to
+	pass->has_gate ()
+	(register_dump_files): update for change from pass->properties_*
+	fields to pass->props struct
+	(create_pass_tab): passes_by_id_size is now a field of class
+	pipeline
+	(dump_one_pass): opt_pass->gate is now a C++ member function
+	(make_pass_instance): replace todo_flags_* with fields of
+	todo_flags struct
+	(position_pass): ditto
+	(check_profile_consistency): passes_by_id_size is now a field of
+	class pipeline
+	(dump_profile_report): ditto; likewise for passes_by_id; access
+	pass_expand via the_ctxt.passes rather than as a global; no longer
+	need to access .pass to get at static_pass_number
+	(update_properties_after_pass): update for change from
+	pass->properties_* fields to pass->props struct
+	(execute_ipa_summary_passes): no longer need to access .pass to
+	cast to an opt_pass; eliminate redundant !pass->gate test; convert
+	ipa_pass->generate_summary test to call to
+	ipa_pass->has_generate_summary(); convert ipa_pass->generate_summary
+	call to ipa_pass->impl_generate_summary
+	(execute_one_ipa_transform_pass): no longer need to access .pass to
+	cast to an opt_pass; replace ipa_pass->function_transform test with
+	call to ipa_pass->has_function_transform; replace call to
+	ipa_pass->generate_summary with one to
+	ipa_pass->impl_generate_summary
+	(execute_one_pass): remove redundant test against pass->gate;
+	replace todo_flags_* with fields of todo_flags struct; update for
+	change from pass->properties_* fields to pass->props struct;
+	replace test against pass->execute != NULL with call to
+	pass->has_execute; replace call to pass->execute with call to
+	impl_execute
+	(ipa_write_summaries_2): replace call to ipa_pass->write_summary
+	with call to ipa_pass->impl_write_summary
+	(ipa_write_optimization_summaries_1): replace call to
+	ipa_pass->write_optimization_summary with call to
+	ipa_pass->impl_write_optimization_summary
+	(ipa_read_summaries_1): eliminate redundant pass->gate == NULL test;
+	convert ipa_pass->read_summary != NULL test into a call to
+	ipa_pass->has_read_summary; convert call to ipa_pass->read_summary
+	into ipa_pass->impl_read_summary
+	(ipa_read_optimization_summaries_1): likewise for
+	"read_optimization_summary"
+	(execute_ipa_stmt_fixups): likewise for "stmt_fixup"
+	* cgraphunit.c (cgraph_process_new_functions): Use the_ctxt.passes
+	when accessing the pass lists.
+	(cgraph_add_new_function): likewise
+	(cgraph_analyze_function): likewise
+	(expand_function): likewise
+	(ipa_passes): likewise
+	(compile): likewise
+	* config/i386/i386.c (rest_of_handle_insert_vzeroupper): Use
+	the_ctxt.passes when locating pass_mode_switching
+	(ix86_option_override): Invoke factory function to make an instance
+	of pass_insert_vzeroupper.
+	* lto-cgraph.c (lto_output_node): now that passes are C++ classes
+	we no longer need to access .pass to get at static_pass_number
+	(input_node): Use the_ctxt.passes when looking up a pass by id
+	* lto/lto.c (read_cgraph_and_symbols): Use
+	the_ctxt.passes when locating pass_ipa_inline
+	(do_whole_program_analysis): Use
+	the_ctxt.passes when locating all_regular_ipa_passes
+	* statistics.c (statistics_fini): get_pass_for_id is now a method of
+	class pipeline
+	* testsuite/g++.dg/plugin/dumb_plugin.c (plugin_init): Update pass
+	registration to reflect the automated refactor.py patch, so that it
+	calls the pass creation function (rather than relying on a single
+	global instance of the pass).
+	* testsuite/g++.dg/plugin/selfassign.c (plugin_init): likewise
+	* testsuite/gcc.dg/plugin/one_time_plugin.c (plugin_init): likewise
+	* testsuite/gcc.dg/plugin/selfassign.c (plugin_init): likewise
+
+2013-04-11  David Malcolm  <dmalcolm@redhat.com>
+
 	Patch autogenerated by refactor.py from
 	https://github.com/davidmalcolm/gcc-refactoring-scripts
 	revision 31647b9efa0e413f85ef0b284f2ae8a95870d5f5
diff --git a/gcc/cgraphunit.c b/gcc/cgraphunit.c
index 7fa8055..2a5bc28 100644
--- a/gcc/cgraphunit.c
+++ b/gcc/cgraphunit.c
@@ -193,6 +193,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "lto-streamer.h"
 #include "except.h"
 #include "regset.h"     /* FIXME: For reg_obstack.  */
+#include "context.h"
+#include "pipeline.h"
 
 /* Queue of cgraph nodes scheduled to be added into cgraph.  This is a
    secondary queue used during optimization to accommodate passes that
@@ -280,6 +282,7 @@  cgraph_process_new_functions (void)
   tree fndecl;
   struct cgraph_node *node;
   cgraph_node_set_iterator csi;
+  pipeline *passes = the_ctxt.passes;
 
   if (!cgraph_new_nodes)
     return false;
@@ -317,7 +320,7 @@  cgraph_process_new_functions (void)
 	      /* When not optimizing, be sure we run early local passes anyway
 		 to expand OMP.  */
 	      || !optimize)
-	    execute_pass_list (pass_early_local_passes.pass.sub);
+	    execute_pass_list (passes->pass_early_local_passes->sub);
 	  else
 	    compute_inline_parameters (node, true);
 	  free_dominance_info (CDI_POST_DOMINATORS);
@@ -465,6 +468,7 @@  cgraph_finalize_function (tree decl, bool nested)
 void
 cgraph_add_new_function (tree fndecl, bool lowered)
 {
+  pipeline *passes = the_ctxt.passes;
   struct cgraph_node *node;
   switch (cgraph_state)
     {
@@ -495,8 +499,8 @@  cgraph_add_new_function (tree fndecl, bool lowered)
 	    push_cfun (DECL_STRUCT_FUNCTION (fndecl));
 	    gimple_register_cfg_hooks ();
 	    bitmap_obstack_initialize (NULL);
-	    execute_pass_list (all_lowering_passes);
-	    execute_pass_list (pass_early_local_passes.pass.sub);
+	    execute_pass_list (passes->all_lowering_passes);
+	    execute_pass_list (passes->pass_early_local_passes->sub);
 	    bitmap_obstack_release (NULL);
 	    pop_cfun ();
 
@@ -520,7 +524,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);
+	  execute_pass_list (passes->pass_early_local_passes->sub);
 	bitmap_obstack_release (NULL);
 	pop_cfun ();
 	expand_function (node);
@@ -591,6 +595,7 @@  fixup_same_cpp_alias_visibility (symtab_node node, symtab_node target, tree alia
 static void
 cgraph_analyze_function (struct cgraph_node *node)
 {
+  pipeline *passes = the_ctxt.passes;
   tree decl = node->symbol.decl;
   location_t saved_loc = input_location;
   input_location = DECL_SOURCE_LOCATION (decl);
@@ -667,7 +672,7 @@  cgraph_analyze_function (struct cgraph_node *node)
 
 	  gimple_register_cfg_hooks ();
 	  bitmap_obstack_initialize (NULL);
-	  execute_pass_list (all_lowering_passes);
+	  execute_pass_list (passes->all_lowering_passes);
 	  free_dominance_info (CDI_POST_DOMINATORS);
 	  free_dominance_info (CDI_DOMINATORS);
 	  compact_blocks ();
@@ -1601,6 +1606,7 @@  assemble_thunks_and_aliases (struct cgraph_node *node)
 static void
 expand_function (struct cgraph_node *node)
 {
+  pipeline *passes = the_ctxt.passes;
   tree decl = node->symbol.decl;
   location_t saved_loc;
 
@@ -1637,7 +1643,7 @@  expand_function (struct cgraph_node *node)
   /* Signal the start of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_START, NULL);
 
-  execute_pass_list (all_passes);
+  execute_pass_list (passes->all_passes);
 
   /* Signal the end of passes.  */
   invoke_plugin_callbacks (PLUGIN_ALL_PASSES_END, NULL);
@@ -1856,6 +1862,8 @@  output_in_order (void)
 static void
 ipa_passes (void)
 {
+  pipeline *passes = the_ctxt.passes;
+
   set_cfun (NULL);
   current_function_decl = NULL;
   gimple_register_cfg_hooks ();
@@ -1865,7 +1873,7 @@  ipa_passes (void)
 
   if (!in_lto_p)
     {
-      execute_ipa_pass_list (all_small_ipa_passes);
+      execute_ipa_pass_list (passes->all_small_ipa_passes);
       if (seen_error ())
 	return;
     }
@@ -1892,14 +1900,14 @@  ipa_passes (void)
       cgraph_process_new_functions ();
 
       execute_ipa_summary_passes
-	((struct ipa_opt_pass_d *) all_regular_ipa_passes);
+	((struct ipa_opt_pass_d *) passes->all_regular_ipa_passes);
     }
 
   /* Some targets need to handle LTO assembler output specially.  */
   if (flag_generate_lto)
     targetm.asm_out.lto_start ();
 
-  execute_ipa_summary_passes ((struct ipa_opt_pass_d *) all_lto_gen_passes);
+  execute_ipa_summary_passes ((struct ipa_opt_pass_d *) passes->all_lto_gen_passes);
 
   if (!in_lto_p)
     ipa_write_summaries ();
@@ -1908,7 +1916,7 @@  ipa_passes (void)
     targetm.asm_out.lto_end ();
 
   if (!flag_ltrans && (in_lto_p || !flag_lto || flag_fat_lto_objects))
-    execute_ipa_pass_list (all_regular_ipa_passes);
+    execute_ipa_pass_list (passes->all_regular_ipa_passes);
   invoke_plugin_callbacks (PLUGIN_ALL_IPA_PASSES_END, NULL);
 
   bitmap_obstack_release (NULL);
@@ -1965,6 +1973,8 @@  init_cgraph (void)
 void
 compile (void)
 {
+  pipeline *passes = the_ctxt.passes;
+
   if (seen_error ())
     return;
 
@@ -2024,7 +2034,7 @@  compile (void)
 
   cgraph_materialize_all_clones ();
   bitmap_obstack_initialize (NULL);
-  execute_ipa_pass_list (all_late_ipa_passes);
+  execute_ipa_pass_list (passes->all_late_ipa_passes);
   symtab_remove_unreachable_nodes (true, dump_file);
 #ifdef ENABLE_CHECKING
   verify_symtab ();
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 1beed80..1cf9695 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 "pipeline.h"
 
 static rtx legitimize_dllimport_symbol (rtx, bool);
 static rtx legitimize_pe_coff_extern_decl (rtx, bool);
@@ -2512,7 +2514,7 @@  rest_of_handle_insert_vzeroupper (void)
   ix86_optimize_mode_switching[AVX_U128] = 1;
 
   /* Call optimize_mode_switching.  */
-  pass_mode_switching.pass.execute ();
+  the_ctxt.passes->pass_mode_switching->impl_execute ();
   return 0;
 }
 
@@ -3954,8 +3956,10 @@  ix86_option_override_internal (bool main_args_p)
 static void
 ix86_option_override (void)
 {
-  static struct register_pass_info insert_vzeroupper_info
-    = { &pass_insert_vzeroupper.pass, "reload",
+  opt_pass *pass = make_pass_insert_vzeroupper (the_ctxt);
+
+  struct register_pass_info insert_vzeroupper_info
+    = { pass, "reload",
 	1, PASS_POS_INSERT_AFTER
       };
 
diff --git a/gcc/context.h b/gcc/context.h
new file mode 100644
index 0000000..c02e438
--- /dev/null
+++ b/gcc/context.h
@@ -0,0 +1,35 @@ 
+/* context.h - Holder for global state
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_CONTEXT_H
+#define GCC_CONTEXT_H
+
+class pipeline;
+
+/* Holder for state */
+class context
+{
+public:
+  pipeline *passes;
+};
+
+/* Global singleton: */
+extern context the_ctxt;
+
+#endif /* ! GCC_CONTEXT_H */
diff --git a/gcc/lto-cgraph.c b/gcc/lto-cgraph.c
index 69f5e3a..5598f07 100644
--- a/gcc/lto-cgraph.c
+++ b/gcc/lto-cgraph.c
@@ -47,6 +47,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "gcov-io.h"
 #include "tree-pass.h"
 #include "profile.h"
+#include "context.h"
+#include "pipeline.h"
 
 static void output_cgraph_opt_summary (void);
 static void input_cgraph_opt_summary (vec<symtab_node>  nodes);
@@ -435,7 +437,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)
     {
@@ -933,6 +935,7 @@  input_node (struct lto_file_decl_data *file_data,
   int clone_ref;
   int order;
   int i, count;
+  pipeline *passes = the_ctxt.passes;
 
   order = streamer_read_hwi (ib) + order_base;
   clone_ref = streamer_read_hwi (ib);
@@ -963,8 +966,8 @@  input_node (struct lto_file_decl_data *file_data,
       struct opt_pass *pass;
       int pid = streamer_read_hwi (ib);
 
-      gcc_assert (pid < passes_by_id_size);
-      pass = passes_by_id[pid];
+      gcc_assert (pid < passes->passes_by_id_size);
+      pass = passes->passes_by_id[pid];
       node->ipa_transforms_to_apply.safe_push ((struct ipa_opt_pass_d *) pass);
     }
 
diff --git a/gcc/lto/lto.c b/gcc/lto/lto.c
index 983fa03..1397158 100644
--- a/gcc/lto/lto.c
+++ b/gcc/lto/lto.c
@@ -45,6 +45,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "tree-streamer.h"
 #include "splay-tree.h"
 #include "lto-partition.h"
+#include "context.h"
+#include "pipeline.h"
 
 static GTY(()) tree first_personality_decl;
 
@@ -3088,7 +3090,7 @@  read_cgraph_and_symbols (unsigned nfiles, const char **fnames)
      this field into ltrans compilation.  */
   if (flag_ltrans)
     FOR_EACH_DEFINED_FUNCTION (node)
-      node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass)&pass_ipa_inline);
+      node->ipa_transforms_to_apply.safe_push ((ipa_opt_pass)the_ctxt.passes->pass_ipa_inline);
 
   timevar_pop (TV_IPA_LTO_CGRAPH_MERGE);
 
@@ -3219,7 +3221,7 @@  do_whole_program_analysis (void)
   bitmap_obstack_initialize (NULL);
   cgraph_state = CGRAPH_STATE_IPA_SSA;
 
-  execute_ipa_pass_list (all_regular_ipa_passes);
+  execute_ipa_pass_list (the_ctxt.passes->all_regular_ipa_passes);
   symtab_remove_unreachable_nodes (false, dump_file);
 
   if (cgraph_dump_file)
diff --git a/gcc/passes.c b/gcc/passes.c
index ed7ae6c..3f1a3d9 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -69,6 +69,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "plugin.h"
 #include "ipa-utils.h"
 #include "tree-pretty-print.h" /* for dump_function_header */
+#include "context.h"
+#include "pipeline.h"
 
 /* This is used for debugging.  It allows the current pass to printed
    from anywhere in compilation.
@@ -224,20 +226,21 @@  finish_optimization_passes (void)
   int i;
   struct dump_file_info *dfi;
   char *name;
+  pipeline *passes = the_ctxt.passes;
 
   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 (passes->pass_profile->static_pass_number, NULL);
       end_branch_prob ();
-      dump_finish (pass_profile.pass.static_pass_number);
+      dump_finish (passes->pass_profile->static_pass_number);
     }
 
   if (optimize > 0)
     {
-      dump_start (pass_profile.pass.static_pass_number, NULL);
+      dump_start (passes->pass_profile->static_pass_number, NULL);
       print_combine_total_stats ();
-      dump_finish (pass_profile.pass.static_pass_number);
+      dump_finish (passes->pass_profile->static_pass_number);
     }
 
   /* Do whatever is necessary to finish printing the graphs.  */
@@ -500,24 +503,11 @@  make_pass_postreload (context &ctxt)
 
 
 
-/* The root of the compilation pass tree, once constructed.  */
-struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
-  *all_regular_ipa_passes, *all_late_ipa_passes, *all_lto_gen_passes;
-
-/* This is used by plugins, and should also be used in register_pass.  */
-#define DEF_PASS_LIST(LIST) &LIST,
-struct opt_pass **gcc_pass_lists[] = { GCC_PASS_LISTS NULL };
-#undef DEF_PASS_LIST
-
-/* A map from static pass id to optimization pass.  */
-struct opt_pass **passes_by_id;
-int passes_by_id_size;
-
 /* Set the static pass number of pass PASS to ID and record that
    in the mapping from static pass number to pass.  */
 
-static void
-set_pass_for_id (int id, struct opt_pass *pass)
+void
+pipeline::set_pass_for_id (int id, struct opt_pass *pass)
 {
   pass->static_pass_number = id;
   if (passes_by_id_size <= id)
@@ -533,7 +523,7 @@  set_pass_for_id (int id, struct opt_pass *pass)
 /* Return the pass with the static pass number ID.  */
 
 struct opt_pass *
-get_pass_for_id (int id)
+pipeline::get_pass_for_id (int id) const
 {
   if (id >= passes_by_id_size)
     return NULL;
@@ -552,6 +542,7 @@  register_one_dump_file (struct opt_pass *pass)
   char num[10];
   int flags, id;
   int optgroup_flags = OPTGROUP_NONE;
+  pipeline *passes = the_ctxt.passes;
 
   /* See below in next_pass_1.  */
   num[0] = '\0';
@@ -588,7 +579,7 @@  register_one_dump_file (struct opt_pass *pass)
   glob_name = concat (prefix, name, NULL);
   optgroup_flags |= pass->optinfo_flags;
   id = dump_register (dot_name, flag_name, glob_name, flags, optgroup_flags);
-  set_pass_for_id (id, pass);
+  passes->set_pass_for_id (id, pass);
   full_name = concat (prefix, pass->name, num, NULL);
   register_pass_name (pass, full_name);
   free (CONST_CAST (char *, full_name));
@@ -601,8 +592,8 @@  register_dump_files_1 (struct opt_pass *pass, int properties)
 {
   do
     {
-      int new_properties = (properties | pass->properties_provided)
-			   & ~pass->properties_destroyed;
+      int new_properties = (properties | pass->props.provided)
+			   & ~pass->props.destroyed;
 
       if (pass->name && pass->name[0] != '*')
         register_one_dump_file (pass);
@@ -612,7 +603,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;
@@ -631,7 +622,7 @@  register_dump_files_1 (struct opt_pass *pass, int properties)
 static void
 register_dump_files (struct opt_pass *pass,int properties)
 {
-  pass->properties_required |= properties;
+  pass->props.required |= properties;
   register_dump_files_1 (pass, properties);
 }
 
@@ -716,10 +707,12 @@  pass_traverse (void **slot, void *data ATTRIBUTE_UNUSED)
 static void
 create_pass_tab (void)
 {
+  pipeline *passes = the_ctxt.passes;
+
   if (!flag_dump_passes)
     return;
 
-  pass_tab.safe_grow_cleared (passes_by_id_size + 1);
+  pass_tab.safe_grow_cleared (passes->passes_by_id_size + 1);
   htab_traverse (name_to_pass_map, pass_traverse, NULL);
 }
 
@@ -735,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->gate();
   is_really_on = override_gate_status (pass, current_function_decl, is_on);
 
   if (pass->static_pass_number <= 0)
@@ -771,6 +764,7 @@  void
 dump_passes (void)
 {
   struct cgraph_node *n, *node = NULL;
+  pipeline *passes = the_ctxt.passes;
 
   create_pass_tab();
 
@@ -786,12 +780,12 @@  dump_passes (void)
 
   push_cfun (DECL_STRUCT_FUNCTION (node->symbol.decl));
 
-  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);
+  dump_pass_list (passes->all_lowering_passes, 1);
+  dump_pass_list (passes->all_small_ipa_passes, 1);
+  dump_pass_list (passes->all_regular_ipa_passes, 1);
+  dump_pass_list (passes->all_lto_gen_passes, 1);
+  dump_pass_list (passes->all_late_ipa_passes, 1);
+  dump_pass_list (passes->all_passes, 1);
 
   pop_cfun ();
 }
@@ -1095,7 +1089,7 @@  make_pass_instance (struct opt_pass *pass, bool track_duplicates)
 
       new_pass->next = NULL;
 
-      new_pass->todo_flags_start &= ~TODO_mark_first_instance;
+      new_pass->todo_flags.start &= ~TODO_mark_first_instance;
 
       /* Indicate to register_dump_files that this pass has duplicates,
          and so it should rename the dump file.  The first instance will
@@ -1110,7 +1104,7 @@  make_pass_instance (struct opt_pass *pass, bool track_duplicates)
     }
   else
     {
-      pass->todo_flags_start |= TODO_mark_first_instance;
+      pass->todo_flags.start |= TODO_mark_first_instance;
       pass->static_pass_number = -1;
 
       invoke_plugin_callbacks (PLUGIN_NEW_PASS, pass);
@@ -1172,7 +1166,7 @@  position_pass (struct register_pass_info *new_pass_info,
               || (new_pass_info->ref_pass_instance_number ==
                   pass->static_pass_number)
               || (new_pass_info->ref_pass_instance_number == 1
-                  && pass->todo_flags_start & TODO_mark_first_instance)))
+                  && pass->todo_flags.start & TODO_mark_first_instance)))
         {
           struct opt_pass *new_pass;
           struct pass_list_node *new_pass_node;
@@ -1246,6 +1240,7 @@  void
 register_pass (struct register_pass_info *pass_info)
 {
   bool all_instances, success;
+  pipeline *passes = the_ctxt.passes;
 
   /* The checks below could fail in buggy plugins.  Existing GCC
      passes should never fail these checks, so we mention plugin in
@@ -1265,17 +1260,17 @@  register_pass (struct register_pass_info *pass_info)
      all five lists as the reference pass could be in one (or all) of
      them.  */
   all_instances = pass_info->ref_pass_instance_number == 0;
-  success = position_pass (pass_info, &all_lowering_passes);
+  success = position_pass (pass_info, &passes->all_lowering_passes);
   if (!success || all_instances)
-    success |= position_pass (pass_info, &all_small_ipa_passes);
+    success |= position_pass (pass_info, &passes->all_small_ipa_passes);
   if (!success || all_instances)
-    success |= position_pass (pass_info, &all_regular_ipa_passes);
+    success |= position_pass (pass_info, &passes->all_regular_ipa_passes);
   if (!success || all_instances)
-    success |= position_pass (pass_info, &all_lto_gen_passes);
+    success |= position_pass (pass_info, &passes->all_lto_gen_passes);
   if (!success || all_instances)
-    success |= position_pass (pass_info, &all_late_ipa_passes);
+    success |= position_pass (pass_info, &passes->all_late_ipa_passes);
   if (!success || all_instances)
-    success |= position_pass (pass_info, &all_passes);
+    success |= position_pass (pass_info, &passes->all_passes);
   if (!success)
     fatal_error
       ("pass %qs not found but is referenced by new pass %qs",
@@ -1339,17 +1334,37 @@  init_optimization_passes (void)
 {
   struct opt_pass **p;
 
+  /* Create the context's pipeline instance, "passes",
+     describing the pass hierarchy: */
+  pipeline *passes;
+  passes = new pipeline();
+  the_ctxt.passes = passes;
+
 #define INSERT_PASSES_AFTER(PASS) \
-  p = &(PASS);
+  do { \
+    p = &passes->PASS; \
+  } while (0);
 
 #define PUSH_INSERT_PASSES_WITHIN(PASS) \
   { \
-    struct opt_pass **p = &(PASS).pass.sub;
+    struct opt_pass **p = &(passes->PASS)->sub;
 
 #define POP_INSERT_PASSES() \
   }
 
-#define NEXT_PASS(PASS)  (p = next_pass_1 (p, &((PASS).pass)))
+#define NEXT_PASS(PASS) \
+  do { \
+    gcc_assert (NULL == passes->PASS); \
+    passes->PASS = make_##PASS (the_ctxt); \
+    p = next_pass_1 (p, passes->PASS); \
+  } while (0)
+
+#define NEXT_PASS_IDX(PASS, IDX) \
+  do { \
+    gcc_assert (NULL == passes->PASS ## _ ## IDX); \
+    passes->PASS ## _ ## IDX = make_##PASS (the_ctxt); \
+    p = next_pass_1 (p, passes->PASS ## _ ## IDX); \
+  } while (0)
 
 #define TERMINATE_PASS_LIST() \
   *p = NULL;
@@ -1360,23 +1375,24 @@  init_optimization_passes (void)
 #undef PUSH_INSERT_PASSES_WITHIN
 #undef POP_INSERT_PASSES
 #undef NEXT_PASS
+#undef NEXT_PASS_IDX
 #undef TERMINATE_PASS_LIST
 
   /* Register the passes with the tree dump code.  */
-  register_dump_files (all_lowering_passes, PROP_gimple_any);
-  register_dump_files (all_small_ipa_passes,
+  register_dump_files (passes->all_lowering_passes, PROP_gimple_any);
+  register_dump_files (passes->all_small_ipa_passes,
 		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
 		       | PROP_cfg);
-  register_dump_files (all_regular_ipa_passes,
+  register_dump_files (passes->all_regular_ipa_passes,
 		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
 		       | PROP_cfg);
-  register_dump_files (all_lto_gen_passes,
+  register_dump_files (passes->all_lto_gen_passes,
 		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
 		       | PROP_cfg);
-  register_dump_files (all_late_ipa_passes,
+  register_dump_files (passes->all_late_ipa_passes,
 		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
 		       | PROP_cfg);
-  register_dump_files (all_passes,
+  register_dump_files (passes->all_passes,
 		       PROP_gimple_any | PROP_gimple_lcf | PROP_gimple_leh
 		       | PROP_cfg);
 }
@@ -1489,12 +1505,14 @@  static struct profile_record *profile_record;
 static void
 check_profile_consistency (int index, int subpass, bool run)
 {
+  pipeline *passes = the_ctxt.passes;
+
   if (index == -1)
     return;
   if (!profile_record)
     profile_record = XCNEWVEC (struct profile_record,
-			       passes_by_id_size);
-  gcc_assert (index < passes_by_id_size && index >= 0);
+			       passes->passes_by_id_size);
+  gcc_assert (index < passes->passes_by_id_size && index >= 0);
   gcc_assert (subpass < 2);
   profile_record[index].run |= run;
   account_profile_record (&profile_record[index], subpass);
@@ -1510,6 +1528,7 @@  dump_profile_report (void)
   gcov_type last_time = 0, last_size = 0;
   double rel_time_change, rel_size_change;
   int last_reported = 0;
+  pipeline *passes = the_ctxt.passes;
 
   if (!profile_record)
     return;
@@ -1517,7 +1536,7 @@  dump_profile_report (void)
   fprintf (stderr, "Pass name                        |mismatch in |mismated out|Overall\n");
   fprintf (stderr, "                                 |freq count  |freq count  |size      time\n");
 	   
-  for (i = 0; i < passes_by_id_size; i++)
+  for (i = 0; i < passes->passes_by_id_size; i++)
     for (j = 0 ; j < 2; j++)
       if (profile_record[i].run)
 	{
@@ -1540,7 +1559,7 @@  dump_profile_report (void)
 	    {
 	      last_reported = i;
               fprintf (stderr, "%-20s %s",
-		       passes_by_id [i]->name,
+		       passes->passes_by_id [i]->name,
 		       j ? "(after TODO)" : "            ");
 	      if (profile_record[i].num_mismatched_freq_in[j] != last_freq_in)
 		fprintf (stderr, "| %+5i",
@@ -1568,7 +1587,7 @@  dump_profile_report (void)
 		fprintf (stderr, "      ");
 
 	      /* Size/time units change across gimple and RTL.  */
-	      if (i == pass_expand.pass.static_pass_number)
+	      if (i == passes->pass_expand->static_pass_number)
 		fprintf (stderr, "|----------");
 	      else
 		{
@@ -1589,7 +1608,7 @@  dump_profile_report (void)
 	    {
 	      last_reported = i;
               fprintf (stderr, "%-20s ------------|            |            |\n",
-		       passes_by_id [i]->name);
+		       passes->passes_by_id [i]->name);
 	    }
 	  last_time = profile_record[i].time[j];
 	  last_size = profile_record[i].size[j];
@@ -1794,8 +1813,8 @@  static void
 update_properties_after_pass (void *data)
 {
   struct opt_pass *pass = (struct opt_pass *) data;
-  cfun->curr_properties = (cfun->curr_properties | pass->properties_provided)
-		           & ~pass->properties_destroyed;
+  cfun->curr_properties = (cfun->curr_properties | pass->props.provided)
+		           & ~pass->props.destroyed;
 }
 
 /* Execute summary generation for all of the passes in IPA_PASS.  */
@@ -1805,12 +1824,12 @@  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 ())
-	  && ipa_pass->generate_summary)
+      if (ipa_pass->type == IPA_PASS
+	  && pass->gate ()
+	  && ipa_pass->has_generate_summary ())
 	{
 	  pass_init_dump_file (pass);
 
@@ -1818,7 +1837,7 @@  execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
 	  if (pass->tv_id)
 	    timevar_push (pass->tv_id);
 
-	  ipa_pass->generate_summary ();
+	  ipa_pass->impl_generate_summary ();
 
 	  /* Stop timevar.  */
 	  if (pass->tv_id)
@@ -1826,7 +1845,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;
     }
 }
 
@@ -1836,11 +1855,11 @@  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;
-  if (!ipa_pass->function_transform)
+  if (!ipa_pass->has_function_transform ())
     return;
 
   /* Note that the folders should only create gimple expressions.
@@ -1857,7 +1876,7 @@  execute_one_ipa_transform_pass (struct cgraph_node *node,
     timevar_push (pass->tv_id);
 
   /* Do it!  */
-  todo_after = ipa_pass->function_transform (node);
+  todo_after = ipa_pass->impl_function_transform (node);
 
   /* Stop timevar.  */
   if (pass->tv_id != TV_NONE)
@@ -1960,7 +1979,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->gate();
   gate_status = override_gate_status (pass, current_function_decl, gate_status);
 
   /* Override gate with plugin.  */
@@ -2005,11 +2024,11 @@  execute_one_pass (struct opt_pass *pass)
   pass_init_dump_file (pass);
 
   /* Run pre-pass verification.  */
-  execute_todo (pass->todo_flags_start);
+  execute_todo (pass->todo_flags.start);
 
 #ifdef ENABLE_CHECKING
   do_per_function (verify_curr_properties,
-		   (void *)(size_t)pass->properties_required);
+		   (void *)(size_t)pass->props.required);
 #endif
 
   /* If a timevar is present, start it.  */
@@ -2017,9 +2036,9 @@  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 ();
+      todo_after = pass->impl_execute ();
       do_per_function (clear_last_verified, NULL);
     }
 
@@ -2033,7 +2052,7 @@  execute_one_pass (struct opt_pass *pass)
     check_profile_consistency (pass->static_pass_number, 0, true);
 
   /* Run post-pass cleanup and verification.  */
-  execute_todo (todo_after | pass->todo_flags_finish);
+  execute_todo (todo_after | pass->todo_flags.finish);
   if (profile_report && cfun && (cfun->curr_properties & PROP_cfg))
     check_profile_consistency (pass->static_pass_number, 1, true);
 
@@ -2058,7 +2077,7 @@  execute_one_pass (struct opt_pass *pass)
   current_pass = NULL;
 
   /* Signal this is a suitable GC collection point.  */
-  if (!((todo_after | pass->todo_flags_finish) & TODO_do_not_ggc_collect))
+  if (!((todo_after | pass->todo_flags.finish) & TODO_do_not_ggc_collect))
     ggc_collect ();
 
   return true;
@@ -2092,8 +2111,8 @@  ipa_write_summaries_2 (struct opt_pass *pass, struct lto_out_decl_state *state)
       gcc_assert (!cfun);
       gcc_assert (pass->type == SIMPLE_IPA_PASS || pass->type == IPA_PASS);
       if (pass->type == IPA_PASS
-	  && ipa_pass->write_summary
-	  && (!pass->gate || pass->gate ()))
+	  && ipa_pass->has_write_summary ()
+	  && pass->gate ())
 	{
 	  /* If a timevar is present, start it.  */
 	  if (pass->tv_id)
@@ -2101,7 +2120,7 @@  ipa_write_summaries_2 (struct opt_pass *pass, struct lto_out_decl_state *state)
 
           pass_init_dump_file (pass);
 
-	  ipa_pass->write_summary ();
+	  ipa_pass->impl_write_summary ();
 
           pass_fini_dump_file (pass);
 
@@ -2126,12 +2145,13 @@  ipa_write_summaries_1 (lto_symtab_encoder_t encoder)
 {
   struct lto_out_decl_state *state = lto_new_out_decl_state ();
   state->symtab_node_encoder = encoder;
+  pipeline *passes = the_ctxt.passes;
 
   lto_push_out_decl_state (state);
 
   gcc_assert (!flag_wpa);
-  ipa_write_summaries_2 (all_regular_ipa_passes, state);
-  ipa_write_summaries_2 (all_lto_gen_passes, state);
+  ipa_write_summaries_2 (passes->all_regular_ipa_passes, state);
+  ipa_write_summaries_2 (passes->all_lto_gen_passes, state);
 
   gcc_assert (lto_get_out_decl_state () == state);
   lto_pop_out_decl_state ();
@@ -2204,8 +2224,8 @@  ipa_write_optimization_summaries_1 (struct opt_pass *pass, struct lto_out_decl_s
       gcc_assert (!cfun);
       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 ()))
+	  && ipa_pass->has_write_optimization_summary ()
+	  && pass->gate ())
 	{
 	  /* If a timevar is present, start it.  */
 	  if (pass->tv_id)
@@ -2213,7 +2233,7 @@  ipa_write_optimization_summaries_1 (struct opt_pass *pass, struct lto_out_decl_s
 
           pass_init_dump_file (pass);
 
-	  ipa_pass->write_optimization_summary ();
+	  ipa_pass->impl_write_optimization_summary ();
 
           pass_fini_dump_file (pass);
 
@@ -2237,6 +2257,7 @@  ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
 {
   struct lto_out_decl_state *state = lto_new_out_decl_state ();
   lto_symtab_encoder_iterator lsei;
+  pipeline *passes = the_ctxt.passes;
   state->symtab_node_encoder = encoder;
 
   lto_push_out_decl_state (state);
@@ -2259,8 +2280,8 @@  ipa_write_optimization_summaries (lto_symtab_encoder_t encoder)
     }
 
   gcc_assert (flag_wpa);
-  ipa_write_optimization_summaries_1 (all_regular_ipa_passes, state);
-  ipa_write_optimization_summaries_1 (all_lto_gen_passes, state);
+  ipa_write_optimization_summaries_1 (passes->all_regular_ipa_passes, state);
+  ipa_write_optimization_summaries_1 (passes->all_lto_gen_passes, state);
 
   gcc_assert (lto_get_out_decl_state () == state);
   lto_pop_out_decl_state ();
@@ -2281,9 +2302,9 @@  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->gate ())
 	{
-	  if (pass->type == IPA_PASS && ipa_pass->read_summary)
+	  if (pass->type == IPA_PASS && ipa_pass->has_read_summary ())
 	    {
 	      /* If a timevar is present, start it.  */
 	      if (pass->tv_id)
@@ -2291,7 +2312,7 @@  ipa_read_summaries_1 (struct opt_pass *pass)
 
 	      pass_init_dump_file (pass);
 
-	      ipa_pass->read_summary ();
+	      ipa_pass->impl_read_summary ();
 
 	      pass_fini_dump_file (pass);
 
@@ -2313,8 +2334,9 @@  ipa_read_summaries_1 (struct opt_pass *pass)
 void
 ipa_read_summaries (void)
 {
-  ipa_read_summaries_1 (all_regular_ipa_passes);
-  ipa_read_summaries_1 (all_lto_gen_passes);
+  pipeline *passes = the_ctxt.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
@@ -2331,9 +2353,9 @@  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->gate ())
 	{
-	  if (pass->type == IPA_PASS && ipa_pass->read_optimization_summary)
+	  if (pass->type == IPA_PASS && ipa_pass->has_read_optimization_summary ())
 	    {
 	      /* If a timevar is present, start it.  */
 	      if (pass->tv_id)
@@ -2341,7 +2363,7 @@  ipa_read_optimization_summaries_1 (struct opt_pass *pass)
 
 	      pass_init_dump_file (pass);
 
-	      ipa_pass->read_optimization_summary ();
+	      ipa_pass->impl_read_optimization_summary ();
 
 	      pass_fini_dump_file (pass);
 
@@ -2362,8 +2384,9 @@  ipa_read_optimization_summaries_1 (struct opt_pass *pass)
 void
 ipa_read_optimization_summaries (void)
 {
-  ipa_read_optimization_summaries_1 (all_regular_ipa_passes);
-  ipa_read_optimization_summaries_1 (all_lto_gen_passes);
+  pipeline *passes = the_ctxt.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
@@ -2408,18 +2431,18 @@  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->gate ())
 	{
 	  struct ipa_opt_pass_d *ipa_pass = (struct ipa_opt_pass_d *) pass;
 
-	  if (ipa_pass->stmt_fixup)
+	  if (ipa_pass->has_stmt_fixup ())
 	    {
 	      pass_init_dump_file (pass);
 	      /* If a timevar is present, start it.  */
 	      if (pass->tv_id)
 		timevar_push (pass->tv_id);
 
-	      ipa_pass->stmt_fixup (node, stmts);
+	      ipa_pass->impl_stmt_fixup (node, stmts);
 
 	      /* Stop timevar.  */
 	      if (pass->tv_id)
@@ -2438,7 +2461,8 @@  execute_ipa_stmt_fixups (struct opt_pass *pass,
 void
 execute_all_ipa_stmt_fixups (struct cgraph_node *node, gimple *stmts)
 {
-  execute_ipa_stmt_fixups (all_regular_ipa_passes, node, stmts);
+  pipeline *passes = the_ctxt.passes;
+  execute_ipa_stmt_fixups (passes->all_regular_ipa_passes, node, stmts);
 }
 
 
diff --git a/gcc/passes.def b/gcc/passes.def
index d2444e0..8909186 100644
--- a/gcc/passes.def
+++ b/gcc/passes.def
@@ -23,6 +23,7 @@  along with GCC; see the file COPYING3.  If not see
    PUSH_INSERT_PASSES_WITHIN (PASS)
    POP_INSERT_PASSES ()
    NEXT_PASS (PASS)
+   NEXT_PASS_IDX (PASS)
    TERMINATE_PASS_LIST ()
  */
 
@@ -51,45 +52,45 @@  along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_ipa_function_and_variable_visibility);
   NEXT_PASS (pass_early_local_passes);
   PUSH_INSERT_PASSES_WITHIN (pass_early_local_passes)
-      NEXT_PASS (pass_fixup_cfg);
+      NEXT_PASS_IDX (pass_fixup_cfg, 0);
       NEXT_PASS (pass_init_datastructures);
       NEXT_PASS (pass_expand_omp);
 
       NEXT_PASS (pass_build_ssa);
       NEXT_PASS (pass_early_warn_uninitialized);
-      NEXT_PASS (pass_rebuild_cgraph_edges);
-      NEXT_PASS (pass_inline_parameters);
+      NEXT_PASS_IDX (pass_rebuild_cgraph_edges, 0);
+      NEXT_PASS_IDX (pass_inline_parameters, 0);
       NEXT_PASS (pass_early_inline);
       NEXT_PASS (pass_all_early_optimizations);
       PUSH_INSERT_PASSES_WITHIN (pass_all_early_optimizations)
-	  NEXT_PASS (pass_remove_cgraph_callee_edges);
-	  NEXT_PASS (pass_rename_ssa_copies);
-	  NEXT_PASS (pass_ccp);
+	  NEXT_PASS_IDX (pass_remove_cgraph_callee_edges, 0);
+	  NEXT_PASS_IDX (pass_rename_ssa_copies, 0);
+	  NEXT_PASS_IDX (pass_ccp, 0);
 	  /* After CCP we rewrite no longer addressed locals into SSA
 	     form if possible.  */
-	  NEXT_PASS (pass_forwprop);
+	  NEXT_PASS_IDX (pass_forwprop, 0);
 	  /* pass_build_ealias is a dummy pass that ensures that we
 	     execute TODO_rebuild_alias at this point.  */
 	  NEXT_PASS (pass_build_ealias);
 	  NEXT_PASS (pass_sra_early);
-	  NEXT_PASS (pass_fre);
-	  NEXT_PASS (pass_copy_prop);
-	  NEXT_PASS (pass_merge_phi);
-	  NEXT_PASS (pass_cd_dce);
+	  NEXT_PASS_IDX (pass_fre, 0);
+	  NEXT_PASS_IDX (pass_copy_prop, 0);
+	  NEXT_PASS_IDX (pass_merge_phi, 0);
+	  NEXT_PASS_IDX (pass_cd_dce, 0);
 	  NEXT_PASS (pass_early_ipa_sra);
-	  NEXT_PASS (pass_tail_recursion);
+	  NEXT_PASS_IDX (pass_tail_recursion, 0);
 	  NEXT_PASS (pass_convert_switch);
-          NEXT_PASS (pass_cleanup_eh);
+          NEXT_PASS_IDX (pass_cleanup_eh, 0);
           NEXT_PASS (pass_profile);
-          NEXT_PASS (pass_local_pure_const);
+          NEXT_PASS_IDX (pass_local_pure_const, 0);
 	  /* Split functions creates parts that are not run through
 	     early optimizations again.  It is thus good idea to do this
 	     late.  */
           NEXT_PASS (pass_split_functions);
       POP_INSERT_PASSES ()
       NEXT_PASS (pass_release_ssa_names);
-      NEXT_PASS (pass_rebuild_cgraph_edges);
-      NEXT_PASS (pass_inline_parameters);
+      NEXT_PASS_IDX (pass_rebuild_cgraph_edges, 1);
+      NEXT_PASS_IDX (pass_inline_parameters, 1);
   POP_INSERT_PASSES ()
   NEXT_PASS (pass_ipa_free_inline_summary);
   NEXT_PASS (pass_ipa_tree_profile);
@@ -126,94 +127,94 @@  along with GCC; see the file COPYING3.  If not see
   /* These passes are run after IPA passes on every function that is being
      output to the assembler file.  */
   INSERT_PASSES_AFTER (all_passes)
-  NEXT_PASS (pass_fixup_cfg);
+  NEXT_PASS_IDX (pass_fixup_cfg, 1);
   NEXT_PASS (pass_lower_eh_dispatch);
   NEXT_PASS (pass_all_optimizations);
   PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations)
-      NEXT_PASS (pass_remove_cgraph_callee_edges);
+      NEXT_PASS_IDX (pass_remove_cgraph_callee_edges, 1);
       /* Initial scalar cleanups before alias computation.
 	 They ensure memory accesses are not indirect wherever possible.  */
-      NEXT_PASS (pass_strip_predict_hints);
-      NEXT_PASS (pass_rename_ssa_copies);
+      NEXT_PASS_IDX (pass_strip_predict_hints, 0);
+      NEXT_PASS_IDX (pass_rename_ssa_copies, 1);
       NEXT_PASS (pass_complete_unrolli);
-      NEXT_PASS (pass_ccp);
+      NEXT_PASS_IDX (pass_ccp, 1);
       /* After CCP we rewrite no longer addressed locals into SSA
 	 form if possible.  */
-      NEXT_PASS (pass_forwprop);
+      NEXT_PASS_IDX (pass_forwprop, 1);
       /* pass_build_alias is a dummy pass that ensures that we
 	 execute TODO_rebuild_alias at this point.  */
       NEXT_PASS (pass_build_alias);
       NEXT_PASS (pass_return_slot);
       NEXT_PASS (pass_phiprop);
-      NEXT_PASS (pass_fre);
-      NEXT_PASS (pass_copy_prop);
-      NEXT_PASS (pass_merge_phi);
-      NEXT_PASS (pass_vrp);
-      NEXT_PASS (pass_dce);
+      NEXT_PASS_IDX (pass_fre, 1);
+      NEXT_PASS_IDX (pass_copy_prop, 1);
+      NEXT_PASS_IDX (pass_merge_phi, 1);
+      NEXT_PASS_IDX (pass_vrp, 0);
+      NEXT_PASS_IDX (pass_dce, 0);
       NEXT_PASS (pass_call_cdce);
       NEXT_PASS (pass_cselim);
       NEXT_PASS (pass_tree_ifcombine);
-      NEXT_PASS (pass_phiopt);
-      NEXT_PASS (pass_tail_recursion);
+      NEXT_PASS_IDX (pass_phiopt, 0);
+      NEXT_PASS_IDX (pass_tail_recursion, 1);
       NEXT_PASS (pass_ch);
       NEXT_PASS (pass_stdarg);
-      NEXT_PASS (pass_lower_complex);
+      NEXT_PASS_IDX (pass_lower_complex, 0);
       NEXT_PASS (pass_sra);
-      NEXT_PASS (pass_rename_ssa_copies);
+      NEXT_PASS_IDX (pass_rename_ssa_copies, 2);
       /* The dom pass will also resolve all __builtin_constant_p calls
          that are still there to 0.  This has to be done after some
 	 propagations have already run, but before some more dead code
 	 is removed, and this place fits nicely.  Remember this when
 	 trying to move or duplicate pass_dominator somewhere earlier.  */
-      NEXT_PASS (pass_dominator);
+      NEXT_PASS_IDX (pass_dominator, 0);
       /* The only const/copy propagation opportunities left after
 	 DOM should be due to degenerate PHI nodes.  So rather than
 	 run the full propagators, run a specialized pass which
 	 only examines PHIs to discover const/copy propagation
 	 opportunities.  */
-      NEXT_PASS (pass_phi_only_cprop);
-      NEXT_PASS (pass_dse);
-      NEXT_PASS (pass_reassoc);
-      NEXT_PASS (pass_dce);
-      NEXT_PASS (pass_forwprop);
-      NEXT_PASS (pass_phiopt);
-      NEXT_PASS (pass_object_sizes);
+      NEXT_PASS_IDX (pass_phi_only_cprop, 0);
+      NEXT_PASS_IDX (pass_dse, 0);
+      NEXT_PASS_IDX (pass_reassoc, 0);
+      NEXT_PASS_IDX (pass_dce, 1);
+      NEXT_PASS_IDX (pass_forwprop, 2);
+      NEXT_PASS_IDX (pass_phiopt, 1);
+      NEXT_PASS_IDX (pass_object_sizes, 0);
       NEXT_PASS (pass_strlen);
-      NEXT_PASS (pass_ccp);
+      NEXT_PASS_IDX (pass_ccp, 2);
       /* After CCP we rewrite no longer addressed locals into SSA
 	 form if possible.  */
-      NEXT_PASS (pass_copy_prop);
+      NEXT_PASS_IDX (pass_copy_prop, 2);
       NEXT_PASS (pass_cse_sincos);
       NEXT_PASS (pass_optimize_bswap);
       NEXT_PASS (pass_split_crit_edges);
       NEXT_PASS (pass_pre);
       NEXT_PASS (pass_sink_code);
-      NEXT_PASS (pass_asan);
-      NEXT_PASS (pass_tsan);
+      NEXT_PASS_IDX (pass_asan, 0);
+      NEXT_PASS_IDX (pass_tsan, 0);
       NEXT_PASS (pass_tree_loop);
       PUSH_INSERT_PASSES_WITHIN (pass_tree_loop)
 	  NEXT_PASS (pass_tree_loop_init);
-	  NEXT_PASS (pass_lim);
-	  NEXT_PASS (pass_copy_prop);
-	  NEXT_PASS (pass_dce_loop);
+	  NEXT_PASS_IDX (pass_lim, 0);
+	  NEXT_PASS_IDX (pass_copy_prop, 3);
+	  NEXT_PASS_IDX (pass_dce_loop, 0);
 	  NEXT_PASS (pass_tree_unswitch);
 	  NEXT_PASS (pass_scev_cprop);
 	  NEXT_PASS (pass_record_bounds);
 	  NEXT_PASS (pass_check_data_deps);
 	  NEXT_PASS (pass_loop_distribution);
-	  NEXT_PASS (pass_copy_prop);
+	  NEXT_PASS_IDX (pass_copy_prop, 4);
 	  NEXT_PASS (pass_graphite);
 	  PUSH_INSERT_PASSES_WITHIN (pass_graphite)
 	      NEXT_PASS (pass_graphite_transforms);
-	      NEXT_PASS (pass_lim);
-	      NEXT_PASS (pass_copy_prop);
-	      NEXT_PASS (pass_dce_loop);
+	      NEXT_PASS_IDX (pass_lim, 1);
+	      NEXT_PASS_IDX (pass_copy_prop, 5);
+	      NEXT_PASS_IDX (pass_dce_loop, 1);
 	  POP_INSERT_PASSES ()
 	  NEXT_PASS (pass_iv_canon);
 	  NEXT_PASS (pass_if_conversion);
 	  NEXT_PASS (pass_vectorize);
           PUSH_INSERT_PASSES_WITHIN (pass_vectorize)
-	      NEXT_PASS (pass_dce_loop);
+	      NEXT_PASS_IDX (pass_dce_loop, 2);
           POP_INSERT_PASSES ()
           NEXT_PASS (pass_predcom);
 	  NEXT_PASS (pass_complete_unroll);
@@ -221,22 +222,22 @@  along with GCC; see the file COPYING3.  If not see
 	  NEXT_PASS (pass_parallelize_loops);
 	  NEXT_PASS (pass_loop_prefetch);
 	  NEXT_PASS (pass_iv_optimize);
-	  NEXT_PASS (pass_lim);
+	  NEXT_PASS_IDX (pass_lim, 2);
 	  NEXT_PASS (pass_tree_loop_done);
       POP_INSERT_PASSES ()
-      NEXT_PASS (pass_lower_vector_ssa);
+      NEXT_PASS_IDX (pass_lower_vector_ssa, 0);
       NEXT_PASS (pass_cse_reciprocals);
-      NEXT_PASS (pass_reassoc);
+      NEXT_PASS_IDX (pass_reassoc, 1);
       NEXT_PASS (pass_strength_reduction);
-      NEXT_PASS (pass_dominator);
+      NEXT_PASS_IDX (pass_dominator, 1);
       /* The only const/copy propagation opportunities left after
 	 DOM should be due to degenerate PHI nodes.  So rather than
 	 run the full propagators, run a specialized pass which
 	 only examines PHIs to discover const/copy propagation
 	 opportunities.  */
-      NEXT_PASS (pass_phi_only_cprop);
-      NEXT_PASS (pass_vrp);
-      NEXT_PASS (pass_cd_dce);
+      NEXT_PASS_IDX (pass_phi_only_cprop, 1);
+      NEXT_PASS_IDX (pass_vrp, 1);
+      NEXT_PASS_IDX (pass_cd_dce, 1);
       NEXT_PASS (pass_tracer);
 
       /* FIXME: If DCE is not run before checking for uninitialized uses,
@@ -248,42 +249,42 @@  along with GCC; see the file COPYING3.  If not see
 	 account for the predicates protecting the set and the use of each
 	 variable.  Using a representation like Gated Single Assignment
 	 may help.  */
-      NEXT_PASS (pass_late_warn_uninitialized);
-      NEXT_PASS (pass_dse);
-      NEXT_PASS (pass_forwprop);
+      NEXT_PASS_IDX (pass_late_warn_uninitialized, 0);
+      NEXT_PASS_IDX (pass_dse, 1);
+      NEXT_PASS_IDX (pass_forwprop, 3);
       NEXT_PASS (pass_phiopt);
-      NEXT_PASS (pass_fold_builtins);
+      NEXT_PASS_IDX (pass_fold_builtins, 0);
       NEXT_PASS (pass_optimize_widening_mul);
       NEXT_PASS (pass_tail_calls);
-      NEXT_PASS (pass_rename_ssa_copies);
-      NEXT_PASS (pass_uncprop);
-      NEXT_PASS (pass_local_pure_const);
+      NEXT_PASS_IDX (pass_rename_ssa_copies, 3);
+      NEXT_PASS_IDX (pass_uncprop, 0);
+      NEXT_PASS_IDX (pass_local_pure_const, 1);
   POP_INSERT_PASSES ()
   NEXT_PASS (pass_all_optimizations_g);
   PUSH_INSERT_PASSES_WITHIN (pass_all_optimizations_g)
       NEXT_PASS (pass_remove_cgraph_callee_edges);
-      NEXT_PASS (pass_strip_predict_hints);
+      NEXT_PASS_IDX (pass_strip_predict_hints, 1);
       /* Lower remaining pieces of GIMPLE.  */
-      NEXT_PASS (pass_lower_complex);
-      NEXT_PASS (pass_lower_vector_ssa);
+      NEXT_PASS_IDX (pass_lower_complex, 1);
+      NEXT_PASS_IDX (pass_lower_vector_ssa, 1);
       /* Perform simple scalar cleanup which is constant/copy propagation.  */
-      NEXT_PASS (pass_ccp);
-      NEXT_PASS (pass_object_sizes);
+      NEXT_PASS_IDX (pass_ccp, 3);
+      NEXT_PASS_IDX (pass_object_sizes, 1);
       /* Copy propagation also copy-propagates constants, this is necessary
          to forward object-size results properly.  */
-      NEXT_PASS (pass_copy_prop);
-      NEXT_PASS (pass_asan);
-      NEXT_PASS (pass_tsan);
-      NEXT_PASS (pass_rename_ssa_copies);
+      NEXT_PASS_IDX (pass_copy_prop, 6);
+      NEXT_PASS_IDX (pass_asan, 1);
+      NEXT_PASS_IDX (pass_tsan, 1);
+      NEXT_PASS_IDX (pass_rename_ssa_copies, 4);
       NEXT_PASS (pass_dce);
       /* Fold remaining builtins.  */
-      NEXT_PASS (pass_fold_builtins);
+      NEXT_PASS_IDX (pass_fold_builtins, 1);
       /* ???  We do want some kind of loop invariant motion, but we possibly
          need to adjust LIM to be more friendly towards preserving accurate
 	 debug information here.  */
-      NEXT_PASS (pass_late_warn_uninitialized);
-      NEXT_PASS (pass_uncprop);
-      NEXT_PASS (pass_local_pure_const);
+      NEXT_PASS_IDX (pass_late_warn_uninitialized, 1);
+      NEXT_PASS_IDX (pass_uncprop, 1);
+      NEXT_PASS_IDX (pass_local_pure_const, 2);
   POP_INSERT_PASSES ()
   NEXT_PASS (pass_tm_init);
   PUSH_INSERT_PASSES_WITHIN (pass_tm_init)
@@ -295,7 +296,7 @@  along with GCC; see the file COPYING3.  If not see
   NEXT_PASS (pass_lower_complex_O0);
   NEXT_PASS (pass_asan_O0);
   NEXT_PASS (pass_tsan_O0);
-  NEXT_PASS (pass_cleanup_eh);
+  NEXT_PASS_IDX (pass_cleanup_eh, 1);
   NEXT_PASS (pass_lower_resx);
   NEXT_PASS (pass_nrv);
   NEXT_PASS (pass_mudflap_2);
@@ -313,10 +314,10 @@  along with GCC; see the file COPYING3.  If not see
       NEXT_PASS (pass_df_initialize_opt);
       NEXT_PASS (pass_cse);
       NEXT_PASS (pass_rtl_fwprop);
-      NEXT_PASS (pass_rtl_cprop);
+      NEXT_PASS_IDX (pass_rtl_cprop, 0);
       NEXT_PASS (pass_rtl_pre);
       NEXT_PASS (pass_rtl_hoist);
-      NEXT_PASS (pass_rtl_cprop);
+      NEXT_PASS_IDX (pass_rtl_cprop, 1);
       NEXT_PASS (pass_rtl_store_motion);
       NEXT_PASS (pass_cse_after_global_opts);
       NEXT_PASS (pass_rtl_ifcvt);
@@ -335,7 +336,7 @@  along with GCC; see the file COPYING3.  If not see
 	  TERMINATE_PASS_LIST ()
       POP_INSERT_PASSES ()
       NEXT_PASS (pass_web);
-      NEXT_PASS (pass_rtl_cprop);
+      NEXT_PASS_IDX (pass_rtl_cprop, 2);
       NEXT_PASS (pass_cse2);
       NEXT_PASS (pass_rtl_dse1);
       NEXT_PASS (pass_rtl_fwprop_addr);
diff --git a/gcc/pipeline.h b/gcc/pipeline.h
new file mode 100644
index 0000000..900c107
--- /dev/null
+++ b/gcc/pipeline.h
@@ -0,0 +1,71 @@ 
+/* pipeline.h - The pipeline of optimization passes
+   Copyright (C) 2013 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 3, or (at your option) any later
+version.
+
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
+
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3.  If not see
+<http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_PIPELINE_H
+#define GCC_PIPELINE_H
+
+class pipeline
+{
+public:
+  opt_pass *get_pass_for_id (int id) const;
+  void set_pass_for_id (int id, opt_pass *pass);
+
+public:
+  /* The root of the compilation pass tree, once constructed.  */
+  opt_pass *all_passes;
+  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.  */
+  opt_pass **passes_by_id;
+  int passes_by_id_size;
+
+  /* References to all of the individual passes.
+
+     These fields are generated via macro expansion
+
+     For example:
+         NEXT_PASS (pass_build_cfg);
+     within passes.def means that there is a field:
+         opt_pass *pass_build_cfg;
+  */
+#define INSERT_PASSES_AFTER(PASS)
+#define PUSH_INSERT_PASSES_WITHIN(PASS)
+#define POP_INSERT_PASSES()
+#define NEXT_PASS(PASS) \
+  opt_pass *PASS
+#define NEXT_PASS_IDX(PASS, IDX) opt_pass * PASS ## _ ## IDX
+#define TERMINATE_PASS_LIST()
+
+#include "passes.def"
+
+#undef INSERT_PASSES_AFTER
+#undef PUSH_INSERT_PASSES_WITHIN
+#undef POP_INSERT_PASSES
+#undef NEXT_PASS
+#undef NEXT_PASS_IDX
+#undef TERMINATE_PASS_LIST
+
+};
+
+#endif /* ! GCC_PIPELINE_H */
+
diff --git a/gcc/statistics.c b/gcc/statistics.c
index 3b9685d..75588fc 100644
--- a/gcc/statistics.c
+++ b/gcc/statistics.c
@@ -26,6 +26,8 @@  along with GCC; see the file COPYING3.  If not see
 #include "statistics.h"
 #include "hashtab.h"
 #include "function.h"
+#include "context.h"
+#include "pipeline.h"
 
 static int statistics_dump_nr;
 static int statistics_dump_flags;
@@ -223,6 +225,8 @@  statistics_fini_1 (void **slot, void *data)
 void
 statistics_fini (void)
 {
+  pipeline *passes = the_ctxt.passes;
+
   if (!statistics_dump_file)
     return;
 
@@ -231,9 +235,9 @@  statistics_fini (void)
       unsigned i;
       for (i = 0; i < nr_statistics_hashes; ++i)
 	if (statistics_hashes[i] != NULL
-	    && get_pass_for_id (i) != NULL)
+	    && passes->get_pass_for_id (i) != NULL)
 	  htab_traverse_noresize (statistics_hashes[i],
-				  statistics_fini_1, get_pass_for_id (i));
+				  statistics_fini_1, passes->get_pass_for_id (i));
     }
 
   dump_end (statistics_dump_nr, statistics_dump_file);
diff --git a/gcc/testsuite/g++.dg/plugin/dumb_plugin.c b/gcc/testsuite/g++.dg/plugin/dumb_plugin.c
index b1610de..984ce16 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;
 
@@ -134,7 +135,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 (the_ctxt);
   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 1b5298a..4816193 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;
 
@@ -319,7 +320,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 (the_ctxt);
   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 4ef813d..c08161e 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;
 
@@ -63,7 +64,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 (the_ctxt);
   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 1b5298a..4816193 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;
 
@@ -319,7 +320,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 (the_ctxt);
   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 b85917d..92d7109 100644
--- a/gcc/toplev.c
+++ b/gcc/toplev.c
@@ -74,6 +74,7 @@  along with GCC; see the file COPYING3.  If not see
 #include "gimple.h"
 #include "tree-ssa-alias.h"
 #include "plugin.h"
+#include "context.h"
 
 #if defined(DBX_DEBUGGING_INFO) || defined(XCOFF_DEBUGGING_INFO)
 #include "dbxout.h"
@@ -1880,6 +1881,9 @@  do_compile (void)
   timevar_print (stderr);
 }
 
+/* The singleton holder of global state: */
+context the_ctxt;
+
 /* 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.
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 24e5d20..2a1e95c 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -25,6 +25,10 @@  along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "dumpfile.h"
 
+class context;
+class pipeline;
+class opt_pass;
+
 /* Optimization pass type.  */
 enum opt_pass_type
 {
@@ -34,10 +38,122 @@  enum opt_pass_type
   IPA_PASS
 };
 
+/* Helper structs so that various property and todo flags can be
+   self-documenting: */
+struct required
+{
+public:
+  required(unsigned int flags) : flags(flags)  {}
+
+  unsigned int flags;
+};
+
+struct provided
+{
+public:
+  provided(unsigned int flags) : flags(flags) {}
+
+  unsigned int flags;
+};
+
+struct destroyed
+{
+public:
+  destroyed(unsigned int flags) : flags(flags) {}
+
+  unsigned int flags;
+};
+
+struct start
+{
+public:
+  start(unsigned int flags) : flags(flags) {}
+
+  unsigned int flags;
+};
+
+struct finish
+{
+public:
+  finish(unsigned int flags) : flags(flags) {}
+
+  unsigned int flags;
+};
+
+/* Sets of properties input and output from this pass.  */
+struct pass_properties
+{
+public:
+  pass_properties(const required &required,
+		  const provided &provided,
+		  const destroyed &destroyed)
+    : required(required.flags),
+      provided(provided.flags),
+      destroyed(destroyed.flags)
+  {}
+
+  unsigned int required;
+  unsigned int provided;
+  unsigned int destroyed;
+};
+
+/* Flags indicating common sets things to do before and after a pass.  */
+struct pass_todo_flags
+{
+public:
+  pass_todo_flags(const start &start,
+		  const finish &finish)
+    : start(start.flags),
+      finish(finish.flags)
+  {}
+
+  unsigned int start;
+  unsigned int finish;
+};
+
 /* Describe one pass; this is the common part shared across different pass
    types.  */
-struct opt_pass
+class opt_pass
 {
+public:
+  virtual ~opt_pass () { }
+
+  /* Public Methods */
+
+  /* This pass and all sub-passes are executed only if
+     the function returns true.  */
+  virtual bool has_gate () { return false; }
+  virtual bool gate () { return true; }
+
+  /* This is the code to run. The return value contains
+     TODOs to execute in addition to those in TODO_flags_finish.   */
+  virtual bool has_execute () = 0;
+  virtual unsigned int impl_execute () = 0;
+
+protected:
+  opt_pass(context &ctxt,
+	   enum opt_pass_type type,
+	   const char *name,
+	   unsigned int optinfo_flags,
+	   timevar_id_t tv_id,
+	   const pass_properties &props,
+	   const pass_todo_flags &todo_flags)
+    : ctxt(ctxt),
+      type(type),
+      name(name),
+      optinfo_flags(optinfo_flags),
+      sub(NULL),
+      next(NULL),
+      static_pass_number(0),
+      tv_id(tv_id),
+      props(props),
+      todo_flags(todo_flags)
+  {}
+
+/* We should eventually make these fields private: */
+public:
+  context &ctxt;
+
   /* Optimization pass type.  */
   enum opt_pass_type type;
 
@@ -48,15 +164,6 @@  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);
-
-  /* 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;
 
@@ -70,26 +177,48 @@  struct opt_pass
   /* ??? Ideally would be dynamically assigned.  */
   timevar_id_t tv_id;
 
-  /* Sets of properties input and output from this pass.  */
-  unsigned int properties_required;
-  unsigned int properties_provided;
-  unsigned int properties_destroyed;
-
-  /* Flags indicating common sets things to do before and after.  */
-  unsigned int todo_flags_start;
-  unsigned int todo_flags_finish;
+  pass_properties props;
+  pass_todo_flags todo_flags;
 };
 
 /* Description of GIMPLE pass.  */
-struct gimple_opt_pass
+class gimple_opt_pass : public opt_pass
 {
-  struct opt_pass pass;
+public:
+  gimple_opt_pass(context &ctxt,
+		  const char *name,
+		  unsigned int optinfo_flags,
+		  timevar_id_t tv_id,
+		  const pass_properties &props,
+		  const pass_todo_flags &todo_flags)
+    : opt_pass(ctxt,
+	       GIMPLE_PASS,
+	       name,
+	       optinfo_flags,
+	       tv_id,
+	       props,
+	       todo_flags)
+  {}
 };
 
 /* Description of RTL pass.  */
-struct rtl_opt_pass
+class rtl_opt_pass : public opt_pass
 {
-  struct opt_pass pass;
+public:
+  rtl_opt_pass(context &ctxt,
+	       const char *name,
+	       unsigned int optinfo_flags,
+	       timevar_id_t tv_id,
+	       const pass_properties &props,
+	       const pass_todo_flags &todo_flags)
+    : opt_pass(ctxt,
+	       RTL_PASS,
+	       name,
+	       optinfo_flags,
+	       tv_id,
+	       props,
+	       todo_flags)
+  {}
 };
 
 struct varpool_node;
@@ -98,42 +227,82 @@  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_opt_pass_d(context &ctxt,
+		 const char *name,
+		 unsigned int optinfo_flags,
+		 timevar_id_t tv_id,
+		 const pass_properties &props,
+		 const pass_todo_flags &todo_flags,
+		 unsigned int function_transform_todo_flags_start)
+    : opt_pass(ctxt,
+	       IPA_PASS,
+	       name,
+	       optinfo_flags,
+	       tv_id,
+	       props,
+	       todo_flags),
+      function_transform_todo_flags_start(function_transform_todo_flags_start)
+  {}
 
   /* IPA passes can analyze function body and variable initializers
       using this hook and produce summary.  */
-  void (*generate_summary) (void);
+  virtual bool has_generate_summary () = 0;
+  virtual void impl_generate_summary () = 0;
 
   /* This hook is used to serialize IPA summaries on disk.  */
-  void (*write_summary) (void);
+  virtual bool has_write_summary () = 0;
+  virtual void impl_write_summary () = 0;
 
   /* This hook is used to deserialize IPA summaries from disk.  */
-  void (*read_summary) (void);
+  virtual bool has_read_summary () = 0;
+  virtual void impl_read_summary () = 0;
 
   /* This hook is used to serialize IPA optimization summaries on disk.  */
-  void (*write_optimization_summary) (void);
+  virtual bool has_write_optimization_summary () = 0;
+  virtual void impl_write_optimization_summary () = 0;
 
   /* This hook is used to deserialize IPA summaries from disk.  */
-  void (*read_optimization_summary) (void);
+  virtual bool has_read_optimization_summary () = 0;
+  virtual void impl_read_optimization_summary () = 0;
 
   /* Hook to convert gimple stmt uids into true gimple statements.  The second
      parameter is an array of statements indexed by their uid. */
-  void (*stmt_fixup) (struct cgraph_node *, gimple *);
+  virtual bool has_stmt_fixup () = 0;
+  virtual void impl_stmt_fixup (struct cgraph_node *, gimple *) = 0;
+
+  virtual bool has_function_transform () = 0;
+  virtual unsigned int impl_function_transform (struct cgraph_node *) = 0;
+
+  virtual bool has_variable_transform () = 0;
+  virtual void impl_variable_transform (struct varpool_node *) = 0;
 
   /* Results of interprocedural propagation of an IPA pass is applied to
      function body via this hook.  */
   unsigned int function_transform_todo_flags_start;
-  unsigned int (*function_transform) (struct cgraph_node *);
-  void (*variable_transform) (struct varpool_node *);
 };
 
 /* 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;
+public:
+  simple_ipa_opt_pass(context &ctxt,
+		      const char *name,
+		      unsigned int optinfo_flags,
+		      timevar_id_t tv_id,
+		      const pass_properties &props,
+		      const pass_todo_flags &todo_flags)
+    : opt_pass(ctxt,
+	       SIMPLE_IPA_PASS,
+	       name,
+	       optinfo_flags,
+	       tv_id,
+	       props,
+	       todo_flags)
+  {}
 };
 
 /* Pass properties.  */
@@ -490,10 +659,6 @@  extern gimple_opt_pass *make_pass_inline_parameters (context &ctxt);
 extern gimple_opt_pass *make_pass_update_address_taken (context &ctxt);
 extern gimple_opt_pass *make_pass_convert_switch (context &ctxt);
 
-/* The root of the compilation pass tree, once constructed.  */
-extern struct opt_pass *all_passes, *all_small_ipa_passes, *all_lowering_passes,
-                       *all_regular_ipa_passes, *all_lto_gen_passes, *all_late_ipa_passes;
-
 /* Define a list of pass lists so that both passes.c and plugins can easily
    find all the pass lists.  */
 #define GCC_PASS_LISTS \
@@ -511,14 +676,9 @@  enum
 };
 #undef DEF_PASS_LIST
 
-/* This is used by plugins, and should also be used in
-   passes.c:register_pass.  */
-extern struct opt_pass **gcc_pass_lists[];
-
 /* Current optimization pass.  */
 extern struct opt_pass *current_pass;
 
-extern struct opt_pass * get_pass_for_id (int);
 extern bool execute_one_pass (struct opt_pass *);
 extern void execute_pass_list (struct opt_pass *);
 extern void execute_ipa_pass_list (struct opt_pass *);
@@ -548,9 +708,6 @@  extern void register_pass (struct register_pass_info *);
    directly in jump threading, and avoid peeling them next time.  */
 extern bool first_pass_instance;
 
-extern struct opt_pass **passes_by_id;
-extern int passes_by_id_size;
-
 /* Declare for plugins.  */
 extern void do_per_function_toporder (void (*) (void *), void *);