On Tue, 2017-01-17 at 10:28 +0100, Richard Biener wrote: > On Mon, Jan 16, 2017 at 10:42 PM, Jeff Law <l...@redhat.com> wrote: > > On 01/09/2017 07:38 PM, David Malcolm wrote: > > > > > > gcc/ChangeLog: > > > * passes.c: Include "insn-addr.h". > > > (should_skip_pass_p): Add logging. Update logic for > > > running > > > "expand" to be compatible with both __GIMPLE and __RTL. > > > Guard > > > property-provider override so it is only done for gimple > > > passes. > > > Don't skip dfinit. > > > (skip_pass): New function. > > > (execute_one_pass): Call skip_pass when skipping passes. > > > --- > > > gcc/passes.c | 65 > > > +++++++++++++++++++++++++++++++++++++++++++++++++++++------- > > > 1 file changed, 58 insertions(+), 7 deletions(-) > > > > > > diff --git a/gcc/passes.c b/gcc/passes.c > > > index 31262ed..6954d1e 100644 > > > --- a/gcc/passes.c > > > +++ b/gcc/passes.c > > > @@ -59,6 +59,7 @@ along with GCC; see the file COPYING3. If not > > > see > > > #include "cfgrtl.h" > > > #include "tree-ssa-live.h" /* For remove_unused_locals. */ > > > #include "tree-cfgcleanup.h" > > > +#include "insn-addr.h" /* for INSN_ADDRESSES_ALLOC. */ > > > > insn-addr? Yuk. > > > > > > > > > > using namespace gcc; > > > > > > @@ -2315,26 +2316,73 @@ should_skip_pass_p (opt_pass *pass) > > > if (!cfun->pass_startwith) > > > return false; > > > > > > - /* We can't skip the lowering phase yet -- ideally we'd > > > - drive that phase fully via properties. */ > > > - if (!(cfun->curr_properties & PROP_ssa)) > > > - return false; > > > + /* For __GIMPLE functions, we have to at least start when we > > > leave > > > + SSA. */ > > > + if (pass->properties_destroyed & PROP_ssa) > > > + { > > > + if (!quiet_flag) > > > + fprintf (stderr, "starting anyway when leaving SSA: > > > %s\n", > > > pass->name); > > > + cfun->pass_startwith = NULL; > > > + return false; > > > + } > > > > This seems to need a comment -- it's not obvious how destroying the > > SSA > > property maps to a pass that can not be skipped. > > > > > > > > > > > > - /* And also run any property provider. */ > > > - if (pass->properties_provided != 0) > > > + /* Run any property provider. */ > > > + if (pass->type == GIMPLE_PASS > > > + && pass->properties_provided != 0) > > > return false; > > > > So comment needed here too. I read this as "if a gimple pass > > provides a > > property then it should not be skipped. Which means that an RTL > > pass that > > provides a property can? > > > > > > > > > > + /* Don't skip df init; later RTL passes need it. */ > > > + if (strstr (pass->name, "dfinit") != NULL) > > > + return false; > > > > Which seems like a failing in RTL passes saying they need DF init. > > > > > > > > > +/* Skip the given pass, for handling passes before "startwith" > > > + in __GIMPLE and__RTL-marked functions. > > > + In theory, this ought to be a no-op, but some of the RTL > > > passes > > > + need additional processing here. */ > > > + > > > +static void > > > +skip_pass (opt_pass *pass) > > > > ... > > This all feels like a failing in how we handle state in the RTL > > world. And I > > suspect it's prone to error. Imagine if I'm hacking on something > > in the RTL > > world and my code depends on something else being set up. I > > really ought > > to have a way within my pass to indicate what I depend on. Having > > it hidden > > away in passes.c makes it easy to miss/forget. > > > > > > > +{ > > > + /* Pass "reload" sets the global "reload_completed", and many > > > + things depend on this (e.g. instructions in .md files). */ > > > + if (strcmp (pass->name, "reload") == 0) > > > + reload_completed = 1; > > > > Seems like this ought to be a property provided by LRA/reload. > > > > > > > + > > > + /* The INSN_ADDRESSES vec is normally set up by > > > + shorten_branches; set it up for the benefit of passes that > > > + run after this. */ > > > + if (strcmp (pass->name, "shorten") == 0) > > > + INSN_ADDRESSES_ALLOC (get_max_uid ()); > > > > Similarly ought to be provided by shorten-branches > > > > > + > > > + /* Update the cfg hooks as appropriate. */ > > > + if (strcmp (pass->name, "into_cfglayout") == 0) > > > + { > > > + cfg_layout_rtl_register_cfg_hooks (); > > > + cfun->curr_properties |= PROP_cfglayout; > > > + } > > > + if (strcmp (pass->name, "outof_cfglayout") == 0) > > > + { > > > + rtl_register_cfg_hooks (); > > > + cfun->curr_properties &= ~PROP_cfglayout; > > > + } > > > +} > > > > This feels somewhat different, but still a hack. > > > > I don't have strong suggestions on how to approach this, but what > > we've got > > here feels like a hack and one prone to bitrot. > > All the above needs a bit of cleanup in the way we use (or not use) > PROP_xxx. > For example right now you can't startwith a __GIMPLE with a pass > inside the > loop pipeline because those passes expect loops to be initialized and > be in > loop-closed SSA. And with the hack above for the property providers > you'll > always run pass_crited (that's a bad user of a PROP_). > > Ideally we'd figure out required properties from the startwith pass > (but there's not > an easy way to compute it w/o actually "executing" the passes) and > then enable > enough passes on the way to it providing those properties. > > Or finally restructure things in a way that the pass manager > automatically runs > property provider passes before passes requiring properties that are > not yet available... > > Instead of those pass->name comparisions we could invent a new flag > in the > pass structure whether a pass should always be run for __GIMPLE or > ___RTL > but that's a bit noisy right now. > > So I'm fine with the (localized) "hacks" for the moment. >
Another approach for handling this would be to add another virtual function to class opt_pass, something like: virtual void skip (); The patch as-is groups together all of the various state-management hacks into passes.c:skip_pass, whereas with a virtual function, all of these hacks could be moved to the passes themselves. Here's a patch (on top of 9e) which implements the idea. Do you prefer this approach? gcc/ChangeLog: * cfgrtl.c (pass_into_cfg_layout_mode::skip): New method. (pass_outof_cfg_layout_mode::skip): New method. * final.c (pass_shorten_branches::skip): New method. * ira.c (pass_reload::skip): New method. * passes.c: Drop redundant include of "insn-addr.h". (opt_pass::skip): New method. (skip_pass): Delete. (execute_one_pass): Use virtual function when skipping passes. * tree-pass.h (opt_pass::skip): New virtual function. --- gcc/cfgrtl.c | 22 ++++++++++++++++++++++ gcc/final.c | 9 +++++++++ gcc/ira.c | 9 +++++++++ gcc/passes.c | 42 ++++++++---------------------------------- gcc/tree-pass.h | 8 ++++++++ 5 files changed, 56 insertions(+), 34 deletions(-) diff --git a/gcc/cfgrtl.c b/gcc/cfgrtl.c index b3b1146..953f807 100644 --- a/gcc/cfgrtl.c +++ b/gcc/cfgrtl.c @@ -3519,9 +3519,20 @@ public: cfg_layout_initialize (0); return 0; } + void skip (function *) FINAL OVERRIDE; }; // class pass_into_cfg_layout_mode +/* Minimal version of this pass, for use when skipping this pass + with __RTL functions that start at a later pass. */ + +void +pass_into_cfg_layout_mode::skip (function *) +{ + cfg_layout_rtl_register_cfg_hooks (); + cfun->curr_properties |= PROP_cfglayout; +} + } // anon namespace rtl_opt_pass * @@ -3554,6 +3565,7 @@ public: /* opt_pass methods: */ virtual unsigned int execute (function *); + void skip (function *) FINAL OVERRIDE; }; // class pass_outof_cfg_layout_mode @@ -3571,6 +3583,16 @@ pass_outof_cfg_layout_mode::execute (function *fun) return 0; } +/* Minimal version of this pass, for use when skipping this pass + with __RTL functions that start at a later pass. */ + +void +pass_outof_cfg_layout_mode::skip (function *) +{ + rtl_register_cfg_hooks (); + cfun->curr_properties &= ~PROP_cfglayout; +} + } // anon namespace rtl_opt_pass * diff --git a/gcc/final.c b/gcc/final.c index 2483381..e869031 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -4594,6 +4594,15 @@ public: return rest_of_handle_shorten_branches (); } + /* The INSN_ADDRESSES vec is normally set up by shorten_branches. + If we're skipping the pass for an __RTL function that starts at a + later pass, set it up for the benefit of passes that run after + this. */ + void skip (function *) FINAL OVERRIDE + { + INSN_ADDRESSES_ALLOC (get_max_uid ()); + } + }; // class pass_shorten_branches } // anon namespace diff --git a/gcc/ira.c b/gcc/ira.c index 96b4b62..97f81da 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -5585,6 +5585,15 @@ public: return 0; } + /* Pass "reload" sets the global "reload_completed", and many + things depend on this (e.g. instructions in .md files). + Hence when skipping the pass for __RTL functions with "startwith" a + later pass, we need to set the flag. */ + void skip (function *) FINAL OVERRIDE + { + reload_completed = 1; + } + }; // class pass_reload } // anon namespace diff --git a/gcc/passes.c b/gcc/passes.c index 6954d1e..deb72f0 100644 --- a/gcc/passes.c +++ b/gcc/passes.c @@ -59,7 +59,6 @@ along with GCC; see the file COPYING3. If not see #include "cfgrtl.h" #include "tree-ssa-live.h" /* For remove_unused_locals. */ #include "tree-cfgcleanup.h" -#include "insn-addr.h" /* for INSN_ADDRESSES_ALLOC. */ using namespace gcc; @@ -100,6 +99,13 @@ opt_pass::execute (function *) return 0; } +/* The base class implementation of "skip" is a no-op. */ + +void +opt_pass::skip (function *) +{ +} + opt_pass::opt_pass (const pass_data &data, context *ctxt) : pass_data (data), sub (NULL), @@ -2351,38 +2357,6 @@ should_skip_pass_p (opt_pass *pass) return true; } -/* Skip the given pass, for handling passes before "startwith" - in __GIMPLE and__RTL-marked functions. - In theory, this ought to be a no-op, but some of the RTL passes - need additional processing here. */ - -static void -skip_pass (opt_pass *pass) -{ - /* Pass "reload" sets the global "reload_completed", and many - things depend on this (e.g. instructions in .md files). */ - if (strcmp (pass->name, "reload") == 0) - reload_completed = 1; - - /* The INSN_ADDRESSES vec is normally set up by - shorten_branches; set it up for the benefit of passes that - run after this. */ - if (strcmp (pass->name, "shorten") == 0) - INSN_ADDRESSES_ALLOC (get_max_uid ()); - - /* Update the cfg hooks as appropriate. */ - if (strcmp (pass->name, "into_cfglayout") == 0) - { - cfg_layout_rtl_register_cfg_hooks (); - cfun->curr_properties |= PROP_cfglayout; - } - if (strcmp (pass->name, "outof_cfglayout") == 0) - { - rtl_register_cfg_hooks (); - cfun->curr_properties &= ~PROP_cfglayout; - } -} - /* Execute PASS. */ bool @@ -2424,7 +2398,7 @@ execute_one_pass (opt_pass *pass) if (should_skip_pass_p (pass)) { - skip_pass (pass); + pass->skip (cfun); return true; } diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h index 85bfba7..c32e126 100644 --- a/gcc/tree-pass.h +++ b/gcc/tree-pass.h @@ -95,6 +95,14 @@ public: TODO_flags_finish. */ virtual unsigned int execute (function *fun); + /* A hook for use by the __GIMPLE and __RTL "frontends" when starting + at a specific pass. This hook is called for all of the skipped passes + before the start pass, in order to give them a chance to update any + internal state that isn't captured in the __GIMPLE or __RTL dumps. + Any usage of this function is considered a wart, since any such state + really ought to be captured in the dump. */ + virtual void skip (function *fun); + protected: opt_pass (const pass_data&, gcc::context *); -- 1.8.5.3