Patchwork RFC: elimination of global state relating to passes

login
register
mail settings
Submitter David Malcolm
Date April 3, 2013, 4:13 p.m.
Message ID <1365005585.24820.35.camel@surprise>
Download mbox | patch
Permalink /patch/233553/
State New
Headers show

Comments

David Malcolm - April 3, 2013, 4:13 p.m.
I'm working on my first gcc contribution, but it's a large patch, and I
wanted to sound things out on this list.

I want to eliminate/minimize global state within gcc, since I think
doing so is a key part of making gcc more modular.

Currently there's a lot of global state associated with passes:
* the pass tree itself: a single global tree of passes, with callbacks
("gate" and "execute")
* globals within individual pass .c files

My plan is to instead have the passes be dynamically created instances
of pass subclasses, where each pass has a custom subclass of the
appropriate pass class:

So, for example, mudflap would become something like:

   class pass_mudflap_2 : public gimple_opt_pass
   {
     public:
      bool gate() { return gate_mudflap(); }
      unsigned int execute() { return execute_mudflap_function_ops(); }
   };

where these subclasses are hidden inside the .c files (in this case
inside gcc/tree-mudflap.c).

All that's exposed to the headers would then be a factory function:

  gimple_opt_pass *
  make_pass_mudflap_2 (context &ctxt)
  {
     return new pass_mudflap_2 (ctxt);
  }

Globals within a .c file that are specific to a particular pass may then
be movable to instance data of the pass subclass (on a case-by-case
basis).

Each pass also has a reference back to a new "context" class, shared by
all the passes: this is currently empty, but I see it being useful as a
place to add any global state that isn't part of the pass itself: given
that this patch is touching hundreds of files I'd rather add it now,
rather than having to go back and add it later.

I started doing this by hand, however, there are hundreds of passes, so
to avoid lots of error-prone typing I've written a refactoring script.

You can see the test suite for the refactoring script here:
https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/test_refactor.py
which should give a better idea of the before/after when applying the
refactoring (and the use of a test suite hopefully increases the
credibility that the resulting patch doesn't change the effective
behavior of the code).

When run, the refactoring script generates this
107 files changed, 5008 insertions(+), 4214 deletions(-)

There's also a hand-written part of the patch, which I'm attaching the
most pertinent parts of i.e. gcc/tree-pass.h

It doesn't quite compile yet, gcc/passes.c needs work - in particular
the code to construct and manage the tree of passes (I think I can do
this, but it may need moving the bulk of init_optimization_passes() into
a new passes.def file so that I can include it again elsewhere with a
different defintion of NEXT_PASS).   There's also a new "pipeline" class
representing the pass hierarchy, which stores the pointers to the pass
instances, so that it's easy to access them from gdb when debugging.

One wart in my plan is that a lot of the existing callbacks are checked
against NULL and if non-NULL, then extra things happen before/after the
call.

I don't know of a portable way to do this for a C++ virtual function, so
each callback becomes *two* vtable entries:
  bool has_FOO()   // equivalent to (pass->FOO != NULL) in old code
and 
  impl_FOO()       // equivalent to (pass->FOO ()) in old code

I'm currently working off of this git repo:
  git://gcc.gnu.org/git/gcc.git
in the hope of getting this into 4.9 during stage 1.

Hope this is constructive
Dave
Richard Guenther - April 4, 2013, 8:42 a.m.
On Wed, Apr 3, 2013 at 6:13 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> I'm working on my first gcc contribution, but it's a large patch, and I
> wanted to sound things out on this list.
>
> I want to eliminate/minimize global state within gcc, since I think
> doing so is a key part of making gcc more modular.
>
> Currently there's a lot of global state associated with passes:
> * the pass tree itself: a single global tree of passes, with callbacks
> ("gate" and "execute")
> * globals within individual pass .c files
>
> My plan is to instead have the passes be dynamically created instances
> of pass subclasses, where each pass has a custom subclass of the
> appropriate pass class:
>
> So, for example, mudflap would become something like:
>
>    class pass_mudflap_2 : public gimple_opt_pass
>    {
>      public:
>       bool gate() { return gate_mudflap(); }
>       unsigned int execute() { return execute_mudflap_function_ops(); }
>    };
>
> where these subclasses are hidden inside the .c files (in this case
> inside gcc/tree-mudflap.c).
>
> All that's exposed to the headers would then be a factory function:
>
>   gimple_opt_pass *
>   make_pass_mudflap_2 (context &ctxt)
>   {
>      return new pass_mudflap_2 (ctxt);
>   }
>
> Globals within a .c file that are specific to a particular pass may then
> be movable to instance data of the pass subclass (on a case-by-case
> basis).
>
> Each pass also has a reference back to a new "context" class, shared by
> all the passes: this is currently empty, but I see it being useful as a
> place to add any global state that isn't part of the pass itself: given
> that this patch is touching hundreds of files I'd rather add it now,
> rather than having to go back and add it later.
>
> I started doing this by hand, however, there are hundreds of passes, so
> to avoid lots of error-prone typing I've written a refactoring script.
>
> You can see the test suite for the refactoring script here:
> https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/test_refactor.py
> which should give a better idea of the before/after when applying the
> refactoring (and the use of a test suite hopefully increases the
> credibility that the resulting patch doesn't change the effective
> behavior of the code).
>
> When run, the refactoring script generates this
> 107 files changed, 5008 insertions(+), 4214 deletions(-)
>
> There's also a hand-written part of the patch, which I'm attaching the
> most pertinent parts of i.e. gcc/tree-pass.h

Sounds like a good plan - though I doubt moving "global" pass state
into pass class members will be easy for refactoring (all functions
refering to that data would need to become member functions).

Eventually having both mechanisms in place for a transition time
and convert each pass separately is easier to review.

> It doesn't quite compile yet, gcc/passes.c needs work - in particular
> the code to construct and manage the tree of passes (I think I can do
> this, but it may need moving the bulk of init_optimization_passes() into
> a new passes.def file so that I can include it again elsewhere with a
> different defintion of NEXT_PASS).   There's also a new "pipeline" class
> representing the pass hierarchy, which stores the pointers to the pass
> instances, so that it's easy to access them from gdb when debugging.

One of my silly plans was to make the tree of passes dynamic - thus
no longer static in source as it is right now.  Mainly to allow easier
experiments with re-ordering of passes but also to allow "dynamic"
pass scheduling, like do { pass1, pass2, ... } until nothing changes.
Basically have a tiny pass scripting language ;)  Your patches would
make that a lot easier.

One complication is that with dynamic scheduling dumpfile names
suddenly are no longer predictable which is a problem for the testsuite.

> One wart in my plan is that a lot of the existing callbacks are checked
> against NULL and if non-NULL, then extra things happen before/after the
> call.
>
> I don't know of a portable way to do this for a C++ virtual function, so
> each callback becomes *two* vtable entries:
>   bool has_FOO()   // equivalent to (pass->FOO != NULL) in old code
> and
>   impl_FOO()       // equivalent to (pass->FOO ()) in old code

Ick.  It might be easier to figure out what semantics the NULL check
dependent code has and implement that in a more sensible way.

> I'm currently working off of this git repo:
>   git://gcc.gnu.org/git/gcc.git
> in the hope of getting this into 4.9 during stage 1.
>
> Hope this is constructive

For sure.

I originally thought of using namespaces to fend off pass-specific globals,
but eventually moving it all to a pass specific class would work, too.

Note that there are some passes that have global data that is allocated
and initialized once per compilation, so the pass class objects will
probably not be short-lived (like construct / destruct per pass invocation
which would be the cleanest design IMHO, at least for pass local data
lifetime management ...).  Thus eventually the 'pass' object should be
split into a global and per invocation object?

Richard.

> Dave
David Malcolm - April 4, 2013, 2:54 p.m.
On Thu, 2013-04-04 at 10:42 +0200, Richard Biener wrote:

Thanks for looking at this; comments inline throughout.

> On Wed, Apr 3, 2013 at 6:13 PM, David Malcolm <dmalcolm@redhat.com> wrote:
> > I'm working on my first gcc contribution, but it's a large patch, and I
> > wanted to sound things out on this list.
> >
> > I want to eliminate/minimize global state within gcc, since I think
> > doing so is a key part of making gcc more modular.
> >
> > Currently there's a lot of global state associated with passes:
> > * the pass tree itself: a single global tree of passes, with callbacks
> > ("gate" and "execute")
> > * globals within individual pass .c files
> >
> > My plan is to instead have the passes be dynamically created instances
> > of pass subclasses, where each pass has a custom subclass of the
> > appropriate pass class:
> >
> > So, for example, mudflap would become something like:
> >
> >    class pass_mudflap_2 : public gimple_opt_pass
> >    {
> >      public:
> >       bool gate() { return gate_mudflap(); }
> >       unsigned int execute() { return execute_mudflap_function_ops(); }
> >    };
> >
> > where these subclasses are hidden inside the .c files (in this case
> > inside gcc/tree-mudflap.c).
> >
> > All that's exposed to the headers would then be a factory function:
> >
> >   gimple_opt_pass *
> >   make_pass_mudflap_2 (context &ctxt)
> >   {
> >      return new pass_mudflap_2 (ctxt);
> >   }
> >
> > Globals within a .c file that are specific to a particular pass may then
> > be movable to instance data of the pass subclass (on a case-by-case
> > basis).
> >
> > Each pass also has a reference back to a new "context" class, shared by
> > all the passes: this is currently empty, but I see it being useful as a
> > place to add any global state that isn't part of the pass itself: given
> > that this patch is touching hundreds of files I'd rather add it now,
> > rather than having to go back and add it later.
> >
> > I started doing this by hand, however, there are hundreds of passes, so
> > to avoid lots of error-prone typing I've written a refactoring script.
> >
> > You can see the test suite for the refactoring script here:
> > https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/test_refactor.py
> > which should give a better idea of the before/after when applying the
> > refactoring (and the use of a test suite hopefully increases the
> > credibility that the resulting patch doesn't change the effective
> > behavior of the code).
> >
> > When run, the refactoring script generates this
> > 107 files changed, 5008 insertions(+), 4214 deletions(-)
> >
> > There's also a hand-written part of the patch, which I'm attaching the
> > most pertinent parts of i.e. gcc/tree-pass.h
> 
> Sounds like a good plan - though I doubt moving "global" pass state
> into pass class members will be easy for refactoring (all functions
> refering to that data would need to become member functions).
> 
> Eventually having both mechanisms in place for a transition time
> and convert each pass separately is easier to review.


Perhaps the use of "friend" on those functions would make for a good
transition path, minimizing the size of the code diffs, whilst giving us
the state-encapsulation that I'm trying for..


> > It doesn't quite compile yet, gcc/passes.c needs work - in particular
> > the code to construct and manage the tree of passes (I think I can do
> > this, but it may need moving the bulk of init_optimization_passes() into
> > a new passes.def file so that I can include it again elsewhere with a
> > different defintion of NEXT_PASS).   There's also a new "pipeline" class
> > representing the pass hierarchy, which stores the pointers to the pass
> > instances, so that it's easy to access them from gdb when debugging.
> 
> One of my silly plans was to make the tree of passes dynamic - thus
> no longer static in source as it is right now.  Mainly to allow easier
> experiments with re-ordering of passes but also to allow "dynamic"
> pass scheduling, like do { pass1, pass2, ... } until nothing changes.
> Basically have a tiny pass scripting language ;)  Your patches would
> make that a lot easier.

(nods)

> One complication is that with dynamic scheduling dumpfile names
> suddenly are no longer predictable which is a problem for the testsuite.

Thanks for the heads-up :)

> > One wart in my plan is that a lot of the existing callbacks are checked
> > against NULL and if non-NULL, then extra things happen before/after the
> > call.
> >
> > I don't know of a portable way to do this for a C++ virtual function, so
> > each callback becomes *two* vtable entries:
> >   bool has_FOO()   // equivalent to (pass->FOO != NULL) in old code
> > and
> >   impl_FOO()       // equivalent to (pass->FOO ()) in old code
> 
> Ick.  It might be easier to figure out what semantics the NULL check
> dependent code has and implement that in a more sensible way.

It's this kind of code from gcc/passes.c; see annotations inline:

  void
  execute_ipa_summary_passes (struct ipa_opt_pass_d *ipa_pass)
  {
    while (ipa_pass)
      {
        struct opt_pass *pass = ipa_pass;

        /* Execute all of the IPA_PASSes in the list.  */
        if (ipa_pass->type == IPA_PASS
           && pass->gate ()
-          && ipa_pass->generate_summary)
+	   && ipa_pass->has_generate_summary ())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
^^^ Here's the conditional
	{

Non-trivial setup code follows:

	  pass_init_dump_file (pass);

	  /* If a timevar is present, start it.  */
	  if (pass->tv_id)
	    timevar_push (pass->tv_id);


Here's the actual virtual function call:
-         ipa_pass->generate_summary ();
+	  ipa_pass->impl_generate_summary ();

and here's the non-trivial cleanup code:

	  /* Stop timevar.  */
	  if (pass->tv_id)
	    timevar_pop (pass->tv_id);

	  pass_fini_dump_file (pass);
	}
      ipa_pass = (struct ipa_opt_pass_d *)ipa_pass->next;
    }
}

so the rather ugly "has_generate_summary()" exists to try to avoid any
behavior changes relative to the old "ipa_pass->generate_summary (!
=NULL)" code (given that this is going to be a huge patch, I want to
avoid touching anything I don't need to).  I wonder if there's a
cleaner, portable way of achieving this?

> > I'm currently working off of this git repo:
> >   git://gcc.gnu.org/git/gcc.git
> > in the hope of getting this into 4.9 during stage 1.
> >
> > Hope this is constructive
> 
> For sure.
> 
> I originally thought of using namespaces to fend off pass-specific globals,
> but eventually moving it all to a pass specific class would work, too.
> 
> Note that there are some passes that have global data that is allocated
> and initialized once per compilation, so the pass class objects will
> probably not be short-lived (like construct / destruct per pass invocation
> which would be the cleanest design IMHO, at least for pass local data
> lifetime management ...).  Thus eventually the 'pass' object should be
> split into a global and per invocation object?

My idea is that there's a:

  class pipeline;
  pipeline *passes;

pipeline instance representing the tree of passes, constructed once at
the beginning of compilation, which constructs and holds references on
the pass objects (I'm still working on this aspect of the patch).  The
individual pass objects' (and their internal state) thus have
whole-compilation lifetime.

Thanks again for looking at the patch
Dave
Jakub Jelinek - April 4, 2013, 3:07 p.m.
On Thu, Apr 04, 2013 at 10:42:47AM +0200, Richard Biener wrote:
> I originally thought of using namespaces to fend off pass-specific globals,
> but eventually moving it all to a pass specific class would work, too.
> 
> Note that there are some passes that have global data that is allocated
> and initialized once per compilation, so the pass class objects will
> probably not be short-lived (like construct / destruct per pass invocation
> which would be the cleanest design IMHO, at least for pass local data
> lifetime management ...).  Thus eventually the 'pass' object should be
> split into a global and per invocation object?

But you don't want to pass around to all functions two extra pointers (for
global and per invocation object).  Also, some of the global state, even the
intra-pass ostate that is initialized once, is GTY, we'd need to somehow
arrange for that to be walked by GC.
Passing this or context pointers to half of the functions in the compiler
might be quite expensive, wonder if just making all the global vars __thread
when building the library variant (in form of some macro that would expand
to nothing for the supposedly faster compiler binary) wouldn't be cheaper,
if you run the whole or most of the optimization pipeline, you probably
aren't going to interrupt it many times and run 3 passes on CU 1, 3 passes
on CU 2, 3 passes on CU 3 in the same thread.

	Jakub
David Malcolm - April 20, 2013, 1:22 a.m.
I want to eliminate/minimize global state within gcc, since I think
doing so is a key part of making gcc more modular.

Currently there's a lot of global state associated with passes:
* the pass tree itself: a single global tree of passes, with callbacks
("gate" and "execute")
* globals within individual pass .c files

My plan is to instead have the passes be dynamically created instances
of pass subclasses, where each pass has a custom subclass of the
appropriate pass class:

So, for example, mudflap would become something like:

   class pass_mudflap_2 : public gimple_opt_pass
   {
     public:
      bool gate () { return gate_mudflap(); }
      unsigned int execute () { return execute_mudflap_function_ops(); }
   };

where these subclasses are hidden inside the .c files (in this case
inside gcc/tree-mudflap.c).

All that's exposed to the headers would then be a factory function:

  gimple_opt_pass *
  make_pass_mudflap_2 (context &ctxt)
  {
     return new pass_mudflap_2 (ctxt);
  }

Globals within a .c file that are specific to a particular pass may then
be movable to instance data of the pass subclass (on a case-by-case
basis).

Each pass also has a reference back to a new "context" class, shared by
all the passes: this is currently empty, but I see it being useful as a
place to add any global state that isn't part of the pass itself: given
that this patch is touching hundreds of files I'd rather add it now,
rather than having to go back and add it later.

I started doing this by hand, however, there are hundreds of passes, so
to avoid lots of error-prone typing I've written a refactoring script.

You can see the test suite for the refactoring script here:
https://github.com/davidmalcolm/gcc-refactoring-scripts/blob/master/test_refactor.py
which should give a better idea of the before/after when applying the
refactoring (and the use of a test suite hopefully increases the
credibility that the resulting patch doesn't change the effective
behavior of the code).

When run, the refactoring script generates this:
 117 files changed, 7668 insertions(+), 4336 deletions(-)

There's also a new "pipeline" class representing the pass hierarchy, which
stores the pointers to the pass instances, so that it's easy to access them
from gdb when debugging.

One wart in my plan is that a lot of the existing callbacks are checked
against NULL and if non-NULL, then extra things happen before/after the
call.

I don't know of a portable way to do this for a C++ virtual function, so
each callback becomes *two* vtable entries:
  bool has_FOO ()   // equivalent to (pass->FOO != NULL) in old code
and 
  impl_FOO ()       // equivalent to (pass->FOO ()) in old code

I'm currently working off of this git repo:
  git://gcc.gnu.org/git/gcc.git
in the hope of getting this into 4.9 during stage 1.

This is my first patch to GCC.

I'm aware of the following remaining issues with this:

* I haven't yet integrated "context" or "pipeline" with the garbage collector
* pass instances are currently allocated using "new"
* there's no error checking for detecting if allocating a pass fails (e.g.
  under very low memory conditions at startup)
* I'm using C++ references for things that can't legally be NULL.  Is this
  OK?  I don't see any mention of them in
    http://gcc.gnu.org/codingconventions.html#Cxx_Language
  but given that they've been in the language for decades and are "just a
  pointer" internally, I assumed that they're OK.
* Should I be manually updating dependencies anywhere? (this patch sequence
  adds three new source file - two .h and a .def)

Having said that, I've successfully done the 3-stage bootstrap (against
gcc-4.7.2-2.fc17.x86_64 on this Fedora 17 x86_64 box), and the great
majority of tests pass:

  $ for f in $(find gcc/testsuite -name "*.log") ; do \
      printf "%s: \n" $f; \
      printf "  PASS: " ; grep -e "^PASS" $f | wc -l ; \
      printf "  FAIL: " ; grep -e "^FAIL" $f | wc -l ; \
    done
  gcc/testsuite/g++/g++.log: 
    PASS: 54447
    FAIL: 50
  gcc/testsuite/gfortran/gfortran.log: 
    PASS: 44038
    FAIL: 13
  gcc/testsuite/objc/objc.log: 
    PASS: 2982
    FAIL: 0
  gcc/testsuite/gcc/gcc.log: 
    PASS: 96473
    FAIL: 629

so I thought it was worth posting for more feedback.

The change is split into the following 6 patches:

  Introduce macros when constructing the tree of passes
  Move the construction of the pass hierarchy into a new passes.def
    file
  Autogenerated part of conversion of passes to instances of C++
    classes
  Handwritten part of conversion of passes to instances of C++ classes
  Introduce virtual functions in
    testsuite/gcc.dg/plugin/one_time_plugin.c
  Example of converting global state to per-pass state

 gcc/ChangeLog                                 | 1578 +++++++++++++++++++++++++
 gcc/asan.c                                    |   94 +-
 gcc/auto-inc-dec.c                            |   46 +-
 gcc/bb-reorder.c                              |  140 ++-
 gcc/bt-load.c                                 |   96 +-
 gcc/cfgcleanup.c                              |   92 +-
 gcc/cfgexpand.c                               |   49 +-
 gcc/cfgrtl.c                                  |  138 ++-
 gcc/cgraphbuild.c                             |  138 ++-
 gcc/cgraphunit.c                              |   32 +-
 gcc/combine-stack-adj.c                       |   48 +-
 gcc/combine.c                                 |   46 +-
 gcc/compare-elim.c                            |   50 +-
 gcc/config/epiphany/epiphany.h                |    4 +-
 gcc/config/epiphany/mode-switch-use.c         |   46 +-
 gcc/config/epiphany/resolve-sw-modes.c        |   47 +-
 gcc/config/i386/i386.c                        |   59 +-
 gcc/config/sparc/sparc.c                      |   48 +-
 gcc/context.h                                 |   35 +
 gcc/cprop.c                                   |   47 +-
 gcc/cse.c                                     |  143 ++-
 gcc/dce.c                                     |   92 +-
 gcc/df-core.c                                 |  142 ++-
 gcc/dse.c                                     |   96 +-
 gcc/dwarf2cfi.c                               |   48 +-
 gcc/except.c                                  |   96 +-
 gcc/final.c                                   |  186 +--
 gcc/function.c                                |  197 +--
 gcc/fwprop.c                                  |   94 +-
 gcc/gcse.c                                    |   94 +-
 gcc/gimple-low.c                              |   46 +-
 gcc/gimple-ssa-strength-reduction.c           |   48 +-
 gcc/ifcvt.c                                   |  143 ++-
 gcc/init-regs.c                               |   48 +-
 gcc/ipa-cp.c                                  |   90 +-
 gcc/ipa-inline-analysis.c                     |   48 +-
 gcc/ipa-inline.c                              |  130 +-
 gcc/ipa-pure-const.c                          |  127 +-
 gcc/ipa-reference.c                           |   85 +-
 gcc/ipa-split.c                               |   94 +-
 gcc/ipa.c                                     |  341 ++++--
 gcc/ira.c                                     |   92 +-
 gcc/jump.c                                    |   46 +-
 gcc/loop-init.c                               |  324 +++--
 gcc/lower-subreg.c                            |   93 +-
 gcc/lto-cgraph.c                              |    9 +-
 gcc/lto-streamer-out.c                        |  162 ++-
 gcc/lto/lto.c                                 |    6 +-
 gcc/mode-switching.c                          |   47 +-
 gcc/modulo-sched.c                            |   50 +-
 gcc/omp-low.c                                 |  138 ++-
 gcc/passes.c                                  |  899 +++++---------
 gcc/passes.def                                |  405 +++++++
 gcc/pipeline.h                                |   71 ++
 gcc/postreload-gcse.c                         |   47 +-
 gcc/postreload.c                              |   47 +-
 gcc/predict.c                                 |   98 +-
 gcc/recog.c                                   |  297 +++--
 gcc/ree.c                                     |   47 +-
 gcc/reg-stack.c                               |   92 +-
 gcc/regcprop.c                                |   47 +-
 gcc/reginfo.c                                 |   46 +-
 gcc/regmove.c                                 |   46 +-
 gcc/regrename.c                               |   47 +-
 gcc/reorg.c                                   |   92 +-
 gcc/sched-rgn.c                               |   98 +-
 gcc/stack-ptr-mod.c                           |   46 +-
 gcc/statistics.c                              |    8 +-
 gcc/store-motion.c                            |   47 +-
 gcc/testsuite/g++.dg/plugin/dumb_plugin.c     |   49 +-
 gcc/testsuite/g++.dg/plugin/selfassign.c      |   49 +-
 gcc/testsuite/gcc.dg/plugin/one_time_plugin.c |   58 +-
 gcc/testsuite/gcc.dg/plugin/selfassign.c      |   49 +-
 gcc/toplev.c                                  |    4 +
 gcc/tracer.c                                  |   47 +-
 gcc/trans-mem.c                               |  336 +++---
 gcc/tree-call-cdce.c                          |   46 +-
 gcc/tree-cfg.c                                |  242 ++--
 gcc/tree-cfgcleanup.c                         |   46 +-
 gcc/tree-complex.c                            |   94 +-
 gcc/tree-eh.c                                 |  231 ++--
 gcc/tree-emutls.c                             |   46 +-
 gcc/tree-if-conv.c                            |   47 +-
 gcc/tree-into-ssa.c                           |   49 +-
 gcc/tree-loop-distribution.c                  |   46 +-
 gcc/tree-mudflap.c                            |   95 +-
 gcc/tree-nomudflap.c                          |   92 +-
 gcc/tree-nrv.c                                |   92 +-
 gcc/tree-object-size.c                        |   46 +-
 gcc/tree-optimize.c                           |   94 +-
 gcc/tree-pass.h                               |  707 ++++++-----
 gcc/tree-profile.c                            |   46 +-
 gcc/tree-sra.c                                |  140 ++-
 gcc/tree-ssa-ccp.c                            |   95 +-
 gcc/tree-ssa-copy.c                           |   48 +-
 gcc/tree-ssa-copyrename.c                     |   46 +-
 gcc/tree-ssa-dce.c                            |  143 ++-
 gcc/tree-ssa-dom.c                            |   98 +-
 gcc/tree-ssa-dse.c                            |   46 +-
 gcc/tree-ssa-forwprop.c                       |   49 +-
 gcc/tree-ssa-ifcombine.c                      |   47 +-
 gcc/tree-ssa-loop-ch.c                        |   48 +-
 gcc/tree-ssa-loop.c                           |  870 ++++++++------
 gcc/tree-ssa-math-opts.c                      |  188 +--
 gcc/tree-ssa-phiopt.c                         |   96 +-
 gcc/tree-ssa-phiprop.c                        |   47 +-
 gcc/tree-ssa-pre.c                            |   93 +-
 gcc/tree-ssa-reassoc.c                        |   48 +-
 gcc/tree-ssa-sink.c                           |   49 +-
 gcc/tree-ssa-strlen.c                         |   46 +-
 gcc/tree-ssa-structalias.c                    |  144 ++-
 gcc/tree-ssa-uncprop.c                        |   46 +-
 gcc/tree-ssa-uninit.c                         |   48 +-
 gcc/tree-ssa.c                                |  140 ++-
 gcc/tree-ssanames.c                           |   46 +-
 gcc/tree-stdarg.c                             |   46 +-
 gcc/tree-switch-conversion.c                  |   49 +-
 gcc/tree-tailcall.c                           |   92 +-
 gcc/tree-vect-generic.c                       |  100 +-
 gcc/tree-vectorizer.c                         |   96 +-
 gcc/tree-vrp.c                                |   51 +-
 gcc/tree.c                                    |   48 +-
 gcc/tsan.c                                    |   92 +-
 gcc/var-tracking.c                            |   49 +-
 gcc/web.c                                     |   46 +-
 125 files changed, 9450 insertions(+), 5119 deletions(-)
 create mode 100644 gcc/context.h
 create mode 100644 gcc/passes.def
 create mode 100644 gcc/pipeline.h
David Malcolm - April 20, 2013, 1:22 a.m.
This patch is 546kb in size, so I've uploaded it to:

http://fedorapeople.org/~dmalcolm/gcc/large-patches/57dc196fd5efa2c59fd57ef21974e8a281f800e3-0003-Autogenerated-part-of-conversion-of-passes-to-instan.patch

Patch

diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 0942ad7..d45b6a5 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -25,6 +25,17 @@  along with GCC; see the file COPYING3.  If not see
 #include "timevar.h"
 #include "dumpfile.h"
 
+class context;
+class pipeline;
+class opt_pass;
+
+/* Holder for state */
+class context
+{
+public:
+  pipeline *passes;
+};
+
 /* Optimization pass type.  */
 enum opt_pass_type
 {
@@ -34,10 +45,80 @@  enum opt_pass_type
   IPA_PASS
 };
 
+/* Sets of properties input and output from this pass.  */
+struct pass_properties
+{
+public:
+  pass_properties(unsigned int required,
+                  unsigned int provided,
+                  unsigned int destroyed)
+    : required(required),
+      provided(provided),
+      destroyed(destroyed)
+  {}
+
+  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(unsigned int start,
+                  unsigned int finish)
+    : start(start),
+      finish(finish)
+  {}
+
+  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 +129,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 +142,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 +192,81 @@  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 void 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.  */