On Tue, Oct 4, 2016 at 10:53 AM, Richard Biener <rguent...@suse.de> wrote:
> On Fri, 30 Sep 2016, Jakub Jelinek wrote:
>
>> Hi!
>>
>> As discussed earlier on IRC, the current way of registering target specific
>> passes has various issues:
>> 1) for -da, the target specific dump files appear last, regardless on where
>>    exactly they appear in the pass queue, so one has to look up the sources
>>    or remember where the pass is invoked if e.g. looking for when certain
>>    change in the IL first appears
>> 2) -fdump-rtl-stv-details and similar options don't work, the option
>>    processing happens before the passes are registered
>>
>> This patch allows backends to provide their *-passes.def file with
>> instructions how to ammend passes.def, which then can be inspected in
>> pass-instances.def the script generates.
>>
>> I've only converted the i386 backend so far, other maintainers can easily
>> convert their backends later on.
>>
>> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> I'm fine with the approach but I can't really review the awk parts
> so I'd appreciate a second eye on them.
>
> Thus, ok from the overall view, leaving to Uros and maybe some awk
> expert (if none appears within a reasonable amount of time consider
> this as approval anyway).

I thought I have already approved what little is of x86 changes. But
as you said, most of the changes are target-independent awk scripts.

That said, the change is surely beneficial, I've been annoyed by dump
file order for quite some time...

Thanks,
Uros.

>
> Thanks,
> Richard.
>
>> 2016-09-30  Jakub Jelinek  <ja...@redhat.com>
>>
>>       * gen-pass-instances.awk: Rewritten.
>>       * Makefile.in (pass-instances.def): Depend on $(PASSES_EXTRA), pass
>>       $(PASSES_EXTRA) after passes.def to the script.
>>       * config/i386/t-i386 (PASSES_EXTRA): Add i386-passes.def.
>>       * config/i386/i386-passes.def: New file.
>>       * config/i386/i386-protos.h (make_pass_insert_vzeroupper,
>>       make_pass_stv): Declare.
>>       * config/i386/i386.c (pass_stv::pass_stv): Initialize timode_p to
>>       false.
>>       (pass_stv::gate): Depending on timode_p member require TARGET_64BIT
>>       or !TARGET_64BIT.
>>       (pass_stv::clone, pass_stv::set_pass_param): New methods.
>>       (pass_stv::timode_p): New non-static data member.
>>       (ix86_option_override): Don't register passes here.
>>
>> --- gcc/gen-pass-instances.awk.jj     2016-09-29 22:53:10.264776158 +0200
>> +++ gcc/gen-pass-instances.awk        2016-09-30 13:22:53.745373889 +0200
>> @@ -17,6 +17,8 @@
>>  # This Awk script takes passes.def and writes pass-instances.def,
>>  # counting the instances of each kind of pass, adding an instance number
>>  # to everywhere that NEXT_PASS is used.
>> +# Also handle INSERT_PASS_AFTER, INSERT_PASS_BEFORE and REPLACE_PASS
>> +# directives.
>>  #
>>  # For example, the single-instanced pass:
>>  #     NEXT_PASS (pass_warn_unused_result);
>> @@ -30,81 +32,201 @@
>>  # through:
>>  #   NEXT_PASS (pass_copy_prop, 8);
>>  # (currently there are 8 instances of that pass)
>> +#
>> +#     INSERT_PASS_AFTER (pass_copy_prop, 1, pass_stv);
>> +# will insert
>> +#     NEXT_PASS (pass_stv, 1);
>> +# after immediately after the NEXT_PASS (pass_copy_prop, 1) line,
>> +# similarly INSERT_PASS_BEFORE inserts immediately before that line.
>> +#     REPLACE_PASS (pass_copy_prop, 1, pass_stv, true);
>> +# will replace NEXT_PASS (pass_copy_prop, 1) line with
>> +#     NEXT_PASS (pass_stv, 1, true);
>> +# line and renumber all higher pass_copy_prop instances if any.
>>
>>  # Usage: awk -f gen-pass-instances.awk passes.def
>>
>>  BEGIN {
>> -     print "/* This file is auto-generated by gen-pass-instances.awk";
>> -     print "   from passes.def.  */";
>> +  print "/* This file is auto-generated by gen-pass-instances.awk";
>> +  print "   from passes.def.  */";
>> +  lineno = 1;
>>  }
>>
>> -function handle_line()
>> +function parse_line(line, fnname,    len_of_call, len_of_start,
>> +                                     len_of_open, len_of_close,
>> +                                     len_of_args, args_start_at,
>> +                                     args_str, len_of_prefix,
>> +                                     call_starts_at,
>> +                                     postfix_starts_at)
>>  {
>> -     line = $0;
>> +  # Find call expression.
>> +  call_starts_at = match(line, fnname " \\(.+\\)");
>> +  if (call_starts_at == 0)
>> +    return 0;
>> +
>> +  # Length of the call expression.
>> +  len_of_call = RLENGTH;
>> +
>> +  len_of_start = length(fnname " (");
>> +  len_of_open = length("(");
>> +  len_of_close = length(")");
>> +
>> +  # Find arguments
>> +  len_of_args = len_of_call - (len_of_start + len_of_close);
>> +  args_start_at = call_starts_at + len_of_start;
>> +  args_str = substr(line, args_start_at, len_of_args);
>> +  split(args_str, args, ",");
>> +
>> +  # Find call expression prefix
>> +  len_of_prefix = call_starts_at - 1;
>> +  prefix = substr(line, 1, len_of_prefix);
>> +
>> +  # Find call expression postfix
>> +  postfix_starts_at = call_starts_at + len_of_call;
>> +  postfix = substr(line, postfix_starts_at);
>> +  return 1;
>> +}
>>
>> -     # Find call expression.
>> -     call_starts_at = match(line, /NEXT_PASS \(.+\)/);
>> -     if (call_starts_at == 0)
>> -     {
>> -             print line;
>> -             return;
>> -     }
>> +function adjust_linenos(above, increment,    p, i)
>> +{
>> +  for (p in pass_lines)
>> +    if (pass_lines[p] >= above)
>> +      pass_lines[p] += pass_lines[p];
>> +  if (increment > 0)
>> +    for (i = lineno - 1; i >= above; i--)
>> +      lines[i + increment] = lines[i];
>> +  else
>> +    for (i = above; i < lineno; i++)
>> +      lines[i + increment] = lines[i];
>> +  lineno += increment;
>> +}
>>
>> -     # Length of the call expression.
>> -     len_of_call = RLENGTH;
>> +function insert_remove_pass(line, fnname)
>> +{
>> +  parse_line($0, fnname);
>> +  pass_name = args[1];
>> +  if (pass_name == "PASS")
>> +    return 1;
>> +  pass_num = args[2] + 0;
>> +  new_line = prefix "NEXT_PASS (" args[3];
>> +  if (args[4])
>> +    new_line = new_line ", " args[4];
>> +  new_line = new_line ")" postfix;
>> +  if (!pass_lines[pass_name, pass_num])
>> +    {
>> +      print "ERROR: Can't locate instance of the pass mentioned in " fnname;
>> +      return 1;
>> +    }
>> +  return 0;
>> +}
>>
>> -     len_of_start = length("NEXT_PASS (");
>> -     len_of_open = length("(");
>> -     len_of_close = length(")");
>> -
>> -     # Find arguments
>> -     len_of_args = len_of_call - (len_of_start + len_of_close);
>> -     args_start_at = call_starts_at + len_of_start;
>> -     args_str = substr(line, args_start_at, len_of_args);
>> -     split(args_str, args, ",");
>> -
>> -     # Set pass_name argument, an optional with_arg argument
>> -     pass_name = args[1];
>> -     with_arg = args[2];
>> -
>> -     # Find call expression prefix
>> -     len_of_prefix = call_starts_at - 1;
>> -     prefix = substr(line, 1, len_of_prefix);
>> -
>> -     # Find call expression postfix
>> -     postfix_starts_at = call_starts_at + len_of_call;
>> -     postfix = substr(line, postfix_starts_at);
>> -
>> -     # Set pass_counts
>> -     if (pass_name in pass_counts)
>> -             pass_counts[pass_name]++;
>> -     else
>> -             pass_counts[pass_name] = 1;
>> -
>> -     pass_num = pass_counts[pass_name];
>> -
>> -     # Print call expression with extra pass_num argument
>> -     printf "%s", prefix;
>> -     if (with_arg)
>> -     {
>> -             printf "NEXT_PASS_WITH_ARG";
>> -     }
>> -     else
>> -     {
>> -             printf "NEXT_PASS";
>> -     }
>> -     printf " (";
>> -     printf "%s", pass_name;
>> -     printf ", %s", pass_num;
>> -     if (with_arg)
>> +function insert_pass(line, fnname, after,            num)
>> +{
>> +  if (insert_remove_pass(line, fnname))
>> +    return;
>> +  num = pass_lines[pass_name, pass_num];
>> +  adjust_linenos(num + after, 1);
>> +  pass_name = args[3];
>> +  # Set pass_counts
>> +  if (args[3] in pass_counts)
>> +    pass_counts[pass_name]++;
>> +  else
>> +    pass_counts[pass_name] = 1;
>> +
>> +  pass_lines[pass_name, pass_counts[pass_name]] = num + after;
>> +  lines[num + after] = new_line;
>> +}
>> +
>> +function replace_pass(line, fnname,                  num, i)
>> +{
>> +  if (insert_remove_pass(line, "REPLACE_PASS"))
>> +    return;
>> +  num = pass_lines[pass_name, pass_num];
>> +  for (i = pass_counts[pass_name]; i > pass_num; i--)
>> +    pass_lines[pass_name, i - 1] = pass_lines[pass_name, i];
>> +  delete pass_lines[pass_name, pass_counts[pass_name]];
>> +  if (pass_counts[pass_name] == 1)
>> +    delete pass_counts[pass_name];
>> +  else
>> +    pass_counts[pass_name]--;
>> +
>> +  pass_name = args[3];
>> +  # Set pass_counts
>> +  if (args[3] in pass_counts)
>> +    pass_counts[pass_name]++;
>> +  else
>> +    pass_counts[pass_name] = 1;
>> +
>> +  pass_lines[pass_name, pass_counts[pass_name]] = num;
>> +  lines[num] = new_line;
>> +}
>> +
>> +/INSERT_PASS_AFTER \(.+\)/ {
>> +  insert_pass($0, "INSERT_PASS_AFTER", 1);
>> +  next;
>> +}
>> +
>> +/INSERT_PASS_BEFORE \(.+\)/ {
>> +  insert_pass($0, "INSERT_PASS_BEFORE", 0);
>> +  next;
>> +}
>> +
>> +/REPLACE_PASS \(.+\)/ {
>> +  replace_pass($0, "REPLACE_PASS");
>> +  next;
>> +}
>> +
>> +{
>> +  ret = parse_line($0, "NEXT_PASS");
>> +  if (ret)
>> +    {
>> +      pass_name = args[1];
>> +
>> +      # Set pass_counts
>> +      if (pass_name in pass_counts)
>> +     pass_counts[pass_name]++;
>> +      else
>> +     pass_counts[pass_name] = 1;
>> +
>> +      pass_lines[pass_name, pass_counts[pass_name]] = lineno;
>> +    }
>> +  lines[lineno++] = $0;
>> +}
>> +
>> +END {
>> +  delete pass_counts;
>> +  for (i = 1; i < lineno; i++)
>> +    {
>> +      ret = parse_line(lines[i], "NEXT_PASS");
>> +      if (ret)
>>       {
>> -             printf ", %s", with_arg;
>> +       # Set pass_name argument, an optional with_arg argument
>> +       pass_name = args[1];
>> +       with_arg = args[2];
>> +
>> +       # Set pass_counts
>> +       if (pass_name in pass_counts)
>> +         pass_counts[pass_name]++;
>> +       else
>> +         pass_counts[pass_name] = 1;
>> +
>> +       pass_num = pass_counts[pass_name];
>> +
>> +       # Print call expression with extra pass_num argument
>> +       printf "%s", prefix;
>> +       if (with_arg)
>> +         printf "NEXT_PASS_WITH_ARG";
>> +       else
>> +         printf "NEXT_PASS";
>> +       printf " (%s, %s", pass_name, pass_num;
>> +       if (with_arg)
>> +         printf ", %s", with_arg;
>> +       printf ")%s\n", postfix;
>>       }
>> -     printf ")%s\n", postfix;
>> +      else
>> +     print lines[i];
>> +    }
>>  }
>>
>> -{ handle_line() }
>> -
>>  # Local Variables:
>>  # mode:awk
>>  # c-basic-offset:8
>> --- gcc/Makefile.in.jj        2016-09-29 22:53:15.000000000 +0200
>> +++ gcc/Makefile.in   2016-09-30 13:25:05.100723726 +0200
>> @@ -2158,9 +2158,10 @@ s-bversion: BASE-VER
>>
>>  CFLAGS-toplev.o += -DTARGET_NAME=\"$(target_noncanonical)\"
>>
>> -pass-instances.def: $(srcdir)/passes.def $(srcdir)/gen-pass-instances.awk
>> +pass-instances.def: $(srcdir)/passes.def $(PASSES_EXTRA) \
>> +                 $(srcdir)/gen-pass-instances.awk
>>       $(AWK) -f $(srcdir)/gen-pass-instances.awk \
>> -       $(srcdir)/passes.def > pass-instances.def
>> +       $(srcdir)/passes.def $(PASSES_EXTRA) > pass-instances.def
>>
>>  $(out_object_file): $(out_file)
>>       $(COMPILE) $<
>> --- gcc/config/i386/t-i386.jj 2016-08-19 17:23:17.000000000 +0200
>> +++ gcc/config/i386/t-i386    2016-09-30 13:20:45.748981856 +0200
>> @@ -18,6 +18,7 @@
>>
>>  OPTIONS_H_EXTRA += $(srcdir)/config/i386/stringop.def
>>  TM_H += $(srcdir)/config/i386/x86-tune.def
>> +PASSES_EXTRA += $(srcdir)/config/i386/i386-passes.def
>>
>>  i386-c.o: $(srcdir)/config/i386/i386-c.c
>>         $(COMPILE) $<
>> --- gcc/config/i386/i386-passes.def.jj        2016-09-30 12:54:29.959793738 
>> +0200
>> +++ gcc/config/i386/i386-passes.def   2016-09-30 14:01:31.237200032 +0200
>> @@ -0,0 +1,31 @@
>> +/* Description of target passes for IA-32
>> +   Copyright (C) 2016 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/>.  */
>> +
>> +/*
>> + Macros that should be defined used in this file:
>> +   INSERT_PASS_AFTER (PASS, INSTANCE, TGT_PASS)
>> +   INSERT_PASS_BEFORE (PASS, INSTANCE, TGT_PASS)
>> +   REPLACE_PASS (PASS, INSTANCE, TGT_PASS)
>> + */
>> +
>> +  INSERT_PASS_AFTER (pass_reload, 1, pass_insert_vzeroupper);
>> +  INSERT_PASS_AFTER (pass_combine, 1, pass_stv, false /* timode_p */);
>> +  /* Run the 64-bit STV pass before the CSE pass so that CONST0_RTX and
>> +     CONSTM1_RTX generated by the STV pass can be CSEed.  */
>> +  INSERT_PASS_BEFORE (pass_cse2, 1, pass_stv, true /* timode_p */);
>> --- gcc/config/i386/i386-protos.h.jj  2016-06-24 12:59:29.000000000 +0200
>> +++ gcc/config/i386/i386-protos.h     2016-09-30 14:00:54.759659671 +0200
>> @@ -338,3 +338,9 @@ struct ix86_first_cycle_multipass_data_
>>
>>  const addr_space_t ADDR_SPACE_SEG_FS = 1;
>>  const addr_space_t ADDR_SPACE_SEG_GS = 2;
>> +
>> +namespace gcc { class context; }
>> +class rtl_opt_pass;
>> +
>> +extern rtl_opt_pass *make_pass_insert_vzeroupper (gcc::context *);
>> +extern rtl_opt_pass *make_pass_stv (gcc::context *);
>> --- gcc/config/i386/i386.c.jj 2016-09-27 10:14:35.000000000 +0200
>> +++ gcc/config/i386/i386.c    2016-09-30 14:07:36.413598596 +0200
>> @@ -4105,13 +4105,15 @@ class pass_stv : public rtl_opt_pass
>>  {
>>  public:
>>    pass_stv (gcc::context *ctxt)
>> -    : rtl_opt_pass (pass_data_stv, ctxt)
>> +    : rtl_opt_pass (pass_data_stv, ctxt),
>> +      timode_p (false)
>>    {}
>>
>>    /* opt_pass methods: */
>>    virtual bool gate (function *)
>>      {
>> -      return TARGET_STV && TARGET_SSE2 && optimize > 1;
>> +      return (timode_p ^ (TARGET_64BIT == 0))
>> +          && TARGET_STV && TARGET_SSE2 && optimize > 1;
>>      }
>>
>>    virtual unsigned int execute (function *)
>> @@ -4119,6 +4121,19 @@ public:
>>        return convert_scalars_to_vector ();
>>      }
>>
>> +  opt_pass *clone ()
>> +    {
>> +      return new pass_stv (m_ctxt);
>> +    }
>> +
>> +  void set_pass_param (unsigned int n, bool param)
>> +    {
>> +      gcc_assert (n == 0);
>> +      timode_p = param;
>> +    }
>> +
>> +private:
>> +  bool timode_p;
>>  }; // class pass_stv
>>
>>  } // anon namespace
>> @@ -6155,29 +6170,7 @@ ix86_option_override_internal (bool main
>>  static void
>>  ix86_option_override (void)
>>  {
>> -  opt_pass *pass_insert_vzeroupper = make_pass_insert_vzeroupper (g);
>> -  struct register_pass_info insert_vzeroupper_info
>> -    = { pass_insert_vzeroupper, "reload",
>> -     1, PASS_POS_INSERT_AFTER
>> -      };
>> -  opt_pass *pass_stv = make_pass_stv (g);
>> -  struct register_pass_info stv_info_dimode
>> -    = { pass_stv, "combine",
>> -     1, PASS_POS_INSERT_AFTER
>> -      };
>> -  /* Run the 64-bit STV pass before the CSE pass so that CONST0_RTX and
>> -     CONSTM1_RTX generated by the STV pass can be CSEed.  */
>> -  struct register_pass_info stv_info_timode
>> -    = { pass_stv, "cse2",
>> -     1, PASS_POS_INSERT_BEFORE
>> -      };
>> -
>>    ix86_option_override_internal (true, &global_options, 
>> &global_options_set);
>> -
>> -
>> -  /* This needs to be done at start up.  It's convenient to do it here.  */
>> -  register_pass (&insert_vzeroupper_info);
>> -  register_pass (TARGET_64BIT ? &stv_info_timode : &stv_info_dimode);
>>  }
>>
>>  /* Implement the TARGET_OFFLOAD_OPTIONS hook.  */
>>
>>
>>       Jakub
>>
>>
>
> --
> Richard Biener <rguent...@suse.de>
> SUSE LINUX GmbH, GF: Felix Imendoerffer, Jane Smithard, Graham Norton, HRB 
> 21284 (AG Nuernberg)

Reply via email to