diff mbox series

[01/10] Convert dump and optgroup flags to enums

Message ID 1527626483-4723-2-git-send-email-dmalcolm@redhat.com
State New
Headers show
Series RFC: Prototype of compiler-assisted performance analysis | expand

Commit Message

David Malcolm May 29, 2018, 8:41 p.m. UTC
The dump machinery uses "int" in a few places, for two different
sets of bitmasks.

This patch makes things more self-documenting and type-safe by using
a new pair of enums: one for the dump_flags_t and another for the
optgroup_flags.

This requires adding some overloaded bit operations to the enums
in question, which, in this patch is done for each enum .  If the basic
idea is OK, should I add a template for this?  (with some kind of
magic to express that bitmasking operations are only supported on
certain opt-in enums).

gcc/c-family/ChangeLog:
	* c-pretty-print.c (c_pretty_printer::statement): Use TDF_NONE
	rather than 0.

gcc/ChangeLog:
	* cfg.c (debug): Use TDF_NONE rather than 0.
	* cfghooks.c (debug): Likewise.
	* dumpfile.c (DUMP_FILE_INFO): Likewise; also for OPTGROUP.
	(struct dump_option_value_info): Convert to...
	(struct kv_pair): ...this template type.
	(dump_options): Convert to kv_pair<dump_flags_t>; use TDF_NONE
	rather than 0.
	(optinfo_verbosity_options): Likewise.
	(optgroup_options): Convert to kv_pair<optgroup_flags_t>; use
	OPTGROUP_NONE.
	(gcc::dump_manager::dump_register): Use optgroup_flags_t rather
	than int for "optgroup_flags" param.
	(dump_generic_expr_loc): Use dump_flags_t rather than int for
	"dump_kind" param.
	(dump_finish): Use TDF_NONE rather than 0.
	(gcc::dump_manager::opt_info_enable_passes): Use optgroup_flags_t
	rather than int for "optgroup_flags" param.  Use TDF_NONE rather
	than 0.  Update for change to option_ptr.
	(opt_info_switch_p_1): Convert "optgroup_flags" param from int *
	to optgroup_flags_t *.  Use TDF_NONE and OPTGROUP_NONE rather than
	0.  Update for changes to optinfo_verbosity_options and
	optgroup_options.
	(opt_info_switch_p): Convert optgroup_flags from int to
	optgroup_flags_t.
	* dumpfile.h (TDF_ADDRESS, TDF_SLIM, TDF_RAW, TDF_DETAILS,
	TDF_STATS, TDF_BLOCKS, TDF_VOPS, TDF_LINENO, TDF_UID)
	TDF_STMTADDR, TDF_GRAPH, TDF_MEMSYMS, TDF_RHS_ONLY, TDF_ASMNAME,
	TDF_EH, TDF_NOUID, TDF_ALIAS, TDF_ENUMERATE_LOCALS, TDF_CSELIB,
	TDF_SCEV, TDF_GIMPLE, TDF_FOLDING, MSG_OPTIMIZED_LOCATIONS,
	MSG_MISSED_OPTIMIZATION, MSG_NOTE, MSG_ALL, TDF_COMPARE_DEBUG,
	TDF_NONE): Convert from macros to...
	(enum dump_flag): ...this new enum.
	(dump_flags_t): Update to use enum.
	(operator|, operator&, operator~, operator|=, operator&=):
	Implement for dump_flags_t.
	(OPTGROUP_NONE, OPTGROUP_IPA, OPTGROUP_LOOP, OPTGROUP_INLINE,
	OPTGROUP_OMP, OPTGROUP_VEC, OPTGROUP_OTHER, OPTGROUP_ALL):
	Convert from macros to...
	(enum optgroup_flag): ...this new enum.
	(optgroup_flags_t): New typedef.
	(operator|, operator|=): Implement for optgroup_flags_t.
	(struct dump_file_info): Convert field "alt_flags" to
	dump_flags_t.  Convert field "optgroup_flags" to
	optgroup_flags_t.
	(dump_register): Convert param "optgroup_flags" to
	optgroup_flags_t.
	(opt_info_enable_passes): Likewise.
	* early-remat.c (early_remat::dump_edge_list): Use TDF_NONE rather
	than 0.
	* gimple-pretty-print.c (debug): Likewise.
	* gimple-ssa-store-merging.c (bswap_replace): Likewise.
	(merged_store_group::apply_stores): Likewise.
	* gimple-ssa-strength-reduction.c (insert_initializers): Likewise.
	* gimple.c (verify_gimple_pp): Likewise.
	* passes.c (pass_manager::register_one_dump_file): Convert
	local "optgroup_flags" to optgroup_flags_t.
	* print-tree.c (print_node): Use TDF_NONE rather than 0.
	(debug): Likewise.
	(debug_body): Likewise.
	* tree-pass.h (struct pass_data): Convert field "optgroup_flags"
	to optgroup_flags_t.
	* tree-pretty-print.c (print_struct_decl): Use TDF_NONE rather
	than 0.
	* tree-ssa-math-opts.c (convert_mult_to_fma_1): Likewise.
	(convert_mult_to_fma): Likewise.
	* tree-ssa-reassoc.c (undistribute_ops_list): Likewise.
	* tree-ssa-sccvn.c (vn_eliminate): Likewise.
	* tree-vect-data-refs.c (dump_lower_bound): Convert param
	"dump_kind" to dump_flags_t.
---
 gcc/c-family/c-pretty-print.c       |   2 +-
 gcc/cfg.c                           |   4 +-
 gcc/cfghooks.c                      |   2 +-
 gcc/dumpfile.c                      |  56 ++++-----
 gcc/dumpfile.h                      | 227 +++++++++++++++++++++++++++---------
 gcc/early-remat.c                   |   2 +-
 gcc/gimple-pretty-print.c           |   2 +-
 gcc/gimple-ssa-store-merging.c      |   6 +-
 gcc/gimple-ssa-strength-reduction.c |   2 +-
 gcc/gimple.c                        |   2 +-
 gcc/passes.c                        |   2 +-
 gcc/print-tree.c                    |   7 +-
 gcc/tree-pass.h                     |   2 +-
 gcc/tree-pretty-print.c             |   2 +-
 gcc/tree-ssa-math-opts.c            |   4 +-
 gcc/tree-ssa-reassoc.c              |   2 +-
 gcc/tree-ssa-sccvn.c                |   2 +-
 gcc/tree-vect-data-refs.c           |   2 +-
 18 files changed, 222 insertions(+), 106 deletions(-)

Comments

Richard Biener June 1, 2018, 10 a.m. UTC | #1
On Tue, May 29, 2018 at 10:32 PM David Malcolm <dmalcolm@redhat.com> wrote:
>
> The dump machinery uses "int" in a few places, for two different
> sets of bitmasks.
>
> This patch makes things more self-documenting and type-safe by using
> a new pair of enums: one for the dump_flags_t and another for the
> optgroup_flags.

Great!  This should also make them accessible in gdb w/o using -g3.

> This requires adding some overloaded bit operations to the enums
> in question, which, in this patch is done for each enum .  If the basic
> idea is OK, should I add a template for this?  (with some kind of
> magic to express that bitmasking operations are only supported on
> certain opt-in enums).

Does C++ allow > int enums?  I think we want some way of knowing
when either enum exceeds int (dump_flags_t was already uint64_t
but you now make it effectively int again).  That is, general wrapping
for enum ops should chose an appropriate unsigned integer for
the operation.  So yes, a common implementation looks useful to me.

I think this patch is independently useful.

Thanks,
Richard.

>
> gcc/c-family/ChangeLog:
>         * c-pretty-print.c (c_pretty_printer::statement): Use TDF_NONE
>         rather than 0.
>
> gcc/ChangeLog:
>         * cfg.c (debug): Use TDF_NONE rather than 0.
>         * cfghooks.c (debug): Likewise.
>         * dumpfile.c (DUMP_FILE_INFO): Likewise; also for OPTGROUP.
>         (struct dump_option_value_info): Convert to...
>         (struct kv_pair): ...this template type.
>         (dump_options): Convert to kv_pair<dump_flags_t>; use TDF_NONE
>         rather than 0.
>         (optinfo_verbosity_options): Likewise.
>         (optgroup_options): Convert to kv_pair<optgroup_flags_t>; use
>         OPTGROUP_NONE.
>         (gcc::dump_manager::dump_register): Use optgroup_flags_t rather
>         than int for "optgroup_flags" param.
>         (dump_generic_expr_loc): Use dump_flags_t rather than int for
>         "dump_kind" param.
>         (dump_finish): Use TDF_NONE rather than 0.
>         (gcc::dump_manager::opt_info_enable_passes): Use optgroup_flags_t
>         rather than int for "optgroup_flags" param.  Use TDF_NONE rather
>         than 0.  Update for change to option_ptr.
>         (opt_info_switch_p_1): Convert "optgroup_flags" param from int *
>         to optgroup_flags_t *.  Use TDF_NONE and OPTGROUP_NONE rather than
>         0.  Update for changes to optinfo_verbosity_options and
>         optgroup_options.
>         (opt_info_switch_p): Convert optgroup_flags from int to
>         optgroup_flags_t.
>         * dumpfile.h (TDF_ADDRESS, TDF_SLIM, TDF_RAW, TDF_DETAILS,
>         TDF_STATS, TDF_BLOCKS, TDF_VOPS, TDF_LINENO, TDF_UID)
>         TDF_STMTADDR, TDF_GRAPH, TDF_MEMSYMS, TDF_RHS_ONLY, TDF_ASMNAME,
>         TDF_EH, TDF_NOUID, TDF_ALIAS, TDF_ENUMERATE_LOCALS, TDF_CSELIB,
>         TDF_SCEV, TDF_GIMPLE, TDF_FOLDING, MSG_OPTIMIZED_LOCATIONS,
>         MSG_MISSED_OPTIMIZATION, MSG_NOTE, MSG_ALL, TDF_COMPARE_DEBUG,
>         TDF_NONE): Convert from macros to...
>         (enum dump_flag): ...this new enum.
>         (dump_flags_t): Update to use enum.
>         (operator|, operator&, operator~, operator|=, operator&=):
>         Implement for dump_flags_t.
>         (OPTGROUP_NONE, OPTGROUP_IPA, OPTGROUP_LOOP, OPTGROUP_INLINE,
>         OPTGROUP_OMP, OPTGROUP_VEC, OPTGROUP_OTHER, OPTGROUP_ALL):
>         Convert from macros to...
>         (enum optgroup_flag): ...this new enum.
>         (optgroup_flags_t): New typedef.
>         (operator|, operator|=): Implement for optgroup_flags_t.
>         (struct dump_file_info): Convert field "alt_flags" to
>         dump_flags_t.  Convert field "optgroup_flags" to
>         optgroup_flags_t.
>         (dump_register): Convert param "optgroup_flags" to
>         optgroup_flags_t.
>         (opt_info_enable_passes): Likewise.
>         * early-remat.c (early_remat::dump_edge_list): Use TDF_NONE rather
>         than 0.
>         * gimple-pretty-print.c (debug): Likewise.
>         * gimple-ssa-store-merging.c (bswap_replace): Likewise.
>         (merged_store_group::apply_stores): Likewise.
>         * gimple-ssa-strength-reduction.c (insert_initializers): Likewise.
>         * gimple.c (verify_gimple_pp): Likewise.
>         * passes.c (pass_manager::register_one_dump_file): Convert
>         local "optgroup_flags" to optgroup_flags_t.
>         * print-tree.c (print_node): Use TDF_NONE rather than 0.
>         (debug): Likewise.
>         (debug_body): Likewise.
>         * tree-pass.h (struct pass_data): Convert field "optgroup_flags"
>         to optgroup_flags_t.
>         * tree-pretty-print.c (print_struct_decl): Use TDF_NONE rather
>         than 0.
>         * tree-ssa-math-opts.c (convert_mult_to_fma_1): Likewise.
>         (convert_mult_to_fma): Likewise.
>         * tree-ssa-reassoc.c (undistribute_ops_list): Likewise.
>         * tree-ssa-sccvn.c (vn_eliminate): Likewise.
>         * tree-vect-data-refs.c (dump_lower_bound): Convert param
>         "dump_kind" to dump_flags_t.
> ---
>  gcc/c-family/c-pretty-print.c       |   2 +-
>  gcc/cfg.c                           |   4 +-
>  gcc/cfghooks.c                      |   2 +-
>  gcc/dumpfile.c                      |  56 ++++-----
>  gcc/dumpfile.h                      | 227 +++++++++++++++++++++++++++---------
>  gcc/early-remat.c                   |   2 +-
>  gcc/gimple-pretty-print.c           |   2 +-
>  gcc/gimple-ssa-store-merging.c      |   6 +-
>  gcc/gimple-ssa-strength-reduction.c |   2 +-
>  gcc/gimple.c                        |   2 +-
>  gcc/passes.c                        |   2 +-
>  gcc/print-tree.c                    |   7 +-
>  gcc/tree-pass.h                     |   2 +-
>  gcc/tree-pretty-print.c             |   2 +-
>  gcc/tree-ssa-math-opts.c            |   4 +-
>  gcc/tree-ssa-reassoc.c              |   2 +-
>  gcc/tree-ssa-sccvn.c                |   2 +-
>  gcc/tree-vect-data-refs.c           |   2 +-
>  18 files changed, 222 insertions(+), 106 deletions(-)
>
> diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
> index dc76c99..efb41c5 100644
> --- a/gcc/c-family/c-pretty-print.c
> +++ b/gcc/c-family/c-pretty-print.c
> @@ -2341,7 +2341,7 @@ c_pretty_printer::statement (tree stmt)
>    if (pp_needs_newline (this))
>      pp_newline_and_indent (this, 0);
>
> -  dump_generic_node (this, stmt, pp_indentation (this), 0, true);
> +  dump_generic_node (this, stmt, pp_indentation (this), TDF_NONE, true);
>  }
>
>
> diff --git a/gcc/cfg.c b/gcc/cfg.c
> index 11026e7..6d55516 100644
> --- a/gcc/cfg.c
> +++ b/gcc/cfg.c
> @@ -545,8 +545,8 @@ DEBUG_FUNCTION void
>  debug (edge_def &ref)
>  {
>    /* FIXME (crowl): Is this desireable?  */
> -  dump_edge_info (stderr, &ref, 0, false);
> -  dump_edge_info (stderr, &ref, 0, true);
> +  dump_edge_info (stderr, &ref, TDF_NONE, false);
> +  dump_edge_info (stderr, &ref, TDF_NONE, true);
>  }
>
>  DEBUG_FUNCTION void
> diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
> index 87d864c..ea106e0 100644
> --- a/gcc/cfghooks.c
> +++ b/gcc/cfghooks.c
> @@ -288,7 +288,7 @@ dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
>  DEBUG_FUNCTION void
>  debug (basic_block_def &ref)
>  {
> -  dump_bb (stderr, &ref, 0, 0);
> +  dump_bb (stderr, &ref, 0, TDF_NONE);
>  }
>
>  DEBUG_FUNCTION void
> diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
> index 0acc7a9..6af1445 100644
> --- a/gcc/dumpfile.c
> +++ b/gcc/dumpfile.c
> @@ -50,8 +50,8 @@ const char *dump_file_name;
>  dump_flags_t dump_flags;
>
>  #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
> -  {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, 0, 0, 0, 0, 0, num, \
> -   false, false}
> +  {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
> +   OPTGROUP_NONE, 0, 0, num, false, false}
>
>  /* Table of tree dump switches. This must be consistent with the
>     TREE_DUMP_INDEX enumeration in dumpfile.h.  */
> @@ -74,15 +74,16 @@ static struct dump_file_info dump_files[TDI_end] =
>  };
>
>  /* Define a name->number mapping for a dump flag value.  */
> -struct dump_option_value_info
> +template <typename ValueType>
> +struct kv_pair
>  {
>    const char *const name;      /* the name of the value */
> -  const dump_flags_t value;    /* the value of the name */
> +  const ValueType value;       /* the value of the name */
>  };
>
>  /* Table of dump options. This must be consistent with the TDF_* flags
>     in dumpfile.h and opt_info_options below. */
> -static const struct dump_option_value_info dump_options[] =
> +static const kv_pair<dump_flags_t> dump_options[] =
>  {
>    {"address", TDF_ADDRESS},
>    {"asmname", TDF_ASMNAME},
> @@ -114,23 +115,23 @@ static const struct dump_option_value_info dump_options[] =
>    {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
>                         | TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
>                         | TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
> -  {NULL, 0}
> +  {NULL, TDF_NONE}
>  };
>
>  /* A subset of the dump_options table which is used for -fopt-info
>     types. This must be consistent with the MSG_* flags in dumpfile.h.
>   */
> -static const struct dump_option_value_info optinfo_verbosity_options[] =
> +static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
>  {
>    {"optimized", MSG_OPTIMIZED_LOCATIONS},
>    {"missed", MSG_MISSED_OPTIMIZATION},
>    {"note", MSG_NOTE},
>    {"all", MSG_ALL},
> -  {NULL, 0}
> +  {NULL, TDF_NONE}
>  };
>
>  /* Flags used for -fopt-info groups.  */
> -static const struct dump_option_value_info optgroup_options[] =
> +static const kv_pair<optgroup_flags_t> optgroup_options[] =
>  {
>    {"ipa", OPTGROUP_IPA},
>    {"loop", OPTGROUP_LOOP},
> @@ -138,7 +139,7 @@ static const struct dump_option_value_info optgroup_options[] =
>    {"omp", OPTGROUP_OMP},
>    {"vec", OPTGROUP_VEC},
>    {"optall", OPTGROUP_ALL},
> -  {NULL, 0}
> +  {NULL, OPTGROUP_NONE}
>  };
>
>  gcc::dump_manager::dump_manager ():
> @@ -173,7 +174,8 @@ gcc::dump_manager::~dump_manager ()
>  unsigned int
>  gcc::dump_manager::
>  dump_register (const char *suffix, const char *swtch, const char *glob,
> -              dump_kind dkind, int optgroup_flags, bool take_ownership)
> +              dump_kind dkind, optgroup_flags_t optgroup_flags,
> +              bool take_ownership)
>  {
>    int num = m_next_dump++;
>
> @@ -410,7 +412,7 @@ dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
>     location.  */
>
>  void
> -dump_generic_expr_loc (int dump_kind, source_location loc,
> +dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
>                        dump_flags_t extra_dump_flags, tree t)
>  {
>    if (dump_file && (dump_kind & pflags))
> @@ -575,9 +577,9 @@ dump_finish (int phase)
>    dfi->pstream = NULL;
>    dump_file = NULL;
>    alt_dump_file = NULL;
> -  dump_flags = TDI_none;
> -  alt_flags = 0;
> -  pflags = 0;
> +  dump_flags = TDF_NONE;
> +  alt_flags = TDF_NONE;
> +  pflags = TDF_NONE;
>  }
>
>  /* Begin a tree dump for PHASE. Stores any user supplied flag in
> @@ -750,7 +752,7 @@ dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
>
>  int
>  gcc::dump_manager::
> -opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
> +opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
>                         const char *filename)
>  {
>    int n = 0;
> @@ -817,11 +819,11 @@ dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
>      return 0;
>
>    ptr = option_value;
> -  flags = 0;
> +  flags = TDF_NONE;
>
>    while (*ptr)
>      {
> -      const struct dump_option_value_info *option_ptr;
> +      const struct kv_pair<dump_flags_t> *option_ptr;
>        const char *end_ptr;
>        const char *eq_ptr;
>        unsigned length;
> @@ -903,8 +905,8 @@ dump_switch_p (const char *arg)
>     and filename.  Return non-zero if it is a recognized switch.  */
>
>  static int
> -opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
> -                     char **filename)
> +opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
> +                    optgroup_flags_t *optgroup_flags, char **filename)
>  {
>    const char *option_value;
>    const char *ptr;
> @@ -913,15 +915,14 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
>    ptr = option_value;
>
>    *filename = NULL;
> -  *flags = 0;
> -  *optgroup_flags = 0;
> +  *flags = TDF_NONE;
> +  *optgroup_flags = OPTGROUP_NONE;
>
>    if (!ptr)
>      return 1;       /* Handle '-fopt-info' without any additional options.  */
>
>    while (*ptr)
>      {
> -      const struct dump_option_value_info *option_ptr;
>        const char *end_ptr;
>        const char *eq_ptr;
>        unsigned length;
> @@ -938,8 +939,8 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
>         end_ptr = ptr + strlen (ptr);
>        length = end_ptr - ptr;
>
> -      for (option_ptr = optinfo_verbosity_options; option_ptr->name;
> -           option_ptr++)
> +      for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
> +          option_ptr->name; option_ptr++)
>         if (strlen (option_ptr->name) == length
>             && !memcmp (option_ptr->name, ptr, length))
>            {
> @@ -947,7 +948,8 @@ opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
>             goto found;
>            }
>
> -      for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
> +      for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
> +          option_ptr->name; option_ptr++)
>         if (strlen (option_ptr->name) == length
>             && !memcmp (option_ptr->name, ptr, length))
>            {
> @@ -982,7 +984,7 @@ int
>  opt_info_switch_p (const char *arg)
>  {
>    dump_flags_t flags;
> -  int optgroup_flags;
> +  optgroup_flags_t optgroup_flags;
>    char *filename;
>    static char *file_seen = NULL;
>    gcc::dump_manager *dumps = g->get_dumps ();
> diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
> index 21803a6..b5582f7 100644
> --- a/gcc/dumpfile.h
> +++ b/gcc/dumpfile.h
> @@ -58,65 +58,177 @@ enum dump_kind
>     the DUMP_OPTIONS array in dumpfile.c. The TDF_* flags coexist with
>     MSG_* flags (for -fopt-info) and the bit values must be chosen to
>     allow that.  */
> -#define TDF_ADDRESS    (1 << 0)        /* dump node addresses */
> -#define TDF_SLIM       (1 << 1)        /* don't go wild following links */
> -#define TDF_RAW                (1 << 2)        /* don't unparse the function */
> -#define TDF_DETAILS    (1 << 3)        /* show more detailed info about
> -                                          each pass */
> -#define TDF_STATS      (1 << 4)        /* dump various statistics about
> -                                          each pass */
> -#define TDF_BLOCKS     (1 << 5)        /* display basic block boundaries */
> -#define TDF_VOPS       (1 << 6)        /* display virtual operands */
> -#define TDF_LINENO     (1 << 7)        /* display statement line numbers */
> -#define TDF_UID                (1 << 8)        /* display decl UIDs */
> -
> -#define TDF_STMTADDR   (1 << 9)       /* Address of stmt.  */
> -
> -#define TDF_GRAPH      (1 << 10)       /* a graph dump is being emitted */
> -#define TDF_MEMSYMS    (1 << 11)       /* display memory symbols in expr.
> -                                          Implies TDF_VOPS.  */
> -
> -#define TDF_RHS_ONLY   (1 << 12)       /* a flag to only print the RHS of
> -                                          a gimple stmt.  */
> -#define TDF_ASMNAME    (1 << 13)       /* display asm names of decls  */
> -#define TDF_EH         (1 << 14)       /* display EH region number
> -                                          holding this gimple statement.  */
> -#define TDF_NOUID      (1 << 15)       /* omit UIDs from dumps.  */
> -#define TDF_ALIAS      (1 << 16)       /* display alias information  */
> -#define TDF_ENUMERATE_LOCALS (1 << 17) /* Enumerate locals by uid.  */
> -#define TDF_CSELIB     (1 << 18)       /* Dump cselib details.  */
> -#define TDF_SCEV       (1 << 19)       /* Dump SCEV details.  */
> -#define TDF_GIMPLE     (1 << 20)       /* Dump in GIMPLE FE syntax  */
> -#define TDF_FOLDING    (1 << 21)       /* Dump folding details.  */
> -#define MSG_OPTIMIZED_LOCATIONS         (1 << 22)  /* -fopt-info optimized sources */
> -#define MSG_MISSED_OPTIMIZATION         (1 << 23)  /* missed opportunities */
> -#define MSG_NOTE                (1 << 24)  /* general optimization info */
> -#define MSG_ALL                (MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \
> -                        | MSG_NOTE)
> -#define TDF_COMPARE_DEBUG (1 << 25)    /* Dumping for -fcompare-debug.  */
> -
> -
> -/* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK.  */
> -
> -#define TDF_NONE 0
> +enum dump_flag
> +{
> +  /* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK.  */
> +  TDF_NONE  = 0,
> +
> +  /* Dump node addresses.  */
> +  TDF_ADDRESS = (1 << 0),
> +
> +  /* Don't go wild following links.  */
> +  TDF_SLIM = (1 << 1),
> +
> +  /* Don't unparse the function.  */
> +  TDF_RAW = (1 << 2),
> +
> +  /* Show more detailed info about each pass.  */
> +  TDF_DETAILS = (1 << 3),
> +
> +  /* Dump various statistics about each pass.  */
> +  TDF_STATS = (1 << 4),
> +
> +  /* Display basic block boundaries.  */
> +  TDF_BLOCKS = (1 << 5),
> +
> +  /* Display virtual operands.  */
> +  TDF_VOPS = (1 << 6),
> +
> +  /* Display statement line numbers.  */
> +  TDF_LINENO = (1 << 7),
> +
> +  /* Display decl UIDs.  */
> +  TDF_UID  = (1 << 8),
> +
> +  /* Address of stmt.  */
> +  TDF_STMTADDR = (1 << 9),
> +
> +  /* A graph dump is being emitted.  */
> +  TDF_GRAPH = (1 << 10),
> +
> +  /* Display memory symbols in expr.
> +     Implies TDF_VOPS.  */
> +  TDF_MEMSYMS = (1 << 11),
> +
> +  /* A flag to only print the RHS of a gimple stmt.  */
> +  TDF_RHS_ONLY = (1 << 12),
> +
> +  /* Display asm names of decls.  */
> +  TDF_ASMNAME = (1 << 13),
> +
> +  /* Display EH region number holding this gimple statement.  */
> +  TDF_EH  = (1 << 14),
> +
> +  /* Omit UIDs from dumps.  */
> +  TDF_NOUID = (1 << 15),
> +
> +  /* Display alias information.  */
> +  TDF_ALIAS = (1 << 16),
> +
> +  /* Enumerate locals by uid.  */
> +  TDF_ENUMERATE_LOCALS = (1 << 17),
> +
> +  /* Dump cselib details.  */
> +  TDF_CSELIB = (1 << 18),
> +
> +  /* Dump SCEV details.  */
> +  TDF_SCEV = (1 << 19),
> +
> +  /* Dump in GIMPLE FE syntax  */
> +  TDF_GIMPLE = (1 << 20),
> +
> +  /* Dump folding details.  */
> +  TDF_FOLDING = (1 << 21),
> +
> +  /* -fopt-info optimized sources.  */
> +  MSG_OPTIMIZED_LOCATIONS = (1 << 22),
> +
> +  /* Missed opportunities.  */
> +  MSG_MISSED_OPTIMIZATION = (1 << 23),
> +
> +  /* General optimization info.  */
> +  MSG_NOTE = (1 << 24),
> +
> +  MSG_ALL = (MSG_OPTIMIZED_LOCATIONS
> +            | MSG_MISSED_OPTIMIZATION
> +            | MSG_NOTE),
> +
> +  /* Dumping for -fcompare-debug.  */
> +  TDF_COMPARE_DEBUG = (1 << 25),
> +};
> +
> +/* Dump flags type.  */
> +
> +typedef enum dump_flag dump_flags_t;
> +
> +// FIXME: template
> +// FIXME: underlying storage type?
> +static inline dump_flags_t
> +operator| (dump_flags_t lhs, dump_flags_t rhs)
> +{
> +  return (dump_flags_t)((int)lhs | (int)rhs);
> +}
> +
> +static inline dump_flags_t
> +operator& (dump_flags_t lhs, dump_flags_t rhs)
> +{
> +  return (dump_flags_t)((int)lhs & (int)rhs);
> +}
> +
> +static inline dump_flags_t
> +operator~ (dump_flags_t flags)
> +{
> +  return (dump_flags_t)~((int)flags);
> +}
> +
> +static inline dump_flags_t &
> +operator|= (dump_flags_t &lhs, dump_flags_t rhs)
> +{
> +  lhs = (dump_flags_t)((int)lhs | (int)rhs);
> +  return lhs;
> +}
> +
> +static inline dump_flags_t &
> +operator&= (dump_flags_t &lhs, dump_flags_t rhs)
> +{
> +  lhs = (dump_flags_t)((int)lhs & (int)rhs);
> +  return lhs;
> +}
>
>  /* Flags to control high-level -fopt-info dumps.  Usually these flags
>     define a group of passes.  An optimization pass can be part of
>     multiple groups.  */
> -#define OPTGROUP_NONE       (0)
> -#define OPTGROUP_IPA        (1 << 1)   /* IPA optimization passes */
> -#define OPTGROUP_LOOP       (1 << 2)   /* Loop optimization passes */
> -#define OPTGROUP_INLINE             (1 << 3)   /* Inlining passes */
> -#define OPTGROUP_OMP        (1 << 4)   /* OMP (Offloading and Multi
> -                                          Processing) transformations */
> -#define OPTGROUP_VEC        (1 << 5)   /* Vectorization passes */
> -#define OPTGROUP_OTHER      (1 << 6)   /* All other passes */
> -#define OPTGROUP_ALL        (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE \
> -                             | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
>
> -/* Dump flags type.  */
> +enum optgroup_flag
> +{
> +  OPTGROUP_NONE = 0,
> +
> +  /* IPA optimization passes */
> +  OPTGROUP_IPA  = (1 << 1),
> +
> +  /* Loop optimization passes */
> +  OPTGROUP_LOOP = (1 << 2),
> +
> +  /* Inlining passes */
> +  OPTGROUP_INLINE = (1 << 3),
>
> -typedef uint64_t dump_flags_t;
> +  /* OMP (Offloading and Multi Processing) transformations */
> +  OPTGROUP_OMP = (1 << 4),
> +
> +  /* Vectorization passes */
> +  OPTGROUP_VEC = (1 << 5),
> +
> +  /* All other passes */
> +  OPTGROUP_OTHER = (1 << 6),
> +
> +  OPTGROUP_ALL = (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE
> +                 | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
> +};
> +
> +typedef enum optgroup_flag optgroup_flags_t;
> +
> +static inline optgroup_flags_t
> +operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
> +{
> +  return (optgroup_flags_t)((int)lhs | (int)rhs);
> +}
> +
> +static inline optgroup_flags_t &
> +operator|= (optgroup_flags_t &lhs, optgroup_flags_t rhs)
> +{
> +  lhs = (optgroup_flags_t)((int)lhs | (int)rhs);
> +  return lhs;
> +}
>
>  /* Define a tree dump switch.  */
>  struct dump_file_info
> @@ -140,9 +252,9 @@ struct dump_file_info
>    /* Dump flags.  */
>    dump_flags_t pflags;
>    /* A pass flags for -fopt-info.  */
> -  int alt_flags;
> +  dump_flags_t alt_flags;
>    /* Flags for -fopt-info given by a user.  */
> -  int optgroup_flags;
> +  optgroup_flags_t optgroup_flags;
>    /* State of pass-specific stream.  */
>    int pstate;
>    /* State of the -fopt-info stream.  */
> @@ -214,7 +326,8 @@ public:
>       SUFFIX, SWTCH, and GLOB. */
>    unsigned int
>    dump_register (const char *suffix, const char *swtch, const char *glob,
> -                dump_kind dkind, int optgroup_flags, bool take_ownership);
> +                dump_kind dkind, optgroup_flags_t optgroup_flags,
> +                bool take_ownership);
>
>    /* Allow languages and middle-end to register their dumps before the
>       optimization passes.  */
> @@ -275,7 +388,7 @@ private:
>    dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename);
>
>    int
> -  opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
> +  opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
>                           const char *filename);
>
>  private:
> diff --git a/gcc/early-remat.c b/gcc/early-remat.c
> index 28eb9b4..776b2d0 100644
> --- a/gcc/early-remat.c
> +++ b/gcc/early-remat.c
> @@ -657,7 +657,7 @@ early_remat::dump_edge_list (basic_block bb, bool do_succ)
>    edge e;
>    edge_iterator ei;
>    FOR_EACH_EDGE (e, ei, do_succ ? bb->succs : bb->preds)
> -    dump_edge_info (dump_file, e, 0, do_succ);
> +    dump_edge_info (dump_file, e, TDF_NONE, do_succ);
>  }
>
>  /* Print information about basic block BB to the dump file.  */
> diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
> index 6695526..39edaa1 100644
> --- a/gcc/gimple-pretty-print.c
> +++ b/gcc/gimple-pretty-print.c
> @@ -153,7 +153,7 @@ print_gimple_stmt (FILE *file, gimple *g, int spc, dump_flags_t flags)
>  DEBUG_FUNCTION void
>  debug (gimple &ref)
>  {
> -  print_gimple_stmt (stderr, &ref, 0, 0);
> +  print_gimple_stmt (stderr, &ref, 0, TDF_NONE);
>  }
>
>  DEBUG_FUNCTION void
> diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
> index 6f6538b..7362128 100644
> --- a/gcc/gimple-ssa-store-merging.c
> +++ b/gcc/gimple-ssa-store-merging.c
> @@ -1075,7 +1075,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
>             print_gimple_stmt (dump_file, cur_stmt, 0);
>           else
>             {
> -             print_generic_expr (dump_file, tgt, 0);
> +             print_generic_expr (dump_file, tgt, TDF_NONE);
>               fprintf (dump_file, "\n");
>             }
>         }
> @@ -1145,7 +1145,7 @@ bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
>         print_gimple_stmt (dump_file, cur_stmt, 0);
>        else
>         {
> -         print_generic_expr (dump_file, tgt, 0);
> +         print_generic_expr (dump_file, tgt, TDF_NONE);
>           fprintf (dump_file, "\n");
>         }
>      }
> @@ -1956,7 +1956,7 @@ merged_store_group::apply_stores ()
>           if (ret)
>             {
>               fprintf (dump_file, "After writing ");
> -             print_generic_expr (dump_file, cst, 0);
> +             print_generic_expr (dump_file, cst, TDF_NONE);
>               fprintf (dump_file, " of size " HOST_WIDE_INT_PRINT_DEC
>                        " at position %d the merged region contains:\n",
>                        info->bitsize, pos_in_buffer);
> diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
> index 1c00f09..14fc420 100644
> --- a/gcc/gimple-ssa-strength-reduction.c
> +++ b/gcc/gimple-ssa-strength-reduction.c
> @@ -3353,7 +3353,7 @@ insert_initializers (slsr_cand_t c)
>               fputs ("Using existing initializer: ", dump_file);
>               print_gimple_stmt (dump_file,
>                                  SSA_NAME_DEF_STMT (incr_vec[i].initializer),
> -                                0, 0);
> +                                0, TDF_NONE);
>             }
>           continue;
>         }
> diff --git a/gcc/gimple.c b/gcc/gimple.c
> index 9dc4911..c18526a 100644
> --- a/gcc/gimple.c
> +++ b/gcc/gimple.c
> @@ -3148,7 +3148,7 @@ static void
>  verify_gimple_pp (const char *expected, gimple *stmt)
>  {
>    pretty_printer pp;
> -  pp_gimple_stmt_1 (&pp, stmt, 0 /* spc */, 0 /* flags */);
> +  pp_gimple_stmt_1 (&pp, stmt, 0 /* spc */, TDF_NONE /* flags */);
>    ASSERT_STREQ (expected, pp_formatted_text (&pp));
>  }
>
> diff --git a/gcc/passes.c b/gcc/passes.c
> index ad0a912..62fd413 100644
> --- a/gcc/passes.c
> +++ b/gcc/passes.c
> @@ -784,7 +784,7 @@ pass_manager::register_one_dump_file (opt_pass *pass)
>    char num[11];
>    dump_kind dkind;
>    int id;
> -  int optgroup_flags = OPTGROUP_NONE;
> +  optgroup_flags_t optgroup_flags = OPTGROUP_NONE;
>    gcc::dump_manager *dumps = m_ctxt->get_dumps ();
>
>    /* See below in next_pass_1.  */
> diff --git a/gcc/print-tree.c b/gcc/print-tree.c
> index caf5f26..5c736c5 100644
> --- a/gcc/print-tree.c
> +++ b/gcc/print-tree.c
> @@ -894,7 +894,8 @@ print_node (FILE *file, const char *prefix, tree node, int indent,
>           {
>             pretty_printer buffer;
>             buffer.buffer->stream = file;
> -           pp_gimple_stmt_1 (&buffer, SSA_NAME_DEF_STMT (node), indent + 4, 0);
> +           pp_gimple_stmt_1 (&buffer, SSA_NAME_DEF_STMT (node), indent + 4,
> +                             TDF_NONE);
>             pp_flush (&buffer);
>           }
>
> @@ -1039,7 +1040,7 @@ dump_tree_via_hooks (const tree_node *ptr, dump_flags_t options)
>  DEBUG_FUNCTION void
>  debug (const tree_node &ref)
>  {
> -  dump_tree_via_hooks (&ref, 0);
> +  dump_tree_via_hooks (&ref, TDF_NONE);
>  }
>
>  DEBUG_FUNCTION void
> @@ -1070,7 +1071,7 @@ DEBUG_FUNCTION void
>  debug_body (const tree_node &ref)
>  {
>    if (TREE_CODE (&ref) == FUNCTION_DECL)
> -    dump_function_to_file (const_cast <tree_node*> (&ref), stderr, 0);
> +    dump_function_to_file (const_cast <tree_node*> (&ref), stderr, TDF_NONE);
>    else
>      debug (ref);
>  }
> diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
> index 93a6a99..c757591 100644
> --- a/gcc/tree-pass.h
> +++ b/gcc/tree-pass.h
> @@ -47,7 +47,7 @@ struct pass_data
>    const char *name;
>
>    /* The -fopt-info optimization group flags as defined in dumpfile.h. */
> -  unsigned int optinfo_flags;
> +  optgroup_flags_t optinfo_flags;
>
>    /* The timevar id associated with this pass.  */
>    /* ??? Ideally would be dynamically assigned.  */
> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> index 276ad00..8963ae0 100644
> --- a/gcc/tree-pretty-print.c
> +++ b/gcc/tree-pretty-print.c
> @@ -3404,7 +3404,7 @@ print_struct_decl (pretty_printer *pp, const_tree node, int spc,
>                 || TREE_CODE (node) == QUAL_UNION_TYPE))
>         pp_string (pp, "union ");
>
> -      dump_generic_node (pp, TYPE_NAME (node), spc, 0, false);
> +      dump_generic_node (pp, TYPE_NAME (node), spc, TDF_NONE, false);
>      }
>
>    /* Print the contents of the structure.  */
> diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
> index 16d9399..b3f8cb6 100644
> --- a/gcc/tree-ssa-math-opts.c
> +++ b/gcc/tree-ssa-math-opts.c
> @@ -2710,7 +2710,7 @@ convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
>        if (dump_file && (dump_flags & TDF_DETAILS))
>         {
>           fprintf (dump_file, "Generated FMA ");
> -         print_gimple_stmt (dump_file, fma_stmt, 0, 0);
> +         print_gimple_stmt (dump_file, fma_stmt, 0, TDF_NONE);
>           fprintf (dump_file, "\n");
>         }
>
> @@ -3046,7 +3046,7 @@ convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
>        if (dump_file && (dump_flags & TDF_DETAILS))
>         {
>           fprintf (dump_file, "Deferred generating FMA for multiplication ");
> -         print_gimple_stmt (dump_file, mul_stmt, 0, 0);
> +         print_gimple_stmt (dump_file, mul_stmt, 0, TDF_NONE);
>           fprintf (dump_file, "\n");
>         }
>
> diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
> index 0e59bb5..dde9701 100644
> --- a/gcc/tree-ssa-reassoc.c
> +++ b/gcc/tree-ssa-reassoc.c
> @@ -1606,7 +1606,7 @@ undistribute_ops_list (enum tree_code opcode,
>      {
>        fprintf (dump_file, "searching for un-distribute opportunities ");
>        print_generic_expr (dump_file,
> -       (*ops)[bitmap_first_set_bit (candidates)]->op, 0);
> +       (*ops)[bitmap_first_set_bit (candidates)]->op, TDF_NONE);
>        fprintf (dump_file, " %d\n", nr_candidates);
>      }
>
> diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
> index 1463c1d..d8ab1f0 100644
> --- a/gcc/tree-ssa-sccvn.c
> +++ b/gcc/tree-ssa-sccvn.c
> @@ -5921,7 +5921,7 @@ vn_eliminate (bitmap inserted_exprs)
>        if (dump_file && (dump_flags & TDF_DETAILS))
>         {
>           fprintf (dump_file, "Removing dead stmt ");
> -         print_gimple_stmt (dump_file, stmt, 0, 0);
> +         print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
>         }
>
>        gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
> diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
> index 9aabcc1..ebc56c0 100644
> --- a/gcc/tree-vect-data-refs.c
> +++ b/gcc/tree-vect-data-refs.c
> @@ -3229,7 +3229,7 @@ dependence_distance_ge_vf (data_dependence_relation *ddr,
>  /* Dump LOWER_BOUND using flags DUMP_KIND.  Dumps are known to be enabled.  */
>
>  static void
> -dump_lower_bound (int dump_kind, const vec_lower_bound &lower_bound)
> +dump_lower_bound (dump_flags_t dump_kind, const vec_lower_bound &lower_bound)
>  {
>    dump_printf (dump_kind, "%s (", lower_bound.unsigned_p ? "unsigned" : "abs");
>    dump_generic_expr (dump_kind, TDF_SLIM, lower_bound.expr);
> --
> 1.8.5.3
>
Trevor Saunders June 5, 2018, 8:40 a.m. UTC | #2
On Fri, Jun 01, 2018 at 12:00:09PM +0200, Richard Biener wrote:
> On Tue, May 29, 2018 at 10:32 PM David Malcolm <dmalcolm@redhat.com> wrote:
> >
> > The dump machinery uses "int" in a few places, for two different
> > sets of bitmasks.
> >
> > This patch makes things more self-documenting and type-safe by using
> > a new pair of enums: one for the dump_flags_t and another for the
> > optgroup_flags.
> 
> Great!  This should also make them accessible in gdb w/o using -g3.
> 
> > This requires adding some overloaded bit operations to the enums
> > in question, which, in this patch is done for each enum .  If the basic
> > idea is OK, should I add a template for this?  (with some kind of
> > magic to express that bitmasking operations are only supported on
> > certain opt-in enums).

You may want to look at gdb's enum-flags.h which I think already
implements what your doing here.

> 
> Does C++ allow > int enums?  I think we want some way of knowing
> when either enum exceeds int (dump_flags_t was already uint64_t
> but you now make it effectively int again).  That is, general wrapping
> for enum ops should chose an appropriate unsigned integer for
> the operation.  So yes, a common implementation looks useful to me.

I don't remember very well, but istr C++ will actually use a 8 byte
integer if the enum contains constants larger than 2^32.  Testing
sizeof enum x { A =0x400000000 }; gives the desired thing for me, but it
would still be good to check the standard.

Trev


> 
> I think this patch is independently useful.
> 
> Thanks,
> Richard.
> 
> >
David Malcolm June 5, 2018, 2:49 p.m. UTC | #3
On Tue, 2018-06-05 at 04:40 -0400, Trevor Saunders wrote:
> On Fri, Jun 01, 2018 at 12:00:09PM +0200, Richard Biener wrote:
> > On Tue, May 29, 2018 at 10:32 PM David Malcolm <dmalcolm@redhat.com
> > > wrote:
> > > 
> > > The dump machinery uses "int" in a few places, for two different
> > > sets of bitmasks.
> > > 
> > > This patch makes things more self-documenting and type-safe by
> > > using
> > > a new pair of enums: one for the dump_flags_t and another for the
> > > optgroup_flags.
> > 
> > Great!  This should also make them accessible in gdb w/o using -g3.
> > 
> > > This requires adding some overloaded bit operations to the enums
> > > in question, which, in this patch is done for each enum .  If the
> > > basic
> > > idea is OK, should I add a template for this?  (with some kind of
> > > magic to express that bitmasking operations are only supported on
> > > certain opt-in enums).
> 
> You may want to look at gdb's enum-flags.h which I think already
> implements what your doing here.

Aha!  Thanks!

Browsing the git web UI, that gdb header was introduced by Pedro Alves
in:
  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=8d297bbf604c8318ffc72d5a7b3db654409c5ed9
and the current state is here:
  https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/common/enum-flags.h;hb=HEAD

I'll try this out with GCC; hopefully it works with C++98.

Presumably it would be good to share this header between GCC and GDB;
CCing Pedro; Pedro: hi!  Does this sound sane?
(for reference, the GCC patch we're discussing here is:
  https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01685.html )

Presumably gcc's copy should live in the gcc's top-level "include"
subdirectory?

Would we need to change that "This file is part of GDB." comment, and
the include guards' "COMMON_ENUM_FLAGS_H"?

> > Does C++ allow > int enums?  I think we want some way of knowing
> > when either enum exceeds int (dump_flags_t was already uint64_t
> > but you now make it effectively int again).  That is, general
> > wrapping
> > for enum ops should chose an appropriate unsigned integer for
> > the operation.  So yes, a common implementation looks useful to me.
> 
> I don't remember very well, but istr C++ will actually use a 8 byte
> integer if the enum contains constants larger than 2^32.  Testing
> sizeof enum x { A =0x400000000 }; gives the desired thing for me, but
> it
> would still be good to check the standard.

FWIW C++11 onwards has a std::underlying_type for enums:
  http://en.cppreference.com/w/cpp/types/underlying_type
(GCC is on C++98).  The gdb header seems to emulate this via the use of
sizeof(T) to select an appropriate integer_for_size specialization and
thus the appropriate struct enum_underlying_type specialization (if I'm
reading it right).

> Trev
> 
> 
> > 
> > I think this patch is independently useful.

Richard: by this, did you mean that the patch is OK for trunk as-is?
(keeping a more general bitflags enum patch as followup work)  Note to
self: still needs bootstrap-and-testing.

> > Thanks,
> > Richard.

Thanks
Dave
Pedro Alves June 5, 2018, 4:13 p.m. UTC | #4
On 06/05/2018 03:49 PM, David Malcolm wrote:
> On Tue, 2018-06-05 at 04:40 -0400, Trevor Saunders wrote:

>> You may want to look at gdb's enum-flags.h which I think already
>> implements what your doing here.
> 
> Aha!  Thanks!
> 
> Browsing the git web UI, that gdb header was introduced by Pedro Alves
> in:
>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=8d297bbf604c8318ffc72d5a7b3db654409c5ed9
> and the current state is here:
>   https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/common/enum-flags.h;hb=HEAD
> 
> I'll try this out with GCC; hopefully it works with C++98.

It should -- it was written/added while GDB still required C++98.

Note I have a WIP series here:

 https://github.com/palves/gdb/commits/palves/cxx11-enum-flags

that fixes a few things, and adds a bunch of unit tests.  In
the process, it uses C++11 constructs (hence the branch's name),
but I think that can be reverted to still work with C++98.

I had seen some noises recently about GCC maybe considering
requiring C++11.  Is that reasonable to expect in this cycle?
(GDB requires GCC 4.8 or later, FWIW.)

Getting that branch into master had fallen lower on my TODO,
but if there's interest, I can try to finish it off soon, so we
can share a better baseline.  (I posted it once, but found
some issues which I fixed since but never managed to repost.)

> 
> Presumably it would be good to share this header between GCC and GDB;
> CCing Pedro; Pedro: hi!  Does this sound sane?
> (for reference, the GCC patch we're discussing here is:
>   https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01685.html )

Sure!

Thanks,
Pedro Alves
Richard Biener June 5, 2018, 4:16 p.m. UTC | #5
On June 5, 2018 4:49:21 PM GMT+02:00, David Malcolm <dmalcolm@redhat.com> wrote:
>On Tue, 2018-06-05 at 04:40 -0400, Trevor Saunders wrote:
>> On Fri, Jun 01, 2018 at 12:00:09PM +0200, Richard Biener wrote:
>> > On Tue, May 29, 2018 at 10:32 PM David Malcolm <dmalcolm@redhat.com
>> > > wrote:
>> > > 
>> > > The dump machinery uses "int" in a few places, for two different
>> > > sets of bitmasks.
>> > > 
>> > > This patch makes things more self-documenting and type-safe by
>> > > using
>> > > a new pair of enums: one for the dump_flags_t and another for the
>> > > optgroup_flags.
>> > 
>> > Great!  This should also make them accessible in gdb w/o using -g3.
>> > 
>> > > This requires adding some overloaded bit operations to the enums
>> > > in question, which, in this patch is done for each enum .  If the
>> > > basic
>> > > idea is OK, should I add a template for this?  (with some kind of
>> > > magic to express that bitmasking operations are only supported on
>> > > certain opt-in enums).
>> 
>> You may want to look at gdb's enum-flags.h which I think already
>> implements what your doing here.
>
>Aha!  Thanks!
>
>Browsing the git web UI, that gdb header was introduced by Pedro Alves
>in:
>https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=commitdiff;h=8d297bbf604c8318ffc72d5a7b3db654409c5ed9
>and the current state is here:
>https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;a=blob;f=gdb/common/enum-flags.h;hb=HEAD
>
>I'll try this out with GCC; hopefully it works with C++98.
>
>Presumably it would be good to share this header between GCC and GDB;
>CCing Pedro; Pedro: hi!  Does this sound sane?
>(for reference, the GCC patch we're discussing here is:
>  https://gcc.gnu.org/ml/gcc-patches/2018-05/msg01685.html )
>
>Presumably gcc's copy should live in the gcc's top-level "include"
>subdirectory?
>
>Would we need to change that "This file is part of GDB." comment, and
>the include guards' "COMMON_ENUM_FLAGS_H"?
>
>> > Does C++ allow > int enums?  I think we want some way of knowing
>> > when either enum exceeds int (dump_flags_t was already uint64_t
>> > but you now make it effectively int again).  That is, general
>> > wrapping
>> > for enum ops should chose an appropriate unsigned integer for
>> > the operation.  So yes, a common implementation looks useful to me.
>> 
>> I don't remember very well, but istr C++ will actually use a 8 byte
>> integer if the enum contains constants larger than 2^32.  Testing
>> sizeof enum x { A =0x400000000 }; gives the desired thing for me, but
>> it
>> would still be good to check the standard.
>
>FWIW C++11 onwards has a std::underlying_type for enums:
>  http://en.cppreference.com/w/cpp/types/underlying_type
>(GCC is on C++98).  The gdb header seems to emulate this via the use of
>sizeof(T) to select an appropriate integer_for_size specialization and
>thus the appropriate struct enum_underlying_type specialization (if I'm
>reading it right).
>
>> Trev
>> 
>> 
>> > 
>> > I think this patch is independently useful.
>
>Richard: by this, did you mean that the patch is OK for trunk as-is?

Yes. 

Richard. 

>(keeping a more general bitflags enum patch as followup work)  Note to
>self: still needs bootstrap-and-testing.
>
>> > Thanks,
>> > Richard.
>
>Thanks
>Dave
diff mbox series

Patch

diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index dc76c99..efb41c5 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -2341,7 +2341,7 @@  c_pretty_printer::statement (tree stmt)
   if (pp_needs_newline (this))
     pp_newline_and_indent (this, 0);
 
-  dump_generic_node (this, stmt, pp_indentation (this), 0, true);
+  dump_generic_node (this, stmt, pp_indentation (this), TDF_NONE, true);
 }
 
 
diff --git a/gcc/cfg.c b/gcc/cfg.c
index 11026e7..6d55516 100644
--- a/gcc/cfg.c
+++ b/gcc/cfg.c
@@ -545,8 +545,8 @@  DEBUG_FUNCTION void
 debug (edge_def &ref)
 {
   /* FIXME (crowl): Is this desireable?  */
-  dump_edge_info (stderr, &ref, 0, false);
-  dump_edge_info (stderr, &ref, 0, true);
+  dump_edge_info (stderr, &ref, TDF_NONE, false);
+  dump_edge_info (stderr, &ref, TDF_NONE, true);
 }
 
 DEBUG_FUNCTION void
diff --git a/gcc/cfghooks.c b/gcc/cfghooks.c
index 87d864c..ea106e0 100644
--- a/gcc/cfghooks.c
+++ b/gcc/cfghooks.c
@@ -288,7 +288,7 @@  dump_bb (FILE *outf, basic_block bb, int indent, dump_flags_t flags)
 DEBUG_FUNCTION void
 debug (basic_block_def &ref)
 {
-  dump_bb (stderr, &ref, 0, 0);
+  dump_bb (stderr, &ref, 0, TDF_NONE);
 }
 
 DEBUG_FUNCTION void
diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 0acc7a9..6af1445 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -50,8 +50,8 @@  const char *dump_file_name;
 dump_flags_t dump_flags;
 
 #define DUMP_FILE_INFO(suffix, swtch, dkind, num) \
-  {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, 0, 0, 0, 0, 0, num, \
-   false, false}
+  {suffix, swtch, NULL, NULL, NULL, NULL, NULL, dkind, TDF_NONE, TDF_NONE, \
+   OPTGROUP_NONE, 0, 0, num, false, false}
 
 /* Table of tree dump switches. This must be consistent with the
    TREE_DUMP_INDEX enumeration in dumpfile.h.  */
@@ -74,15 +74,16 @@  static struct dump_file_info dump_files[TDI_end] =
 };
 
 /* Define a name->number mapping for a dump flag value.  */
-struct dump_option_value_info
+template <typename ValueType>
+struct kv_pair
 {
   const char *const name;	/* the name of the value */
-  const dump_flags_t value;	/* the value of the name */
+  const ValueType value;	/* the value of the name */
 };
 
 /* Table of dump options. This must be consistent with the TDF_* flags
    in dumpfile.h and opt_info_options below. */
-static const struct dump_option_value_info dump_options[] =
+static const kv_pair<dump_flags_t> dump_options[] =
 {
   {"address", TDF_ADDRESS},
   {"asmname", TDF_ASMNAME},
@@ -114,23 +115,23 @@  static const struct dump_option_value_info dump_options[] =
   {"all", dump_flags_t (~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_GRAPH
 			| TDF_STMTADDR | TDF_RHS_ONLY | TDF_NOUID
 			| TDF_ENUMERATE_LOCALS | TDF_SCEV | TDF_GIMPLE))},
-  {NULL, 0}
+  {NULL, TDF_NONE}
 };
 
 /* A subset of the dump_options table which is used for -fopt-info
    types. This must be consistent with the MSG_* flags in dumpfile.h.
  */
-static const struct dump_option_value_info optinfo_verbosity_options[] =
+static const kv_pair<dump_flags_t> optinfo_verbosity_options[] =
 {
   {"optimized", MSG_OPTIMIZED_LOCATIONS},
   {"missed", MSG_MISSED_OPTIMIZATION},
   {"note", MSG_NOTE},
   {"all", MSG_ALL},
-  {NULL, 0}
+  {NULL, TDF_NONE}
 };
 
 /* Flags used for -fopt-info groups.  */
-static const struct dump_option_value_info optgroup_options[] =
+static const kv_pair<optgroup_flags_t> optgroup_options[] =
 {
   {"ipa", OPTGROUP_IPA},
   {"loop", OPTGROUP_LOOP},
@@ -138,7 +139,7 @@  static const struct dump_option_value_info optgroup_options[] =
   {"omp", OPTGROUP_OMP},
   {"vec", OPTGROUP_VEC},
   {"optall", OPTGROUP_ALL},
-  {NULL, 0}
+  {NULL, OPTGROUP_NONE}
 };
 
 gcc::dump_manager::dump_manager ():
@@ -173,7 +174,8 @@  gcc::dump_manager::~dump_manager ()
 unsigned int
 gcc::dump_manager::
 dump_register (const char *suffix, const char *swtch, const char *glob,
-	       dump_kind dkind, int optgroup_flags, bool take_ownership)
+	       dump_kind dkind, optgroup_flags_t optgroup_flags,
+	       bool take_ownership)
 {
   int num = m_next_dump++;
 
@@ -410,7 +412,7 @@  dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
    location.  */
 
 void
-dump_generic_expr_loc (int dump_kind, source_location loc,
+dump_generic_expr_loc (dump_flags_t dump_kind, source_location loc,
 		       dump_flags_t extra_dump_flags, tree t)
 {
   if (dump_file && (dump_kind & pflags))
@@ -575,9 +577,9 @@  dump_finish (int phase)
   dfi->pstream = NULL;
   dump_file = NULL;
   alt_dump_file = NULL;
-  dump_flags = TDI_none;
-  alt_flags = 0;
-  pflags = 0;
+  dump_flags = TDF_NONE;
+  alt_flags = TDF_NONE;
+  pflags = TDF_NONE;
 }
 
 /* Begin a tree dump for PHASE. Stores any user supplied flag in
@@ -750,7 +752,7 @@  dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename)
 
 int
 gcc::dump_manager::
-opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
+opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
 			const char *filename)
 {
   int n = 0;
@@ -817,11 +819,11 @@  dump_switch_p_1 (const char *arg, struct dump_file_info *dfi, bool doglob)
     return 0;
 
   ptr = option_value;
-  flags = 0;
+  flags = TDF_NONE;
 
   while (*ptr)
     {
-      const struct dump_option_value_info *option_ptr;
+      const struct kv_pair<dump_flags_t> *option_ptr;
       const char *end_ptr;
       const char *eq_ptr;
       unsigned length;
@@ -903,8 +905,8 @@  dump_switch_p (const char *arg)
    and filename.  Return non-zero if it is a recognized switch.  */
 
 static int
-opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
-                     char **filename)
+opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
+		     optgroup_flags_t *optgroup_flags, char **filename)
 {
   const char *option_value;
   const char *ptr;
@@ -913,15 +915,14 @@  opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
   ptr = option_value;
 
   *filename = NULL;
-  *flags = 0;
-  *optgroup_flags = 0;
+  *flags = TDF_NONE;
+  *optgroup_flags = OPTGROUP_NONE;
 
   if (!ptr)
     return 1;       /* Handle '-fopt-info' without any additional options.  */
 
   while (*ptr)
     {
-      const struct dump_option_value_info *option_ptr;
       const char *end_ptr;
       const char *eq_ptr;
       unsigned length;
@@ -938,8 +939,8 @@  opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
 	end_ptr = ptr + strlen (ptr);
       length = end_ptr - ptr;
 
-      for (option_ptr = optinfo_verbosity_options; option_ptr->name;
-           option_ptr++)
+      for (const kv_pair<dump_flags_t> *option_ptr = optinfo_verbosity_options;
+	   option_ptr->name; option_ptr++)
 	if (strlen (option_ptr->name) == length
 	    && !memcmp (option_ptr->name, ptr, length))
           {
@@ -947,7 +948,8 @@  opt_info_switch_p_1 (const char *arg, dump_flags_t *flags, int *optgroup_flags,
 	    goto found;
           }
 
-      for (option_ptr = optgroup_options; option_ptr->name; option_ptr++)
+      for (const kv_pair<optgroup_flags_t> *option_ptr = optgroup_options;
+	   option_ptr->name; option_ptr++)
 	if (strlen (option_ptr->name) == length
 	    && !memcmp (option_ptr->name, ptr, length))
           {
@@ -982,7 +984,7 @@  int
 opt_info_switch_p (const char *arg)
 {
   dump_flags_t flags;
-  int optgroup_flags;
+  optgroup_flags_t optgroup_flags;
   char *filename;
   static char *file_seen = NULL;
   gcc::dump_manager *dumps = g->get_dumps ();
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 21803a6..b5582f7 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -58,65 +58,177 @@  enum dump_kind
    the DUMP_OPTIONS array in dumpfile.c. The TDF_* flags coexist with
    MSG_* flags (for -fopt-info) and the bit values must be chosen to
    allow that.  */
-#define TDF_ADDRESS	(1 << 0)	/* dump node addresses */
-#define TDF_SLIM	(1 << 1)	/* don't go wild following links */
-#define TDF_RAW		(1 << 2)	/* don't unparse the function */
-#define TDF_DETAILS	(1 << 3)	/* show more detailed info about
-					   each pass */
-#define TDF_STATS	(1 << 4)	/* dump various statistics about
-					   each pass */
-#define TDF_BLOCKS	(1 << 5)	/* display basic block boundaries */
-#define TDF_VOPS	(1 << 6)	/* display virtual operands */
-#define TDF_LINENO	(1 << 7)	/* display statement line numbers */
-#define TDF_UID		(1 << 8)	/* display decl UIDs */
-
-#define TDF_STMTADDR	(1 << 9)       /* Address of stmt.  */
-
-#define TDF_GRAPH	(1 << 10)	/* a graph dump is being emitted */
-#define TDF_MEMSYMS	(1 << 11)	/* display memory symbols in expr.
-					   Implies TDF_VOPS.  */
-
-#define TDF_RHS_ONLY	(1 << 12)	/* a flag to only print the RHS of
-					   a gimple stmt.  */
-#define TDF_ASMNAME	(1 << 13)	/* display asm names of decls  */
-#define TDF_EH		(1 << 14)	/* display EH region number
-					   holding this gimple statement.  */
-#define TDF_NOUID	(1 << 15)	/* omit UIDs from dumps.  */
-#define TDF_ALIAS	(1 << 16)	/* display alias information  */
-#define TDF_ENUMERATE_LOCALS (1 << 17)	/* Enumerate locals by uid.  */
-#define TDF_CSELIB	(1 << 18)	/* Dump cselib details.  */
-#define TDF_SCEV	(1 << 19)	/* Dump SCEV details.  */
-#define TDF_GIMPLE	(1 << 20)	/* Dump in GIMPLE FE syntax  */
-#define TDF_FOLDING	(1 << 21)	/* Dump folding details.  */
-#define MSG_OPTIMIZED_LOCATIONS	 (1 << 22)  /* -fopt-info optimized sources */
-#define MSG_MISSED_OPTIMIZATION	 (1 << 23)  /* missed opportunities */
-#define MSG_NOTE		 (1 << 24)  /* general optimization info */
-#define MSG_ALL		(MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \
-			 | MSG_NOTE)
-#define TDF_COMPARE_DEBUG (1 << 25)	/* Dumping for -fcompare-debug.  */
-
-
-/* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK.  */
-
-#define TDF_NONE 0
+enum dump_flag
+{
+  /* Value of TDF_NONE is used just for bits filtered by TDF_KIND_MASK.  */
+  TDF_NONE  = 0,
+
+  /* Dump node addresses.  */
+  TDF_ADDRESS = (1 << 0),
+
+  /* Don't go wild following links.  */
+  TDF_SLIM = (1 << 1),
+
+  /* Don't unparse the function.  */
+  TDF_RAW = (1 << 2),
+
+  /* Show more detailed info about each pass.  */
+  TDF_DETAILS = (1 << 3),
+
+  /* Dump various statistics about each pass.  */
+  TDF_STATS = (1 << 4),
+
+  /* Display basic block boundaries.  */
+  TDF_BLOCKS = (1 << 5),
+
+  /* Display virtual operands.  */
+  TDF_VOPS = (1 << 6),
+
+  /* Display statement line numbers.  */
+  TDF_LINENO = (1 << 7),
+
+  /* Display decl UIDs.  */
+  TDF_UID  = (1 << 8),
+
+  /* Address of stmt.  */
+  TDF_STMTADDR = (1 << 9),
+
+  /* A graph dump is being emitted.  */
+  TDF_GRAPH = (1 << 10),
+
+  /* Display memory symbols in expr.
+     Implies TDF_VOPS.  */
+  TDF_MEMSYMS = (1 << 11),
+
+  /* A flag to only print the RHS of a gimple stmt.  */
+  TDF_RHS_ONLY = (1 << 12),
+
+  /* Display asm names of decls.  */
+  TDF_ASMNAME = (1 << 13),
+
+  /* Display EH region number holding this gimple statement.  */
+  TDF_EH  = (1 << 14),
+
+  /* Omit UIDs from dumps.  */
+  TDF_NOUID = (1 << 15),
+
+  /* Display alias information.  */
+  TDF_ALIAS = (1 << 16),
+
+  /* Enumerate locals by uid.  */
+  TDF_ENUMERATE_LOCALS = (1 << 17),
+
+  /* Dump cselib details.  */
+  TDF_CSELIB = (1 << 18),
+
+  /* Dump SCEV details.  */
+  TDF_SCEV = (1 << 19),
+
+  /* Dump in GIMPLE FE syntax  */
+  TDF_GIMPLE = (1 << 20),
+
+  /* Dump folding details.  */
+  TDF_FOLDING = (1 << 21),
+
+  /* -fopt-info optimized sources.  */
+  MSG_OPTIMIZED_LOCATIONS = (1 << 22),
+
+  /* Missed opportunities.  */
+  MSG_MISSED_OPTIMIZATION = (1 << 23),
+
+  /* General optimization info.  */
+  MSG_NOTE = (1 << 24),
+
+  MSG_ALL = (MSG_OPTIMIZED_LOCATIONS
+	     | MSG_MISSED_OPTIMIZATION
+	     | MSG_NOTE),
+
+  /* Dumping for -fcompare-debug.  */
+  TDF_COMPARE_DEBUG = (1 << 25),
+};
+
+/* Dump flags type.  */
+
+typedef enum dump_flag dump_flags_t;
+
+// FIXME: template
+// FIXME: underlying storage type?
+static inline dump_flags_t
+operator| (dump_flags_t lhs, dump_flags_t rhs)
+{
+  return (dump_flags_t)((int)lhs | (int)rhs);
+}
+
+static inline dump_flags_t
+operator& (dump_flags_t lhs, dump_flags_t rhs)
+{
+  return (dump_flags_t)((int)lhs & (int)rhs);
+}
+
+static inline dump_flags_t
+operator~ (dump_flags_t flags)
+{
+  return (dump_flags_t)~((int)flags);
+}
+
+static inline dump_flags_t &
+operator|= (dump_flags_t &lhs, dump_flags_t rhs)
+{
+  lhs = (dump_flags_t)((int)lhs | (int)rhs);
+  return lhs;
+}
+
+static inline dump_flags_t &
+operator&= (dump_flags_t &lhs, dump_flags_t rhs)
+{
+  lhs = (dump_flags_t)((int)lhs & (int)rhs);
+  return lhs;
+}
 
 /* Flags to control high-level -fopt-info dumps.  Usually these flags
    define a group of passes.  An optimization pass can be part of
    multiple groups.  */
-#define OPTGROUP_NONE	     (0)
-#define OPTGROUP_IPA	     (1 << 1)	/* IPA optimization passes */
-#define OPTGROUP_LOOP	     (1 << 2)	/* Loop optimization passes */
-#define OPTGROUP_INLINE	     (1 << 3)	/* Inlining passes */
-#define OPTGROUP_OMP	     (1 << 4)	/* OMP (Offloading and Multi
-					   Processing) transformations */
-#define OPTGROUP_VEC	     (1 << 5)	/* Vectorization passes */
-#define OPTGROUP_OTHER	     (1 << 6)	/* All other passes */
-#define OPTGROUP_ALL	     (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE \
-			      | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
 
-/* Dump flags type.  */
+enum optgroup_flag
+{
+  OPTGROUP_NONE = 0,
+
+  /* IPA optimization passes */
+  OPTGROUP_IPA  = (1 << 1),
+
+  /* Loop optimization passes */
+  OPTGROUP_LOOP = (1 << 2),
+
+  /* Inlining passes */
+  OPTGROUP_INLINE = (1 << 3),
 
-typedef uint64_t dump_flags_t;
+  /* OMP (Offloading and Multi Processing) transformations */
+  OPTGROUP_OMP = (1 << 4),
+
+  /* Vectorization passes */
+  OPTGROUP_VEC = (1 << 5),
+
+  /* All other passes */
+  OPTGROUP_OTHER = (1 << 6),
+
+  OPTGROUP_ALL = (OPTGROUP_IPA | OPTGROUP_LOOP | OPTGROUP_INLINE
+		  | OPTGROUP_OMP | OPTGROUP_VEC | OPTGROUP_OTHER)
+};
+
+typedef enum optgroup_flag optgroup_flags_t;
+
+static inline optgroup_flags_t
+operator| (optgroup_flags_t lhs, optgroup_flags_t rhs)
+{
+  return (optgroup_flags_t)((int)lhs | (int)rhs);
+}
+
+static inline optgroup_flags_t &
+operator|= (optgroup_flags_t &lhs, optgroup_flags_t rhs)
+{
+  lhs = (optgroup_flags_t)((int)lhs | (int)rhs);
+  return lhs;
+}
 
 /* Define a tree dump switch.  */
 struct dump_file_info
@@ -140,9 +252,9 @@  struct dump_file_info
   /* Dump flags.  */
   dump_flags_t pflags;
   /* A pass flags for -fopt-info.  */
-  int alt_flags;
+  dump_flags_t alt_flags;
   /* Flags for -fopt-info given by a user.  */
-  int optgroup_flags;
+  optgroup_flags_t optgroup_flags;
   /* State of pass-specific stream.  */
   int pstate;
   /* State of the -fopt-info stream.  */
@@ -214,7 +326,8 @@  public:
      SUFFIX, SWTCH, and GLOB. */
   unsigned int
   dump_register (const char *suffix, const char *swtch, const char *glob,
-		 dump_kind dkind, int optgroup_flags, bool take_ownership);
+		 dump_kind dkind, optgroup_flags_t optgroup_flags,
+		 bool take_ownership);
 
   /* Allow languages and middle-end to register their dumps before the
      optimization passes.  */
@@ -275,7 +388,7 @@  private:
   dump_enable_all (dump_kind dkind, dump_flags_t flags, const char *filename);
 
   int
-  opt_info_enable_passes (int optgroup_flags, dump_flags_t flags,
+  opt_info_enable_passes (optgroup_flags_t optgroup_flags, dump_flags_t flags,
 			  const char *filename);
 
 private:
diff --git a/gcc/early-remat.c b/gcc/early-remat.c
index 28eb9b4..776b2d0 100644
--- a/gcc/early-remat.c
+++ b/gcc/early-remat.c
@@ -657,7 +657,7 @@  early_remat::dump_edge_list (basic_block bb, bool do_succ)
   edge e;
   edge_iterator ei;
   FOR_EACH_EDGE (e, ei, do_succ ? bb->succs : bb->preds)
-    dump_edge_info (dump_file, e, 0, do_succ);
+    dump_edge_info (dump_file, e, TDF_NONE, do_succ);
 }
 
 /* Print information about basic block BB to the dump file.  */
diff --git a/gcc/gimple-pretty-print.c b/gcc/gimple-pretty-print.c
index 6695526..39edaa1 100644
--- a/gcc/gimple-pretty-print.c
+++ b/gcc/gimple-pretty-print.c
@@ -153,7 +153,7 @@  print_gimple_stmt (FILE *file, gimple *g, int spc, dump_flags_t flags)
 DEBUG_FUNCTION void
 debug (gimple &ref)
 {
-  print_gimple_stmt (stderr, &ref, 0, 0);
+  print_gimple_stmt (stderr, &ref, 0, TDF_NONE);
 }
 
 DEBUG_FUNCTION void
diff --git a/gcc/gimple-ssa-store-merging.c b/gcc/gimple-ssa-store-merging.c
index 6f6538b..7362128 100644
--- a/gcc/gimple-ssa-store-merging.c
+++ b/gcc/gimple-ssa-store-merging.c
@@ -1075,7 +1075,7 @@  bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
 	    print_gimple_stmt (dump_file, cur_stmt, 0);
 	  else
 	    {
-	      print_generic_expr (dump_file, tgt, 0);
+	      print_generic_expr (dump_file, tgt, TDF_NONE);
 	      fprintf (dump_file, "\n");
 	    }
 	}
@@ -1145,7 +1145,7 @@  bswap_replace (gimple_stmt_iterator gsi, gimple *ins_stmt, tree fndecl,
 	print_gimple_stmt (dump_file, cur_stmt, 0);
       else
 	{
-	  print_generic_expr (dump_file, tgt, 0);
+	  print_generic_expr (dump_file, tgt, TDF_NONE);
 	  fprintf (dump_file, "\n");
 	}
     }
@@ -1956,7 +1956,7 @@  merged_store_group::apply_stores ()
 	  if (ret)
 	    {
 	      fprintf (dump_file, "After writing ");
-	      print_generic_expr (dump_file, cst, 0);
+	      print_generic_expr (dump_file, cst, TDF_NONE);
 	      fprintf (dump_file, " of size " HOST_WIDE_INT_PRINT_DEC
 		       " at position %d the merged region contains:\n",
 		       info->bitsize, pos_in_buffer);
diff --git a/gcc/gimple-ssa-strength-reduction.c b/gcc/gimple-ssa-strength-reduction.c
index 1c00f09..14fc420 100644
--- a/gcc/gimple-ssa-strength-reduction.c
+++ b/gcc/gimple-ssa-strength-reduction.c
@@ -3353,7 +3353,7 @@  insert_initializers (slsr_cand_t c)
 	      fputs ("Using existing initializer: ", dump_file);
 	      print_gimple_stmt (dump_file,
 				 SSA_NAME_DEF_STMT (incr_vec[i].initializer),
-				 0, 0);
+				 0, TDF_NONE);
 	    }
 	  continue;
 	}
diff --git a/gcc/gimple.c b/gcc/gimple.c
index 9dc4911..c18526a 100644
--- a/gcc/gimple.c
+++ b/gcc/gimple.c
@@ -3148,7 +3148,7 @@  static void
 verify_gimple_pp (const char *expected, gimple *stmt)
 {
   pretty_printer pp;
-  pp_gimple_stmt_1 (&pp, stmt, 0 /* spc */, 0 /* flags */);
+  pp_gimple_stmt_1 (&pp, stmt, 0 /* spc */, TDF_NONE /* flags */);
   ASSERT_STREQ (expected, pp_formatted_text (&pp));
 }
 
diff --git a/gcc/passes.c b/gcc/passes.c
index ad0a912..62fd413 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -784,7 +784,7 @@  pass_manager::register_one_dump_file (opt_pass *pass)
   char num[11];
   dump_kind dkind;
   int id;
-  int optgroup_flags = OPTGROUP_NONE;
+  optgroup_flags_t optgroup_flags = OPTGROUP_NONE;
   gcc::dump_manager *dumps = m_ctxt->get_dumps ();
 
   /* See below in next_pass_1.  */
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index caf5f26..5c736c5 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -894,7 +894,8 @@  print_node (FILE *file, const char *prefix, tree node, int indent,
 	  {
 	    pretty_printer buffer;
 	    buffer.buffer->stream = file;
-	    pp_gimple_stmt_1 (&buffer, SSA_NAME_DEF_STMT (node), indent + 4, 0);
+	    pp_gimple_stmt_1 (&buffer, SSA_NAME_DEF_STMT (node), indent + 4,
+			      TDF_NONE);
 	    pp_flush (&buffer);
 	  }
 
@@ -1039,7 +1040,7 @@  dump_tree_via_hooks (const tree_node *ptr, dump_flags_t options)
 DEBUG_FUNCTION void
 debug (const tree_node &ref)
 {
-  dump_tree_via_hooks (&ref, 0);
+  dump_tree_via_hooks (&ref, TDF_NONE);
 }
 
 DEBUG_FUNCTION void
@@ -1070,7 +1071,7 @@  DEBUG_FUNCTION void
 debug_body (const tree_node &ref)
 {
   if (TREE_CODE (&ref) == FUNCTION_DECL)
-    dump_function_to_file (const_cast <tree_node*> (&ref), stderr, 0);
+    dump_function_to_file (const_cast <tree_node*> (&ref), stderr, TDF_NONE);
   else
     debug (ref);
 }
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 93a6a99..c757591 100644
--- a/gcc/tree-pass.h
+++ b/gcc/tree-pass.h
@@ -47,7 +47,7 @@  struct pass_data
   const char *name;
 
   /* The -fopt-info optimization group flags as defined in dumpfile.h. */
-  unsigned int optinfo_flags;
+  optgroup_flags_t optinfo_flags;
 
   /* The timevar id associated with this pass.  */
   /* ??? Ideally would be dynamically assigned.  */
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 276ad00..8963ae0 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -3404,7 +3404,7 @@  print_struct_decl (pretty_printer *pp, const_tree node, int spc,
 		|| TREE_CODE (node) == QUAL_UNION_TYPE))
 	pp_string (pp, "union ");
 
-      dump_generic_node (pp, TYPE_NAME (node), spc, 0, false);
+      dump_generic_node (pp, TYPE_NAME (node), spc, TDF_NONE, false);
     }
 
   /* Print the contents of the structure.  */
diff --git a/gcc/tree-ssa-math-opts.c b/gcc/tree-ssa-math-opts.c
index 16d9399..b3f8cb6 100644
--- a/gcc/tree-ssa-math-opts.c
+++ b/gcc/tree-ssa-math-opts.c
@@ -2710,7 +2710,7 @@  convert_mult_to_fma_1 (tree mul_result, tree op1, tree op2)
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, "Generated FMA ");
-	  print_gimple_stmt (dump_file, fma_stmt, 0, 0);
+	  print_gimple_stmt (dump_file, fma_stmt, 0, TDF_NONE);
 	  fprintf (dump_file, "\n");
 	}
 
@@ -3046,7 +3046,7 @@  convert_mult_to_fma (gimple *mul_stmt, tree op1, tree op2,
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, "Deferred generating FMA for multiplication ");
-	  print_gimple_stmt (dump_file, mul_stmt, 0, 0);
+	  print_gimple_stmt (dump_file, mul_stmt, 0, TDF_NONE);
 	  fprintf (dump_file, "\n");
 	}
 
diff --git a/gcc/tree-ssa-reassoc.c b/gcc/tree-ssa-reassoc.c
index 0e59bb5..dde9701 100644
--- a/gcc/tree-ssa-reassoc.c
+++ b/gcc/tree-ssa-reassoc.c
@@ -1606,7 +1606,7 @@  undistribute_ops_list (enum tree_code opcode,
     {
       fprintf (dump_file, "searching for un-distribute opportunities ");
       print_generic_expr (dump_file,
-	(*ops)[bitmap_first_set_bit (candidates)]->op, 0);
+	(*ops)[bitmap_first_set_bit (candidates)]->op, TDF_NONE);
       fprintf (dump_file, " %d\n", nr_candidates);
     }
 
diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c
index 1463c1d..d8ab1f0 100644
--- a/gcc/tree-ssa-sccvn.c
+++ b/gcc/tree-ssa-sccvn.c
@@ -5921,7 +5921,7 @@  vn_eliminate (bitmap inserted_exprs)
       if (dump_file && (dump_flags & TDF_DETAILS))
 	{
 	  fprintf (dump_file, "Removing dead stmt ");
-	  print_gimple_stmt (dump_file, stmt, 0, 0);
+	  print_gimple_stmt (dump_file, stmt, 0, TDF_NONE);
 	}
 
       gimple_stmt_iterator gsi = gsi_for_stmt (stmt);
diff --git a/gcc/tree-vect-data-refs.c b/gcc/tree-vect-data-refs.c
index 9aabcc1..ebc56c0 100644
--- a/gcc/tree-vect-data-refs.c
+++ b/gcc/tree-vect-data-refs.c
@@ -3229,7 +3229,7 @@  dependence_distance_ge_vf (data_dependence_relation *ddr,
 /* Dump LOWER_BOUND using flags DUMP_KIND.  Dumps are known to be enabled.  */
 
 static void
-dump_lower_bound (int dump_kind, const vec_lower_bound &lower_bound)
+dump_lower_bound (dump_flags_t dump_kind, const vec_lower_bound &lower_bound)
 {
   dump_printf (dump_kind, "%s (", lower_bound.unsigned_p ? "unsigned" : "abs");
   dump_generic_expr (dump_kind, TDF_SLIM, lower_bound.expr);