On Tue, Nov 15, 2016 at 10:07 PM, David Malcolm <[email protected]> wrote:
> On Mon, 2016-11-14 at 16:14 +0100, Richard Biener wrote:
>> On Fri, Nov 11, 2016 at 10:15 PM, David Malcolm <[email protected]>
>> wrote:
>> > Changed in this version:
>> >
>> > * Rather than running just one pass, run *all* passes, but start at
>> > the given pass; support for "dg-do run" tests that execute the
>> > resulting code.
>> > * Updated test cases to new "compact" dump format; more test cases;
>> > use "dg-do run" in various places.
>> > * Lots of bugfixing
>> >
>> > Links to previous versions:
>> > https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00263.html
>> > https://gcc.gnu.org/ml/gcc-patches/2016-10/msg00500.html
>
>> Does running the RTL passes right from the parser work with -fsyntax
>> -only?
>
> It depends what you mean by "work". If I run it with -fsyntax-only,
> then pass_rest_of_compilation::gate returns false, and none of the RTL
> passes are run. Is this behavior correct?
Yes.
>> Doing it like __GIMPLE has the advantage of not exposing
>> "rest_of_compilation", etc..
>
> The gimple part of the compiler supports having multiple functions in
> memory at once, and then compiling them in arbitrary order based on
> decisions made by the callgraph.
>
> By contrast, the RTL part of the compiler is full of singleton state:
> things like crtl (aka x_rtl), the state of emit-rtl.c,
> "reload_completed", etc etc.
Ah, of course - I forgot that...
> To try to limit the scope of the project, for the RTL frontend work I'm
> merely attempting to restore the singleton RTL state from a dump,
> rather than to support having per function stashes of RTL state.
>
> Hence the rest of compilation gets invoked directly from the frontend
> for the __RTL case, since it will get overwritten if there's a second
> __RTL function in the source file (which sounds like an idea for a test
> case; I'll attempt such a test case).
>
> I hope this is a reasonable approach. If not, I suppose I can attempt
> to bundle it up into some kind of RTL function state, but that seems
> like significant scope creep.
Yeah, I think it's a good approach for now.
>> I'm now handling __GIMPLE from within declspecs (the GIMPLE FE stuff
>> has been committed), it would be nice to match the __RTL piece here.
>
> (Congratulations on getting the GIMPLE FE stuff in)
>
> I'm not sure I understand you here - do you want me to rewrite the
> __RTL parsing to match the __GIMPLE piece, or the other way around?
> If the former, presumably I should reuse (and rename)
> c_parser_gimple_pass_list?
Handle __RTL like __GIMPLE, thus as declspec. Of course ultimatively
Joseph has the last word here.
>
>> > gcc/ChangeLog:
>> > * Makefile.in (OBJS): Add run-rtl-passes.o.
>> >
>> > gcc/c-family/ChangeLog:
>> > * c-common.c (c_common_reswords): Add "__RTL".
>> > * c-common.h (enum rid): Add RID_RTL.
>> >
>> > gcc/c/ChangeLog:
>> > * c-parser.c: Include "read-rtl-function.h" and
>> > "run-rtl-passes.h".
>> > (c_parser_declaration_or_fndef): In the "GNU extensions"
>> > part of
>> > the leading comment, add an alternate production for
>> > "function-definition", along with new "rtl-body-specifier"
>> > and
>> > "rtl-body-pass-specifier" productions. Handle "__RTL" by
>> > calling
>> > c_parser_parse_rtl_body. Convert a timevar_push/pop pair
>> > to an auto_timevar, to cope with early exit.
>> > (c_parser_parse_rtl_body): New function.
>> >
>> > gcc/ChangeLog:
>> > * cfg.c (free_original_copy_tables): Remove assertion
>> > on original_copy_bb_pool.
>>
>> How can that trigger?
>
> It happens when running pass_outof_cfg_layout_mode::execute; seen with
> gcc.dg/rtl/x86_64/test-return-const.c.before-fwprop.c.
>
> The input file is a dump taken in cfg_layout mode (although in this
> case it's a trivial 3-basic-block CFG, but ideally there would be cases
> with non-trivial control flow); it has "fwprop1" as its starting pass.
>
> Running without -quiet shows:
>
> skipping pass: *rest_of_compilation
> skipping pass: vregs
> skipping pass: into_cfglayout
> skipping pass: jump
> skipping pass: subreg1
> skipping pass: cse1
> found starting pass: fwprop1
>
> i.e. it skips the into_cfglayout (amongst others), to start with
> fwprop1.
>
> In theory skipping a pass ought to be a no-op, assuming that we're
> faithfully reconstructing all RTL state. However, RTL state management
> is fiddly, so the patch introduces some logic in passes.c to do some
> things when skipping a pass; in particular, it has:
>
> /* 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;
> }
>
> so that even when skipping "into_cfglayout", the CFG hooks are at least
> correct.
I suppose the pass manager could handle the hook switching based on
a (RTL) pass setting/clearing PROP_cfglayout. Or all passes needing
cfglayout would need to set prop_required accordingly and thus
the into/outouf cfglayout passes would be implicit.
> The assertion fires when running outof_cfglayout later on (rather than
> skipping it); the assertion:
>
> gcc_assert (original_copy_bb_pool);
>
> assumes that into_cfglayout was actually run, rather than just the
> simple "skipping" version of it.
Ah, I see cfg_layout_initialize calls initialize_original_copy_tables ()
for whatever reason and they are kept initialized until out-of-cfglayout...
GIMPLE passes do init/free them all the time. I think a better
fix would be to add a original_copy_tables_initialized () function
and guard the free_original_copy_tables call with that (keeping
the assertion that they run in pairs).
>> > * cgraph.h (symtab_node::native_rtl_p): New decl.
>> > * cgraphunit.c (symtab_node::native_rtl_p): New function.
>> > (symtab_node::needed_p): Don't assert for early assembly
>> > output
>> > for __RTL functions.
>> > (cgraph_node::finalize_function): Set "force_output" for
>> > __RTL
>> > functions.
>> > (cgraph_node::analyze): Bail out early for __RTL functions.
>> > (analyze_functions): Update assertion to support __RTL
>> > functions.
>> > (cgraph_node::expand): Bail out early for __RTL functions.
>> > * emit-rtl.c (unshare_all_rtl_again): Wrap set_used_decls
>> > call
>> > in check for DECL_INITIAL.
>>
>> You should simply set DECL_INITIAL of your function decl (make_node
>> (BLOCK);).
>> There's too much code assuming that is not NULL (and I've fixed quite
>> a bit of
>> code during stage1 not doing that).
>
> Thanks; fixed.
>
>> > * final.c (rest_of_clean_state): Don't call delete_tree_ssa
>> > for
>> > _RTL functions.
>> > * function.h (struct function): Add field "native_RTL".
>>
>> I wonder if you could simply use ->curr_properties & PROP_rtl? (and
>> set that
>> property during parsing, of course)
>
> I tried to doing that; it mostly works, but this assertion fails:
>
> 237 symtab_node::needed_p (void)
> 238 {
> 239 /* Double check that no one output the function into assembly file
> 240 early. */
> 241 if (!native_rtl_p ())
> 242 gcc_checking_assert
> 243 (!DECL_ASSEMBLER_NAME_SET_P (decl)
> 244 || !TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)));
>
> [I added the "if (!native_rtl_p ())" guard in the patch]
>
> The issue here is that when this is run, the __RTL function has been
> compiled and cleaned up, and the curr_properties & PROP_rtl has been
> cleared:
>
> (gdb) p decl->function_decl->f->curr_properties
> $7 = 0
>
> I could set the flag again after running the passes; on doing so, the
> test suite successfully runs.
Hmm, so if you are finished with the function you should set
symtab_node->analyzed
to false I think (it signals it's now merely an "extern" symbol and no
longer has a body).
Or set body_removed. Maybe just ask Honza what to do ...
Richard.
> Would you prefer I use curr_properties & PROP_rtl for this?
> [...snip...]
>
> Thanks
> Dave