diff mbox

Add option for dumping to stderr (issue6190057)

Message ID CAKxPW65MhmoGHQ0u2_0tsQc=9VfXCN4+afmqBULDKM=LwZqHvg@mail.gmail.com
State New
Headers show

Commit Message

Sharad Singhai May 9, 2012, 11:56 p.m. UTC
Thanks for your suggestions/comments. I have updated the patch and
documentation. It supports the following usage:

gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
-fdump-rtl-ira=ira.dump

Here all tree dumps except the PRE are output into tree.dump, PRE dump
goes to stdout and the IRA dump goes to ira.dump.

Thanks,
Sharad

2012-05-09   Sharad Singhai  <singhai@google.com>

	* doc/invoke.texi: Add documentation for the new option.
	* tree-dump.c (dump_get_standard_stream): New function.
	(dump_files): Update for new field.
	(dump_switch_p_1): Handle dump filenames.
	(dump_begin): Likewise.
	(get_dump_file_name): Likewise.
	(dump_end): Remove attribute.
	(dump_enable_all): Add new parameter FILENAME.
	All callers updated.
	(enable_rtl_dump_file):
	* tree-pass.h (enum tree_dump_index): Add new constant.
	(struct dump_file_info): Add new field FILENAME.
	* testsuite/g++.dg/other/dump-filename-1.C: New test.



On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
<gdr@integrable-solutions.net> wrote:
> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
> [...]
>
>> +@item -fdump-rtl-all=stderr
>> +@opindex fdump-rtl-all=stderr
>
> You do not need to have a separate index entry for '=stderr' or '=stdout'.
> Rather, expand the description to state this in all the documentation
> for -fdump-xxx=yyy.
>
> [...]
>
>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>> +   stderr stream.  */
>> +
>> +static int
>> +dump_stream_p (const char *user_filename)
>> +{
>> +  if (user_filename)
>> +    return !strncmp ("stderr", user_filename, 6) ||
>> +      !strncmp ("stdout", user_filename, 6);
>> +  else
>> +    return 0;
>> +}
>
> The name is ambiguous.
> This function is testing whether its string argument designates one of
> the *standard* output streams.  Name it to reflect that..
> Have it take the dump state context. Also the coding convention: the binary
> operator "||" should be on next line.  In fact the thing could be
> simpler.   Instead of
> testing over and over again against "stderr" (once in this function, then again
> later), just return the corresponding standard FILE* pointer.
> Also, this is a case of overuse of strncmp.  If you name the function
> dump_get_standard_stream:
>
>    return strcmp("stderr", dfi->user_filename) == 0
>       ? stderr
>        : stdcmp("stdout", dfi->use_filename)
>        ?  stdout
>        : NULL;
>
> you can simplify:
>
>> -  name = get_dump_file_name (phase);
>>   dfi = get_dump_file_info (phase);
>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>> -  if (!stream)
>> -    error ("could not open dump file %qs: %m", name);
>> +  if (dump_stream_p (dfi->user_filename))
>> +    {
>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>> +        stream = stderr;
>> +      else
>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>> +          stream = stdout;
>> +        else
>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>> +      dfi->state = 1;
>> +    }
>>   else
>> -    dfi->state = 1;
>> -  free (name);
>> +    {
>> +      name = get_dump_file_name (phase);
>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>> +      if (!stream)
>> +        error ("could not open dump file %qs: %m", name);
>> +      else
>> +        dfi->state = 1;
>> +      free (name);
>> +    }
>>
>>   if (flag_ptr)
>>     *flag_ptr = dfi->flags;
>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>    dump_begin.  */
>>
>>  void
>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>> +dump_end (int phase, FILE *stream)
>>  {
>> -  fclose (stream);
>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>> +  if (!dump_stream_p (dfi->user_filename))
>> +    fclose (stream);
>>  }
>>
>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>
>>  static int
>> -dump_enable_all (int flags)
>> +dump_enable_all (int flags, const char *user_filename)
>>  {
>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>   int n = 0;
>>   size_t i;
>>
>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>> -    if ((dump_files[i].flags & ir_dump_type))
>> -      {
>> -        dump_files[i].state = -1;
>> -        dump_files[i].flags |= flags;
>> -        n++;
>> -      }
>> +    {
>> +      if ((dump_files[i].flags & ir_dump_type))
>> +        {
>> +          dump_files[i].state = -1;
>> +          dump_files[i].flags |= flags;
>> +          n++;
>> +        }
>> +      if (user_filename)
>> +        dump_files[i].user_filename = user_filename;
>> +    }
>>
>>   for (i = 0; i < extra_dump_files_in_use; i++)
>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>> -      {
>> -        extra_dump_files[i].state = -1;
>> -        extra_dump_files[i].flags |= flags;
>> -       n++;
>> -      }
>> +    {
>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>> +        {
>> +          extra_dump_files[i].state = -1;
>> +          extra_dump_files[i].flags |= flags;
>> +          n++;
>> +        }
>> +      if (user_filename)
>> +        extra_dump_files[i].user_filename = user_filename;
>> +    }
>>
>>   return n;
>>  }
>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>   if (!option_value)
>>     return 0;
>>
>> -  if (*option_value && *option_value != '-')
>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>     return 0;
>>
>>   ptr = option_value;
>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>       while (*ptr == '-')
>>        ptr++;
>>       end_ptr = strchr (ptr, '-');
>> +
>>       if (!end_ptr)
>>        end_ptr = ptr + strlen (ptr);
>>       length = end_ptr - ptr;
>>
>> +      if (*ptr == '=')
>> +        {
>> +          /* Interpret rest of the argument as a dump filename.  The
>> +             user provided filename overrides generated dump names as
>> +             well as other command line filenames.  */
>> +          flags |= TDF_USER_FILENAME;
>> +          if (dfi->user_filename)
>> +            free (dfi->user_filename);
>> +          dfi->user_filename = xstrdup (ptr + 1);
>> +          break;
>> +        }
>> +
>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>        if (strlen (option_ptr->name) == length
>>            && !memcmp (option_ptr->name, ptr, length))
>> -         {
>> -           flags |= option_ptr->value;
>> +          {
>> +            flags |= option_ptr->value;
>>            goto found;
>> -         }
>> +          }
>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>               length, ptr, dfi->swtch);
>>     found:;
>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>      known dumps.  */
>>   if (dfi->suffix == NULL)
>> -    dump_enable_all (dfi->flags);
>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>
>>   return 1;
>>  }
>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>  bool
>>  enable_rtl_dump_file (void)
>>  {
>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>  }
>> Index: tree-pass.h
>> ===================================================================
>> --- tree-pass.h (revision 187265)
>> +++ tree-pass.h (working copy)
>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>> +                                           instead of constructing one. */
>>
>> -
>>  /* In tree-dump.c */
>>
>>  extern char *get_dump_file_name (int);
>> @@ -222,6 +223,8 @@ struct dump_file_info
>>   const char *suffix;           /* suffix to give output file.  */
>>   const char *swtch;            /* command line switch */
>>   const char *glob;             /* command line glob  */
>> +  const char *user_filename;    /* user provided filename instead of making
>> +                                   up one using dump_base_name + suffix.  */
>
> There is "no user" here: we are the users :-)  Just call it "filename".
>
> -- Gaby

Comments

Xinliang David Li May 10, 2012, 12:31 a.m. UTC | #1
Bummer.  I was thinking to reserve '=' for selective  dumping:

-fdump-tree-pre=<func_list_regexp>

I guess this can be achieved via @

-fdump-tree-pre@<func_list>

-fdump-tree-pre=<file_name>@<func_list>


Another issue -- I don't think the current precedence rule is correct.
Consider that -fopt-info=2 will be mapped to

-fdump-tree-all-transform-verbose2=stderr
-fdump-rtl-all-transform-verbose2=stderr

then

the current precedence rule will cause surprise when the following is used

-fopt-info -fdump-tree-pre

The PRE dump will be emitted to stderr which is not what user wants.
In short, special streams should be treated as 'weak' the same way as
your previous implementation.

thanks,

David



On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
> Thanks for your suggestions/comments. I have updated the patch and
> documentation. It supports the following usage:
>
> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
> -fdump-rtl-ira=ira.dump
>
> Here all tree dumps except the PRE are output into tree.dump, PRE dump
> goes to stdout and the IRA dump goes to ira.dump.
>
> Thanks,
> Sharad
>
> 2012-05-09   Sharad Singhai  <singhai@google.com>
>
>        * doc/invoke.texi: Add documentation for the new option.
>        * tree-dump.c (dump_get_standard_stream): New function.
>        (dump_files): Update for new field.
>        (dump_switch_p_1): Handle dump filenames.
>        (dump_begin): Likewise.
>        (get_dump_file_name): Likewise.
>        (dump_end): Remove attribute.
>        (dump_enable_all): Add new parameter FILENAME.
>        All callers updated.
>        (enable_rtl_dump_file):
>        * tree-pass.h (enum tree_dump_index): Add new constant.
>        (struct dump_file_info): Add new field FILENAME.
>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>
> Index: doc/invoke.texi
> ===================================================================
> --- doc/invoke.texi     (revision 187265)
> +++ doc/invoke.texi     (working copy)
> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>
>  @item -d@var{letters}
>  @itemx -fdump-rtl-@var{pass}
> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>  @opindex d
>  Says to make debugging dumps during compilation at times specified by
>  @var{letters}.  This is used for debugging the RTL-based passes of the
>  compiler.  The file names for most of the dumps are made by appending
>  a pass number and a word to the @var{dumpname}, and the files are
> -created in the directory of the output file.  Note that the pass
> -number is computed statically as passes get registered into the pass
> -manager.  Thus the numbering is not related to the dynamic order of
> -execution of passes.  In particular, a pass installed by a plugin
> -could have a number over 200 even if it executed quite early.
> -@var{dumpname} is generated from the name of the output file, if
> -explicitly specified and it is not an executable, otherwise it is the
> -basename of the source file. These switches may have different effects
> -when @option{-E} is used for preprocessing.
> +created in the directory of the output file. If the
> +@option{=@var{filename}} is appended to the longer form of the dump
> +option then the dump is done on that file instead of numbered
> +files. Note that the pass number is computed statically as passes get
> +registered into the pass manager.  Thus the numbering is not related
> +to the dynamic order of execution of passes.  In particular, a pass
> +installed by a plugin could have a number over 200 even if it executed
> +quite early.  @var{dumpname} is generated from the name of the output
> +file, if explicitly specified and it is not an executable, otherwise
> +it is the basename of the source file. These switches may have
> +different effects when @option{-E} is used for preprocessing.
>
>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>  @option{-d} option @var{letters}.  Here are the possible
> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>
>  @item -fdump-tree-@var{switch}
>  @itemx -fdump-tree-@var{switch}-@var{options}
> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>  @opindex fdump-tree
>  Control the dumping at various stages of processing the intermediate
>  language tree to a file.  The file name is generated by appending a
>  switch specific suffix to the source file name, and the file is
> -created in the same directory as the output file.  If the
> -@samp{-@var{options}} form is used, @var{options} is a list of
> -@samp{-} separated options which control the details of the dump.  Not
> -all options are applicable to all dumps; those that are not
> -meaningful are ignored.  The following options are available
> +created in the same directory as the output file. In case of
> +@option{=@var{filename}} option, the dump is output on the given file
> +name instead.  If the @samp{-@var{options}} form is used,
> +@var{options} is a list of @samp{-} separated options which control
> +the details or location of the dump.  Not all options are applicable
> +to all dumps; those that are not meaningful are ignored.  The
> +following options are available
>
>  @table @samp
>  @item address
> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>  Enable showing the EH region number holding each statement.
>  @item scev
>  Enable showing scalar evolution analysis details.
> +@item slim
> +Inhibit dumping of members of a scope or body of a function merely
> +because that scope has been reached.  Only dump such items when they
> +are directly reachable by some other path.  When dumping pretty-printed
> +trees, this option inhibits dumping the bodies of control structures.
> +@item =@var{filename}
> +Instead of using an auto generated dump file name, use the given file
> +name. The file names @file{stdout} and @file{stderr} are treated
> +specially and are considered already open standard streams. For
> +example:
> +
> +@smallexample
> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
> +@end smallexample
> +
> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
> +file named @file{ira.txt}.
> +
> +In case of any conflicts, the command line file name takes precedence
> +over generated file names. For example:
> +
> +@smallexample
> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
> +@end smallexample
> +
> +Both of the above output the PRE dump on @file{stdout}. However, if
> +there are multiple command line file names are applicable then the
> +last one is used. Thus the command
> +
> +@smallexample
> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
> +@end smallexample
> +
> +outputs all the dumps in @file{all.txt} because the stderr option for
> +PRE dump is overridden by a later option.
> +
>  @item all
> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
> -and @option{lineno}.
> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
> +@option{lineno}.
>  @end table
>
>  The following tree dumps are possible:
> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>  @item all
>  @opindex fdump-tree-all
>  Enable all the available tree dumps with the flags provided in this option.
> +
>  @end table
>
>  @item -ftree-vectorizer-verbose=@var{n}
> Index: tree-dump.c
> ===================================================================
> --- tree-dump.c (revision 187265)
> +++ tree-dump.c (working copy)
> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>    tree_dump_index enumeration in tree-pass.h.  */
>  static struct dump_file_info dump_files[TDI_end] =
>  {
> -  {NULL, NULL, NULL, 0, 0, 0},
> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
> -  {".ads", "ada-spec", NULL, 0, 0, 7},
> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>  #define FIRST_AUTO_NUMBERED_DUMP 8
>
> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>  };
>
>  /* Dynamically registered tree dump files and switches.  */
> @@ -802,7 +802,7 @@ struct dump_option_value_info
>  };
>
>  /* Table of dump options. This must be consistent with the TDF_* flags
> -   in tree.h */
> +   in tree-pass.h */
>  static const struct dump_option_value_info dump_options[] =
>  {
>   {"address", TDF_ADDRESS},
> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>   if (dfi->state == 0)
>     return NULL;
>
> +  if (dfi->filename)
> +    return xstrdup (dfi->filename);
> +
>   if (dfi->num < 0)
>     dump_id[0] = '\0';
>   else
> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>  }
>
> +/* If the DFI dump output corresponds to stdout or stderr stream,
> +   return that stream, NULL otherwise.  */
> +
> +static FILE *
> +dump_get_standard_stream (struct dump_file_info *dfi)
> +{
> +  if (!dfi->filename)
> +    return NULL;
> +
> +  return strcmp("stderr", dfi->filename) == 0
> +    ? stderr
> +    : strcmp("stdout", dfi->filename) == 0
> +    ?  stdout
> +    : NULL;
> +}
> +
>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>    *FLAG_PTR and returns a stream to write to. If the dump is not
>    enabled, returns NULL.
> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>   if (phase == TDI_none || !dump_enabled_p (phase))
>     return NULL;
>
> -  name = get_dump_file_name (phase);
>   dfi = get_dump_file_info (phase);
> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
> -  if (!stream)
> -    error ("could not open dump file %qs: %m", name);
> +  stream = dump_get_standard_stream (dfi);
> +  if (stream)
> +    dfi->state = 1;
>   else
> -    dfi->state = 1;
> -  free (name);
> +    {
> +      name = get_dump_file_name (phase);
> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
> +      if (!stream)
> +        error ("could not open dump file %qs: %m", name);
> +      else
> +        dfi->state = 1;
> +      free (name);
> +    }
>
>   if (flag_ptr)
>     *flag_ptr = dfi->flags;
> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>    dump_begin.  */
>
>  void
> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
> +dump_end (int phase, FILE *stream)
>  {
> -  fclose (stream);
> +  struct dump_file_info *dfi = get_dump_file_info (phase);
> +  if (!dump_get_standard_stream (dfi))
> +    fclose (stream);
>  }
>
> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
> +   enabled tree dumps.  */
>
>  static int
> -dump_enable_all (int flags)
> +dump_enable_all (int flags, const char *filename)
>  {
>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>   int n = 0;
>   size_t i;
>
>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
> -    if ((dump_files[i].flags & ir_dump_type))
> -      {
> -        dump_files[i].state = -1;
> -        dump_files[i].flags |= flags;
> -        n++;
> -      }
> +    {
> +      if ((dump_files[i].flags & ir_dump_type))
> +        {
> +          dump_files[i].state = -1;
> +          dump_files[i].flags |= flags;
> +          n++;
> +          if (filename)
> +            dump_files[i].filename = xstrdup (filename);
> +        }
> +    }
>
>   for (i = 0; i < extra_dump_files_in_use; i++)
> -    if ((extra_dump_files[i].flags & ir_dump_type))
> -      {
> -        extra_dump_files[i].state = -1;
> -        extra_dump_files[i].flags |= flags;
> -       n++;
> -      }
> +    {
> +      if ((extra_dump_files[i].flags & ir_dump_type))
> +        {
> +          extra_dump_files[i].state = -1;
> +          extra_dump_files[i].flags |= flags;
> +          n++;
> +          if (filename)
> +            extra_dump_files[i].filename = xstrdup (filename);
> +        }
> +    }
>
>   return n;
>  }
> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>   if (!option_value)
>     return 0;
>
> -  if (*option_value && *option_value != '-')
> +  if (*option_value && *option_value != '-' && *option_value != '=')
>     return 0;
>
>   ptr = option_value;
> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>       while (*ptr == '-')
>        ptr++;
>       end_ptr = strchr (ptr, '-');
> +
>       if (!end_ptr)
>        end_ptr = ptr + strlen (ptr);
>       length = end_ptr - ptr;
>
> +      if (*ptr == '=')
> +        {
> +          /* Interpret rest of the argument as a dump filename.  This
> +             filename overrides generated dump names as well as other
> +             command line filenames.  */
> +          flags |= TDF_FILENAME;
> +          if (dfi->filename)
> +            free (dfi->filename);
> +          dfi->filename = xstrdup (ptr + 1);
> +          break;
> +        }
> +
>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>        if (strlen (option_ptr->name) == length
>            && !memcmp (option_ptr->name, ptr, length))
> -         {
> -           flags |= option_ptr->value;
> +          {
> +            flags |= option_ptr->value;
>            goto found;
> -         }
> +          }
>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>               length, ptr, dfi->swtch);
>     found:;
> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>      known dumps.  */
>   if (dfi->suffix == NULL)
> -    dump_enable_all (dfi->flags);
> +    dump_enable_all (dfi->flags, dfi->filename);
>
>   return 1;
>  }
> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>  bool
>  enable_rtl_dump_file (void)
>  {
> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>  }
> Index: tree-pass.h
> ===================================================================
> --- tree-pass.h (revision 187265)
> +++ tree-pass.h (working copy)
> @@ -84,8 +84,9 @@ enum tree_dump_index
>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
> +                                           instead of constructing one. */
>
> -
>  /* In tree-dump.c */
>
>  extern char *get_dump_file_name (int);
> @@ -222,6 +223,8 @@ struct dump_file_info
>   const char *suffix;           /* suffix to give output file.  */
>   const char *swtch;            /* command line switch */
>   const char *glob;             /* command line glob  */
> +  const char *filename;         /* use this filename instead of making
> +                                   up one using dump_base_name + suffix.  */
>   int flags;                    /* user flags */
>   int state;                    /* state of play */
>   int num;                      /* dump file number */
> Index: testsuite/g++.dg/other/dump-filename-1.C
> ===================================================================
> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
> @@ -0,0 +1,11 @@
> +// Test that the dump to a user-defined file works correctly.
> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
> +
> +void test (int *b, int *e, int stride)
> +  {
> +    for (int *p = b; p != e; p += stride)
> +      *p = 1;
> +  }
> +
> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
> +/* { dg-final { remove-build-file "foobar.dump" } } */
>
>
> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
> <gdr@integrable-solutions.net> wrote:
>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>> [...]
>>
>>> +@item -fdump-rtl-all=stderr
>>> +@opindex fdump-rtl-all=stderr
>>
>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>> Rather, expand the description to state this in all the documentation
>> for -fdump-xxx=yyy.
>>
>> [...]
>>
>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>> +   stderr stream.  */
>>> +
>>> +static int
>>> +dump_stream_p (const char *user_filename)
>>> +{
>>> +  if (user_filename)
>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>> +      !strncmp ("stdout", user_filename, 6);
>>> +  else
>>> +    return 0;
>>> +}
>>
>> The name is ambiguous.
>> This function is testing whether its string argument designates one of
>> the *standard* output streams.  Name it to reflect that..
>> Have it take the dump state context. Also the coding convention: the binary
>> operator "||" should be on next line.  In fact the thing could be
>> simpler.   Instead of
>> testing over and over again against "stderr" (once in this function, then again
>> later), just return the corresponding standard FILE* pointer.
>> Also, this is a case of overuse of strncmp.  If you name the function
>> dump_get_standard_stream:
>>
>>    return strcmp("stderr", dfi->user_filename) == 0
>>       ? stderr
>>        : stdcmp("stdout", dfi->use_filename)
>>        ?  stdout
>>        : NULL;
>>
>> you can simplify:
>>
>>> -  name = get_dump_file_name (phase);
>>>   dfi = get_dump_file_info (phase);
>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>> -  if (!stream)
>>> -    error ("could not open dump file %qs: %m", name);
>>> +  if (dump_stream_p (dfi->user_filename))
>>> +    {
>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>> +        stream = stderr;
>>> +      else
>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>> +          stream = stdout;
>>> +        else
>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>> +      dfi->state = 1;
>>> +    }
>>>   else
>>> -    dfi->state = 1;
>>> -  free (name);
>>> +    {
>>> +      name = get_dump_file_name (phase);
>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>> +      if (!stream)
>>> +        error ("could not open dump file %qs: %m", name);
>>> +      else
>>> +        dfi->state = 1;
>>> +      free (name);
>>> +    }
>>>
>>>   if (flag_ptr)
>>>     *flag_ptr = dfi->flags;
>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>    dump_begin.  */
>>>
>>>  void
>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>> +dump_end (int phase, FILE *stream)
>>>  {
>>> -  fclose (stream);
>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>> +  if (!dump_stream_p (dfi->user_filename))
>>> +    fclose (stream);
>>>  }
>>>
>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>
>>>  static int
>>> -dump_enable_all (int flags)
>>> +dump_enable_all (int flags, const char *user_filename)
>>>  {
>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>   int n = 0;
>>>   size_t i;
>>>
>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>> -    if ((dump_files[i].flags & ir_dump_type))
>>> -      {
>>> -        dump_files[i].state = -1;
>>> -        dump_files[i].flags |= flags;
>>> -        n++;
>>> -      }
>>> +    {
>>> +      if ((dump_files[i].flags & ir_dump_type))
>>> +        {
>>> +          dump_files[i].state = -1;
>>> +          dump_files[i].flags |= flags;
>>> +          n++;
>>> +        }
>>> +      if (user_filename)
>>> +        dump_files[i].user_filename = user_filename;
>>> +    }
>>>
>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>> -      {
>>> -        extra_dump_files[i].state = -1;
>>> -        extra_dump_files[i].flags |= flags;
>>> -       n++;
>>> -      }
>>> +    {
>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>> +        {
>>> +          extra_dump_files[i].state = -1;
>>> +          extra_dump_files[i].flags |= flags;
>>> +          n++;
>>> +        }
>>> +      if (user_filename)
>>> +        extra_dump_files[i].user_filename = user_filename;
>>> +    }
>>>
>>>   return n;
>>>  }
>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>   if (!option_value)
>>>     return 0;
>>>
>>> -  if (*option_value && *option_value != '-')
>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>     return 0;
>>>
>>>   ptr = option_value;
>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>       while (*ptr == '-')
>>>        ptr++;
>>>       end_ptr = strchr (ptr, '-');
>>> +
>>>       if (!end_ptr)
>>>        end_ptr = ptr + strlen (ptr);
>>>       length = end_ptr - ptr;
>>>
>>> +      if (*ptr == '=')
>>> +        {
>>> +          /* Interpret rest of the argument as a dump filename.  The
>>> +             user provided filename overrides generated dump names as
>>> +             well as other command line filenames.  */
>>> +          flags |= TDF_USER_FILENAME;
>>> +          if (dfi->user_filename)
>>> +            free (dfi->user_filename);
>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>> +          break;
>>> +        }
>>> +
>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>        if (strlen (option_ptr->name) == length
>>>            && !memcmp (option_ptr->name, ptr, length))
>>> -         {
>>> -           flags |= option_ptr->value;
>>> +          {
>>> +            flags |= option_ptr->value;
>>>            goto found;
>>> -         }
>>> +          }
>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>               length, ptr, dfi->swtch);
>>>     found:;
>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>      known dumps.  */
>>>   if (dfi->suffix == NULL)
>>> -    dump_enable_all (dfi->flags);
>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>
>>>   return 1;
>>>  }
>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>  bool
>>>  enable_rtl_dump_file (void)
>>>  {
>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>  }
>>> Index: tree-pass.h
>>> ===================================================================
>>> --- tree-pass.h (revision 187265)
>>> +++ tree-pass.h (working copy)
>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>> +                                           instead of constructing one. */
>>>
>>> -
>>>  /* In tree-dump.c */
>>>
>>>  extern char *get_dump_file_name (int);
>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>   const char *suffix;           /* suffix to give output file.  */
>>>   const char *swtch;            /* command line switch */
>>>   const char *glob;             /* command line glob  */
>>> +  const char *user_filename;    /* user provided filename instead of making
>>> +                                   up one using dump_base_name + suffix.  */
>>
>> There is "no user" here: we are the users :-)  Just call it "filename".
>>
>> -- Gaby
Richard Biener May 10, 2012, 8:18 a.m. UTC | #2
On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
> Bummer.  I was thinking to reserve '=' for selective  dumping:
>
> -fdump-tree-pre=<func_list_regexp>
>
> I guess this can be achieved via @
>
> -fdump-tree-pre@<func_list>
>
> -fdump-tree-pre=<file_name>@<func_list>
>
>
> Another issue -- I don't think the current precedence rule is correct.
> Consider that -fopt-info=2 will be mapped to
>
> -fdump-tree-all-transform-verbose2=stderr
> -fdump-rtl-all-transform-verbose2=stderr
>
> then
>
> the current precedence rule will cause surprise when the following is used
>
> -fopt-info -fdump-tree-pre
>
> The PRE dump will be emitted to stderr which is not what user wants.
> In short, special streams should be treated as 'weak' the same way as
> your previous implementation.

Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
With -fopt-info -fdump-tree-pre I do not want some information to be
present only on stderr or in the dump file!  I want it in _both_ places!
(-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
information :()

Thus, the information where dumping goes has to be done differently
(which is why I asked for some re-org originally, so that passes no
longer explicitely reference dump_file - dump_file may be different
for different kind of information it dumps!).  Passes should, instead of

  fprintf (dump_file, "...", ...)

do

 dump_printf (TDF_scev, "...", ...)

thus, specify the kind of information they dump (would be mostly
TDF_details vs. 0 today I guess).  The dump_printf routine would
then properly direct to one or more places to dump at.

I realize this needs some more dispatchers for dumping expressions
and statements (but it should not be too many).  Dumping to
dump_file would in any case dump to the passes private dump file
only (unqualified stuff would never be useful for -fopt-info).

The perfect candidate to convert to this kind of scheme is obviously
the vectorizer with its existing -fvectorizer-verbose.

If the patch doesn't work towards this kind of end-result I'd rather
not have it.

Thanks,
Richard.

> thanks,
>
> David
>
>
>
> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>> Thanks for your suggestions/comments. I have updated the patch and
>> documentation. It supports the following usage:
>>
>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>> -fdump-rtl-ira=ira.dump
>>
>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>> goes to stdout and the IRA dump goes to ira.dump.
>>
>> Thanks,
>> Sharad
>>
>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>
>>        * doc/invoke.texi: Add documentation for the new option.
>>        * tree-dump.c (dump_get_standard_stream): New function.
>>        (dump_files): Update for new field.
>>        (dump_switch_p_1): Handle dump filenames.
>>        (dump_begin): Likewise.
>>        (get_dump_file_name): Likewise.
>>        (dump_end): Remove attribute.
>>        (dump_enable_all): Add new parameter FILENAME.
>>        All callers updated.
>>        (enable_rtl_dump_file):
>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>        (struct dump_file_info): Add new field FILENAME.
>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>
>> Index: doc/invoke.texi
>> ===================================================================
>> --- doc/invoke.texi     (revision 187265)
>> +++ doc/invoke.texi     (working copy)
>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>
>>  @item -d@var{letters}
>>  @itemx -fdump-rtl-@var{pass}
>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>  @opindex d
>>  Says to make debugging dumps during compilation at times specified by
>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>  compiler.  The file names for most of the dumps are made by appending
>>  a pass number and a word to the @var{dumpname}, and the files are
>> -created in the directory of the output file.  Note that the pass
>> -number is computed statically as passes get registered into the pass
>> -manager.  Thus the numbering is not related to the dynamic order of
>> -execution of passes.  In particular, a pass installed by a plugin
>> -could have a number over 200 even if it executed quite early.
>> -@var{dumpname} is generated from the name of the output file, if
>> -explicitly specified and it is not an executable, otherwise it is the
>> -basename of the source file. These switches may have different effects
>> -when @option{-E} is used for preprocessing.
>> +created in the directory of the output file. If the
>> +@option{=@var{filename}} is appended to the longer form of the dump
>> +option then the dump is done on that file instead of numbered
>> +files. Note that the pass number is computed statically as passes get
>> +registered into the pass manager.  Thus the numbering is not related
>> +to the dynamic order of execution of passes.  In particular, a pass
>> +installed by a plugin could have a number over 200 even if it executed
>> +quite early.  @var{dumpname} is generated from the name of the output
>> +file, if explicitly specified and it is not an executable, otherwise
>> +it is the basename of the source file. These switches may have
>> +different effects when @option{-E} is used for preprocessing.
>>
>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>  @option{-d} option @var{letters}.  Here are the possible
>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>
>>  @item -fdump-tree-@var{switch}
>>  @itemx -fdump-tree-@var{switch}-@var{options}
>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>  @opindex fdump-tree
>>  Control the dumping at various stages of processing the intermediate
>>  language tree to a file.  The file name is generated by appending a
>>  switch specific suffix to the source file name, and the file is
>> -created in the same directory as the output file.  If the
>> -@samp{-@var{options}} form is used, @var{options} is a list of
>> -@samp{-} separated options which control the details of the dump.  Not
>> -all options are applicable to all dumps; those that are not
>> -meaningful are ignored.  The following options are available
>> +created in the same directory as the output file. In case of
>> +@option{=@var{filename}} option, the dump is output on the given file
>> +name instead.  If the @samp{-@var{options}} form is used,
>> +@var{options} is a list of @samp{-} separated options which control
>> +the details or location of the dump.  Not all options are applicable
>> +to all dumps; those that are not meaningful are ignored.  The
>> +following options are available
>>
>>  @table @samp
>>  @item address
>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>  Enable showing the EH region number holding each statement.
>>  @item scev
>>  Enable showing scalar evolution analysis details.
>> +@item slim
>> +Inhibit dumping of members of a scope or body of a function merely
>> +because that scope has been reached.  Only dump such items when they
>> +are directly reachable by some other path.  When dumping pretty-printed
>> +trees, this option inhibits dumping the bodies of control structures.
>> +@item =@var{filename}
>> +Instead of using an auto generated dump file name, use the given file
>> +name. The file names @file{stdout} and @file{stderr} are treated
>> +specially and are considered already open standard streams. For
>> +example:
>> +
>> +@smallexample
>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>> +@end smallexample
>> +
>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>> +file named @file{ira.txt}.
>> +
>> +In case of any conflicts, the command line file name takes precedence
>> +over generated file names. For example:
>> +
>> +@smallexample
>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>> +@end smallexample
>> +
>> +Both of the above output the PRE dump on @file{stdout}. However, if
>> +there are multiple command line file names are applicable then the
>> +last one is used. Thus the command
>> +
>> +@smallexample
>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>> +@end smallexample
>> +
>> +outputs all the dumps in @file{all.txt} because the stderr option for
>> +PRE dump is overridden by a later option.
>> +
>>  @item all
>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>> -and @option{lineno}.
>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>> +@option{lineno}.
>>  @end table
>>
>>  The following tree dumps are possible:
>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>  @item all
>>  @opindex fdump-tree-all
>>  Enable all the available tree dumps with the flags provided in this option.
>> +
>>  @end table
>>
>>  @item -ftree-vectorizer-verbose=@var{n}
>> Index: tree-dump.c
>> ===================================================================
>> --- tree-dump.c (revision 187265)
>> +++ tree-dump.c (working copy)
>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>    tree_dump_index enumeration in tree-pass.h.  */
>>  static struct dump_file_info dump_files[TDI_end] =
>>  {
>> -  {NULL, NULL, NULL, 0, 0, 0},
>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>
>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>  };
>>
>>  /* Dynamically registered tree dump files and switches.  */
>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>  };
>>
>>  /* Table of dump options. This must be consistent with the TDF_* flags
>> -   in tree.h */
>> +   in tree-pass.h */
>>  static const struct dump_option_value_info dump_options[] =
>>  {
>>   {"address", TDF_ADDRESS},
>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>   if (dfi->state == 0)
>>     return NULL;
>>
>> +  if (dfi->filename)
>> +    return xstrdup (dfi->filename);
>> +
>>   if (dfi->num < 0)
>>     dump_id[0] = '\0';
>>   else
>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>  }
>>
>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>> +   return that stream, NULL otherwise.  */
>> +
>> +static FILE *
>> +dump_get_standard_stream (struct dump_file_info *dfi)
>> +{
>> +  if (!dfi->filename)
>> +    return NULL;
>> +
>> +  return strcmp("stderr", dfi->filename) == 0
>> +    ? stderr
>> +    : strcmp("stdout", dfi->filename) == 0
>> +    ?  stdout
>> +    : NULL;
>> +}
>> +
>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>    enabled, returns NULL.
>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>     return NULL;
>>
>> -  name = get_dump_file_name (phase);
>>   dfi = get_dump_file_info (phase);
>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>> -  if (!stream)
>> -    error ("could not open dump file %qs: %m", name);
>> +  stream = dump_get_standard_stream (dfi);
>> +  if (stream)
>> +    dfi->state = 1;
>>   else
>> -    dfi->state = 1;
>> -  free (name);
>> +    {
>> +      name = get_dump_file_name (phase);
>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>> +      if (!stream)
>> +        error ("could not open dump file %qs: %m", name);
>> +      else
>> +        dfi->state = 1;
>> +      free (name);
>> +    }
>>
>>   if (flag_ptr)
>>     *flag_ptr = dfi->flags;
>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>    dump_begin.  */
>>
>>  void
>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>> +dump_end (int phase, FILE *stream)
>>  {
>> -  fclose (stream);
>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>> +  if (!dump_get_standard_stream (dfi))
>> +    fclose (stream);
>>  }
>>
>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>> +   enabled tree dumps.  */
>>
>>  static int
>> -dump_enable_all (int flags)
>> +dump_enable_all (int flags, const char *filename)
>>  {
>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>   int n = 0;
>>   size_t i;
>>
>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>> -    if ((dump_files[i].flags & ir_dump_type))
>> -      {
>> -        dump_files[i].state = -1;
>> -        dump_files[i].flags |= flags;
>> -        n++;
>> -      }
>> +    {
>> +      if ((dump_files[i].flags & ir_dump_type))
>> +        {
>> +          dump_files[i].state = -1;
>> +          dump_files[i].flags |= flags;
>> +          n++;
>> +          if (filename)
>> +            dump_files[i].filename = xstrdup (filename);
>> +        }
>> +    }
>>
>>   for (i = 0; i < extra_dump_files_in_use; i++)
>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>> -      {
>> -        extra_dump_files[i].state = -1;
>> -        extra_dump_files[i].flags |= flags;
>> -       n++;
>> -      }
>> +    {
>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>> +        {
>> +          extra_dump_files[i].state = -1;
>> +          extra_dump_files[i].flags |= flags;
>> +          n++;
>> +          if (filename)
>> +            extra_dump_files[i].filename = xstrdup (filename);
>> +        }
>> +    }
>>
>>   return n;
>>  }
>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>   if (!option_value)
>>     return 0;
>>
>> -  if (*option_value && *option_value != '-')
>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>     return 0;
>>
>>   ptr = option_value;
>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>       while (*ptr == '-')
>>        ptr++;
>>       end_ptr = strchr (ptr, '-');
>> +
>>       if (!end_ptr)
>>        end_ptr = ptr + strlen (ptr);
>>       length = end_ptr - ptr;
>>
>> +      if (*ptr == '=')
>> +        {
>> +          /* Interpret rest of the argument as a dump filename.  This
>> +             filename overrides generated dump names as well as other
>> +             command line filenames.  */
>> +          flags |= TDF_FILENAME;
>> +          if (dfi->filename)
>> +            free (dfi->filename);
>> +          dfi->filename = xstrdup (ptr + 1);
>> +          break;
>> +        }
>> +
>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>        if (strlen (option_ptr->name) == length
>>            && !memcmp (option_ptr->name, ptr, length))
>> -         {
>> -           flags |= option_ptr->value;
>> +          {
>> +            flags |= option_ptr->value;
>>            goto found;
>> -         }
>> +          }
>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>               length, ptr, dfi->swtch);
>>     found:;
>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>      known dumps.  */
>>   if (dfi->suffix == NULL)
>> -    dump_enable_all (dfi->flags);
>> +    dump_enable_all (dfi->flags, dfi->filename);
>>
>>   return 1;
>>  }
>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>  bool
>>  enable_rtl_dump_file (void)
>>  {
>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>  }
>> Index: tree-pass.h
>> ===================================================================
>> --- tree-pass.h (revision 187265)
>> +++ tree-pass.h (working copy)
>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>> +                                           instead of constructing one. */
>>
>> -
>>  /* In tree-dump.c */
>>
>>  extern char *get_dump_file_name (int);
>> @@ -222,6 +223,8 @@ struct dump_file_info
>>   const char *suffix;           /* suffix to give output file.  */
>>   const char *swtch;            /* command line switch */
>>   const char *glob;             /* command line glob  */
>> +  const char *filename;         /* use this filename instead of making
>> +                                   up one using dump_base_name + suffix.  */
>>   int flags;                    /* user flags */
>>   int state;                    /* state of play */
>>   int num;                      /* dump file number */
>> Index: testsuite/g++.dg/other/dump-filename-1.C
>> ===================================================================
>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>> @@ -0,0 +1,11 @@
>> +// Test that the dump to a user-defined file works correctly.
>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>> +
>> +void test (int *b, int *e, int stride)
>> +  {
>> +    for (int *p = b; p != e; p += stride)
>> +      *p = 1;
>> +  }
>> +
>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>
>>
>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>> <gdr@integrable-solutions.net> wrote:
>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>> [...]
>>>
>>>> +@item -fdump-rtl-all=stderr
>>>> +@opindex fdump-rtl-all=stderr
>>>
>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>> Rather, expand the description to state this in all the documentation
>>> for -fdump-xxx=yyy.
>>>
>>> [...]
>>>
>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>> +   stderr stream.  */
>>>> +
>>>> +static int
>>>> +dump_stream_p (const char *user_filename)
>>>> +{
>>>> +  if (user_filename)
>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>> +      !strncmp ("stdout", user_filename, 6);
>>>> +  else
>>>> +    return 0;
>>>> +}
>>>
>>> The name is ambiguous.
>>> This function is testing whether its string argument designates one of
>>> the *standard* output streams.  Name it to reflect that..
>>> Have it take the dump state context. Also the coding convention: the binary
>>> operator "||" should be on next line.  In fact the thing could be
>>> simpler.   Instead of
>>> testing over and over again against "stderr" (once in this function, then again
>>> later), just return the corresponding standard FILE* pointer.
>>> Also, this is a case of overuse of strncmp.  If you name the function
>>> dump_get_standard_stream:
>>>
>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>       ? stderr
>>>        : stdcmp("stdout", dfi->use_filename)
>>>        ?  stdout
>>>        : NULL;
>>>
>>> you can simplify:
>>>
>>>> -  name = get_dump_file_name (phase);
>>>>   dfi = get_dump_file_info (phase);
>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>> -  if (!stream)
>>>> -    error ("could not open dump file %qs: %m", name);
>>>> +  if (dump_stream_p (dfi->user_filename))
>>>> +    {
>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>> +        stream = stderr;
>>>> +      else
>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>> +          stream = stdout;
>>>> +        else
>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>> +      dfi->state = 1;
>>>> +    }
>>>>   else
>>>> -    dfi->state = 1;
>>>> -  free (name);
>>>> +    {
>>>> +      name = get_dump_file_name (phase);
>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>> +      if (!stream)
>>>> +        error ("could not open dump file %qs: %m", name);
>>>> +      else
>>>> +        dfi->state = 1;
>>>> +      free (name);
>>>> +    }
>>>>
>>>>   if (flag_ptr)
>>>>     *flag_ptr = dfi->flags;
>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>    dump_begin.  */
>>>>
>>>>  void
>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>> +dump_end (int phase, FILE *stream)
>>>>  {
>>>> -  fclose (stream);
>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>> +    fclose (stream);
>>>>  }
>>>>
>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>
>>>>  static int
>>>> -dump_enable_all (int flags)
>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>  {
>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>   int n = 0;
>>>>   size_t i;
>>>>
>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>> -      {
>>>> -        dump_files[i].state = -1;
>>>> -        dump_files[i].flags |= flags;
>>>> -        n++;
>>>> -      }
>>>> +    {
>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>> +        {
>>>> +          dump_files[i].state = -1;
>>>> +          dump_files[i].flags |= flags;
>>>> +          n++;
>>>> +        }
>>>> +      if (user_filename)
>>>> +        dump_files[i].user_filename = user_filename;
>>>> +    }
>>>>
>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>> -      {
>>>> -        extra_dump_files[i].state = -1;
>>>> -        extra_dump_files[i].flags |= flags;
>>>> -       n++;
>>>> -      }
>>>> +    {
>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>> +        {
>>>> +          extra_dump_files[i].state = -1;
>>>> +          extra_dump_files[i].flags |= flags;
>>>> +          n++;
>>>> +        }
>>>> +      if (user_filename)
>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>> +    }
>>>>
>>>>   return n;
>>>>  }
>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>   if (!option_value)
>>>>     return 0;
>>>>
>>>> -  if (*option_value && *option_value != '-')
>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>     return 0;
>>>>
>>>>   ptr = option_value;
>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>       while (*ptr == '-')
>>>>        ptr++;
>>>>       end_ptr = strchr (ptr, '-');
>>>> +
>>>>       if (!end_ptr)
>>>>        end_ptr = ptr + strlen (ptr);
>>>>       length = end_ptr - ptr;
>>>>
>>>> +      if (*ptr == '=')
>>>> +        {
>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>> +             user provided filename overrides generated dump names as
>>>> +             well as other command line filenames.  */
>>>> +          flags |= TDF_USER_FILENAME;
>>>> +          if (dfi->user_filename)
>>>> +            free (dfi->user_filename);
>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>> +          break;
>>>> +        }
>>>> +
>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>        if (strlen (option_ptr->name) == length
>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>> -         {
>>>> -           flags |= option_ptr->value;
>>>> +          {
>>>> +            flags |= option_ptr->value;
>>>>            goto found;
>>>> -         }
>>>> +          }
>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>               length, ptr, dfi->swtch);
>>>>     found:;
>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>      known dumps.  */
>>>>   if (dfi->suffix == NULL)
>>>> -    dump_enable_all (dfi->flags);
>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>
>>>>   return 1;
>>>>  }
>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>  bool
>>>>  enable_rtl_dump_file (void)
>>>>  {
>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>  }
>>>> Index: tree-pass.h
>>>> ===================================================================
>>>> --- tree-pass.h (revision 187265)
>>>> +++ tree-pass.h (working copy)
>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>> +                                           instead of constructing one. */
>>>>
>>>> -
>>>>  /* In tree-dump.c */
>>>>
>>>>  extern char *get_dump_file_name (int);
>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>   const char *swtch;            /* command line switch */
>>>>   const char *glob;             /* command line glob  */
>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>> +                                   up one using dump_base_name + suffix.  */
>>>
>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>
>>> -- Gaby
Xinliang David Li May 10, 2012, 4:28 p.m. UTC | #3
I like your suggestion and support the end goal you have.  I don't
like the -fopt-info behavior to interfere with regular -fdump-xxx
options either.

I think we should stage the changes in multiple steps as originally
planned. Is Sharad's change good to be checked in for the first stage?

After this one is checked in, the new dump interfaces will be worked
on (and to allow multiple streams). Most of the remaining changes will
be massive text replacement.

thanks,

David


On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>
>> -fdump-tree-pre=<func_list_regexp>
>>
>> I guess this can be achieved via @
>>
>> -fdump-tree-pre@<func_list>
>>
>> -fdump-tree-pre=<file_name>@<func_list>
>>
>>
>> Another issue -- I don't think the current precedence rule is correct.
>> Consider that -fopt-info=2 will be mapped to
>>
>> -fdump-tree-all-transform-verbose2=stderr
>> -fdump-rtl-all-transform-verbose2=stderr
>>
>> then
>>
>> the current precedence rule will cause surprise when the following is used
>>
>> -fopt-info -fdump-tree-pre
>>
>> The PRE dump will be emitted to stderr which is not what user wants.
>> In short, special streams should be treated as 'weak' the same way as
>> your previous implementation.
>
> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
> With -fopt-info -fdump-tree-pre I do not want some information to be
> present only on stderr or in the dump file!  I want it in _both_ places!
> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
> information :()
>
> Thus, the information where dumping goes has to be done differently
> (which is why I asked for some re-org originally, so that passes no
> longer explicitely reference dump_file - dump_file may be different
> for different kind of information it dumps!).  Passes should, instead of
>
>  fprintf (dump_file, "...", ...)
>
> do
>
>  dump_printf (TDF_scev, "...", ...)
>
> thus, specify the kind of information they dump (would be mostly
> TDF_details vs. 0 today I guess).  The dump_printf routine would
> then properly direct to one or more places to dump at.
>
> I realize this needs some more dispatchers for dumping expressions
> and statements (but it should not be too many).  Dumping to
> dump_file would in any case dump to the passes private dump file
> only (unqualified stuff would never be useful for -fopt-info).
>
> The perfect candidate to convert to this kind of scheme is obviously
> the vectorizer with its existing -fvectorizer-verbose.
>
> If the patch doesn't work towards this kind of end-result I'd rather
> not have it.
>
> Thanks,
> Richard.
>
>> thanks,
>>
>> David
>>
>>
>>
>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>> Thanks for your suggestions/comments. I have updated the patch and
>>> documentation. It supports the following usage:
>>>
>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>> -fdump-rtl-ira=ira.dump
>>>
>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>> goes to stdout and the IRA dump goes to ira.dump.
>>>
>>> Thanks,
>>> Sharad
>>>
>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>
>>>        * doc/invoke.texi: Add documentation for the new option.
>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>        (dump_files): Update for new field.
>>>        (dump_switch_p_1): Handle dump filenames.
>>>        (dump_begin): Likewise.
>>>        (get_dump_file_name): Likewise.
>>>        (dump_end): Remove attribute.
>>>        (dump_enable_all): Add new parameter FILENAME.
>>>        All callers updated.
>>>        (enable_rtl_dump_file):
>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>        (struct dump_file_info): Add new field FILENAME.
>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>
>>> Index: doc/invoke.texi
>>> ===================================================================
>>> --- doc/invoke.texi     (revision 187265)
>>> +++ doc/invoke.texi     (working copy)
>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>
>>>  @item -d@var{letters}
>>>  @itemx -fdump-rtl-@var{pass}
>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>  @opindex d
>>>  Says to make debugging dumps during compilation at times specified by
>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>  compiler.  The file names for most of the dumps are made by appending
>>>  a pass number and a word to the @var{dumpname}, and the files are
>>> -created in the directory of the output file.  Note that the pass
>>> -number is computed statically as passes get registered into the pass
>>> -manager.  Thus the numbering is not related to the dynamic order of
>>> -execution of passes.  In particular, a pass installed by a plugin
>>> -could have a number over 200 even if it executed quite early.
>>> -@var{dumpname} is generated from the name of the output file, if
>>> -explicitly specified and it is not an executable, otherwise it is the
>>> -basename of the source file. These switches may have different effects
>>> -when @option{-E} is used for preprocessing.
>>> +created in the directory of the output file. If the
>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>> +option then the dump is done on that file instead of numbered
>>> +files. Note that the pass number is computed statically as passes get
>>> +registered into the pass manager.  Thus the numbering is not related
>>> +to the dynamic order of execution of passes.  In particular, a pass
>>> +installed by a plugin could have a number over 200 even if it executed
>>> +quite early.  @var{dumpname} is generated from the name of the output
>>> +file, if explicitly specified and it is not an executable, otherwise
>>> +it is the basename of the source file. These switches may have
>>> +different effects when @option{-E} is used for preprocessing.
>>>
>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>  @option{-d} option @var{letters}.  Here are the possible
>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>
>>>  @item -fdump-tree-@var{switch}
>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>  @opindex fdump-tree
>>>  Control the dumping at various stages of processing the intermediate
>>>  language tree to a file.  The file name is generated by appending a
>>>  switch specific suffix to the source file name, and the file is
>>> -created in the same directory as the output file.  If the
>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>> -@samp{-} separated options which control the details of the dump.  Not
>>> -all options are applicable to all dumps; those that are not
>>> -meaningful are ignored.  The following options are available
>>> +created in the same directory as the output file. In case of
>>> +@option{=@var{filename}} option, the dump is output on the given file
>>> +name instead.  If the @samp{-@var{options}} form is used,
>>> +@var{options} is a list of @samp{-} separated options which control
>>> +the details or location of the dump.  Not all options are applicable
>>> +to all dumps; those that are not meaningful are ignored.  The
>>> +following options are available
>>>
>>>  @table @samp
>>>  @item address
>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>  Enable showing the EH region number holding each statement.
>>>  @item scev
>>>  Enable showing scalar evolution analysis details.
>>> +@item slim
>>> +Inhibit dumping of members of a scope or body of a function merely
>>> +because that scope has been reached.  Only dump such items when they
>>> +are directly reachable by some other path.  When dumping pretty-printed
>>> +trees, this option inhibits dumping the bodies of control structures.
>>> +@item =@var{filename}
>>> +Instead of using an auto generated dump file name, use the given file
>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>> +specially and are considered already open standard streams. For
>>> +example:
>>> +
>>> +@smallexample
>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>> +@end smallexample
>>> +
>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>> +file named @file{ira.txt}.
>>> +
>>> +In case of any conflicts, the command line file name takes precedence
>>> +over generated file names. For example:
>>> +
>>> +@smallexample
>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>> +@end smallexample
>>> +
>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>> +there are multiple command line file names are applicable then the
>>> +last one is used. Thus the command
>>> +
>>> +@smallexample
>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>> +@end smallexample
>>> +
>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>> +PRE dump is overridden by a later option.
>>> +
>>>  @item all
>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>> -and @option{lineno}.
>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>> +@option{lineno}.
>>>  @end table
>>>
>>>  The following tree dumps are possible:
>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>  @item all
>>>  @opindex fdump-tree-all
>>>  Enable all the available tree dumps with the flags provided in this option.
>>> +
>>>  @end table
>>>
>>>  @item -ftree-vectorizer-verbose=@var{n}
>>> Index: tree-dump.c
>>> ===================================================================
>>> --- tree-dump.c (revision 187265)
>>> +++ tree-dump.c (working copy)
>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>  static struct dump_file_info dump_files[TDI_end] =
>>>  {
>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>
>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>  };
>>>
>>>  /* Dynamically registered tree dump files and switches.  */
>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>  };
>>>
>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>> -   in tree.h */
>>> +   in tree-pass.h */
>>>  static const struct dump_option_value_info dump_options[] =
>>>  {
>>>   {"address", TDF_ADDRESS},
>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>   if (dfi->state == 0)
>>>     return NULL;
>>>
>>> +  if (dfi->filename)
>>> +    return xstrdup (dfi->filename);
>>> +
>>>   if (dfi->num < 0)
>>>     dump_id[0] = '\0';
>>>   else
>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>  }
>>>
>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>> +   return that stream, NULL otherwise.  */
>>> +
>>> +static FILE *
>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>> +{
>>> +  if (!dfi->filename)
>>> +    return NULL;
>>> +
>>> +  return strcmp("stderr", dfi->filename) == 0
>>> +    ? stderr
>>> +    : strcmp("stdout", dfi->filename) == 0
>>> +    ?  stdout
>>> +    : NULL;
>>> +}
>>> +
>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>    enabled, returns NULL.
>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>     return NULL;
>>>
>>> -  name = get_dump_file_name (phase);
>>>   dfi = get_dump_file_info (phase);
>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>> -  if (!stream)
>>> -    error ("could not open dump file %qs: %m", name);
>>> +  stream = dump_get_standard_stream (dfi);
>>> +  if (stream)
>>> +    dfi->state = 1;
>>>   else
>>> -    dfi->state = 1;
>>> -  free (name);
>>> +    {
>>> +      name = get_dump_file_name (phase);
>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>> +      if (!stream)
>>> +        error ("could not open dump file %qs: %m", name);
>>> +      else
>>> +        dfi->state = 1;
>>> +      free (name);
>>> +    }
>>>
>>>   if (flag_ptr)
>>>     *flag_ptr = dfi->flags;
>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>    dump_begin.  */
>>>
>>>  void
>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>> +dump_end (int phase, FILE *stream)
>>>  {
>>> -  fclose (stream);
>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>> +  if (!dump_get_standard_stream (dfi))
>>> +    fclose (stream);
>>>  }
>>>
>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>> +   enabled tree dumps.  */
>>>
>>>  static int
>>> -dump_enable_all (int flags)
>>> +dump_enable_all (int flags, const char *filename)
>>>  {
>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>   int n = 0;
>>>   size_t i;
>>>
>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>> -    if ((dump_files[i].flags & ir_dump_type))
>>> -      {
>>> -        dump_files[i].state = -1;
>>> -        dump_files[i].flags |= flags;
>>> -        n++;
>>> -      }
>>> +    {
>>> +      if ((dump_files[i].flags & ir_dump_type))
>>> +        {
>>> +          dump_files[i].state = -1;
>>> +          dump_files[i].flags |= flags;
>>> +          n++;
>>> +          if (filename)
>>> +            dump_files[i].filename = xstrdup (filename);
>>> +        }
>>> +    }
>>>
>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>> -      {
>>> -        extra_dump_files[i].state = -1;
>>> -        extra_dump_files[i].flags |= flags;
>>> -       n++;
>>> -      }
>>> +    {
>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>> +        {
>>> +          extra_dump_files[i].state = -1;
>>> +          extra_dump_files[i].flags |= flags;
>>> +          n++;
>>> +          if (filename)
>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>> +        }
>>> +    }
>>>
>>>   return n;
>>>  }
>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>   if (!option_value)
>>>     return 0;
>>>
>>> -  if (*option_value && *option_value != '-')
>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>     return 0;
>>>
>>>   ptr = option_value;
>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>       while (*ptr == '-')
>>>        ptr++;
>>>       end_ptr = strchr (ptr, '-');
>>> +
>>>       if (!end_ptr)
>>>        end_ptr = ptr + strlen (ptr);
>>>       length = end_ptr - ptr;
>>>
>>> +      if (*ptr == '=')
>>> +        {
>>> +          /* Interpret rest of the argument as a dump filename.  This
>>> +             filename overrides generated dump names as well as other
>>> +             command line filenames.  */
>>> +          flags |= TDF_FILENAME;
>>> +          if (dfi->filename)
>>> +            free (dfi->filename);
>>> +          dfi->filename = xstrdup (ptr + 1);
>>> +          break;
>>> +        }
>>> +
>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>        if (strlen (option_ptr->name) == length
>>>            && !memcmp (option_ptr->name, ptr, length))
>>> -         {
>>> -           flags |= option_ptr->value;
>>> +          {
>>> +            flags |= option_ptr->value;
>>>            goto found;
>>> -         }
>>> +          }
>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>               length, ptr, dfi->swtch);
>>>     found:;
>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>      known dumps.  */
>>>   if (dfi->suffix == NULL)
>>> -    dump_enable_all (dfi->flags);
>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>
>>>   return 1;
>>>  }
>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>  bool
>>>  enable_rtl_dump_file (void)
>>>  {
>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>  }
>>> Index: tree-pass.h
>>> ===================================================================
>>> --- tree-pass.h (revision 187265)
>>> +++ tree-pass.h (working copy)
>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>> +                                           instead of constructing one. */
>>>
>>> -
>>>  /* In tree-dump.c */
>>>
>>>  extern char *get_dump_file_name (int);
>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>   const char *suffix;           /* suffix to give output file.  */
>>>   const char *swtch;            /* command line switch */
>>>   const char *glob;             /* command line glob  */
>>> +  const char *filename;         /* use this filename instead of making
>>> +                                   up one using dump_base_name + suffix.  */
>>>   int flags;                    /* user flags */
>>>   int state;                    /* state of play */
>>>   int num;                      /* dump file number */
>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>> ===================================================================
>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>> @@ -0,0 +1,11 @@
>>> +// Test that the dump to a user-defined file works correctly.
>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>> +
>>> +void test (int *b, int *e, int stride)
>>> +  {
>>> +    for (int *p = b; p != e; p += stride)
>>> +      *p = 1;
>>> +  }
>>> +
>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>
>>>
>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>> <gdr@integrable-solutions.net> wrote:
>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>> [...]
>>>>
>>>>> +@item -fdump-rtl-all=stderr
>>>>> +@opindex fdump-rtl-all=stderr
>>>>
>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>> Rather, expand the description to state this in all the documentation
>>>> for -fdump-xxx=yyy.
>>>>
>>>> [...]
>>>>
>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>> +   stderr stream.  */
>>>>> +
>>>>> +static int
>>>>> +dump_stream_p (const char *user_filename)
>>>>> +{
>>>>> +  if (user_filename)
>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>> +  else
>>>>> +    return 0;
>>>>> +}
>>>>
>>>> The name is ambiguous.
>>>> This function is testing whether its string argument designates one of
>>>> the *standard* output streams.  Name it to reflect that..
>>>> Have it take the dump state context. Also the coding convention: the binary
>>>> operator "||" should be on next line.  In fact the thing could be
>>>> simpler.   Instead of
>>>> testing over and over again against "stderr" (once in this function, then again
>>>> later), just return the corresponding standard FILE* pointer.
>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>> dump_get_standard_stream:
>>>>
>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>       ? stderr
>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>        ?  stdout
>>>>        : NULL;
>>>>
>>>> you can simplify:
>>>>
>>>>> -  name = get_dump_file_name (phase);
>>>>>   dfi = get_dump_file_info (phase);
>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>> -  if (!stream)
>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>> +    {
>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>> +        stream = stderr;
>>>>> +      else
>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>> +          stream = stdout;
>>>>> +        else
>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>> +      dfi->state = 1;
>>>>> +    }
>>>>>   else
>>>>> -    dfi->state = 1;
>>>>> -  free (name);
>>>>> +    {
>>>>> +      name = get_dump_file_name (phase);
>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>> +      if (!stream)
>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>> +      else
>>>>> +        dfi->state = 1;
>>>>> +      free (name);
>>>>> +    }
>>>>>
>>>>>   if (flag_ptr)
>>>>>     *flag_ptr = dfi->flags;
>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>    dump_begin.  */
>>>>>
>>>>>  void
>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>> +dump_end (int phase, FILE *stream)
>>>>>  {
>>>>> -  fclose (stream);
>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>> +    fclose (stream);
>>>>>  }
>>>>>
>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>
>>>>>  static int
>>>>> -dump_enable_all (int flags)
>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>  {
>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>   int n = 0;
>>>>>   size_t i;
>>>>>
>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>> -      {
>>>>> -        dump_files[i].state = -1;
>>>>> -        dump_files[i].flags |= flags;
>>>>> -        n++;
>>>>> -      }
>>>>> +    {
>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>> +        {
>>>>> +          dump_files[i].state = -1;
>>>>> +          dump_files[i].flags |= flags;
>>>>> +          n++;
>>>>> +        }
>>>>> +      if (user_filename)
>>>>> +        dump_files[i].user_filename = user_filename;
>>>>> +    }
>>>>>
>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>> -      {
>>>>> -        extra_dump_files[i].state = -1;
>>>>> -        extra_dump_files[i].flags |= flags;
>>>>> -       n++;
>>>>> -      }
>>>>> +    {
>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>> +        {
>>>>> +          extra_dump_files[i].state = -1;
>>>>> +          extra_dump_files[i].flags |= flags;
>>>>> +          n++;
>>>>> +        }
>>>>> +      if (user_filename)
>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>> +    }
>>>>>
>>>>>   return n;
>>>>>  }
>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>   if (!option_value)
>>>>>     return 0;
>>>>>
>>>>> -  if (*option_value && *option_value != '-')
>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>     return 0;
>>>>>
>>>>>   ptr = option_value;
>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>       while (*ptr == '-')
>>>>>        ptr++;
>>>>>       end_ptr = strchr (ptr, '-');
>>>>> +
>>>>>       if (!end_ptr)
>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>       length = end_ptr - ptr;
>>>>>
>>>>> +      if (*ptr == '=')
>>>>> +        {
>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>> +             user provided filename overrides generated dump names as
>>>>> +             well as other command line filenames.  */
>>>>> +          flags |= TDF_USER_FILENAME;
>>>>> +          if (dfi->user_filename)
>>>>> +            free (dfi->user_filename);
>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>> +          break;
>>>>> +        }
>>>>> +
>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>        if (strlen (option_ptr->name) == length
>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>> -         {
>>>>> -           flags |= option_ptr->value;
>>>>> +          {
>>>>> +            flags |= option_ptr->value;
>>>>>            goto found;
>>>>> -         }
>>>>> +          }
>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>               length, ptr, dfi->swtch);
>>>>>     found:;
>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>      known dumps.  */
>>>>>   if (dfi->suffix == NULL)
>>>>> -    dump_enable_all (dfi->flags);
>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>
>>>>>   return 1;
>>>>>  }
>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>  bool
>>>>>  enable_rtl_dump_file (void)
>>>>>  {
>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>  }
>>>>> Index: tree-pass.h
>>>>> ===================================================================
>>>>> --- tree-pass.h (revision 187265)
>>>>> +++ tree-pass.h (working copy)
>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>> +                                           instead of constructing one. */
>>>>>
>>>>> -
>>>>>  /* In tree-dump.c */
>>>>>
>>>>>  extern char *get_dump_file_name (int);
>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>   const char *swtch;            /* command line switch */
>>>>>   const char *glob;             /* command line glob  */
>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>
>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>
>>>> -- Gaby
Richard Biener May 11, 2012, 8:49 a.m. UTC | #4
On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davidxl@google.com> wrote:
> I like your suggestion and support the end goal you have.  I don't
> like the -fopt-info behavior to interfere with regular -fdump-xxx
> options either.
>
> I think we should stage the changes in multiple steps as originally
> planned. Is Sharad's change good to be checked in for the first stage?

Well - I don't think the change walks in the direction we want to go, so I don't
see a good reason to make that change.

> After this one is checked in, the new dump interfaces will be worked
> on (and to allow multiple streams). Most of the remaining changes will
> be massive text replacement.
>
> thanks,
>
> David
>
>
> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>>
>>> -fdump-tree-pre=<func_list_regexp>
>>>
>>> I guess this can be achieved via @
>>>
>>> -fdump-tree-pre@<func_list>
>>>
>>> -fdump-tree-pre=<file_name>@<func_list>
>>>
>>>
>>> Another issue -- I don't think the current precedence rule is correct.
>>> Consider that -fopt-info=2 will be mapped to
>>>
>>> -fdump-tree-all-transform-verbose2=stderr
>>> -fdump-rtl-all-transform-verbose2=stderr
>>>
>>> then
>>>
>>> the current precedence rule will cause surprise when the following is used
>>>
>>> -fopt-info -fdump-tree-pre
>>>
>>> The PRE dump will be emitted to stderr which is not what user wants.
>>> In short, special streams should be treated as 'weak' the same way as
>>> your previous implementation.
>>
>> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
>> With -fopt-info -fdump-tree-pre I do not want some information to be
>> present only on stderr or in the dump file!  I want it in _both_ places!
>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
>> information :()
>>
>> Thus, the information where dumping goes has to be done differently
>> (which is why I asked for some re-org originally, so that passes no
>> longer explicitely reference dump_file - dump_file may be different
>> for different kind of information it dumps!).  Passes should, instead of
>>
>>  fprintf (dump_file, "...", ...)
>>
>> do
>>
>>  dump_printf (TDF_scev, "...", ...)
>>
>> thus, specify the kind of information they dump (would be mostly
>> TDF_details vs. 0 today I guess).  The dump_printf routine would
>> then properly direct to one or more places to dump at.
>>
>> I realize this needs some more dispatchers for dumping expressions
>> and statements (but it should not be too many).  Dumping to
>> dump_file would in any case dump to the passes private dump file
>> only (unqualified stuff would never be useful for -fopt-info).
>>
>> The perfect candidate to convert to this kind of scheme is obviously
>> the vectorizer with its existing -fvectorizer-verbose.
>>
>> If the patch doesn't work towards this kind of end-result I'd rather
>> not have it.
>>
>> Thanks,
>> Richard.
>>
>>> thanks,
>>>
>>> David
>>>
>>>
>>>
>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>>> Thanks for your suggestions/comments. I have updated the patch and
>>>> documentation. It supports the following usage:
>>>>
>>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>>> -fdump-rtl-ira=ira.dump
>>>>
>>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>>> goes to stdout and the IRA dump goes to ira.dump.
>>>>
>>>> Thanks,
>>>> Sharad
>>>>
>>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>>
>>>>        * doc/invoke.texi: Add documentation for the new option.
>>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>>        (dump_files): Update for new field.
>>>>        (dump_switch_p_1): Handle dump filenames.
>>>>        (dump_begin): Likewise.
>>>>        (get_dump_file_name): Likewise.
>>>>        (dump_end): Remove attribute.
>>>>        (dump_enable_all): Add new parameter FILENAME.
>>>>        All callers updated.
>>>>        (enable_rtl_dump_file):
>>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>>        (struct dump_file_info): Add new field FILENAME.
>>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>>
>>>> Index: doc/invoke.texi
>>>> ===================================================================
>>>> --- doc/invoke.texi     (revision 187265)
>>>> +++ doc/invoke.texi     (working copy)
>>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>>
>>>>  @item -d@var{letters}
>>>>  @itemx -fdump-rtl-@var{pass}
>>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>>  @opindex d
>>>>  Says to make debugging dumps during compilation at times specified by
>>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>>  compiler.  The file names for most of the dumps are made by appending
>>>>  a pass number and a word to the @var{dumpname}, and the files are
>>>> -created in the directory of the output file.  Note that the pass
>>>> -number is computed statically as passes get registered into the pass
>>>> -manager.  Thus the numbering is not related to the dynamic order of
>>>> -execution of passes.  In particular, a pass installed by a plugin
>>>> -could have a number over 200 even if it executed quite early.
>>>> -@var{dumpname} is generated from the name of the output file, if
>>>> -explicitly specified and it is not an executable, otherwise it is the
>>>> -basename of the source file. These switches may have different effects
>>>> -when @option{-E} is used for preprocessing.
>>>> +created in the directory of the output file. If the
>>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>>> +option then the dump is done on that file instead of numbered
>>>> +files. Note that the pass number is computed statically as passes get
>>>> +registered into the pass manager.  Thus the numbering is not related
>>>> +to the dynamic order of execution of passes.  In particular, a pass
>>>> +installed by a plugin could have a number over 200 even if it executed
>>>> +quite early.  @var{dumpname} is generated from the name of the output
>>>> +file, if explicitly specified and it is not an executable, otherwise
>>>> +it is the basename of the source file. These switches may have
>>>> +different effects when @option{-E} is used for preprocessing.
>>>>
>>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>>  @option{-d} option @var{letters}.  Here are the possible
>>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>>
>>>>  @item -fdump-tree-@var{switch}
>>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>>  @opindex fdump-tree
>>>>  Control the dumping at various stages of processing the intermediate
>>>>  language tree to a file.  The file name is generated by appending a
>>>>  switch specific suffix to the source file name, and the file is
>>>> -created in the same directory as the output file.  If the
>>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>>> -@samp{-} separated options which control the details of the dump.  Not
>>>> -all options are applicable to all dumps; those that are not
>>>> -meaningful are ignored.  The following options are available
>>>> +created in the same directory as the output file. In case of
>>>> +@option{=@var{filename}} option, the dump is output on the given file
>>>> +name instead.  If the @samp{-@var{options}} form is used,
>>>> +@var{options} is a list of @samp{-} separated options which control
>>>> +the details or location of the dump.  Not all options are applicable
>>>> +to all dumps; those that are not meaningful are ignored.  The
>>>> +following options are available
>>>>
>>>>  @table @samp
>>>>  @item address
>>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>>  Enable showing the EH region number holding each statement.
>>>>  @item scev
>>>>  Enable showing scalar evolution analysis details.
>>>> +@item slim
>>>> +Inhibit dumping of members of a scope or body of a function merely
>>>> +because that scope has been reached.  Only dump such items when they
>>>> +are directly reachable by some other path.  When dumping pretty-printed
>>>> +trees, this option inhibits dumping the bodies of control structures.
>>>> +@item =@var{filename}
>>>> +Instead of using an auto generated dump file name, use the given file
>>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>>> +specially and are considered already open standard streams. For
>>>> +example:
>>>> +
>>>> +@smallexample
>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>>> +@end smallexample
>>>> +
>>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>>> +file named @file{ira.txt}.
>>>> +
>>>> +In case of any conflicts, the command line file name takes precedence
>>>> +over generated file names. For example:
>>>> +
>>>> +@smallexample
>>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>>> +@end smallexample
>>>> +
>>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>>> +there are multiple command line file names are applicable then the
>>>> +last one is used. Thus the command
>>>> +
>>>> +@smallexample
>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>>> +@end smallexample
>>>> +
>>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>>> +PRE dump is overridden by a later option.
>>>> +
>>>>  @item all
>>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>>> -and @option{lineno}.
>>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>>> +@option{lineno}.
>>>>  @end table
>>>>
>>>>  The following tree dumps are possible:
>>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>>  @item all
>>>>  @opindex fdump-tree-all
>>>>  Enable all the available tree dumps with the flags provided in this option.
>>>> +
>>>>  @end table
>>>>
>>>>  @item -ftree-vectorizer-verbose=@var{n}
>>>> Index: tree-dump.c
>>>> ===================================================================
>>>> --- tree-dump.c (revision 187265)
>>>> +++ tree-dump.c (working copy)
>>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>>  static struct dump_file_info dump_files[TDI_end] =
>>>>  {
>>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>>
>>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>>  };
>>>>
>>>>  /* Dynamically registered tree dump files and switches.  */
>>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>>  };
>>>>
>>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>>> -   in tree.h */
>>>> +   in tree-pass.h */
>>>>  static const struct dump_option_value_info dump_options[] =
>>>>  {
>>>>   {"address", TDF_ADDRESS},
>>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>>   if (dfi->state == 0)
>>>>     return NULL;
>>>>
>>>> +  if (dfi->filename)
>>>> +    return xstrdup (dfi->filename);
>>>> +
>>>>   if (dfi->num < 0)
>>>>     dump_id[0] = '\0';
>>>>   else
>>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>>  }
>>>>
>>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>>> +   return that stream, NULL otherwise.  */
>>>> +
>>>> +static FILE *
>>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>>> +{
>>>> +  if (!dfi->filename)
>>>> +    return NULL;
>>>> +
>>>> +  return strcmp("stderr", dfi->filename) == 0
>>>> +    ? stderr
>>>> +    : strcmp("stdout", dfi->filename) == 0
>>>> +    ?  stdout
>>>> +    : NULL;
>>>> +}
>>>> +
>>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>>    enabled, returns NULL.
>>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>>     return NULL;
>>>>
>>>> -  name = get_dump_file_name (phase);
>>>>   dfi = get_dump_file_info (phase);
>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>> -  if (!stream)
>>>> -    error ("could not open dump file %qs: %m", name);
>>>> +  stream = dump_get_standard_stream (dfi);
>>>> +  if (stream)
>>>> +    dfi->state = 1;
>>>>   else
>>>> -    dfi->state = 1;
>>>> -  free (name);
>>>> +    {
>>>> +      name = get_dump_file_name (phase);
>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>> +      if (!stream)
>>>> +        error ("could not open dump file %qs: %m", name);
>>>> +      else
>>>> +        dfi->state = 1;
>>>> +      free (name);
>>>> +    }
>>>>
>>>>   if (flag_ptr)
>>>>     *flag_ptr = dfi->flags;
>>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>>    dump_begin.  */
>>>>
>>>>  void
>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>> +dump_end (int phase, FILE *stream)
>>>>  {
>>>> -  fclose (stream);
>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>> +  if (!dump_get_standard_stream (dfi))
>>>> +    fclose (stream);
>>>>  }
>>>>
>>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>>> +   enabled tree dumps.  */
>>>>
>>>>  static int
>>>> -dump_enable_all (int flags)
>>>> +dump_enable_all (int flags, const char *filename)
>>>>  {
>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>   int n = 0;
>>>>   size_t i;
>>>>
>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>> -      {
>>>> -        dump_files[i].state = -1;
>>>> -        dump_files[i].flags |= flags;
>>>> -        n++;
>>>> -      }
>>>> +    {
>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>> +        {
>>>> +          dump_files[i].state = -1;
>>>> +          dump_files[i].flags |= flags;
>>>> +          n++;
>>>> +          if (filename)
>>>> +            dump_files[i].filename = xstrdup (filename);
>>>> +        }
>>>> +    }
>>>>
>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>> -      {
>>>> -        extra_dump_files[i].state = -1;
>>>> -        extra_dump_files[i].flags |= flags;
>>>> -       n++;
>>>> -      }
>>>> +    {
>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>> +        {
>>>> +          extra_dump_files[i].state = -1;
>>>> +          extra_dump_files[i].flags |= flags;
>>>> +          n++;
>>>> +          if (filename)
>>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>>> +        }
>>>> +    }
>>>>
>>>>   return n;
>>>>  }
>>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>   if (!option_value)
>>>>     return 0;
>>>>
>>>> -  if (*option_value && *option_value != '-')
>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>     return 0;
>>>>
>>>>   ptr = option_value;
>>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>       while (*ptr == '-')
>>>>        ptr++;
>>>>       end_ptr = strchr (ptr, '-');
>>>> +
>>>>       if (!end_ptr)
>>>>        end_ptr = ptr + strlen (ptr);
>>>>       length = end_ptr - ptr;
>>>>
>>>> +      if (*ptr == '=')
>>>> +        {
>>>> +          /* Interpret rest of the argument as a dump filename.  This
>>>> +             filename overrides generated dump names as well as other
>>>> +             command line filenames.  */
>>>> +          flags |= TDF_FILENAME;
>>>> +          if (dfi->filename)
>>>> +            free (dfi->filename);
>>>> +          dfi->filename = xstrdup (ptr + 1);
>>>> +          break;
>>>> +        }
>>>> +
>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>        if (strlen (option_ptr->name) == length
>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>> -         {
>>>> -           flags |= option_ptr->value;
>>>> +          {
>>>> +            flags |= option_ptr->value;
>>>>            goto found;
>>>> -         }
>>>> +          }
>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>               length, ptr, dfi->swtch);
>>>>     found:;
>>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>      known dumps.  */
>>>>   if (dfi->suffix == NULL)
>>>> -    dump_enable_all (dfi->flags);
>>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>>
>>>>   return 1;
>>>>  }
>>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>>  bool
>>>>  enable_rtl_dump_file (void)
>>>>  {
>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>  }
>>>> Index: tree-pass.h
>>>> ===================================================================
>>>> --- tree-pass.h (revision 187265)
>>>> +++ tree-pass.h (working copy)
>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>>> +                                           instead of constructing one. */
>>>>
>>>> -
>>>>  /* In tree-dump.c */
>>>>
>>>>  extern char *get_dump_file_name (int);
>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>   const char *swtch;            /* command line switch */
>>>>   const char *glob;             /* command line glob  */
>>>> +  const char *filename;         /* use this filename instead of making
>>>> +                                   up one using dump_base_name + suffix.  */
>>>>   int flags;                    /* user flags */
>>>>   int state;                    /* state of play */
>>>>   int num;                      /* dump file number */
>>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>>> ===================================================================
>>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>> @@ -0,0 +1,11 @@
>>>> +// Test that the dump to a user-defined file works correctly.
>>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>>> +
>>>> +void test (int *b, int *e, int stride)
>>>> +  {
>>>> +    for (int *p = b; p != e; p += stride)
>>>> +      *p = 1;
>>>> +  }
>>>> +
>>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>>
>>>>
>>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>>> <gdr@integrable-solutions.net> wrote:
>>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>>> [...]
>>>>>
>>>>>> +@item -fdump-rtl-all=stderr
>>>>>> +@opindex fdump-rtl-all=stderr
>>>>>
>>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>>> Rather, expand the description to state this in all the documentation
>>>>> for -fdump-xxx=yyy.
>>>>>
>>>>> [...]
>>>>>
>>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>>> +   stderr stream.  */
>>>>>> +
>>>>>> +static int
>>>>>> +dump_stream_p (const char *user_filename)
>>>>>> +{
>>>>>> +  if (user_filename)
>>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>>> +  else
>>>>>> +    return 0;
>>>>>> +}
>>>>>
>>>>> The name is ambiguous.
>>>>> This function is testing whether its string argument designates one of
>>>>> the *standard* output streams.  Name it to reflect that..
>>>>> Have it take the dump state context. Also the coding convention: the binary
>>>>> operator "||" should be on next line.  In fact the thing could be
>>>>> simpler.   Instead of
>>>>> testing over and over again against "stderr" (once in this function, then again
>>>>> later), just return the corresponding standard FILE* pointer.
>>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>>> dump_get_standard_stream:
>>>>>
>>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>>       ? stderr
>>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>>        ?  stdout
>>>>>        : NULL;
>>>>>
>>>>> you can simplify:
>>>>>
>>>>>> -  name = get_dump_file_name (phase);
>>>>>>   dfi = get_dump_file_info (phase);
>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>> -  if (!stream)
>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>>> +    {
>>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>>> +        stream = stderr;
>>>>>> +      else
>>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>>> +          stream = stdout;
>>>>>> +        else
>>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>>> +      dfi->state = 1;
>>>>>> +    }
>>>>>>   else
>>>>>> -    dfi->state = 1;
>>>>>> -  free (name);
>>>>>> +    {
>>>>>> +      name = get_dump_file_name (phase);
>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>> +      if (!stream)
>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>> +      else
>>>>>> +        dfi->state = 1;
>>>>>> +      free (name);
>>>>>> +    }
>>>>>>
>>>>>>   if (flag_ptr)
>>>>>>     *flag_ptr = dfi->flags;
>>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>>    dump_begin.  */
>>>>>>
>>>>>>  void
>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>  {
>>>>>> -  fclose (stream);
>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>>> +    fclose (stream);
>>>>>>  }
>>>>>>
>>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>
>>>>>>  static int
>>>>>> -dump_enable_all (int flags)
>>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>>  {
>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>   int n = 0;
>>>>>>   size_t i;
>>>>>>
>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>> -      {
>>>>>> -        dump_files[i].state = -1;
>>>>>> -        dump_files[i].flags |= flags;
>>>>>> -        n++;
>>>>>> -      }
>>>>>> +    {
>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>> +        {
>>>>>> +          dump_files[i].state = -1;
>>>>>> +          dump_files[i].flags |= flags;
>>>>>> +          n++;
>>>>>> +        }
>>>>>> +      if (user_filename)
>>>>>> +        dump_files[i].user_filename = user_filename;
>>>>>> +    }
>>>>>>
>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>> -      {
>>>>>> -        extra_dump_files[i].state = -1;
>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>> -       n++;
>>>>>> -      }
>>>>>> +    {
>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>> +        {
>>>>>> +          extra_dump_files[i].state = -1;
>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>> +          n++;
>>>>>> +        }
>>>>>> +      if (user_filename)
>>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>>> +    }
>>>>>>
>>>>>>   return n;
>>>>>>  }
>>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>   if (!option_value)
>>>>>>     return 0;
>>>>>>
>>>>>> -  if (*option_value && *option_value != '-')
>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>     return 0;
>>>>>>
>>>>>>   ptr = option_value;
>>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>       while (*ptr == '-')
>>>>>>        ptr++;
>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>> +
>>>>>>       if (!end_ptr)
>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>       length = end_ptr - ptr;
>>>>>>
>>>>>> +      if (*ptr == '=')
>>>>>> +        {
>>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>>> +             user provided filename overrides generated dump names as
>>>>>> +             well as other command line filenames.  */
>>>>>> +          flags |= TDF_USER_FILENAME;
>>>>>> +          if (dfi->user_filename)
>>>>>> +            free (dfi->user_filename);
>>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>>> +          break;
>>>>>> +        }
>>>>>> +
>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>> -         {
>>>>>> -           flags |= option_ptr->value;
>>>>>> +          {
>>>>>> +            flags |= option_ptr->value;
>>>>>>            goto found;
>>>>>> -         }
>>>>>> +          }
>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>               length, ptr, dfi->swtch);
>>>>>>     found:;
>>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>      known dumps.  */
>>>>>>   if (dfi->suffix == NULL)
>>>>>> -    dump_enable_all (dfi->flags);
>>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>>
>>>>>>   return 1;
>>>>>>  }
>>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>>  bool
>>>>>>  enable_rtl_dump_file (void)
>>>>>>  {
>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>  }
>>>>>> Index: tree-pass.h
>>>>>> ===================================================================
>>>>>> --- tree-pass.h (revision 187265)
>>>>>> +++ tree-pass.h (working copy)
>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>>> +                                           instead of constructing one. */
>>>>>>
>>>>>> -
>>>>>>  /* In tree-dump.c */
>>>>>>
>>>>>>  extern char *get_dump_file_name (int);
>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>   const char *swtch;            /* command line switch */
>>>>>>   const char *glob;             /* command line glob  */
>>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>
>>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>>
>>>>> -- Gaby
Xinliang David Li May 11, 2012, 4:06 p.m. UTC | #5
On Fri, May 11, 2012 at 1:49 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>> I like your suggestion and support the end goal you have.  I don't
>> like the -fopt-info behavior to interfere with regular -fdump-xxx
>> options either.
>>
>> I think we should stage the changes in multiple steps as originally
>> planned. Is Sharad's change good to be checked in for the first stage?
>
> Well - I don't think the change walks in the direction we want to go, so I don't
> see a good reason to make that change.

Is your direction misunderstood or you want everything to be changed
in one single patch (including replacement of all fprintf (dump_file,
...)? If the former, please clarify. If the latter, it can be done.

thanks,

David

>
>> After this one is checked in, the new dump interfaces will be worked
>> on (and to allow multiple streams). Most of the remaining changes will
>> be massive text replacement.
>>
>> thanks,
>>
>> David
>>
>>
>> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>>>
>>>> -fdump-tree-pre=<func_list_regexp>
>>>>
>>>> I guess this can be achieved via @
>>>>
>>>> -fdump-tree-pre@<func_list>
>>>>
>>>> -fdump-tree-pre=<file_name>@<func_list>
>>>>
>>>>
>>>> Another issue -- I don't think the current precedence rule is correct.
>>>> Consider that -fopt-info=2 will be mapped to
>>>>
>>>> -fdump-tree-all-transform-verbose2=stderr
>>>> -fdump-rtl-all-transform-verbose2=stderr
>>>>
>>>> then
>>>>
>>>> the current precedence rule will cause surprise when the following is used
>>>>
>>>> -fopt-info -fdump-tree-pre
>>>>
>>>> The PRE dump will be emitted to stderr which is not what user wants.
>>>> In short, special streams should be treated as 'weak' the same way as
>>>> your previous implementation.
>>>
>>> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
>>> With -fopt-info -fdump-tree-pre I do not want some information to be
>>> present only on stderr or in the dump file!  I want it in _both_ places!
>>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
>>> information :()
>>>
>>> Thus, the information where dumping goes has to be done differently
>>> (which is why I asked for some re-org originally, so that passes no
>>> longer explicitely reference dump_file - dump_file may be different
>>> for different kind of information it dumps!).  Passes should, instead of
>>>
>>>  fprintf (dump_file, "...", ...)
>>>
>>> do
>>>
>>>  dump_printf (TDF_scev, "...", ...)
>>>
>>> thus, specify the kind of information they dump (would be mostly
>>> TDF_details vs. 0 today I guess).  The dump_printf routine would
>>> then properly direct to one or more places to dump at.
>>>
>>> I realize this needs some more dispatchers for dumping expressions
>>> and statements (but it should not be too many).  Dumping to
>>> dump_file would in any case dump to the passes private dump file
>>> only (unqualified stuff would never be useful for -fopt-info).
>>>
>>> The perfect candidate to convert to this kind of scheme is obviously
>>> the vectorizer with its existing -fvectorizer-verbose.
>>>
>>> If the patch doesn't work towards this kind of end-result I'd rather
>>> not have it.
>>>
>>> Thanks,
>>> Richard.
>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>>
>>>>
>>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>>>> Thanks for your suggestions/comments. I have updated the patch and
>>>>> documentation. It supports the following usage:
>>>>>
>>>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>>>> -fdump-rtl-ira=ira.dump
>>>>>
>>>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>>>> goes to stdout and the IRA dump goes to ira.dump.
>>>>>
>>>>> Thanks,
>>>>> Sharad
>>>>>
>>>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>>>
>>>>>        * doc/invoke.texi: Add documentation for the new option.
>>>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>>>        (dump_files): Update for new field.
>>>>>        (dump_switch_p_1): Handle dump filenames.
>>>>>        (dump_begin): Likewise.
>>>>>        (get_dump_file_name): Likewise.
>>>>>        (dump_end): Remove attribute.
>>>>>        (dump_enable_all): Add new parameter FILENAME.
>>>>>        All callers updated.
>>>>>        (enable_rtl_dump_file):
>>>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>>>        (struct dump_file_info): Add new field FILENAME.
>>>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>>>
>>>>> Index: doc/invoke.texi
>>>>> ===================================================================
>>>>> --- doc/invoke.texi     (revision 187265)
>>>>> +++ doc/invoke.texi     (working copy)
>>>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>>>
>>>>>  @item -d@var{letters}
>>>>>  @itemx -fdump-rtl-@var{pass}
>>>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>>>  @opindex d
>>>>>  Says to make debugging dumps during compilation at times specified by
>>>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>>>  compiler.  The file names for most of the dumps are made by appending
>>>>>  a pass number and a word to the @var{dumpname}, and the files are
>>>>> -created in the directory of the output file.  Note that the pass
>>>>> -number is computed statically as passes get registered into the pass
>>>>> -manager.  Thus the numbering is not related to the dynamic order of
>>>>> -execution of passes.  In particular, a pass installed by a plugin
>>>>> -could have a number over 200 even if it executed quite early.
>>>>> -@var{dumpname} is generated from the name of the output file, if
>>>>> -explicitly specified and it is not an executable, otherwise it is the
>>>>> -basename of the source file. These switches may have different effects
>>>>> -when @option{-E} is used for preprocessing.
>>>>> +created in the directory of the output file. If the
>>>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>>>> +option then the dump is done on that file instead of numbered
>>>>> +files. Note that the pass number is computed statically as passes get
>>>>> +registered into the pass manager.  Thus the numbering is not related
>>>>> +to the dynamic order of execution of passes.  In particular, a pass
>>>>> +installed by a plugin could have a number over 200 even if it executed
>>>>> +quite early.  @var{dumpname} is generated from the name of the output
>>>>> +file, if explicitly specified and it is not an executable, otherwise
>>>>> +it is the basename of the source file. These switches may have
>>>>> +different effects when @option{-E} is used for preprocessing.
>>>>>
>>>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>>>  @option{-d} option @var{letters}.  Here are the possible
>>>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>>>
>>>>>  @item -fdump-tree-@var{switch}
>>>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>>>  @opindex fdump-tree
>>>>>  Control the dumping at various stages of processing the intermediate
>>>>>  language tree to a file.  The file name is generated by appending a
>>>>>  switch specific suffix to the source file name, and the file is
>>>>> -created in the same directory as the output file.  If the
>>>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>>>> -@samp{-} separated options which control the details of the dump.  Not
>>>>> -all options are applicable to all dumps; those that are not
>>>>> -meaningful are ignored.  The following options are available
>>>>> +created in the same directory as the output file. In case of
>>>>> +@option{=@var{filename}} option, the dump is output on the given file
>>>>> +name instead.  If the @samp{-@var{options}} form is used,
>>>>> +@var{options} is a list of @samp{-} separated options which control
>>>>> +the details or location of the dump.  Not all options are applicable
>>>>> +to all dumps; those that are not meaningful are ignored.  The
>>>>> +following options are available
>>>>>
>>>>>  @table @samp
>>>>>  @item address
>>>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>>>  Enable showing the EH region number holding each statement.
>>>>>  @item scev
>>>>>  Enable showing scalar evolution analysis details.
>>>>> +@item slim
>>>>> +Inhibit dumping of members of a scope or body of a function merely
>>>>> +because that scope has been reached.  Only dump such items when they
>>>>> +are directly reachable by some other path.  When dumping pretty-printed
>>>>> +trees, this option inhibits dumping the bodies of control structures.
>>>>> +@item =@var{filename}
>>>>> +Instead of using an auto generated dump file name, use the given file
>>>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>>>> +specially and are considered already open standard streams. For
>>>>> +example:
>>>>> +
>>>>> +@smallexample
>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>>>> +@end smallexample
>>>>> +
>>>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>>>> +file named @file{ira.txt}.
>>>>> +
>>>>> +In case of any conflicts, the command line file name takes precedence
>>>>> +over generated file names. For example:
>>>>> +
>>>>> +@smallexample
>>>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>>>> +@end smallexample
>>>>> +
>>>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>>>> +there are multiple command line file names are applicable then the
>>>>> +last one is used. Thus the command
>>>>> +
>>>>> +@smallexample
>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>>>> +@end smallexample
>>>>> +
>>>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>>>> +PRE dump is overridden by a later option.
>>>>> +
>>>>>  @item all
>>>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>>>> -and @option{lineno}.
>>>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>>>> +@option{lineno}.
>>>>>  @end table
>>>>>
>>>>>  The following tree dumps are possible:
>>>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>>>  @item all
>>>>>  @opindex fdump-tree-all
>>>>>  Enable all the available tree dumps with the flags provided in this option.
>>>>> +
>>>>>  @end table
>>>>>
>>>>>  @item -ftree-vectorizer-verbose=@var{n}
>>>>> Index: tree-dump.c
>>>>> ===================================================================
>>>>> --- tree-dump.c (revision 187265)
>>>>> +++ tree-dump.c (working copy)
>>>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>>>  static struct dump_file_info dump_files[TDI_end] =
>>>>>  {
>>>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>>>
>>>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>>>  };
>>>>>
>>>>>  /* Dynamically registered tree dump files and switches.  */
>>>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>>>  };
>>>>>
>>>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>>>> -   in tree.h */
>>>>> +   in tree-pass.h */
>>>>>  static const struct dump_option_value_info dump_options[] =
>>>>>  {
>>>>>   {"address", TDF_ADDRESS},
>>>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>>>   if (dfi->state == 0)
>>>>>     return NULL;
>>>>>
>>>>> +  if (dfi->filename)
>>>>> +    return xstrdup (dfi->filename);
>>>>> +
>>>>>   if (dfi->num < 0)
>>>>>     dump_id[0] = '\0';
>>>>>   else
>>>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>>>  }
>>>>>
>>>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>>>> +   return that stream, NULL otherwise.  */
>>>>> +
>>>>> +static FILE *
>>>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>>>> +{
>>>>> +  if (!dfi->filename)
>>>>> +    return NULL;
>>>>> +
>>>>> +  return strcmp("stderr", dfi->filename) == 0
>>>>> +    ? stderr
>>>>> +    : strcmp("stdout", dfi->filename) == 0
>>>>> +    ?  stdout
>>>>> +    : NULL;
>>>>> +}
>>>>> +
>>>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>>>    enabled, returns NULL.
>>>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>>>     return NULL;
>>>>>
>>>>> -  name = get_dump_file_name (phase);
>>>>>   dfi = get_dump_file_info (phase);
>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>> -  if (!stream)
>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>> +  stream = dump_get_standard_stream (dfi);
>>>>> +  if (stream)
>>>>> +    dfi->state = 1;
>>>>>   else
>>>>> -    dfi->state = 1;
>>>>> -  free (name);
>>>>> +    {
>>>>> +      name = get_dump_file_name (phase);
>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>> +      if (!stream)
>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>> +      else
>>>>> +        dfi->state = 1;
>>>>> +      free (name);
>>>>> +    }
>>>>>
>>>>>   if (flag_ptr)
>>>>>     *flag_ptr = dfi->flags;
>>>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>>>    dump_begin.  */
>>>>>
>>>>>  void
>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>> +dump_end (int phase, FILE *stream)
>>>>>  {
>>>>> -  fclose (stream);
>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>> +  if (!dump_get_standard_stream (dfi))
>>>>> +    fclose (stream);
>>>>>  }
>>>>>
>>>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>>>> +   enabled tree dumps.  */
>>>>>
>>>>>  static int
>>>>> -dump_enable_all (int flags)
>>>>> +dump_enable_all (int flags, const char *filename)
>>>>>  {
>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>   int n = 0;
>>>>>   size_t i;
>>>>>
>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>> -      {
>>>>> -        dump_files[i].state = -1;
>>>>> -        dump_files[i].flags |= flags;
>>>>> -        n++;
>>>>> -      }
>>>>> +    {
>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>> +        {
>>>>> +          dump_files[i].state = -1;
>>>>> +          dump_files[i].flags |= flags;
>>>>> +          n++;
>>>>> +          if (filename)
>>>>> +            dump_files[i].filename = xstrdup (filename);
>>>>> +        }
>>>>> +    }
>>>>>
>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>> -      {
>>>>> -        extra_dump_files[i].state = -1;
>>>>> -        extra_dump_files[i].flags |= flags;
>>>>> -       n++;
>>>>> -      }
>>>>> +    {
>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>> +        {
>>>>> +          extra_dump_files[i].state = -1;
>>>>> +          extra_dump_files[i].flags |= flags;
>>>>> +          n++;
>>>>> +          if (filename)
>>>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>>>> +        }
>>>>> +    }
>>>>>
>>>>>   return n;
>>>>>  }
>>>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>   if (!option_value)
>>>>>     return 0;
>>>>>
>>>>> -  if (*option_value && *option_value != '-')
>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>     return 0;
>>>>>
>>>>>   ptr = option_value;
>>>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>       while (*ptr == '-')
>>>>>        ptr++;
>>>>>       end_ptr = strchr (ptr, '-');
>>>>> +
>>>>>       if (!end_ptr)
>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>       length = end_ptr - ptr;
>>>>>
>>>>> +      if (*ptr == '=')
>>>>> +        {
>>>>> +          /* Interpret rest of the argument as a dump filename.  This
>>>>> +             filename overrides generated dump names as well as other
>>>>> +             command line filenames.  */
>>>>> +          flags |= TDF_FILENAME;
>>>>> +          if (dfi->filename)
>>>>> +            free (dfi->filename);
>>>>> +          dfi->filename = xstrdup (ptr + 1);
>>>>> +          break;
>>>>> +        }
>>>>> +
>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>        if (strlen (option_ptr->name) == length
>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>> -         {
>>>>> -           flags |= option_ptr->value;
>>>>> +          {
>>>>> +            flags |= option_ptr->value;
>>>>>            goto found;
>>>>> -         }
>>>>> +          }
>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>               length, ptr, dfi->swtch);
>>>>>     found:;
>>>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>      known dumps.  */
>>>>>   if (dfi->suffix == NULL)
>>>>> -    dump_enable_all (dfi->flags);
>>>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>>>
>>>>>   return 1;
>>>>>  }
>>>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>>>  bool
>>>>>  enable_rtl_dump_file (void)
>>>>>  {
>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>  }
>>>>> Index: tree-pass.h
>>>>> ===================================================================
>>>>> --- tree-pass.h (revision 187265)
>>>>> +++ tree-pass.h (working copy)
>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>>>> +                                           instead of constructing one. */
>>>>>
>>>>> -
>>>>>  /* In tree-dump.c */
>>>>>
>>>>>  extern char *get_dump_file_name (int);
>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>   const char *swtch;            /* command line switch */
>>>>>   const char *glob;             /* command line glob  */
>>>>> +  const char *filename;         /* use this filename instead of making
>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>   int flags;                    /* user flags */
>>>>>   int state;                    /* state of play */
>>>>>   int num;                      /* dump file number */
>>>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>>>> ===================================================================
>>>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>> @@ -0,0 +1,11 @@
>>>>> +// Test that the dump to a user-defined file works correctly.
>>>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>>>> +
>>>>> +void test (int *b, int *e, int stride)
>>>>> +  {
>>>>> +    for (int *p = b; p != e; p += stride)
>>>>> +      *p = 1;
>>>>> +  }
>>>>> +
>>>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>>>
>>>>>
>>>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>>>> <gdr@integrable-solutions.net> wrote:
>>>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>>>> [...]
>>>>>>
>>>>>>> +@item -fdump-rtl-all=stderr
>>>>>>> +@opindex fdump-rtl-all=stderr
>>>>>>
>>>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>>>> Rather, expand the description to state this in all the documentation
>>>>>> for -fdump-xxx=yyy.
>>>>>>
>>>>>> [...]
>>>>>>
>>>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>>>> +   stderr stream.  */
>>>>>>> +
>>>>>>> +static int
>>>>>>> +dump_stream_p (const char *user_filename)
>>>>>>> +{
>>>>>>> +  if (user_filename)
>>>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>>>> +  else
>>>>>>> +    return 0;
>>>>>>> +}
>>>>>>
>>>>>> The name is ambiguous.
>>>>>> This function is testing whether its string argument designates one of
>>>>>> the *standard* output streams.  Name it to reflect that..
>>>>>> Have it take the dump state context. Also the coding convention: the binary
>>>>>> operator "||" should be on next line.  In fact the thing could be
>>>>>> simpler.   Instead of
>>>>>> testing over and over again against "stderr" (once in this function, then again
>>>>>> later), just return the corresponding standard FILE* pointer.
>>>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>>>> dump_get_standard_stream:
>>>>>>
>>>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>>>       ? stderr
>>>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>>>        ?  stdout
>>>>>>        : NULL;
>>>>>>
>>>>>> you can simplify:
>>>>>>
>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>> -  if (!stream)
>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>>>> +    {
>>>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>>>> +        stream = stderr;
>>>>>>> +      else
>>>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>>>> +          stream = stdout;
>>>>>>> +        else
>>>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>>>> +      dfi->state = 1;
>>>>>>> +    }
>>>>>>>   else
>>>>>>> -    dfi->state = 1;
>>>>>>> -  free (name);
>>>>>>> +    {
>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>> +      if (!stream)
>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>> +      else
>>>>>>> +        dfi->state = 1;
>>>>>>> +      free (name);
>>>>>>> +    }
>>>>>>>
>>>>>>>   if (flag_ptr)
>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>>>    dump_begin.  */
>>>>>>>
>>>>>>>  void
>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>  {
>>>>>>> -  fclose (stream);
>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>>>> +    fclose (stream);
>>>>>>>  }
>>>>>>>
>>>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>>
>>>>>>>  static int
>>>>>>> -dump_enable_all (int flags)
>>>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>>>  {
>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>   int n = 0;
>>>>>>>   size_t i;
>>>>>>>
>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>> -      {
>>>>>>> -        dump_files[i].state = -1;
>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>> -        n++;
>>>>>>> -      }
>>>>>>> +    {
>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>> +        {
>>>>>>> +          dump_files[i].state = -1;
>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>> +          n++;
>>>>>>> +        }
>>>>>>> +      if (user_filename)
>>>>>>> +        dump_files[i].user_filename = user_filename;
>>>>>>> +    }
>>>>>>>
>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>> -      {
>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>> -       n++;
>>>>>>> -      }
>>>>>>> +    {
>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>> +        {
>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>> +          n++;
>>>>>>> +        }
>>>>>>> +      if (user_filename)
>>>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>>>> +    }
>>>>>>>
>>>>>>>   return n;
>>>>>>>  }
>>>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>   if (!option_value)
>>>>>>>     return 0;
>>>>>>>
>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>     return 0;
>>>>>>>
>>>>>>>   ptr = option_value;
>>>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>       while (*ptr == '-')
>>>>>>>        ptr++;
>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>> +
>>>>>>>       if (!end_ptr)
>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>       length = end_ptr - ptr;
>>>>>>>
>>>>>>> +      if (*ptr == '=')
>>>>>>> +        {
>>>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>>>> +             user provided filename overrides generated dump names as
>>>>>>> +             well as other command line filenames.  */
>>>>>>> +          flags |= TDF_USER_FILENAME;
>>>>>>> +          if (dfi->user_filename)
>>>>>>> +            free (dfi->user_filename);
>>>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>>>> +          break;
>>>>>>> +        }
>>>>>>> +
>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>> -         {
>>>>>>> -           flags |= option_ptr->value;
>>>>>>> +          {
>>>>>>> +            flags |= option_ptr->value;
>>>>>>>            goto found;
>>>>>>> -         }
>>>>>>> +          }
>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>     found:;
>>>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>      known dumps.  */
>>>>>>>   if (dfi->suffix == NULL)
>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>>>
>>>>>>>   return 1;
>>>>>>>  }
>>>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>>>  bool
>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>  {
>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>  }
>>>>>>> Index: tree-pass.h
>>>>>>> ===================================================================
>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>> +++ tree-pass.h (working copy)
>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>>>> +                                           instead of constructing one. */
>>>>>>>
>>>>>>> -
>>>>>>>  /* In tree-dump.c */
>>>>>>>
>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>
>>>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>>>
>>>>>> -- Gaby
Xinliang David Li May 11, 2012, 6:11 p.m. UTC | #6
To be more specific, does the following match what your envisioned?

1) when multiple streams are specified for dumping, the information
will be dumped to all streams IF the new dumping interfaces are used
(see below). For legacy code, the default dump file will still be used
and the user specified file (including stderr) will be silently
ignored. This is of course temporary until all dumping sites are
converted

2) Define the following new dumping interfaces which will honor all
streams specified

  dump_printf (const char*, ....);   // for raw string dumping
  dump_generic_expr (...); //  wrapper to print_generic_expr without
taking FILE*
  dump_node (...); // wrapper to print_node
  dump_gimple_stmt(...); // wrapper to print_gimple_stmt

  dump_inform (...); //wrapper to inform (..) method, but is aware of
of the dumping streams and modify global_dc appropriately.

3) Implement -fopt-info=N, and take -ftree-vectorizer-verbose as the
first guinea pig to use the new dumping interfaces.

After the infrastructure is ready, gradually deprecate the use of the
original dumper interfaces.

what do you think?

thanks,

David

On Fri, May 11, 2012 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Fri, May 11, 2012 at 1:49 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> I like your suggestion and support the end goal you have.  I don't
>>> like the -fopt-info behavior to interfere with regular -fdump-xxx
>>> options either.
>>>
>>> I think we should stage the changes in multiple steps as originally
>>> planned. Is Sharad's change good to be checked in for the first stage?
>>
>> Well - I don't think the change walks in the direction we want to go, so I don't
>> see a good reason to make that change.
>
> Is your direction misunderstood or you want everything to be changed
> in one single patch (including replacement of all fprintf (dump_file,
> ...)? If the former, please clarify. If the latter, it can be done.
>
> thanks,
>
> David
>
>>
>>> After this one is checked in, the new dump interfaces will be worked
>>> on (and to allow multiple streams). Most of the remaining changes will
>>> be massive text replacement.
>>>
>>> thanks,
>>>
>>> David
>>>
>>>
>>> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>>>>
>>>>> -fdump-tree-pre=<func_list_regexp>
>>>>>
>>>>> I guess this can be achieved via @
>>>>>
>>>>> -fdump-tree-pre@<func_list>
>>>>>
>>>>> -fdump-tree-pre=<file_name>@<func_list>
>>>>>
>>>>>
>>>>> Another issue -- I don't think the current precedence rule is correct.
>>>>> Consider that -fopt-info=2 will be mapped to
>>>>>
>>>>> -fdump-tree-all-transform-verbose2=stderr
>>>>> -fdump-rtl-all-transform-verbose2=stderr
>>>>>
>>>>> then
>>>>>
>>>>> the current precedence rule will cause surprise when the following is used
>>>>>
>>>>> -fopt-info -fdump-tree-pre
>>>>>
>>>>> The PRE dump will be emitted to stderr which is not what user wants.
>>>>> In short, special streams should be treated as 'weak' the same way as
>>>>> your previous implementation.
>>>>
>>>> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
>>>> With -fopt-info -fdump-tree-pre I do not want some information to be
>>>> present only on stderr or in the dump file!  I want it in _both_ places!
>>>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
>>>> information :()
>>>>
>>>> Thus, the information where dumping goes has to be done differently
>>>> (which is why I asked for some re-org originally, so that passes no
>>>> longer explicitely reference dump_file - dump_file may be different
>>>> for different kind of information it dumps!).  Passes should, instead of
>>>>
>>>>  fprintf (dump_file, "...", ...)
>>>>
>>>> do
>>>>
>>>>  dump_printf (TDF_scev, "...", ...)
>>>>
>>>> thus, specify the kind of information they dump (would be mostly
>>>> TDF_details vs. 0 today I guess).  The dump_printf routine would
>>>> then properly direct to one or more places to dump at.
>>>>
>>>> I realize this needs some more dispatchers for dumping expressions
>>>> and statements (but it should not be too many).  Dumping to
>>>> dump_file would in any case dump to the passes private dump file
>>>> only (unqualified stuff would never be useful for -fopt-info).
>>>>
>>>> The perfect candidate to convert to this kind of scheme is obviously
>>>> the vectorizer with its existing -fvectorizer-verbose.
>>>>
>>>> If the patch doesn't work towards this kind of end-result I'd rather
>>>> not have it.
>>>>
>>>> Thanks,
>>>> Richard.
>>>>
>>>>> thanks,
>>>>>
>>>>> David
>>>>>
>>>>>
>>>>>
>>>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>>>>> Thanks for your suggestions/comments. I have updated the patch and
>>>>>> documentation. It supports the following usage:
>>>>>>
>>>>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>>>>> -fdump-rtl-ira=ira.dump
>>>>>>
>>>>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>>>>> goes to stdout and the IRA dump goes to ira.dump.
>>>>>>
>>>>>> Thanks,
>>>>>> Sharad
>>>>>>
>>>>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>>>>
>>>>>>        * doc/invoke.texi: Add documentation for the new option.
>>>>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>>>>        (dump_files): Update for new field.
>>>>>>        (dump_switch_p_1): Handle dump filenames.
>>>>>>        (dump_begin): Likewise.
>>>>>>        (get_dump_file_name): Likewise.
>>>>>>        (dump_end): Remove attribute.
>>>>>>        (dump_enable_all): Add new parameter FILENAME.
>>>>>>        All callers updated.
>>>>>>        (enable_rtl_dump_file):
>>>>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>>>>        (struct dump_file_info): Add new field FILENAME.
>>>>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>>>>
>>>>>> Index: doc/invoke.texi
>>>>>> ===================================================================
>>>>>> --- doc/invoke.texi     (revision 187265)
>>>>>> +++ doc/invoke.texi     (working copy)
>>>>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>>>>
>>>>>>  @item -d@var{letters}
>>>>>>  @itemx -fdump-rtl-@var{pass}
>>>>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>>>>  @opindex d
>>>>>>  Says to make debugging dumps during compilation at times specified by
>>>>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>>>>  compiler.  The file names for most of the dumps are made by appending
>>>>>>  a pass number and a word to the @var{dumpname}, and the files are
>>>>>> -created in the directory of the output file.  Note that the pass
>>>>>> -number is computed statically as passes get registered into the pass
>>>>>> -manager.  Thus the numbering is not related to the dynamic order of
>>>>>> -execution of passes.  In particular, a pass installed by a plugin
>>>>>> -could have a number over 200 even if it executed quite early.
>>>>>> -@var{dumpname} is generated from the name of the output file, if
>>>>>> -explicitly specified and it is not an executable, otherwise it is the
>>>>>> -basename of the source file. These switches may have different effects
>>>>>> -when @option{-E} is used for preprocessing.
>>>>>> +created in the directory of the output file. If the
>>>>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>>>>> +option then the dump is done on that file instead of numbered
>>>>>> +files. Note that the pass number is computed statically as passes get
>>>>>> +registered into the pass manager.  Thus the numbering is not related
>>>>>> +to the dynamic order of execution of passes.  In particular, a pass
>>>>>> +installed by a plugin could have a number over 200 even if it executed
>>>>>> +quite early.  @var{dumpname} is generated from the name of the output
>>>>>> +file, if explicitly specified and it is not an executable, otherwise
>>>>>> +it is the basename of the source file. These switches may have
>>>>>> +different effects when @option{-E} is used for preprocessing.
>>>>>>
>>>>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>>>>  @option{-d} option @var{letters}.  Here are the possible
>>>>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>>>>
>>>>>>  @item -fdump-tree-@var{switch}
>>>>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>>>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>>>>  @opindex fdump-tree
>>>>>>  Control the dumping at various stages of processing the intermediate
>>>>>>  language tree to a file.  The file name is generated by appending a
>>>>>>  switch specific suffix to the source file name, and the file is
>>>>>> -created in the same directory as the output file.  If the
>>>>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>>>>> -@samp{-} separated options which control the details of the dump.  Not
>>>>>> -all options are applicable to all dumps; those that are not
>>>>>> -meaningful are ignored.  The following options are available
>>>>>> +created in the same directory as the output file. In case of
>>>>>> +@option{=@var{filename}} option, the dump is output on the given file
>>>>>> +name instead.  If the @samp{-@var{options}} form is used,
>>>>>> +@var{options} is a list of @samp{-} separated options which control
>>>>>> +the details or location of the dump.  Not all options are applicable
>>>>>> +to all dumps; those that are not meaningful are ignored.  The
>>>>>> +following options are available
>>>>>>
>>>>>>  @table @samp
>>>>>>  @item address
>>>>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>>>>  Enable showing the EH region number holding each statement.
>>>>>>  @item scev
>>>>>>  Enable showing scalar evolution analysis details.
>>>>>> +@item slim
>>>>>> +Inhibit dumping of members of a scope or body of a function merely
>>>>>> +because that scope has been reached.  Only dump such items when they
>>>>>> +are directly reachable by some other path.  When dumping pretty-printed
>>>>>> +trees, this option inhibits dumping the bodies of control structures.
>>>>>> +@item =@var{filename}
>>>>>> +Instead of using an auto generated dump file name, use the given file
>>>>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>>>>> +specially and are considered already open standard streams. For
>>>>>> +example:
>>>>>> +
>>>>>> +@smallexample
>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>>>>> +@end smallexample
>>>>>> +
>>>>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>>>>> +file named @file{ira.txt}.
>>>>>> +
>>>>>> +In case of any conflicts, the command line file name takes precedence
>>>>>> +over generated file names. For example:
>>>>>> +
>>>>>> +@smallexample
>>>>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>>>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>>>>> +@end smallexample
>>>>>> +
>>>>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>>>>> +there are multiple command line file names are applicable then the
>>>>>> +last one is used. Thus the command
>>>>>> +
>>>>>> +@smallexample
>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>>>>> +@end smallexample
>>>>>> +
>>>>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>>>>> +PRE dump is overridden by a later option.
>>>>>> +
>>>>>>  @item all
>>>>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>>>>> -and @option{lineno}.
>>>>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>>>>> +@option{lineno}.
>>>>>>  @end table
>>>>>>
>>>>>>  The following tree dumps are possible:
>>>>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>>>>  @item all
>>>>>>  @opindex fdump-tree-all
>>>>>>  Enable all the available tree dumps with the flags provided in this option.
>>>>>> +
>>>>>>  @end table
>>>>>>
>>>>>>  @item -ftree-vectorizer-verbose=@var{n}
>>>>>> Index: tree-dump.c
>>>>>> ===================================================================
>>>>>> --- tree-dump.c (revision 187265)
>>>>>> +++ tree-dump.c (working copy)
>>>>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>>>>  static struct dump_file_info dump_files[TDI_end] =
>>>>>>  {
>>>>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>>>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>>>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>>>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>>>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>>>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>>>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>>>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>>>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>>>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>>>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>>>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>>>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>>>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>>>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>>>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>>>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>>>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>>>>
>>>>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>>>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>>>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>>>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>>>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>>>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>>>>  };
>>>>>>
>>>>>>  /* Dynamically registered tree dump files and switches.  */
>>>>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>>>>  };
>>>>>>
>>>>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>>>>> -   in tree.h */
>>>>>> +   in tree-pass.h */
>>>>>>  static const struct dump_option_value_info dump_options[] =
>>>>>>  {
>>>>>>   {"address", TDF_ADDRESS},
>>>>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>>>>   if (dfi->state == 0)
>>>>>>     return NULL;
>>>>>>
>>>>>> +  if (dfi->filename)
>>>>>> +    return xstrdup (dfi->filename);
>>>>>> +
>>>>>>   if (dfi->num < 0)
>>>>>>     dump_id[0] = '\0';
>>>>>>   else
>>>>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>>>>  }
>>>>>>
>>>>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>>>>> +   return that stream, NULL otherwise.  */
>>>>>> +
>>>>>> +static FILE *
>>>>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>>>>> +{
>>>>>> +  if (!dfi->filename)
>>>>>> +    return NULL;
>>>>>> +
>>>>>> +  return strcmp("stderr", dfi->filename) == 0
>>>>>> +    ? stderr
>>>>>> +    : strcmp("stdout", dfi->filename) == 0
>>>>>> +    ?  stdout
>>>>>> +    : NULL;
>>>>>> +}
>>>>>> +
>>>>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>>>>    enabled, returns NULL.
>>>>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>>>>     return NULL;
>>>>>>
>>>>>> -  name = get_dump_file_name (phase);
>>>>>>   dfi = get_dump_file_info (phase);
>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>> -  if (!stream)
>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>> +  stream = dump_get_standard_stream (dfi);
>>>>>> +  if (stream)
>>>>>> +    dfi->state = 1;
>>>>>>   else
>>>>>> -    dfi->state = 1;
>>>>>> -  free (name);
>>>>>> +    {
>>>>>> +      name = get_dump_file_name (phase);
>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>> +      if (!stream)
>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>> +      else
>>>>>> +        dfi->state = 1;
>>>>>> +      free (name);
>>>>>> +    }
>>>>>>
>>>>>>   if (flag_ptr)
>>>>>>     *flag_ptr = dfi->flags;
>>>>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>>>>    dump_begin.  */
>>>>>>
>>>>>>  void
>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>  {
>>>>>> -  fclose (stream);
>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>> +  if (!dump_get_standard_stream (dfi))
>>>>>> +    fclose (stream);
>>>>>>  }
>>>>>>
>>>>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>>>>> +   enabled tree dumps.  */
>>>>>>
>>>>>>  static int
>>>>>> -dump_enable_all (int flags)
>>>>>> +dump_enable_all (int flags, const char *filename)
>>>>>>  {
>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>   int n = 0;
>>>>>>   size_t i;
>>>>>>
>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>> -      {
>>>>>> -        dump_files[i].state = -1;
>>>>>> -        dump_files[i].flags |= flags;
>>>>>> -        n++;
>>>>>> -      }
>>>>>> +    {
>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>> +        {
>>>>>> +          dump_files[i].state = -1;
>>>>>> +          dump_files[i].flags |= flags;
>>>>>> +          n++;
>>>>>> +          if (filename)
>>>>>> +            dump_files[i].filename = xstrdup (filename);
>>>>>> +        }
>>>>>> +    }
>>>>>>
>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>> -      {
>>>>>> -        extra_dump_files[i].state = -1;
>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>> -       n++;
>>>>>> -      }
>>>>>> +    {
>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>> +        {
>>>>>> +          extra_dump_files[i].state = -1;
>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>> +          n++;
>>>>>> +          if (filename)
>>>>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>>>>> +        }
>>>>>> +    }
>>>>>>
>>>>>>   return n;
>>>>>>  }
>>>>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>   if (!option_value)
>>>>>>     return 0;
>>>>>>
>>>>>> -  if (*option_value && *option_value != '-')
>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>     return 0;
>>>>>>
>>>>>>   ptr = option_value;
>>>>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>       while (*ptr == '-')
>>>>>>        ptr++;
>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>> +
>>>>>>       if (!end_ptr)
>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>       length = end_ptr - ptr;
>>>>>>
>>>>>> +      if (*ptr == '=')
>>>>>> +        {
>>>>>> +          /* Interpret rest of the argument as a dump filename.  This
>>>>>> +             filename overrides generated dump names as well as other
>>>>>> +             command line filenames.  */
>>>>>> +          flags |= TDF_FILENAME;
>>>>>> +          if (dfi->filename)
>>>>>> +            free (dfi->filename);
>>>>>> +          dfi->filename = xstrdup (ptr + 1);
>>>>>> +          break;
>>>>>> +        }
>>>>>> +
>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>> -         {
>>>>>> -           flags |= option_ptr->value;
>>>>>> +          {
>>>>>> +            flags |= option_ptr->value;
>>>>>>            goto found;
>>>>>> -         }
>>>>>> +          }
>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>               length, ptr, dfi->swtch);
>>>>>>     found:;
>>>>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>      known dumps.  */
>>>>>>   if (dfi->suffix == NULL)
>>>>>> -    dump_enable_all (dfi->flags);
>>>>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>>>>
>>>>>>   return 1;
>>>>>>  }
>>>>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>>>>  bool
>>>>>>  enable_rtl_dump_file (void)
>>>>>>  {
>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>  }
>>>>>> Index: tree-pass.h
>>>>>> ===================================================================
>>>>>> --- tree-pass.h (revision 187265)
>>>>>> +++ tree-pass.h (working copy)
>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>>>>> +                                           instead of constructing one. */
>>>>>>
>>>>>> -
>>>>>>  /* In tree-dump.c */
>>>>>>
>>>>>>  extern char *get_dump_file_name (int);
>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>   const char *swtch;            /* command line switch */
>>>>>>   const char *glob;             /* command line glob  */
>>>>>> +  const char *filename;         /* use this filename instead of making
>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>   int flags;                    /* user flags */
>>>>>>   int state;                    /* state of play */
>>>>>>   int num;                      /* dump file number */
>>>>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>>>>> ===================================================================
>>>>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>> @@ -0,0 +1,11 @@
>>>>>> +// Test that the dump to a user-defined file works correctly.
>>>>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>>>>> +
>>>>>> +void test (int *b, int *e, int stride)
>>>>>> +  {
>>>>>> +    for (int *p = b; p != e; p += stride)
>>>>>> +      *p = 1;
>>>>>> +  }
>>>>>> +
>>>>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>>>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>>>>
>>>>>>
>>>>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>>>>> <gdr@integrable-solutions.net> wrote:
>>>>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>>>>> [...]
>>>>>>>
>>>>>>>> +@item -fdump-rtl-all=stderr
>>>>>>>> +@opindex fdump-rtl-all=stderr
>>>>>>>
>>>>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>>>>> Rather, expand the description to state this in all the documentation
>>>>>>> for -fdump-xxx=yyy.
>>>>>>>
>>>>>>> [...]
>>>>>>>
>>>>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>>>>> +   stderr stream.  */
>>>>>>>> +
>>>>>>>> +static int
>>>>>>>> +dump_stream_p (const char *user_filename)
>>>>>>>> +{
>>>>>>>> +  if (user_filename)
>>>>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>>>>> +  else
>>>>>>>> +    return 0;
>>>>>>>> +}
>>>>>>>
>>>>>>> The name is ambiguous.
>>>>>>> This function is testing whether its string argument designates one of
>>>>>>> the *standard* output streams.  Name it to reflect that..
>>>>>>> Have it take the dump state context. Also the coding convention: the binary
>>>>>>> operator "||" should be on next line.  In fact the thing could be
>>>>>>> simpler.   Instead of
>>>>>>> testing over and over again against "stderr" (once in this function, then again
>>>>>>> later), just return the corresponding standard FILE* pointer.
>>>>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>>>>> dump_get_standard_stream:
>>>>>>>
>>>>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>>>>       ? stderr
>>>>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>>>>        ?  stdout
>>>>>>>        : NULL;
>>>>>>>
>>>>>>> you can simplify:
>>>>>>>
>>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>> -  if (!stream)
>>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>>>>> +    {
>>>>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>>>>> +        stream = stderr;
>>>>>>>> +      else
>>>>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>>>>> +          stream = stdout;
>>>>>>>> +        else
>>>>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>>>>> +      dfi->state = 1;
>>>>>>>> +    }
>>>>>>>>   else
>>>>>>>> -    dfi->state = 1;
>>>>>>>> -  free (name);
>>>>>>>> +    {
>>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>> +      if (!stream)
>>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>>> +      else
>>>>>>>> +        dfi->state = 1;
>>>>>>>> +      free (name);
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   if (flag_ptr)
>>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>>>>    dump_begin.  */
>>>>>>>>
>>>>>>>>  void
>>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>>  {
>>>>>>>> -  fclose (stream);
>>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>>>>> +    fclose (stream);
>>>>>>>>  }
>>>>>>>>
>>>>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>>>
>>>>>>>>  static int
>>>>>>>> -dump_enable_all (int flags)
>>>>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>>>>  {
>>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>>   int n = 0;
>>>>>>>>   size_t i;
>>>>>>>>
>>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>>> -      {
>>>>>>>> -        dump_files[i].state = -1;
>>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>>> -        n++;
>>>>>>>> -      }
>>>>>>>> +    {
>>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>>> +        {
>>>>>>>> +          dump_files[i].state = -1;
>>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>>> +          n++;
>>>>>>>> +        }
>>>>>>>> +      if (user_filename)
>>>>>>>> +        dump_files[i].user_filename = user_filename;
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>> -      {
>>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>>> -       n++;
>>>>>>>> -      }
>>>>>>>> +    {
>>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>> +        {
>>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>>> +          n++;
>>>>>>>> +        }
>>>>>>>> +      if (user_filename)
>>>>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   return n;
>>>>>>>>  }
>>>>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>   if (!option_value)
>>>>>>>>     return 0;
>>>>>>>>
>>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>>     return 0;
>>>>>>>>
>>>>>>>>   ptr = option_value;
>>>>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>       while (*ptr == '-')
>>>>>>>>        ptr++;
>>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>>> +
>>>>>>>>       if (!end_ptr)
>>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>>       length = end_ptr - ptr;
>>>>>>>>
>>>>>>>> +      if (*ptr == '=')
>>>>>>>> +        {
>>>>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>>>>> +             user provided filename overrides generated dump names as
>>>>>>>> +             well as other command line filenames.  */
>>>>>>>> +          flags |= TDF_USER_FILENAME;
>>>>>>>> +          if (dfi->user_filename)
>>>>>>>> +            free (dfi->user_filename);
>>>>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>>>>> +          break;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>>> -         {
>>>>>>>> -           flags |= option_ptr->value;
>>>>>>>> +          {
>>>>>>>> +            flags |= option_ptr->value;
>>>>>>>>            goto found;
>>>>>>>> -         }
>>>>>>>> +          }
>>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>>     found:;
>>>>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>>      known dumps.  */
>>>>>>>>   if (dfi->suffix == NULL)
>>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>>>>
>>>>>>>>   return 1;
>>>>>>>>  }
>>>>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>>>>  bool
>>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>>  {
>>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>>  }
>>>>>>>> Index: tree-pass.h
>>>>>>>> ===================================================================
>>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>>> +++ tree-pass.h (working copy)
>>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>>>>> +                                           instead of constructing one. */
>>>>>>>>
>>>>>>>> -
>>>>>>>>  /* In tree-dump.c */
>>>>>>>>
>>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>>
>>>>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>>>>
>>>>>>> -- Gaby
Richard Biener May 12, 2012, 10:31 a.m. UTC | #7
On Fri, May 11, 2012 at 8:11 PM, Xinliang David Li <davidxl@google.com> wrote:
> To be more specific, does the following match what your envisioned?
>
> 1) when multiple streams are specified for dumping, the information
> will be dumped to all streams IF the new dumping interfaces are used
> (see below). For legacy code, the default dump file will still be used
> and the user specified file (including stderr) will be silently
> ignored. This is of course temporary until all dumping sites are
> converted

Yes, that sounds reasonable.

> 2) Define the following new dumping interfaces which will honor all
> streams specified
>
>  dump_printf (const char*, ....);   // for raw string dumping
>  dump_generic_expr (...); //  wrapper to print_generic_expr without
> taking FILE*
>  dump_node (...); // wrapper to print_node
>  dump_gimple_stmt(...); // wrapper to print_gimple_stmt

Yes.  Please add a classification argument to each of the wrappers
to allow selective filtering (I'd simply use the existing TDF_* flags
for now - in the future they should be made more granular than
0 vs. TDF_details).

The existing if (dump_file && (dump_flags & ...)) checks need to be
adjusted, of course.  if (dump_enabled_p ()) or if (dump_enabled_p (flags)).

>  dump_inform (...); //wrapper to inform (..) method, but is aware of
> of the dumping streams and modify global_dc appropriately.

inform () is not part of the dumping infrastructure, thus passes should not
use it.  The dumping implementation, if re-directed via -fopt-report, might
use inform () to print messages though.

> 3) Implement -fopt-info=N, and take -ftree-vectorizer-verbose as the
> first guinea pig to use the new dumping interfaces.

Yes, I think all of 1) to 2) do not make sense without 3), so I'd prefer
to see all that (well, the relevant bits of 2) to make 3) work) together.

> After the infrastructure is ready, gradually deprecate the use of the
> original dumper interfaces.

Yes, passes can be converted independently.

> what do you think?

That plan sounds good to me.

Thanks,
Richard.

> thanks,
>
> David
>
> On Fri, May 11, 2012 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Fri, May 11, 2012 at 1:49 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> I like your suggestion and support the end goal you have.  I don't
>>>> like the -fopt-info behavior to interfere with regular -fdump-xxx
>>>> options either.
>>>>
>>>> I think we should stage the changes in multiple steps as originally
>>>> planned. Is Sharad's change good to be checked in for the first stage?
>>>
>>> Well - I don't think the change walks in the direction we want to go, so I don't
>>> see a good reason to make that change.
>>
>> Is your direction misunderstood or you want everything to be changed
>> in one single patch (including replacement of all fprintf (dump_file,
>> ...)? If the former, please clarify. If the latter, it can be done.
>>
>> thanks,
>>
>> David
>>
>>>
>>>> After this one is checked in, the new dump interfaces will be worked
>>>> on (and to allow multiple streams). Most of the remaining changes will
>>>> be massive text replacement.
>>>>
>>>> thanks,
>>>>
>>>> David
>>>>
>>>>
>>>> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
>>>> <richard.guenther@gmail.com> wrote:
>>>>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>>>>>
>>>>>> -fdump-tree-pre=<func_list_regexp>
>>>>>>
>>>>>> I guess this can be achieved via @
>>>>>>
>>>>>> -fdump-tree-pre@<func_list>
>>>>>>
>>>>>> -fdump-tree-pre=<file_name>@<func_list>
>>>>>>
>>>>>>
>>>>>> Another issue -- I don't think the current precedence rule is correct.
>>>>>> Consider that -fopt-info=2 will be mapped to
>>>>>>
>>>>>> -fdump-tree-all-transform-verbose2=stderr
>>>>>> -fdump-rtl-all-transform-verbose2=stderr
>>>>>>
>>>>>> then
>>>>>>
>>>>>> the current precedence rule will cause surprise when the following is used
>>>>>>
>>>>>> -fopt-info -fdump-tree-pre
>>>>>>
>>>>>> The PRE dump will be emitted to stderr which is not what user wants.
>>>>>> In short, special streams should be treated as 'weak' the same way as
>>>>>> your previous implementation.
>>>>>
>>>>> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
>>>>> With -fopt-info -fdump-tree-pre I do not want some information to be
>>>>> present only on stderr or in the dump file!  I want it in _both_ places!
>>>>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
>>>>> information :()
>>>>>
>>>>> Thus, the information where dumping goes has to be done differently
>>>>> (which is why I asked for some re-org originally, so that passes no
>>>>> longer explicitely reference dump_file - dump_file may be different
>>>>> for different kind of information it dumps!).  Passes should, instead of
>>>>>
>>>>>  fprintf (dump_file, "...", ...)
>>>>>
>>>>> do
>>>>>
>>>>>  dump_printf (TDF_scev, "...", ...)
>>>>>
>>>>> thus, specify the kind of information they dump (would be mostly
>>>>> TDF_details vs. 0 today I guess).  The dump_printf routine would
>>>>> then properly direct to one or more places to dump at.
>>>>>
>>>>> I realize this needs some more dispatchers for dumping expressions
>>>>> and statements (but it should not be too many).  Dumping to
>>>>> dump_file would in any case dump to the passes private dump file
>>>>> only (unqualified stuff would never be useful for -fopt-info).
>>>>>
>>>>> The perfect candidate to convert to this kind of scheme is obviously
>>>>> the vectorizer with its existing -fvectorizer-verbose.
>>>>>
>>>>> If the patch doesn't work towards this kind of end-result I'd rather
>>>>> not have it.
>>>>>
>>>>> Thanks,
>>>>> Richard.
>>>>>
>>>>>> thanks,
>>>>>>
>>>>>> David
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>>>>>> Thanks for your suggestions/comments. I have updated the patch and
>>>>>>> documentation. It supports the following usage:
>>>>>>>
>>>>>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>>>>>> -fdump-rtl-ira=ira.dump
>>>>>>>
>>>>>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>>>>>> goes to stdout and the IRA dump goes to ira.dump.
>>>>>>>
>>>>>>> Thanks,
>>>>>>> Sharad
>>>>>>>
>>>>>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>>>>>
>>>>>>>        * doc/invoke.texi: Add documentation for the new option.
>>>>>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>>>>>        (dump_files): Update for new field.
>>>>>>>        (dump_switch_p_1): Handle dump filenames.
>>>>>>>        (dump_begin): Likewise.
>>>>>>>        (get_dump_file_name): Likewise.
>>>>>>>        (dump_end): Remove attribute.
>>>>>>>        (dump_enable_all): Add new parameter FILENAME.
>>>>>>>        All callers updated.
>>>>>>>        (enable_rtl_dump_file):
>>>>>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>>>>>        (struct dump_file_info): Add new field FILENAME.
>>>>>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>>>>>
>>>>>>> Index: doc/invoke.texi
>>>>>>> ===================================================================
>>>>>>> --- doc/invoke.texi     (revision 187265)
>>>>>>> +++ doc/invoke.texi     (working copy)
>>>>>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>>>>>
>>>>>>>  @item -d@var{letters}
>>>>>>>  @itemx -fdump-rtl-@var{pass}
>>>>>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>>>>>  @opindex d
>>>>>>>  Says to make debugging dumps during compilation at times specified by
>>>>>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>>>>>  compiler.  The file names for most of the dumps are made by appending
>>>>>>>  a pass number and a word to the @var{dumpname}, and the files are
>>>>>>> -created in the directory of the output file.  Note that the pass
>>>>>>> -number is computed statically as passes get registered into the pass
>>>>>>> -manager.  Thus the numbering is not related to the dynamic order of
>>>>>>> -execution of passes.  In particular, a pass installed by a plugin
>>>>>>> -could have a number over 200 even if it executed quite early.
>>>>>>> -@var{dumpname} is generated from the name of the output file, if
>>>>>>> -explicitly specified and it is not an executable, otherwise it is the
>>>>>>> -basename of the source file. These switches may have different effects
>>>>>>> -when @option{-E} is used for preprocessing.
>>>>>>> +created in the directory of the output file. If the
>>>>>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>>>>>> +option then the dump is done on that file instead of numbered
>>>>>>> +files. Note that the pass number is computed statically as passes get
>>>>>>> +registered into the pass manager.  Thus the numbering is not related
>>>>>>> +to the dynamic order of execution of passes.  In particular, a pass
>>>>>>> +installed by a plugin could have a number over 200 even if it executed
>>>>>>> +quite early.  @var{dumpname} is generated from the name of the output
>>>>>>> +file, if explicitly specified and it is not an executable, otherwise
>>>>>>> +it is the basename of the source file. These switches may have
>>>>>>> +different effects when @option{-E} is used for preprocessing.
>>>>>>>
>>>>>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>>>>>  @option{-d} option @var{letters}.  Here are the possible
>>>>>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>>>>>
>>>>>>>  @item -fdump-tree-@var{switch}
>>>>>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>>>>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>>>>>  @opindex fdump-tree
>>>>>>>  Control the dumping at various stages of processing the intermediate
>>>>>>>  language tree to a file.  The file name is generated by appending a
>>>>>>>  switch specific suffix to the source file name, and the file is
>>>>>>> -created in the same directory as the output file.  If the
>>>>>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>>>>>> -@samp{-} separated options which control the details of the dump.  Not
>>>>>>> -all options are applicable to all dumps; those that are not
>>>>>>> -meaningful are ignored.  The following options are available
>>>>>>> +created in the same directory as the output file. In case of
>>>>>>> +@option{=@var{filename}} option, the dump is output on the given file
>>>>>>> +name instead.  If the @samp{-@var{options}} form is used,
>>>>>>> +@var{options} is a list of @samp{-} separated options which control
>>>>>>> +the details or location of the dump.  Not all options are applicable
>>>>>>> +to all dumps; those that are not meaningful are ignored.  The
>>>>>>> +following options are available
>>>>>>>
>>>>>>>  @table @samp
>>>>>>>  @item address
>>>>>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>>>>>  Enable showing the EH region number holding each statement.
>>>>>>>  @item scev
>>>>>>>  Enable showing scalar evolution analysis details.
>>>>>>> +@item slim
>>>>>>> +Inhibit dumping of members of a scope or body of a function merely
>>>>>>> +because that scope has been reached.  Only dump such items when they
>>>>>>> +are directly reachable by some other path.  When dumping pretty-printed
>>>>>>> +trees, this option inhibits dumping the bodies of control structures.
>>>>>>> +@item =@var{filename}
>>>>>>> +Instead of using an auto generated dump file name, use the given file
>>>>>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>>>>>> +specially and are considered already open standard streams. For
>>>>>>> +example:
>>>>>>> +
>>>>>>> +@smallexample
>>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>>>>>> +@end smallexample
>>>>>>> +
>>>>>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>>>>>> +file named @file{ira.txt}.
>>>>>>> +
>>>>>>> +In case of any conflicts, the command line file name takes precedence
>>>>>>> +over generated file names. For example:
>>>>>>> +
>>>>>>> +@smallexample
>>>>>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>>>>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>>>>>> +@end smallexample
>>>>>>> +
>>>>>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>>>>>> +there are multiple command line file names are applicable then the
>>>>>>> +last one is used. Thus the command
>>>>>>> +
>>>>>>> +@smallexample
>>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>>>>>> +@end smallexample
>>>>>>> +
>>>>>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>>>>>> +PRE dump is overridden by a later option.
>>>>>>> +
>>>>>>>  @item all
>>>>>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>>>>>> -and @option{lineno}.
>>>>>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>>>>>> +@option{lineno}.
>>>>>>>  @end table
>>>>>>>
>>>>>>>  The following tree dumps are possible:
>>>>>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>>>>>  @item all
>>>>>>>  @opindex fdump-tree-all
>>>>>>>  Enable all the available tree dumps with the flags provided in this option.
>>>>>>> +
>>>>>>>  @end table
>>>>>>>
>>>>>>>  @item -ftree-vectorizer-verbose=@var{n}
>>>>>>> Index: tree-dump.c
>>>>>>> ===================================================================
>>>>>>> --- tree-dump.c (revision 187265)
>>>>>>> +++ tree-dump.c (working copy)
>>>>>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>>>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>>>>>  static struct dump_file_info dump_files[TDI_end] =
>>>>>>>  {
>>>>>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>>>>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>>>>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>>>>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>>>>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>>>>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>>>>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>>>>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>>>>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>>>>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>>>>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>>>>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>>>>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>>>>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>>>>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>>>>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>>>>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>>>>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>>>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>>>>>
>>>>>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>>>>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>>>>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>>>>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>>>>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>>>>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>>>>>  };
>>>>>>>
>>>>>>>  /* Dynamically registered tree dump files and switches.  */
>>>>>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>>>>>  };
>>>>>>>
>>>>>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>>>>>> -   in tree.h */
>>>>>>> +   in tree-pass.h */
>>>>>>>  static const struct dump_option_value_info dump_options[] =
>>>>>>>  {
>>>>>>>   {"address", TDF_ADDRESS},
>>>>>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>>>>>   if (dfi->state == 0)
>>>>>>>     return NULL;
>>>>>>>
>>>>>>> +  if (dfi->filename)
>>>>>>> +    return xstrdup (dfi->filename);
>>>>>>> +
>>>>>>>   if (dfi->num < 0)
>>>>>>>     dump_id[0] = '\0';
>>>>>>>   else
>>>>>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>>>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>>>>>  }
>>>>>>>
>>>>>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>>>>>> +   return that stream, NULL otherwise.  */
>>>>>>> +
>>>>>>> +static FILE *
>>>>>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>>>>>> +{
>>>>>>> +  if (!dfi->filename)
>>>>>>> +    return NULL;
>>>>>>> +
>>>>>>> +  return strcmp("stderr", dfi->filename) == 0
>>>>>>> +    ? stderr
>>>>>>> +    : strcmp("stdout", dfi->filename) == 0
>>>>>>> +    ?  stdout
>>>>>>> +    : NULL;
>>>>>>> +}
>>>>>>> +
>>>>>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>>>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>>>>>    enabled, returns NULL.
>>>>>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>>>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>>>>>     return NULL;
>>>>>>>
>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>> -  if (!stream)
>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>> +  stream = dump_get_standard_stream (dfi);
>>>>>>> +  if (stream)
>>>>>>> +    dfi->state = 1;
>>>>>>>   else
>>>>>>> -    dfi->state = 1;
>>>>>>> -  free (name);
>>>>>>> +    {
>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>> +      if (!stream)
>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>> +      else
>>>>>>> +        dfi->state = 1;
>>>>>>> +      free (name);
>>>>>>> +    }
>>>>>>>
>>>>>>>   if (flag_ptr)
>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>>>>>    dump_begin.  */
>>>>>>>
>>>>>>>  void
>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>  {
>>>>>>> -  fclose (stream);
>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>> +  if (!dump_get_standard_stream (dfi))
>>>>>>> +    fclose (stream);
>>>>>>>  }
>>>>>>>
>>>>>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>>>>>> +   enabled tree dumps.  */
>>>>>>>
>>>>>>>  static int
>>>>>>> -dump_enable_all (int flags)
>>>>>>> +dump_enable_all (int flags, const char *filename)
>>>>>>>  {
>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>   int n = 0;
>>>>>>>   size_t i;
>>>>>>>
>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>> -      {
>>>>>>> -        dump_files[i].state = -1;
>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>> -        n++;
>>>>>>> -      }
>>>>>>> +    {
>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>> +        {
>>>>>>> +          dump_files[i].state = -1;
>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>> +          n++;
>>>>>>> +          if (filename)
>>>>>>> +            dump_files[i].filename = xstrdup (filename);
>>>>>>> +        }
>>>>>>> +    }
>>>>>>>
>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>> -      {
>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>> -       n++;
>>>>>>> -      }
>>>>>>> +    {
>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>> +        {
>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>> +          n++;
>>>>>>> +          if (filename)
>>>>>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>>>>>> +        }
>>>>>>> +    }
>>>>>>>
>>>>>>>   return n;
>>>>>>>  }
>>>>>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>   if (!option_value)
>>>>>>>     return 0;
>>>>>>>
>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>     return 0;
>>>>>>>
>>>>>>>   ptr = option_value;
>>>>>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>       while (*ptr == '-')
>>>>>>>        ptr++;
>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>> +
>>>>>>>       if (!end_ptr)
>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>       length = end_ptr - ptr;
>>>>>>>
>>>>>>> +      if (*ptr == '=')
>>>>>>> +        {
>>>>>>> +          /* Interpret rest of the argument as a dump filename.  This
>>>>>>> +             filename overrides generated dump names as well as other
>>>>>>> +             command line filenames.  */
>>>>>>> +          flags |= TDF_FILENAME;
>>>>>>> +          if (dfi->filename)
>>>>>>> +            free (dfi->filename);
>>>>>>> +          dfi->filename = xstrdup (ptr + 1);
>>>>>>> +          break;
>>>>>>> +        }
>>>>>>> +
>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>> -         {
>>>>>>> -           flags |= option_ptr->value;
>>>>>>> +          {
>>>>>>> +            flags |= option_ptr->value;
>>>>>>>            goto found;
>>>>>>> -         }
>>>>>>> +          }
>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>     found:;
>>>>>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>      known dumps.  */
>>>>>>>   if (dfi->suffix == NULL)
>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>>>>>
>>>>>>>   return 1;
>>>>>>>  }
>>>>>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>>>>>  bool
>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>  {
>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>  }
>>>>>>> Index: tree-pass.h
>>>>>>> ===================================================================
>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>> +++ tree-pass.h (working copy)
>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>>>>>> +                                           instead of constructing one. */
>>>>>>>
>>>>>>> -
>>>>>>>  /* In tree-dump.c */
>>>>>>>
>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>> +  const char *filename;         /* use this filename instead of making
>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>>   int flags;                    /* user flags */
>>>>>>>   int state;                    /* state of play */
>>>>>>>   int num;                      /* dump file number */
>>>>>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>>>>>> ===================================================================
>>>>>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>>> @@ -0,0 +1,11 @@
>>>>>>> +// Test that the dump to a user-defined file works correctly.
>>>>>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>>>>>> +
>>>>>>> +void test (int *b, int *e, int stride)
>>>>>>> +  {
>>>>>>> +    for (int *p = b; p != e; p += stride)
>>>>>>> +      *p = 1;
>>>>>>> +  }
>>>>>>> +
>>>>>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>>>>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>>>>>
>>>>>>>
>>>>>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>>>>>> <gdr@integrable-solutions.net> wrote:
>>>>>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>>>>>> [...]
>>>>>>>>
>>>>>>>>> +@item -fdump-rtl-all=stderr
>>>>>>>>> +@opindex fdump-rtl-all=stderr
>>>>>>>>
>>>>>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>>>>>> Rather, expand the description to state this in all the documentation
>>>>>>>> for -fdump-xxx=yyy.
>>>>>>>>
>>>>>>>> [...]
>>>>>>>>
>>>>>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>>>>>> +   stderr stream.  */
>>>>>>>>> +
>>>>>>>>> +static int
>>>>>>>>> +dump_stream_p (const char *user_filename)
>>>>>>>>> +{
>>>>>>>>> +  if (user_filename)
>>>>>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>>>>>> +  else
>>>>>>>>> +    return 0;
>>>>>>>>> +}
>>>>>>>>
>>>>>>>> The name is ambiguous.
>>>>>>>> This function is testing whether its string argument designates one of
>>>>>>>> the *standard* output streams.  Name it to reflect that..
>>>>>>>> Have it take the dump state context. Also the coding convention: the binary
>>>>>>>> operator "||" should be on next line.  In fact the thing could be
>>>>>>>> simpler.   Instead of
>>>>>>>> testing over and over again against "stderr" (once in this function, then again
>>>>>>>> later), just return the corresponding standard FILE* pointer.
>>>>>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>>>>>> dump_get_standard_stream:
>>>>>>>>
>>>>>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>>>>>       ? stderr
>>>>>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>>>>>        ?  stdout
>>>>>>>>        : NULL;
>>>>>>>>
>>>>>>>> you can simplify:
>>>>>>>>
>>>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>>> -  if (!stream)
>>>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>>>>>> +    {
>>>>>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>>>>>> +        stream = stderr;
>>>>>>>>> +      else
>>>>>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>>>>>> +          stream = stdout;
>>>>>>>>> +        else
>>>>>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>>>>>> +      dfi->state = 1;
>>>>>>>>> +    }
>>>>>>>>>   else
>>>>>>>>> -    dfi->state = 1;
>>>>>>>>> -  free (name);
>>>>>>>>> +    {
>>>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>>> +      if (!stream)
>>>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>>>> +      else
>>>>>>>>> +        dfi->state = 1;
>>>>>>>>> +      free (name);
>>>>>>>>> +    }
>>>>>>>>>
>>>>>>>>>   if (flag_ptr)
>>>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>>>>>    dump_begin.  */
>>>>>>>>>
>>>>>>>>>  void
>>>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>>>  {
>>>>>>>>> -  fclose (stream);
>>>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>>>>>> +    fclose (stream);
>>>>>>>>>  }
>>>>>>>>>
>>>>>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>>>>
>>>>>>>>>  static int
>>>>>>>>> -dump_enable_all (int flags)
>>>>>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>>>>>  {
>>>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>>>   int n = 0;
>>>>>>>>>   size_t i;
>>>>>>>>>
>>>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>>>> -      {
>>>>>>>>> -        dump_files[i].state = -1;
>>>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>>>> -        n++;
>>>>>>>>> -      }
>>>>>>>>> +    {
>>>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>>>> +        {
>>>>>>>>> +          dump_files[i].state = -1;
>>>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>>>> +          n++;
>>>>>>>>> +        }
>>>>>>>>> +      if (user_filename)
>>>>>>>>> +        dump_files[i].user_filename = user_filename;
>>>>>>>>> +    }
>>>>>>>>>
>>>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>>> -      {
>>>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>>>> -       n++;
>>>>>>>>> -      }
>>>>>>>>> +    {
>>>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>>> +        {
>>>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>>>> +          n++;
>>>>>>>>> +        }
>>>>>>>>> +      if (user_filename)
>>>>>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>>>>>> +    }
>>>>>>>>>
>>>>>>>>>   return n;
>>>>>>>>>  }
>>>>>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>   if (!option_value)
>>>>>>>>>     return 0;
>>>>>>>>>
>>>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>>>     return 0;
>>>>>>>>>
>>>>>>>>>   ptr = option_value;
>>>>>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>       while (*ptr == '-')
>>>>>>>>>        ptr++;
>>>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>>>> +
>>>>>>>>>       if (!end_ptr)
>>>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>>>       length = end_ptr - ptr;
>>>>>>>>>
>>>>>>>>> +      if (*ptr == '=')
>>>>>>>>> +        {
>>>>>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>>>>>> +             user provided filename overrides generated dump names as
>>>>>>>>> +             well as other command line filenames.  */
>>>>>>>>> +          flags |= TDF_USER_FILENAME;
>>>>>>>>> +          if (dfi->user_filename)
>>>>>>>>> +            free (dfi->user_filename);
>>>>>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>>>>>> +          break;
>>>>>>>>> +        }
>>>>>>>>> +
>>>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>>>> -         {
>>>>>>>>> -           flags |= option_ptr->value;
>>>>>>>>> +          {
>>>>>>>>> +            flags |= option_ptr->value;
>>>>>>>>>            goto found;
>>>>>>>>> -         }
>>>>>>>>> +          }
>>>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>>>     found:;
>>>>>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>>>      known dumps.  */
>>>>>>>>>   if (dfi->suffix == NULL)
>>>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>>>>>
>>>>>>>>>   return 1;
>>>>>>>>>  }
>>>>>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>>>>>  bool
>>>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>>>  {
>>>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>>>  }
>>>>>>>>> Index: tree-pass.h
>>>>>>>>> ===================================================================
>>>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>>>> +++ tree-pass.h (working copy)
>>>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>>>>>> +                                           instead of constructing one. */
>>>>>>>>>
>>>>>>>>> -
>>>>>>>>>  /* In tree-dump.c */
>>>>>>>>>
>>>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>>>
>>>>>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>>>>>
>>>>>>>> -- Gaby
Xinliang David Li May 12, 2012, 4:05 p.m. UTC | #8
Sounds good.

On Sat, May 12, 2012 at 3:31 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Fri, May 11, 2012 at 8:11 PM, Xinliang David Li <davidxl@google.com> wrote:
>> To be more specific, does the following match what your envisioned?
>>
>> 1) when multiple streams are specified for dumping, the information
>> will be dumped to all streams IF the new dumping interfaces are used
>> (see below). For legacy code, the default dump file will still be used
>> and the user specified file (including stderr) will be silently
>> ignored. This is of course temporary until all dumping sites are
>> converted
>
> Yes, that sounds reasonable.
>
>> 2) Define the following new dumping interfaces which will honor all
>> streams specified
>>
>>  dump_printf (const char*, ....);   // for raw string dumping
>>  dump_generic_expr (...); //  wrapper to print_generic_expr without
>> taking FILE*
>>  dump_node (...); // wrapper to print_node
>>  dump_gimple_stmt(...); // wrapper to print_gimple_stmt
>
> Yes.  Please add a classification argument to each of the wrappers
> to allow selective filtering (I'd simply use the existing TDF_* flags
> for now - in the future they should be made more granular than
> 0 vs. TDF_details).
>
> The existing if (dump_file && (dump_flags & ...)) checks need to be
> adjusted, of course.  if (dump_enabled_p ()) or if (dump_enabled_p (flags)).
>
>>  dump_inform (...); //wrapper to inform (..) method, but is aware of
>> of the dumping streams and modify global_dc appropriately.
>
> inform () is not part of the dumping infrastructure, thus passes should not
> use it.  The dumping implementation, if re-directed via -fopt-report, might
> use inform () to print messages though.
>

The downside is that the dump file format will look different from the
stderr output which is less than ideal. Setting and restore
diagnostic_context's printter stream is just one-line change, what is
the main concern of doing that?

thanks,

David


>> 3) Implement -fopt-info=N, and take -ftree-vectorizer-verbose as the
>> first guinea pig to use the new dumping interfaces.
>
> Yes, I think all of 1) to 2) do not make sense without 3), so I'd prefer
> to see all that (well, the relevant bits of 2) to make 3) work) together.
>
>> After the infrastructure is ready, gradually deprecate the use of the
>> original dumper interfaces.
>
> Yes, passes can be converted independently.
>
>> what do you think?
>
> That plan sounds good to me.
>
> Thanks,
> Richard.
>
>> thanks,
>>
>> David
>>
>> On Fri, May 11, 2012 at 9:06 AM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Fri, May 11, 2012 at 1:49 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Thu, May 10, 2012 at 6:28 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> I like your suggestion and support the end goal you have.  I don't
>>>>> like the -fopt-info behavior to interfere with regular -fdump-xxx
>>>>> options either.
>>>>>
>>>>> I think we should stage the changes in multiple steps as originally
>>>>> planned. Is Sharad's change good to be checked in for the first stage?
>>>>
>>>> Well - I don't think the change walks in the direction we want to go, so I don't
>>>> see a good reason to make that change.
>>>
>>> Is your direction misunderstood or you want everything to be changed
>>> in one single patch (including replacement of all fprintf (dump_file,
>>> ...)? If the former, please clarify. If the latter, it can be done.
>>>
>>> thanks,
>>>
>>> David
>>>
>>>>
>>>>> After this one is checked in, the new dump interfaces will be worked
>>>>> on (and to allow multiple streams). Most of the remaining changes will
>>>>> be massive text replacement.
>>>>>
>>>>> thanks,
>>>>>
>>>>> David
>>>>>
>>>>>
>>>>> On Thu, May 10, 2012 at 1:18 AM, Richard Guenther
>>>>> <richard.guenther@gmail.com> wrote:
>>>>>> On Thu, May 10, 2012 at 2:31 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>>> Bummer.  I was thinking to reserve '=' for selective  dumping:
>>>>>>>
>>>>>>> -fdump-tree-pre=<func_list_regexp>
>>>>>>>
>>>>>>> I guess this can be achieved via @
>>>>>>>
>>>>>>> -fdump-tree-pre@<func_list>
>>>>>>>
>>>>>>> -fdump-tree-pre=<file_name>@<func_list>
>>>>>>>
>>>>>>>
>>>>>>> Another issue -- I don't think the current precedence rule is correct.
>>>>>>> Consider that -fopt-info=2 will be mapped to
>>>>>>>
>>>>>>> -fdump-tree-all-transform-verbose2=stderr
>>>>>>> -fdump-rtl-all-transform-verbose2=stderr
>>>>>>>
>>>>>>> then
>>>>>>>
>>>>>>> the current precedence rule will cause surprise when the following is used
>>>>>>>
>>>>>>> -fopt-info -fdump-tree-pre
>>>>>>>
>>>>>>> The PRE dump will be emitted to stderr which is not what user wants.
>>>>>>> In short, special streams should be treated as 'weak' the same way as
>>>>>>> your previous implementation.
>>>>>>
>>>>>> Hm, this raises a similar concern I have with the -fvectorizer-verbose flag.
>>>>>> With -fopt-info -fdump-tree-pre I do not want some information to be
>>>>>> present only on stderr or in the dump file!  I want it in _both_ places!
>>>>>> (-fvectorizer-verbose makes the -fdump-tree-vect dump contain less
>>>>>> information :()
>>>>>>
>>>>>> Thus, the information where dumping goes has to be done differently
>>>>>> (which is why I asked for some re-org originally, so that passes no
>>>>>> longer explicitely reference dump_file - dump_file may be different
>>>>>> for different kind of information it dumps!).  Passes should, instead of
>>>>>>
>>>>>>  fprintf (dump_file, "...", ...)
>>>>>>
>>>>>> do
>>>>>>
>>>>>>  dump_printf (TDF_scev, "...", ...)
>>>>>>
>>>>>> thus, specify the kind of information they dump (would be mostly
>>>>>> TDF_details vs. 0 today I guess).  The dump_printf routine would
>>>>>> then properly direct to one or more places to dump at.
>>>>>>
>>>>>> I realize this needs some more dispatchers for dumping expressions
>>>>>> and statements (but it should not be too many).  Dumping to
>>>>>> dump_file would in any case dump to the passes private dump file
>>>>>> only (unqualified stuff would never be useful for -fopt-info).
>>>>>>
>>>>>> The perfect candidate to convert to this kind of scheme is obviously
>>>>>> the vectorizer with its existing -fvectorizer-verbose.
>>>>>>
>>>>>> If the patch doesn't work towards this kind of end-result I'd rather
>>>>>> not have it.
>>>>>>
>>>>>> Thanks,
>>>>>> Richard.
>>>>>>
>>>>>>> thanks,
>>>>>>>
>>>>>>> David
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> On Wed, May 9, 2012 at 4:56 PM, Sharad Singhai <singhai@google.com> wrote:
>>>>>>>> Thanks for your suggestions/comments. I have updated the patch and
>>>>>>>> documentation. It supports the following usage:
>>>>>>>>
>>>>>>>> gcc .... -fdump-tree-all=tree.dump -fdump-tree-pre=stdout
>>>>>>>> -fdump-rtl-ira=ira.dump
>>>>>>>>
>>>>>>>> Here all tree dumps except the PRE are output into tree.dump, PRE dump
>>>>>>>> goes to stdout and the IRA dump goes to ira.dump.
>>>>>>>>
>>>>>>>> Thanks,
>>>>>>>> Sharad
>>>>>>>>
>>>>>>>> 2012-05-09   Sharad Singhai  <singhai@google.com>
>>>>>>>>
>>>>>>>>        * doc/invoke.texi: Add documentation for the new option.
>>>>>>>>        * tree-dump.c (dump_get_standard_stream): New function.
>>>>>>>>        (dump_files): Update for new field.
>>>>>>>>        (dump_switch_p_1): Handle dump filenames.
>>>>>>>>        (dump_begin): Likewise.
>>>>>>>>        (get_dump_file_name): Likewise.
>>>>>>>>        (dump_end): Remove attribute.
>>>>>>>>        (dump_enable_all): Add new parameter FILENAME.
>>>>>>>>        All callers updated.
>>>>>>>>        (enable_rtl_dump_file):
>>>>>>>>        * tree-pass.h (enum tree_dump_index): Add new constant.
>>>>>>>>        (struct dump_file_info): Add new field FILENAME.
>>>>>>>>        * testsuite/g++.dg/other/dump-filename-1.C: New test.
>>>>>>>>
>>>>>>>> Index: doc/invoke.texi
>>>>>>>> ===================================================================
>>>>>>>> --- doc/invoke.texi     (revision 187265)
>>>>>>>> +++ doc/invoke.texi     (working copy)
>>>>>>>> @@ -5322,20 +5322,23 @@ Here are some examples showing uses of these optio
>>>>>>>>
>>>>>>>>  @item -d@var{letters}
>>>>>>>>  @itemx -fdump-rtl-@var{pass}
>>>>>>>> +@itemx -fdump-rtl-@var{pass}=@var{filename}
>>>>>>>>  @opindex d
>>>>>>>>  Says to make debugging dumps during compilation at times specified by
>>>>>>>>  @var{letters}.  This is used for debugging the RTL-based passes of the
>>>>>>>>  compiler.  The file names for most of the dumps are made by appending
>>>>>>>>  a pass number and a word to the @var{dumpname}, and the files are
>>>>>>>> -created in the directory of the output file.  Note that the pass
>>>>>>>> -number is computed statically as passes get registered into the pass
>>>>>>>> -manager.  Thus the numbering is not related to the dynamic order of
>>>>>>>> -execution of passes.  In particular, a pass installed by a plugin
>>>>>>>> -could have a number over 200 even if it executed quite early.
>>>>>>>> -@var{dumpname} is generated from the name of the output file, if
>>>>>>>> -explicitly specified and it is not an executable, otherwise it is the
>>>>>>>> -basename of the source file. These switches may have different effects
>>>>>>>> -when @option{-E} is used for preprocessing.
>>>>>>>> +created in the directory of the output file. If the
>>>>>>>> +@option{=@var{filename}} is appended to the longer form of the dump
>>>>>>>> +option then the dump is done on that file instead of numbered
>>>>>>>> +files. Note that the pass number is computed statically as passes get
>>>>>>>> +registered into the pass manager.  Thus the numbering is not related
>>>>>>>> +to the dynamic order of execution of passes.  In particular, a pass
>>>>>>>> +installed by a plugin could have a number over 200 even if it executed
>>>>>>>> +quite early.  @var{dumpname} is generated from the name of the output
>>>>>>>> +file, if explicitly specified and it is not an executable, otherwise
>>>>>>>> +it is the basename of the source file. These switches may have
>>>>>>>> +different effects when @option{-E} is used for preprocessing.
>>>>>>>>
>>>>>>>>  Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
>>>>>>>>  @option{-d} option @var{letters}.  Here are the possible
>>>>>>>> @@ -5719,15 +5722,18 @@ counters for each function compiled.
>>>>>>>>
>>>>>>>>  @item -fdump-tree-@var{switch}
>>>>>>>>  @itemx -fdump-tree-@var{switch}-@var{options}
>>>>>>>> +@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
>>>>>>>>  @opindex fdump-tree
>>>>>>>>  Control the dumping at various stages of processing the intermediate
>>>>>>>>  language tree to a file.  The file name is generated by appending a
>>>>>>>>  switch specific suffix to the source file name, and the file is
>>>>>>>> -created in the same directory as the output file.  If the
>>>>>>>> -@samp{-@var{options}} form is used, @var{options} is a list of
>>>>>>>> -@samp{-} separated options which control the details of the dump.  Not
>>>>>>>> -all options are applicable to all dumps; those that are not
>>>>>>>> -meaningful are ignored.  The following options are available
>>>>>>>> +created in the same directory as the output file. In case of
>>>>>>>> +@option{=@var{filename}} option, the dump is output on the given file
>>>>>>>> +name instead.  If the @samp{-@var{options}} form is used,
>>>>>>>> +@var{options} is a list of @samp{-} separated options which control
>>>>>>>> +the details or location of the dump.  Not all options are applicable
>>>>>>>> +to all dumps; those that are not meaningful are ignored.  The
>>>>>>>> +following options are available
>>>>>>>>
>>>>>>>>  @table @samp
>>>>>>>>  @item address
>>>>>>>> @@ -5765,9 +5771,46 @@ Enable showing the tree dump for each statement.
>>>>>>>>  Enable showing the EH region number holding each statement.
>>>>>>>>  @item scev
>>>>>>>>  Enable showing scalar evolution analysis details.
>>>>>>>> +@item slim
>>>>>>>> +Inhibit dumping of members of a scope or body of a function merely
>>>>>>>> +because that scope has been reached.  Only dump such items when they
>>>>>>>> +are directly reachable by some other path.  When dumping pretty-printed
>>>>>>>> +trees, this option inhibits dumping the bodies of control structures.
>>>>>>>> +@item =@var{filename}
>>>>>>>> +Instead of using an auto generated dump file name, use the given file
>>>>>>>> +name. The file names @file{stdout} and @file{stderr} are treated
>>>>>>>> +specially and are considered already open standard streams. For
>>>>>>>> +example:
>>>>>>>> +
>>>>>>>> +@smallexample
>>>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
>>>>>>>> +@end smallexample
>>>>>>>> +
>>>>>>>> +outputs PRE dump on @file{stderr}, while the IRA dump is output in a
>>>>>>>> +file named @file{ira.txt}.
>>>>>>>> +
>>>>>>>> +In case of any conflicts, the command line file name takes precedence
>>>>>>>> +over generated file names. For example:
>>>>>>>> +
>>>>>>>> +@smallexample
>>>>>>>> +gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
>>>>>>>> +gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
>>>>>>>> +@end smallexample
>>>>>>>> +
>>>>>>>> +Both of the above output the PRE dump on @file{stdout}. However, if
>>>>>>>> +there are multiple command line file names are applicable then the
>>>>>>>> +last one is used. Thus the command
>>>>>>>> +
>>>>>>>> +@smallexample
>>>>>>>> +gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
>>>>>>>> +@end smallexample
>>>>>>>> +
>>>>>>>> +outputs all the dumps in @file{all.txt} because the stderr option for
>>>>>>>> +PRE dump is overridden by a later option.
>>>>>>>> +
>>>>>>>>  @item all
>>>>>>>> -Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
>>>>>>>> -and @option{lineno}.
>>>>>>>> +Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
>>>>>>>> +@option{lineno}.
>>>>>>>>  @end table
>>>>>>>>
>>>>>>>>  The following tree dumps are possible:
>>>>>>>> @@ -5913,6 +5956,7 @@ is made by appending @file{.vrp} to the source fil
>>>>>>>>  @item all
>>>>>>>>  @opindex fdump-tree-all
>>>>>>>>  Enable all the available tree dumps with the flags provided in this option.
>>>>>>>> +
>>>>>>>>  @end table
>>>>>>>>
>>>>>>>>  @item -ftree-vectorizer-verbose=@var{n}
>>>>>>>> Index: tree-dump.c
>>>>>>>> ===================================================================
>>>>>>>> --- tree-dump.c (revision 187265)
>>>>>>>> +++ tree-dump.c (working copy)
>>>>>>>> @@ -773,20 +773,20 @@ dump_node (const_tree t, int flags, FILE *stream)
>>>>>>>>    tree_dump_index enumeration in tree-pass.h.  */
>>>>>>>>  static struct dump_file_info dump_files[TDI_end] =
>>>>>>>>  {
>>>>>>>> -  {NULL, NULL, NULL, 0, 0, 0},
>>>>>>>> -  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
>>>>>>>> -  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
>>>>>>>> -  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
>>>>>>>> -  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
>>>>>>>> -  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
>>>>>>>> -  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
>>>>>>>> -  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
>>>>>>>> -  {".ads", "ada-spec", NULL, 0, 0, 7},
>>>>>>>> +  {NULL, NULL, NULL, NULL, 0, 0, 0},
>>>>>>>> +  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
>>>>>>>> +  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
>>>>>>>> +  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
>>>>>>>> +  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
>>>>>>>> +  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
>>>>>>>> +  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
>>>>>>>> +  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
>>>>>>>> +  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
>>>>>>>>  #define FIRST_AUTO_NUMBERED_DUMP 8
>>>>>>>>
>>>>>>>> -  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
>>>>>>>> -  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
>>>>>>>> -  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
>>>>>>>> +  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
>>>>>>>> +  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
>>>>>>>> +  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
>>>>>>>>  };
>>>>>>>>
>>>>>>>>  /* Dynamically registered tree dump files and switches.  */
>>>>>>>> @@ -802,7 +802,7 @@ struct dump_option_value_info
>>>>>>>>  };
>>>>>>>>
>>>>>>>>  /* Table of dump options. This must be consistent with the TDF_* flags
>>>>>>>> -   in tree.h */
>>>>>>>> +   in tree-pass.h */
>>>>>>>>  static const struct dump_option_value_info dump_options[] =
>>>>>>>>  {
>>>>>>>>   {"address", TDF_ADDRESS},
>>>>>>>> @@ -892,6 +892,9 @@ get_dump_file_name (int phase)
>>>>>>>>   if (dfi->state == 0)
>>>>>>>>     return NULL;
>>>>>>>>
>>>>>>>> +  if (dfi->filename)
>>>>>>>> +    return xstrdup (dfi->filename);
>>>>>>>> +
>>>>>>>>   if (dfi->num < 0)
>>>>>>>>     dump_id[0] = '\0';
>>>>>>>>   else
>>>>>>>> @@ -911,6 +914,22 @@ get_dump_file_name (int phase)
>>>>>>>>   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
>>>>>>>>  }
>>>>>>>>
>>>>>>>> +/* If the DFI dump output corresponds to stdout or stderr stream,
>>>>>>>> +   return that stream, NULL otherwise.  */
>>>>>>>> +
>>>>>>>> +static FILE *
>>>>>>>> +dump_get_standard_stream (struct dump_file_info *dfi)
>>>>>>>> +{
>>>>>>>> +  if (!dfi->filename)
>>>>>>>> +    return NULL;
>>>>>>>> +
>>>>>>>> +  return strcmp("stderr", dfi->filename) == 0
>>>>>>>> +    ? stderr
>>>>>>>> +    : strcmp("stdout", dfi->filename) == 0
>>>>>>>> +    ?  stdout
>>>>>>>> +    : NULL;
>>>>>>>> +}
>>>>>>>> +
>>>>>>>>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
>>>>>>>>    *FLAG_PTR and returns a stream to write to. If the dump is not
>>>>>>>>    enabled, returns NULL.
>>>>>>>> @@ -926,14 +945,20 @@ dump_begin (int phase, int *flag_ptr)
>>>>>>>>   if (phase == TDI_none || !dump_enabled_p (phase))
>>>>>>>>     return NULL;
>>>>>>>>
>>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>> -  if (!stream)
>>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>>> +  stream = dump_get_standard_stream (dfi);
>>>>>>>> +  if (stream)
>>>>>>>> +    dfi->state = 1;
>>>>>>>>   else
>>>>>>>> -    dfi->state = 1;
>>>>>>>> -  free (name);
>>>>>>>> +    {
>>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>> +      if (!stream)
>>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>>> +      else
>>>>>>>> +        dfi->state = 1;
>>>>>>>> +      free (name);
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   if (flag_ptr)
>>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>>> @@ -987,35 +1012,46 @@ dump_flag_name (int phase)
>>>>>>>>    dump_begin.  */
>>>>>>>>
>>>>>>>>  void
>>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>>  {
>>>>>>>> -  fclose (stream);
>>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>>> +  if (!dump_get_standard_stream (dfi))
>>>>>>>> +    fclose (stream);
>>>>>>>>  }
>>>>>>>>
>>>>>>>> -/* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>>> +/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
>>>>>>>> +   enabled tree dumps.  */
>>>>>>>>
>>>>>>>>  static int
>>>>>>>> -dump_enable_all (int flags)
>>>>>>>> +dump_enable_all (int flags, const char *filename)
>>>>>>>>  {
>>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>>   int n = 0;
>>>>>>>>   size_t i;
>>>>>>>>
>>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>>> -      {
>>>>>>>> -        dump_files[i].state = -1;
>>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>>> -        n++;
>>>>>>>> -      }
>>>>>>>> +    {
>>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>>> +        {
>>>>>>>> +          dump_files[i].state = -1;
>>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>>> +          n++;
>>>>>>>> +          if (filename)
>>>>>>>> +            dump_files[i].filename = xstrdup (filename);
>>>>>>>> +        }
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>> -      {
>>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>>> -       n++;
>>>>>>>> -      }
>>>>>>>> +    {
>>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>> +        {
>>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>>> +          n++;
>>>>>>>> +          if (filename)
>>>>>>>> +            extra_dump_files[i].filename = xstrdup (filename);
>>>>>>>> +        }
>>>>>>>> +    }
>>>>>>>>
>>>>>>>>   return n;
>>>>>>>>  }
>>>>>>>> @@ -1037,7 +1073,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>   if (!option_value)
>>>>>>>>     return 0;
>>>>>>>>
>>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>>     return 0;
>>>>>>>>
>>>>>>>>   ptr = option_value;
>>>>>>>> @@ -1052,17 +1088,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>       while (*ptr == '-')
>>>>>>>>        ptr++;
>>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>>> +
>>>>>>>>       if (!end_ptr)
>>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>>       length = end_ptr - ptr;
>>>>>>>>
>>>>>>>> +      if (*ptr == '=')
>>>>>>>> +        {
>>>>>>>> +          /* Interpret rest of the argument as a dump filename.  This
>>>>>>>> +             filename overrides generated dump names as well as other
>>>>>>>> +             command line filenames.  */
>>>>>>>> +          flags |= TDF_FILENAME;
>>>>>>>> +          if (dfi->filename)
>>>>>>>> +            free (dfi->filename);
>>>>>>>> +          dfi->filename = xstrdup (ptr + 1);
>>>>>>>> +          break;
>>>>>>>> +        }
>>>>>>>> +
>>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>>> -         {
>>>>>>>> -           flags |= option_ptr->value;
>>>>>>>> +          {
>>>>>>>> +            flags |= option_ptr->value;
>>>>>>>>            goto found;
>>>>>>>> -         }
>>>>>>>> +          }
>>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>>     found:;
>>>>>>>> @@ -1075,7 +1124,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>>      known dumps.  */
>>>>>>>>   if (dfi->suffix == NULL)
>>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>>> +    dump_enable_all (dfi->flags, dfi->filename);
>>>>>>>>
>>>>>>>>   return 1;
>>>>>>>>  }
>>>>>>>> @@ -1124,5 +1173,5 @@ dump_function (int phase, tree fn)
>>>>>>>>  bool
>>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>>  {
>>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>>  }
>>>>>>>> Index: tree-pass.h
>>>>>>>> ===================================================================
>>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>>> +++ tree-pass.h (working copy)
>>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>>> +#define TDF_FILENAME    (1 << 25)      /* Dump on provided filename
>>>>>>>> +                                           instead of constructing one. */
>>>>>>>>
>>>>>>>> -
>>>>>>>>  /* In tree-dump.c */
>>>>>>>>
>>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>>> +  const char *filename;         /* use this filename instead of making
>>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>>>   int flags;                    /* user flags */
>>>>>>>>   int state;                    /* state of play */
>>>>>>>>   int num;                      /* dump file number */
>>>>>>>> Index: testsuite/g++.dg/other/dump-filename-1.C
>>>>>>>> ===================================================================
>>>>>>>> --- testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>>>> +++ testsuite/g++.dg/other/dump-filename-1.C    (revision 0)
>>>>>>>> @@ -0,0 +1,11 @@
>>>>>>>> +// Test that the dump to a user-defined file works correctly.
>>>>>>>> +/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
>>>>>>>> +
>>>>>>>> +void test (int *b, int *e, int stride)
>>>>>>>> +  {
>>>>>>>> +    for (int *p = b; p != e; p += stride)
>>>>>>>> +      *p = 1;
>>>>>>>> +  }
>>>>>>>> +
>>>>>>>> +/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
>>>>>>>> +/* { dg-final { remove-build-file "foobar.dump" } } */
>>>>>>>>
>>>>>>>>
>>>>>>>> On Wed, May 9, 2012 at 12:22 AM, Gabriel Dos Reis
>>>>>>>> <gdr@integrable-solutions.net> wrote:
>>>>>>>>> On Wed, May 9, 2012 at 1:46 AM, Sharad Singhai <singhai@google.com> wrote:
>>>>>>>>> [...]
>>>>>>>>>
>>>>>>>>>> +@item -fdump-rtl-all=stderr
>>>>>>>>>> +@opindex fdump-rtl-all=stderr
>>>>>>>>>
>>>>>>>>> You do not need to have a separate index entry for '=stderr' or '=stdout'.
>>>>>>>>> Rather, expand the description to state this in all the documentation
>>>>>>>>> for -fdump-xxx=yyy.
>>>>>>>>>
>>>>>>>>> [...]
>>>>>>>>>
>>>>>>>>>> +/* Return non-zero iff the USER_FILENAME corresponds to stdout or
>>>>>>>>>> +   stderr stream.  */
>>>>>>>>>> +
>>>>>>>>>> +static int
>>>>>>>>>> +dump_stream_p (const char *user_filename)
>>>>>>>>>> +{
>>>>>>>>>> +  if (user_filename)
>>>>>>>>>> +    return !strncmp ("stderr", user_filename, 6) ||
>>>>>>>>>> +      !strncmp ("stdout", user_filename, 6);
>>>>>>>>>> +  else
>>>>>>>>>> +    return 0;
>>>>>>>>>> +}
>>>>>>>>>
>>>>>>>>> The name is ambiguous.
>>>>>>>>> This function is testing whether its string argument designates one of
>>>>>>>>> the *standard* output streams.  Name it to reflect that..
>>>>>>>>> Have it take the dump state context. Also the coding convention: the binary
>>>>>>>>> operator "||" should be on next line.  In fact the thing could be
>>>>>>>>> simpler.   Instead of
>>>>>>>>> testing over and over again against "stderr" (once in this function, then again
>>>>>>>>> later), just return the corresponding standard FILE* pointer.
>>>>>>>>> Also, this is a case of overuse of strncmp.  If you name the function
>>>>>>>>> dump_get_standard_stream:
>>>>>>>>>
>>>>>>>>>    return strcmp("stderr", dfi->user_filename) == 0
>>>>>>>>>       ? stderr
>>>>>>>>>        : stdcmp("stdout", dfi->use_filename)
>>>>>>>>>        ?  stdout
>>>>>>>>>        : NULL;
>>>>>>>>>
>>>>>>>>> you can simplify:
>>>>>>>>>
>>>>>>>>>> -  name = get_dump_file_name (phase);
>>>>>>>>>>   dfi = get_dump_file_info (phase);
>>>>>>>>>> -  stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>>>> -  if (!stream)
>>>>>>>>>> -    error ("could not open dump file %qs: %m", name);
>>>>>>>>>> +  if (dump_stream_p (dfi->user_filename))
>>>>>>>>>> +    {
>>>>>>>>>> +      if (!strncmp ("stderr", dfi->user_filename, 6))
>>>>>>>>>> +        stream = stderr;
>>>>>>>>>> +      else
>>>>>>>>>> +        if (!strncmp ("stdout", dfi->user_filename, 6))
>>>>>>>>>> +          stream = stdout;
>>>>>>>>>> +        else
>>>>>>>>>> +          error ("unknown stream: %qs: %m", dfi->user_filename);
>>>>>>>>>> +      dfi->state = 1;
>>>>>>>>>> +    }
>>>>>>>>>>   else
>>>>>>>>>> -    dfi->state = 1;
>>>>>>>>>> -  free (name);
>>>>>>>>>> +    {
>>>>>>>>>> +      name = get_dump_file_name (phase);
>>>>>>>>>> +      stream = fopen (name, dfi->state < 0 ? "w" : "a");
>>>>>>>>>> +      if (!stream)
>>>>>>>>>> +        error ("could not open dump file %qs: %m", name);
>>>>>>>>>> +      else
>>>>>>>>>> +        dfi->state = 1;
>>>>>>>>>> +      free (name);
>>>>>>>>>> +    }
>>>>>>>>>>
>>>>>>>>>>   if (flag_ptr)
>>>>>>>>>>     *flag_ptr = dfi->flags;
>>>>>>>>>> @@ -987,35 +1017,45 @@ dump_flag_name (int phase)
>>>>>>>>>>    dump_begin.  */
>>>>>>>>>>
>>>>>>>>>>  void
>>>>>>>>>> -dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
>>>>>>>>>> +dump_end (int phase, FILE *stream)
>>>>>>>>>>  {
>>>>>>>>>> -  fclose (stream);
>>>>>>>>>> +  struct dump_file_info *dfi = get_dump_file_info (phase);
>>>>>>>>>> +  if (!dump_stream_p (dfi->user_filename))
>>>>>>>>>> +    fclose (stream);
>>>>>>>>>>  }
>>>>>>>>>>
>>>>>>>>>>  /* Enable all tree dumps.  Return number of enabled tree dumps.  */
>>>>>>>>>>
>>>>>>>>>>  static int
>>>>>>>>>> -dump_enable_all (int flags)
>>>>>>>>>> +dump_enable_all (int flags, const char *user_filename)
>>>>>>>>>>  {
>>>>>>>>>>   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
>>>>>>>>>>   int n = 0;
>>>>>>>>>>   size_t i;
>>>>>>>>>>
>>>>>>>>>>   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
>>>>>>>>>> -    if ((dump_files[i].flags & ir_dump_type))
>>>>>>>>>> -      {
>>>>>>>>>> -        dump_files[i].state = -1;
>>>>>>>>>> -        dump_files[i].flags |= flags;
>>>>>>>>>> -        n++;
>>>>>>>>>> -      }
>>>>>>>>>> +    {
>>>>>>>>>> +      if ((dump_files[i].flags & ir_dump_type))
>>>>>>>>>> +        {
>>>>>>>>>> +          dump_files[i].state = -1;
>>>>>>>>>> +          dump_files[i].flags |= flags;
>>>>>>>>>> +          n++;
>>>>>>>>>> +        }
>>>>>>>>>> +      if (user_filename)
>>>>>>>>>> +        dump_files[i].user_filename = user_filename;
>>>>>>>>>> +    }
>>>>>>>>>>
>>>>>>>>>>   for (i = 0; i < extra_dump_files_in_use; i++)
>>>>>>>>>> -    if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>>>> -      {
>>>>>>>>>> -        extra_dump_files[i].state = -1;
>>>>>>>>>> -        extra_dump_files[i].flags |= flags;
>>>>>>>>>> -       n++;
>>>>>>>>>> -      }
>>>>>>>>>> +    {
>>>>>>>>>> +      if ((extra_dump_files[i].flags & ir_dump_type))
>>>>>>>>>> +        {
>>>>>>>>>> +          extra_dump_files[i].state = -1;
>>>>>>>>>> +          extra_dump_files[i].flags |= flags;
>>>>>>>>>> +          n++;
>>>>>>>>>> +        }
>>>>>>>>>> +      if (user_filename)
>>>>>>>>>> +        extra_dump_files[i].user_filename = user_filename;
>>>>>>>>>> +    }
>>>>>>>>>>
>>>>>>>>>>   return n;
>>>>>>>>>>  }
>>>>>>>>>> @@ -1037,7 +1077,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>>   if (!option_value)
>>>>>>>>>>     return 0;
>>>>>>>>>>
>>>>>>>>>> -  if (*option_value && *option_value != '-')
>>>>>>>>>> +  if (*option_value && *option_value != '-' && *option_value != '=')
>>>>>>>>>>     return 0;
>>>>>>>>>>
>>>>>>>>>>   ptr = option_value;
>>>>>>>>>> @@ -1052,17 +1092,30 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>>       while (*ptr == '-')
>>>>>>>>>>        ptr++;
>>>>>>>>>>       end_ptr = strchr (ptr, '-');
>>>>>>>>>> +
>>>>>>>>>>       if (!end_ptr)
>>>>>>>>>>        end_ptr = ptr + strlen (ptr);
>>>>>>>>>>       length = end_ptr - ptr;
>>>>>>>>>>
>>>>>>>>>> +      if (*ptr == '=')
>>>>>>>>>> +        {
>>>>>>>>>> +          /* Interpret rest of the argument as a dump filename.  The
>>>>>>>>>> +             user provided filename overrides generated dump names as
>>>>>>>>>> +             well as other command line filenames.  */
>>>>>>>>>> +          flags |= TDF_USER_FILENAME;
>>>>>>>>>> +          if (dfi->user_filename)
>>>>>>>>>> +            free (dfi->user_filename);
>>>>>>>>>> +          dfi->user_filename = xstrdup (ptr + 1);
>>>>>>>>>> +          break;
>>>>>>>>>> +        }
>>>>>>>>>> +
>>>>>>>>>>       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
>>>>>>>>>>        if (strlen (option_ptr->name) == length
>>>>>>>>>>            && !memcmp (option_ptr->name, ptr, length))
>>>>>>>>>> -         {
>>>>>>>>>> -           flags |= option_ptr->value;
>>>>>>>>>> +          {
>>>>>>>>>> +            flags |= option_ptr->value;
>>>>>>>>>>            goto found;
>>>>>>>>>> -         }
>>>>>>>>>> +          }
>>>>>>>>>>       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
>>>>>>>>>>               length, ptr, dfi->swtch);
>>>>>>>>>>     found:;
>>>>>>>>>> @@ -1075,7 +1128,7 @@ dump_switch_p_1 (const char *arg, struct dump_file
>>>>>>>>>>   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
>>>>>>>>>>      known dumps.  */
>>>>>>>>>>   if (dfi->suffix == NULL)
>>>>>>>>>> -    dump_enable_all (dfi->flags);
>>>>>>>>>> +    dump_enable_all (dfi->flags, dfi->user_filename);
>>>>>>>>>>
>>>>>>>>>>   return 1;
>>>>>>>>>>  }
>>>>>>>>>> @@ -1124,5 +1177,5 @@ dump_function (int phase, tree fn)
>>>>>>>>>>  bool
>>>>>>>>>>  enable_rtl_dump_file (void)
>>>>>>>>>>  {
>>>>>>>>>> -  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
>>>>>>>>>> +  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
>>>>>>>>>>  }
>>>>>>>>>> Index: tree-pass.h
>>>>>>>>>> ===================================================================
>>>>>>>>>> --- tree-pass.h (revision 187265)
>>>>>>>>>> +++ tree-pass.h (working copy)
>>>>>>>>>> @@ -84,8 +84,9 @@ enum tree_dump_index
>>>>>>>>>>  #define TDF_ENUMERATE_LOCALS (1 << 22) /* Enumerate locals by uid.  */
>>>>>>>>>>  #define TDF_CSELIB     (1 << 23)       /* Dump cselib details.  */
>>>>>>>>>>  #define TDF_SCEV       (1 << 24)       /* Dump SCEV details.  */
>>>>>>>>>> +#define TDF_USER_FILENAME    (1 << 25) /* Dump on user provided filename,
>>>>>>>>>> +                                           instead of constructing one. */
>>>>>>>>>>
>>>>>>>>>> -
>>>>>>>>>>  /* In tree-dump.c */
>>>>>>>>>>
>>>>>>>>>>  extern char *get_dump_file_name (int);
>>>>>>>>>> @@ -222,6 +223,8 @@ struct dump_file_info
>>>>>>>>>>   const char *suffix;           /* suffix to give output file.  */
>>>>>>>>>>   const char *swtch;            /* command line switch */
>>>>>>>>>>   const char *glob;             /* command line glob  */
>>>>>>>>>> +  const char *user_filename;    /* user provided filename instead of making
>>>>>>>>>> +                                   up one using dump_base_name + suffix.  */
>>>>>>>>>
>>>>>>>>> There is "no user" here: we are the users :-)  Just call it "filename".
>>>>>>>>>
>>>>>>>>> -- Gaby
Gabriel Dos Reis May 12, 2012, 4:26 p.m. UTC | #9
On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:

> The downside is that the dump file format will look different from the
> stderr output which is less than ideal.

BTW, why do people want to use stderr for dumping internal IRs,
as opposed to stdout or other files?  That does not sound right.

-- Gaby
Xinliang David Li May 12, 2012, 4:39 p.m. UTC | #10
On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
<gdr@integrable-solutions.net> wrote:
> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>
>> The downside is that the dump file format will look different from the
>> stderr output which is less than ideal.
>
> BTW, why do people want to use stderr for dumping internal IRs,
> as opposed to stdout or other files?  That does not sound right.
>

I was talking about the transformation information difference. In
stderr (where diagnostics go to), we may have

foo.c: in function 'foo':
foo.c:5:6: note: loop was vectorized

but in dump file the format for the information may be different,
unless we want to duplicate the machinery in diagnostics.

David

> -- Gaby
Richard Biener May 14, 2012, 7:26 a.m. UTC | #11
On Sat, May 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
> On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
> <gdr@integrable-solutions.net> wrote:
>> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>>
>>> The downside is that the dump file format will look different from the
>>> stderr output which is less than ideal.
>>
>> BTW, why do people want to use stderr for dumping internal IRs,
>> as opposed to stdout or other files?  That does not sound right.
>>
>
> I was talking about the transformation information difference. In
> stderr (where diagnostics go to), we may have
>
> foo.c: in function 'foo':
> foo.c:5:6: note: loop was vectorized
>
> but in dump file the format for the information may be different,
> unless we want to duplicate the machinery in diagnostics.

So?  What's the problem with that ("different" diagnostics)?

Richard.

> David
>
>> -- Gaby
Sharad Singhai June 7, 2012, 5:58 a.m. UTC | #12
Sorry about the delay. I have finally incorporated all the suggestions
and reorganized the dump infrastructure a bit. The attached patch
updates vectorizer passes so that instead of accessing global
dump_file directly, these passes call dump_printf (FLAG, format, ...).
The dump_printf can choose between two streams, one regular pass dump
file, and another optional command line provided file. Currently, it
doesn't discriminate and all the dump information goes to both the
streams.

Thus, for example,

g++ -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.v -ftree-vectorizer-verbose=3

will output the verbose vectorizer information in both *.vect file and
foo.v file. However, as I have converted only vectorizer passes so
far, there is additional information in *.vect file which is not
present in foo.v file. Once other passes are converted to use this
scheme, then these two dump files should have identical output.

Also note that in this patch -fdump-xxx=yyy format does not override
any auto named dump files as in my earlier patches. Instead the dump
information is output to both places when a command line dump file
option is provided.

To summarize:
- instead of using dump_begin () / dump_end (), the passes should use
dump_start ()/dump_finish (). These new variants do not return the
dump_file. However, they still set the global dump_file/dump_flags for
the benefit of other passes during the transition.
- instead of directly printing to the dump_file, as in
if (dump_file)
  fprintf (dump_file, ...);

The passes should do

dump_printf (dump_flag, ...);
This will output to dump file(s) only when dump_flag is enabled for a
given pass.

I have bootstrapped and tested it on x86_64. Does it look okay?

Thanks,
Sharad


On Mon, May 14, 2012 at 12:26 AM, Richard Guenther
<richard.guenther@gmail.com> wrote:
> On Sat, May 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>> On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
>> <gdr@integrable-solutions.net> wrote:
>>> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>
>>>> The downside is that the dump file format will look different from the
>>>> stderr output which is less than ideal.
>>>
>>> BTW, why do people want to use stderr for dumping internal IRs,
>>> as opposed to stdout or other files?  That does not sound right.
>>>
>>
>> I was talking about the transformation information difference. In
>> stderr (where diagnostics go to), we may have
>>
>> foo.c: in function 'foo':
>> foo.c:5:6: note: loop was vectorized
>>
>> but in dump file the format for the information may be different,
>> unless we want to duplicate the machinery in diagnostics.
>
> So?  What's the problem with that ("different" diagnostics)?
>
> Richard.
>
>> David
>>
>>> -- Gaby
Xinliang David Li June 7, 2012, 7:19 a.m. UTC | #13
On Wed, Jun 6, 2012 at 10:58 PM, Sharad Singhai <singhai@google.com> wrote:
> Sorry about the delay. I have finally incorporated all the suggestions
> and reorganized the dump infrastructure a bit. The attached patch
> updates vectorizer passes so that instead of accessing global
> dump_file directly, these passes call dump_printf (FLAG, format, ...).
> The dump_printf can choose between two streams, one regular pass dump
> file, and another optional command line provided file. Currently, it
> doesn't discriminate and all the dump information goes to both the
> streams.
>
> Thus, for example,
>
> g++ -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.v -ftree-vectorizer-verbose=3

But the default form of dump option (-fdump-tree-vect) no longer
interferes with -ftree-vectorize-verbose=xxx output right? (this is
one of the main requirements). One dumped to the primary stream (named
dump file) and the other to the stderr -- the default diagnostic (alt)
stream.

David

>
> will output the verbose vectorizer information in both *.vect file and
> foo.v file. However, as I have converted only vectorizer passes so
> far, there is additional information in *.vect file which is not
> present in foo.v file. Once other passes are converted to use this
> scheme, then these two dump files should have identical output.
>
> Also note that in this patch -fdump-xxx=yyy format does not override
> any auto named dump files as in my earlier patches. Instead the dump
> information is output to both places when a command line dump file
> option is provided.
>
> To summarize:
> - instead of using dump_begin () / dump_end (), the passes should use
> dump_start ()/dump_finish (). These new variants do not return the
> dump_file. However, they still set the global dump_file/dump_flags for
> the benefit of other passes during the transition.
> - instead of directly printing to the dump_file, as in
> if (dump_file)
>  fprintf (dump_file, ...);
>
> The passes should do
>
> dump_printf (dump_flag, ...);
> This will output to dump file(s) only when dump_flag is enabled for a
> given pass.
>
> I have bootstrapped and tested it on x86_64. Does it look okay?
>
> Thanks,
> Sharad
>
>
> On Mon, May 14, 2012 at 12:26 AM, Richard Guenther
> <richard.guenther@gmail.com> wrote:
>> On Sat, May 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>>> On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
>>> <gdr@integrable-solutions.net> wrote:
>>>> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>
>>>>> The downside is that the dump file format will look different from the
>>>>> stderr output which is less than ideal.
>>>>
>>>> BTW, why do people want to use stderr for dumping internal IRs,
>>>> as opposed to stdout or other files?  That does not sound right.
>>>>
>>>
>>> I was talking about the transformation information difference. In
>>> stderr (where diagnostics go to), we may have
>>>
>>> foo.c: in function 'foo':
>>> foo.c:5:6: note: loop was vectorized
>>>
>>> but in dump file the format for the information may be different,
>>> unless we want to duplicate the machinery in diagnostics.
>>
>> So?  What's the problem with that ("different" diagnostics)?
>>
>> Richard.
>>
>>> David
>>>
>>>> -- Gaby
Sharad Singhai June 8, 2012, 5:16 a.m. UTC | #14
Okay, I have updated the attached patch so that the output from
-ftree-vectorizer-verbose is considered diagnostic information and is
always
sent to stderr. Other functionality remains unchanged. Here is some
more context about this patch.

This patch improves the dump infrastructure and public interfaces so
that the existing private pass-specific dump stream is separated from
the diagnostic dump stream (typically stderr).  The optimization
passes can output information on the two streams independently.

The newly defined interfaces are:

Individual passes do not need to access the dump file directly. Thus Instead
of doing

   if (dump_file && (flags & dump_flags))
      fprintf (dump_file, ...);

they can do

     dump_printf (flags, ...);

If the current pass has FLAGS enabled then the information gets
printed into the dump file otherwise not.

Similar to the dump_printf (), another function is defined, called

	diag_printf (dump_flags, ...)

This prints information only onto the diagnostic stream, typically
standard error. It is useful for separating pass-specific dump
information from
the diagnostic information.

Currently, as a proof of concept, I have converted vectorizer passes
to use the new dump format. For this, I have considered
information printed in vect_dump file as diagnostic. Thus 'fprintf'
calls are changed to 'diag_printf'. Some other information printed to
dump_file is sent to the regular dump file via 'dump_printf ()'. It
helps to separate the two streams because they might serve different
purposes and might have different formatting requirements.

For example, using the trunk compiler, the following invocation

g++ -S v.cc -ftree-vectorize -fdump-tree-vect -ftree-vectorizer-verbose=2

prints tree vectorizer dump into a file named 'v.cc.113t.vect'.
However, the verbose diagnostic output is silently
ignored. This is not desirable as the two types of dump should not interfere.

After this patch, the vectorizer dump is available in 'v.cc.113t.vect'
as before, but the verbose vectorizer diagnostic is additionally
printed on stderr. Thus both types of dump information are output.

An additional feature of this patch is that individual passes can
print dump information into command-line named files instead of auto
numbered filename. For example,

g++ -S -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.vect
     -ftree-vectorizer-verbose=2
     -fdump-tree-pre=foo.pre

This prints the tree vectorizer dump into 'foo.vect', PRE dump into
'foo.pre', and the vectorizer verbose diagnostic dump onto stderr.

Please take another look.

Thanks,
Sharad


On Thu, Jun 7, 2012 at 12:19 AM, Xinliang David Li <davidxl@google.com> wrote:
> On Wed, Jun 6, 2012 at 10:58 PM, Sharad Singhai <singhai@google.com> wrote:
>> Sorry about the delay. I have finally incorporated all the suggestions
>> and reorganized the dump infrastructure a bit. The attached patch
>> updates vectorizer passes so that instead of accessing global
>> dump_file directly, these passes call dump_printf (FLAG, format, ...).
>> The dump_printf can choose between two streams, one regular pass dump
>> file, and another optional command line provided file. Currently, it
>> doesn't discriminate and all the dump information goes to both the
>> streams.
>>
>> Thus, for example,
>>
>> g++ -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.v -ftree-vectorizer-verbose=3
>
> But the default form of dump option (-fdump-tree-vect) no longer
> interferes with -ftree-vectorize-verbose=xxx output right? (this is
> one of the main requirements). One dumped to the primary stream (named
> dump file) and the other to the stderr -- the default diagnostic (alt)
> stream.
>
> David
>
>>
>> will output the verbose vectorizer information in both *.vect file and
>> foo.v file. However, as I have converted only vectorizer passes so
>> far, there is additional information in *.vect file which is not
>> present in foo.v file. Once other passes are converted to use this
>> scheme, then these two dump files should have identical output.
>>
>> Also note that in this patch -fdump-xxx=yyy format does not override
>> any auto named dump files as in my earlier patches. Instead the dump
>> information is output to both places when a command line dump file
>> option is provided.
>>
>> To summarize:
>> - instead of using dump_begin () / dump_end (), the passes should use
>> dump_start ()/dump_finish (). These new variants do not return the
>> dump_file. However, they still set the global dump_file/dump_flags for
>> the benefit of other passes during the transition.
>> - instead of directly printing to the dump_file, as in
>> if (dump_file)
>>  fprintf (dump_file, ...);
>>
>> The passes should do
>>
>> dump_printf (dump_flag, ...);
>> This will output to dump file(s) only when dump_flag is enabled for a
>> given pass.
>>
>> I have bootstrapped and tested it on x86_64. Does it look okay?
>>
>> Thanks,
>> Sharad
>>
>>
>> On Mon, May 14, 2012 at 12:26 AM, Richard Guenther
>> <richard.guenther@gmail.com> wrote:
>>> On Sat, May 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>> On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
>>>> <gdr@integrable-solutions.net> wrote:
>>>>> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>
>>>>>> The downside is that the dump file format will look different from the
>>>>>> stderr output which is less than ideal.
>>>>>
>>>>> BTW, why do people want to use stderr for dumping internal IRs,
>>>>> as opposed to stdout or other files?  That does not sound right.
>>>>>
>>>>
>>>> I was talking about the transformation information difference. In
>>>> stderr (where diagnostics go to), we may have
>>>>
>>>> foo.c: in function 'foo':
>>>> foo.c:5:6: note: loop was vectorized
>>>>
>>>> but in dump file the format for the information may be different,
>>>> unless we want to duplicate the machinery in diagnostics.
>>>
>>> So?  What's the problem with that ("different" diagnostics)?
>>>
>>> Richard.
>>>
>>>> David
>>>>
>>>>> -- Gaby
Sharad Singhai June 13, 2012, 6:08 a.m. UTC | #15
Ping.

Thanks,
Sharad

On Thu, Jun 7, 2012 at 10:16 PM, Sharad Singhai <singhai@google.com> wrote:
> Okay, I have updated the attached patch so that the output from
> -ftree-vectorizer-verbose is considered diagnostic information and is
> always
> sent to stderr. Other functionality remains unchanged. Here is some
> more context about this patch.
>
> This patch improves the dump infrastructure and public interfaces so
> that the existing private pass-specific dump stream is separated from
> the diagnostic dump stream (typically stderr).  The optimization
> passes can output information on the two streams independently.
>
> The newly defined interfaces are:
>
> Individual passes do not need to access the dump file directly. Thus Instead
> of doing
>
>   if (dump_file && (flags & dump_flags))
>      fprintf (dump_file, ...);
>
> they can do
>
>     dump_printf (flags, ...);
>
> If the current pass has FLAGS enabled then the information gets
> printed into the dump file otherwise not.
>
> Similar to the dump_printf (), another function is defined, called
>
>        diag_printf (dump_flags, ...)
>
> This prints information only onto the diagnostic stream, typically
> standard error. It is useful for separating pass-specific dump
> information from
> the diagnostic information.
>
> Currently, as a proof of concept, I have converted vectorizer passes
> to use the new dump format. For this, I have considered
> information printed in vect_dump file as diagnostic. Thus 'fprintf'
> calls are changed to 'diag_printf'. Some other information printed to
> dump_file is sent to the regular dump file via 'dump_printf ()'. It
> helps to separate the two streams because they might serve different
> purposes and might have different formatting requirements.
>
> For example, using the trunk compiler, the following invocation
>
> g++ -S v.cc -ftree-vectorize -fdump-tree-vect -ftree-vectorizer-verbose=2
>
> prints tree vectorizer dump into a file named 'v.cc.113t.vect'.
> However, the verbose diagnostic output is silently
> ignored. This is not desirable as the two types of dump should not interfere.
>
> After this patch, the vectorizer dump is available in 'v.cc.113t.vect'
> as before, but the verbose vectorizer diagnostic is additionally
> printed on stderr. Thus both types of dump information are output.
>
> An additional feature of this patch is that individual passes can
> print dump information into command-line named files instead of auto
> numbered filename. For example,
>
> g++ -S -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.vect
>     -ftree-vectorizer-verbose=2
>     -fdump-tree-pre=foo.pre
>
> This prints the tree vectorizer dump into 'foo.vect', PRE dump into
> 'foo.pre', and the vectorizer verbose diagnostic dump onto stderr.
>
> Please take another look.
>
> Thanks,
> Sharad
>
>
> On Thu, Jun 7, 2012 at 12:19 AM, Xinliang David Li <davidxl@google.com> wrote:
>> On Wed, Jun 6, 2012 at 10:58 PM, Sharad Singhai <singhai@google.com> wrote:
>>> Sorry about the delay. I have finally incorporated all the suggestions
>>> and reorganized the dump infrastructure a bit. The attached patch
>>> updates vectorizer passes so that instead of accessing global
>>> dump_file directly, these passes call dump_printf (FLAG, format, ...).
>>> The dump_printf can choose between two streams, one regular pass dump
>>> file, and another optional command line provided file. Currently, it
>>> doesn't discriminate and all the dump information goes to both the
>>> streams.
>>>
>>> Thus, for example,
>>>
>>> g++ -O2 v.cc -ftree-vectorize -fdump-tree-vect=foo.v -ftree-vectorizer-verbose=3
>>
>> But the default form of dump option (-fdump-tree-vect) no longer
>> interferes with -ftree-vectorize-verbose=xxx output right? (this is
>> one of the main requirements). One dumped to the primary stream (named
>> dump file) and the other to the stderr -- the default diagnostic (alt)
>> stream.
>>
>> David
>>
>>>
>>> will output the verbose vectorizer information in both *.vect file and
>>> foo.v file. However, as I have converted only vectorizer passes so
>>> far, there is additional information in *.vect file which is not
>>> present in foo.v file. Once other passes are converted to use this
>>> scheme, then these two dump files should have identical output.
>>>
>>> Also note that in this patch -fdump-xxx=yyy format does not override
>>> any auto named dump files as in my earlier patches. Instead the dump
>>> information is output to both places when a command line dump file
>>> option is provided.
>>>
>>> To summarize:
>>> - instead of using dump_begin () / dump_end (), the passes should use
>>> dump_start ()/dump_finish (). These new variants do not return the
>>> dump_file. However, they still set the global dump_file/dump_flags for
>>> the benefit of other passes during the transition.
>>> - instead of directly printing to the dump_file, as in
>>> if (dump_file)
>>>  fprintf (dump_file, ...);
>>>
>>> The passes should do
>>>
>>> dump_printf (dump_flag, ...);
>>> This will output to dump file(s) only when dump_flag is enabled for a
>>> given pass.
>>>
>>> I have bootstrapped and tested it on x86_64. Does it look okay?
>>>
>>> Thanks,
>>> Sharad
>>>
>>>
>>> On Mon, May 14, 2012 at 12:26 AM, Richard Guenther
>>> <richard.guenther@gmail.com> wrote:
>>>> On Sat, May 12, 2012 at 6:39 PM, Xinliang David Li <davidxl@google.com> wrote:
>>>>> On Sat, May 12, 2012 at 9:26 AM, Gabriel Dos Reis
>>>>> <gdr@integrable-solutions.net> wrote:
>>>>>> On Sat, May 12, 2012 at 11:05 AM, Xinliang David Li <davidxl@google.com> wrote:
>>>>>>
>>>>>>> The downside is that the dump file format will look different from the
>>>>>>> stderr output which is less than ideal.
>>>>>>
>>>>>> BTW, why do people want to use stderr for dumping internal IRs,
>>>>>> as opposed to stdout or other files?  That does not sound right.
>>>>>>
>>>>>
>>>>> I was talking about the transformation information difference. In
>>>>> stderr (where diagnostics go to), we may have
>>>>>
>>>>> foo.c: in function 'foo':
>>>>> foo.c:5:6: note: loop was vectorized
>>>>>
>>>>> but in dump file the format for the information may be different,
>>>>> unless we want to duplicate the machinery in diagnostics.
>>>>
>>>> So?  What's the problem with that ("different" diagnostics)?
>>>>
>>>> Richard.
>>>>
>>>>> David
>>>>>
>>>>>> -- Gaby
diff mbox

Patch

Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi	(revision 187265)
+++ doc/invoke.texi	(working copy)
@@ -5322,20 +5322,23 @@  Here are some examples showing uses of these optio

 @item -d@var{letters}
 @itemx -fdump-rtl-@var{pass}
+@itemx -fdump-rtl-@var{pass}=@var{filename}
 @opindex d
 Says to make debugging dumps during compilation at times specified by
 @var{letters}.  This is used for debugging the RTL-based passes of the
 compiler.  The file names for most of the dumps are made by appending
 a pass number and a word to the @var{dumpname}, and the files are
-created in the directory of the output file.  Note that the pass
-number is computed statically as passes get registered into the pass
-manager.  Thus the numbering is not related to the dynamic order of
-execution of passes.  In particular, a pass installed by a plugin
-could have a number over 200 even if it executed quite early.
-@var{dumpname} is generated from the name of the output file, if
-explicitly specified and it is not an executable, otherwise it is the
-basename of the source file. These switches may have different effects
-when @option{-E} is used for preprocessing.
+created in the directory of the output file. If the
+@option{=@var{filename}} is appended to the longer form of the dump
+option then the dump is done on that file instead of numbered
+files. Note that the pass number is computed statically as passes get
+registered into the pass manager.  Thus the numbering is not related
+to the dynamic order of execution of passes.  In particular, a pass
+installed by a plugin could have a number over 200 even if it executed
+quite early.  @var{dumpname} is generated from the name of the output
+file, if explicitly specified and it is not an executable, otherwise
+it is the basename of the source file. These switches may have
+different effects when @option{-E} is used for preprocessing.

 Debug dumps can be enabled with a @option{-fdump-rtl} switch or some
 @option{-d} option @var{letters}.  Here are the possible
@@ -5719,15 +5722,18 @@  counters for each function compiled.

 @item -fdump-tree-@var{switch}
 @itemx -fdump-tree-@var{switch}-@var{options}
+@itemx -fdump-tree-@var{switch}-@var{options}=@var{filename}
 @opindex fdump-tree
 Control the dumping at various stages of processing the intermediate
 language tree to a file.  The file name is generated by appending a
 switch specific suffix to the source file name, and the file is
-created in the same directory as the output file.  If the
-@samp{-@var{options}} form is used, @var{options} is a list of
-@samp{-} separated options which control the details of the dump.  Not
-all options are applicable to all dumps; those that are not
-meaningful are ignored.  The following options are available
+created in the same directory as the output file. In case of
+@option{=@var{filename}} option, the dump is output on the given file
+name instead.  If the @samp{-@var{options}} form is used,
+@var{options} is a list of @samp{-} separated options which control
+the details or location of the dump.  Not all options are applicable
+to all dumps; those that are not meaningful are ignored.  The
+following options are available

 @table @samp
 @item address
@@ -5765,9 +5771,46 @@  Enable showing the tree dump for each statement.
 Enable showing the EH region number holding each statement.
 @item scev
 Enable showing scalar evolution analysis details.
+@item slim
+Inhibit dumping of members of a scope or body of a function merely
+because that scope has been reached.  Only dump such items when they
+are directly reachable by some other path.  When dumping pretty-printed
+trees, this option inhibits dumping the bodies of control structures.
+@item =@var{filename}
+Instead of using an auto generated dump file name, use the given file
+name. The file names @file{stdout} and @file{stderr} are treated
+specially and are considered already open standard streams. For
+example:
+
+@smallexample
+gcc -O2 -fdump-tree-pre=stderr -fdump-rtl-ira=ira.txt ...
+@end smallexample
+
+outputs PRE dump on @file{stderr}, while the IRA dump is output in a
+file named @file{ira.txt}.
+
+In case of any conflicts, the command line file name takes precedence
+over generated file names. For example:
+
+@smallexample
+gcc -O2 -fdump-tree-pre=stdout -fdump-tree-pre ...
+gcc -O2 -fdump-tree-pre -fdump-tree-pre=stdout ...
+@end smallexample
+
+Both of the above output the PRE dump on @file{stdout}. However, if
+there are multiple command line file names are applicable then the
+last one is used. Thus the command
+
+@smallexample
+gcc -O2 -fdump-tree-pre=stderr -fdump-tree-all=all.txt
+@end smallexample
+
+outputs all the dumps in @file{all.txt} because the stderr option for
+PRE dump is overridden by a later option.
+
 @item all
-Turn on all options, except @option{raw}, @option{slim}, @option{verbose}
-and @option{lineno}.
+Turn on all options, except @option{raw}, @option{slim}, @option{verbose},
+@option{lineno}.
 @end table

 The following tree dumps are possible:
@@ -5913,6 +5956,7 @@  is made by appending @file{.vrp} to the source fil
 @item all
 @opindex fdump-tree-all
 Enable all the available tree dumps with the flags provided in this option.
+
 @end table

 @item -ftree-vectorizer-verbose=@var{n}
Index: tree-dump.c
===================================================================
--- tree-dump.c	(revision 187265)
+++ tree-dump.c	(working copy)
@@ -773,20 +773,20 @@  dump_node (const_tree t, int flags, FILE *stream)
    tree_dump_index enumeration in tree-pass.h.  */
 static struct dump_file_info dump_files[TDI_end] =
 {
-  {NULL, NULL, NULL, 0, 0, 0},
-  {".cgraph", "ipa-cgraph", NULL, TDF_IPA, 0,  0},
-  {".tu", "translation-unit", NULL, TDF_TREE, 0, 1},
-  {".class", "class-hierarchy", NULL, TDF_TREE, 0, 2},
-  {".original", "tree-original", NULL, TDF_TREE, 0, 3},
-  {".gimple", "tree-gimple", NULL, TDF_TREE, 0, 4},
-  {".nested", "tree-nested", NULL, TDF_TREE, 0, 5},
-  {".vcg", "tree-vcg", NULL, TDF_TREE, 0, 6},
-  {".ads", "ada-spec", NULL, 0, 0, 7},
+  {NULL, NULL, NULL, NULL, 0, 0, 0},
+  {".cgraph", "ipa-cgraph", NULL, NULL, TDF_IPA, 0,  0},
+  {".tu", "translation-unit", NULL, NULL, TDF_TREE, 0, 1},
+  {".class", "class-hierarchy", NULL, NULL, TDF_TREE, 0, 2},
+  {".original", "tree-original", NULL, NULL, TDF_TREE, 0, 3},
+  {".gimple", "tree-gimple", NULL, NULL, TDF_TREE, 0, 4},
+  {".nested", "tree-nested", NULL, NULL, TDF_TREE, 0, 5},
+  {".vcg", "tree-vcg", NULL, NULL, TDF_TREE, 0, 6},
+  {".ads", "ada-spec", NULL, NULL, 0, 0, 7},
 #define FIRST_AUTO_NUMBERED_DUMP 8

-  {NULL, "tree-all", NULL, TDF_TREE, 0, 0},
-  {NULL, "rtl-all", NULL, TDF_RTL, 0, 0},
-  {NULL, "ipa-all", NULL, TDF_IPA, 0, 0},
+  {NULL, "tree-all", NULL, NULL, TDF_TREE, 0, 0},
+  {NULL, "rtl-all", NULL, NULL, TDF_RTL, 0, 0},
+  {NULL, "ipa-all", NULL, NULL, TDF_IPA, 0, 0},
 };

 /* Dynamically registered tree dump files and switches.  */
@@ -802,7 +802,7 @@  struct dump_option_value_info
 };

 /* Table of dump options. This must be consistent with the TDF_* flags
-   in tree.h */
+   in tree-pass.h */
 static const struct dump_option_value_info dump_options[] =
 {
   {"address", TDF_ADDRESS},
@@ -892,6 +892,9 @@  get_dump_file_name (int phase)
   if (dfi->state == 0)
     return NULL;

+  if (dfi->filename)
+    return xstrdup (dfi->filename);
+
   if (dfi->num < 0)
     dump_id[0] = '\0';
   else
@@ -911,6 +914,22 @@  get_dump_file_name (int phase)
   return concat (dump_base_name, dump_id, dfi->suffix, NULL);
 }

+/* If the DFI dump output corresponds to stdout or stderr stream,
+   return that stream, NULL otherwise.  */
+
+static FILE *
+dump_get_standard_stream (struct dump_file_info *dfi)
+{
+  if (!dfi->filename)
+    return NULL;
+
+  return strcmp("stderr", dfi->filename) == 0
+    ? stderr
+    : strcmp("stdout", dfi->filename) == 0
+    ?  stdout
+    : NULL;
+}
+
 /* Begin a tree dump for PHASE. Stores any user supplied flag in
    *FLAG_PTR and returns a stream to write to. If the dump is not
    enabled, returns NULL.
@@ -926,14 +945,20 @@  dump_begin (int phase, int *flag_ptr)
   if (phase == TDI_none || !dump_enabled_p (phase))
     return NULL;

-  name = get_dump_file_name (phase);
   dfi = get_dump_file_info (phase);
-  stream = fopen (name, dfi->state < 0 ? "w" : "a");
-  if (!stream)
-    error ("could not open dump file %qs: %m", name);
+  stream = dump_get_standard_stream (dfi);
+  if (stream)
+    dfi->state = 1;
   else
-    dfi->state = 1;
-  free (name);
+    {
+      name = get_dump_file_name (phase);
+      stream = fopen (name, dfi->state < 0 ? "w" : "a");
+      if (!stream)
+        error ("could not open dump file %qs: %m", name);
+      else
+        dfi->state = 1;
+      free (name);
+    }

   if (flag_ptr)
     *flag_ptr = dfi->flags;
@@ -987,35 +1012,46 @@  dump_flag_name (int phase)
    dump_begin.  */

 void
-dump_end (int phase ATTRIBUTE_UNUSED, FILE *stream)
+dump_end (int phase, FILE *stream)
 {
-  fclose (stream);
+  struct dump_file_info *dfi = get_dump_file_info (phase);
+  if (!dump_get_standard_stream (dfi))
+    fclose (stream);
 }

-/* Enable all tree dumps.  Return number of enabled tree dumps.  */
+/* Enable all tree dumps with FLAGS on FILENAME.  Return number of
+   enabled tree dumps.  */

 static int
-dump_enable_all (int flags)
+dump_enable_all (int flags, const char *filename)
 {
   int ir_dump_type = (flags & (TDF_TREE | TDF_RTL | TDF_IPA));
   int n = 0;
   size_t i;

   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
-    if ((dump_files[i].flags & ir_dump_type))
-      {
-        dump_files[i].state = -1;
-        dump_files[i].flags |= flags;
-        n++;
-      }
+    {
+      if ((dump_files[i].flags & ir_dump_type))
+        {
+          dump_files[i].state = -1;
+          dump_files[i].flags |= flags;
+          n++;
+          if (filename)
+            dump_files[i].filename = xstrdup (filename);
+        }
+    }

   for (i = 0; i < extra_dump_files_in_use; i++)
-    if ((extra_dump_files[i].flags & ir_dump_type))
-      {
-        extra_dump_files[i].state = -1;
-        extra_dump_files[i].flags |= flags;
-	n++;
-      }
+    {
+      if ((extra_dump_files[i].flags & ir_dump_type))
+        {
+          extra_dump_files[i].state = -1;
+          extra_dump_files[i].flags |= flags;
+          n++;
+          if (filename)
+            extra_dump_files[i].filename = xstrdup (filename);
+        }
+    }

   return n;
 }
@@ -1037,7 +1073,7 @@  dump_switch_p_1 (const char *arg, struct dump_file
   if (!option_value)
     return 0;

-  if (*option_value && *option_value != '-')
+  if (*option_value && *option_value != '-' && *option_value != '=')
     return 0;

   ptr = option_value;
@@ -1052,17 +1088,30 @@  dump_switch_p_1 (const char *arg, struct dump_file
       while (*ptr == '-')
 	ptr++;
       end_ptr = strchr (ptr, '-');
+
       if (!end_ptr)
 	end_ptr = ptr + strlen (ptr);
       length = end_ptr - ptr;

+      if (*ptr == '=')
+        {
+          /* Interpret rest of the argument as a dump filename.  This
+             filename overrides generated dump names as well as other
+             command line filenames.  */
+          flags |= TDF_FILENAME;
+          if (dfi->filename)
+            free (dfi->filename);
+          dfi->filename = xstrdup (ptr + 1);
+          break;
+        }
+
       for (option_ptr = dump_options; option_ptr->name; option_ptr++)
 	if (strlen (option_ptr->name) == length
 	    && !memcmp (option_ptr->name, ptr, length))
-	  {
-	    flags |= option_ptr->value;
+          {
+            flags |= option_ptr->value;
 	    goto found;
-	  }
+          }
       warning (0, "ignoring unknown option %q.*s in %<-fdump-%s%>",
 	       length, ptr, dfi->swtch);
     found:;
@@ -1075,7 +1124,7 @@  dump_switch_p_1 (const char *arg, struct dump_file
   /* Process -fdump-tree-all and -fdump-rtl-all, by enabling all the
      known dumps.  */
   if (dfi->suffix == NULL)
-    dump_enable_all (dfi->flags);
+    dump_enable_all (dfi->flags, dfi->filename);

   return 1;
 }
@@ -1124,5 +1173,5 @@  dump_function (int phase, tree fn)
 bool
 enable_rtl_dump_file (void)
 {
-  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS) > 0;
+  return dump_enable_all (TDF_RTL | TDF_DETAILS | TDF_BLOCKS, NULL) > 0;
 }
Index: tree-pass.h
===================================================================
--- tree-pass.h	(revision 187265)
+++ tree-pass.h	(working copy)
@@ -84,8 +84,9 @@  enum tree_dump_index
 #define TDF_ENUMERATE_LOCALS (1 << 22)	/* Enumerate locals by uid.  */
 #define TDF_CSELIB	(1 << 23)	/* Dump cselib details.  */
 #define TDF_SCEV	(1 << 24)	/* Dump SCEV details.  */
+#define TDF_FILENAME    (1 << 25)	/* Dump on provided filename
+                                           instead of constructing one. */

-
 /* In tree-dump.c */

 extern char *get_dump_file_name (int);
@@ -222,6 +223,8 @@  struct dump_file_info
   const char *suffix;           /* suffix to give output file.  */
   const char *swtch;            /* command line switch */
   const char *glob;             /* command line glob  */
+  const char *filename;         /* use this filename instead of making
+                                   up one using dump_base_name + suffix.  */
   int flags;                    /* user flags */
   int state;                    /* state of play */
   int num;                      /* dump file number */
Index: testsuite/g++.dg/other/dump-filename-1.C
===================================================================
--- testsuite/g++.dg/other/dump-filename-1.C	(revision 0)
+++ testsuite/g++.dg/other/dump-filename-1.C	(revision 0)
@@ -0,0 +1,11 @@ 
+// Test that the dump to a user-defined file works correctly.
+/* { dg-options "-O2 -fdump-tree-original=foobar.dump" } */
+
+void test (int *b, int *e, int stride)
+  {
+    for (int *p = b; p != e; p += stride)
+      *p = 1;
+  }
+
+/* { dg-final { scan-file foobar.dump ";; Function void test" } } */
+/* { dg-final { remove-build-file "foobar.dump" } } */