diff mbox

[2/N] Add dump_flags_type<E> for handling of suboptions.

Message ID 8a73764e-e214-21a5-a362-84368c68bf53@suse.cz
State New
Headers show

Commit Message

Martin Liška May 9, 2017, 12:03 p.m. UTC
On 05/05/2017 12:44 PM, Martin Liška wrote:
> Hi.
> 
> This one is more interesting as it implements hierarchical option parsing
> and as a first step I implemented that for optgroup suboptions.
> 
> Next candidates are dump_option_value_info and obviously my primary motivation:
> dump_option_value_info.
> 
> I'm expecting feedback for implementation I've decided to come up with.
> Patch has been tested.
> 
> Thanks,
> Martin
> 

Update version of the patch. Actually it contains of 2 parts, where the second one
is mechanical replacement of enum values.

It's still work-in-progress as we're still tuning internal representation.

Martin
diff mbox

Patch

From 1a6f1dc6333bef2a643eacacbbc31f83a10e28ee Mon Sep 17 00:00:00 2001
From: marxin <mliska@suse.cz>
Date: Tue, 9 May 2017 13:22:23 +0200
Subject: [PATCH 1/2] Port -fopt-info to new option infrastructure.

---
 gcc/dumpfile.c  | 332 ++++++++++++++++++++++++++------------------------------
 gcc/dumpfile.h  | 125 ++++++++++++++-------
 gcc/passes.c    |   2 +-
 gcc/tree-pass.h |   2 +-
 4 files changed, 240 insertions(+), 221 deletions(-)

diff --git a/gcc/dumpfile.c b/gcc/dumpfile.c
index 82c4fc9d4ff..e3db0a5ff7e 100644
--- a/gcc/dumpfile.c
+++ b/gcc/dumpfile.c
@@ -33,10 +33,10 @@  along with GCC; see the file COPYING3.  If not see
 #define skip_leading_substring(whole,  part) \
    (strncmp (whole, part, strlen (part)) ? NULL : whole + strlen (part))
 
-static dump_flags_t pflags;		      /* current dump_flags */
-static dump_flags_t alt_flags;		      /* current opt_info flags */
+static dump_flags_t pflags;		/* current dump_flags */
+static optgroup_dump_flags_t opt_info_flags; /* current opt_info flags */
 
-static void dump_loc (dump_flags_t, FILE *, source_location);
+static void dump_loc (optgroup_dump_flags_t, FILE *, source_location);
 static FILE *dump_open_alternate_stream (struct dump_file_info *);
 
 /* These are currently used for communicating between passes.
@@ -51,31 +51,33 @@  dump_flags_t dump_flags;
    TREE_DUMP_INDEX enumeration in dumpfile.h.  */
 static struct dump_file_info dump_files[TDI_end] =
 {
-  {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0, 0, 0, 0, 0, false, false},
+  {NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, optgroup_dump_flags_t (),
+   optgroup_dump_flags_t (), 0, 0, 0, false, false},
   {".cgraph", "ipa-cgraph", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
-   0, 0, 0, 0, 0, false, false},
-  {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
-   0, 0, 0, 0, 0, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0, false, false},
+  {".type-inheritance", "ipa-type-inheritance", NULL, NULL, NULL, NULL, NULL,
+    TDF_IPA, optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0,
+    false, false},
   {".ipa-clones", "ipa-clones", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
-   0, 0, 0, 0, 0, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0, false, false},
   {".tu", "translation-unit", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 1, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 1, false, false},
   {".class", "class-hierarchy", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 2, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 2, false, false},
   {".original", "tree-original", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 3, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 3, false, false},
   {".gimple", "tree-gimple", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 4, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 4, false, false},
   {".nested", "tree-nested", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 5, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 5, false, false},
 #define FIRST_AUTO_NUMBERED_DUMP 6
 
   {NULL, "tree-all", NULL, NULL, NULL, NULL, NULL, TDF_TREE,
-   0, 0, 0, 0, 0, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0, false, false},
   {NULL, "rtl-all", NULL, NULL, NULL, NULL, NULL, TDF_RTL,
-   0, 0, 0, 0, 0, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0, false, false},
   {NULL, "ipa-all", NULL, NULL, NULL, NULL, NULL, TDF_IPA,
-   0, 0, 0, 0, 0, false, false},
+   optgroup_dump_flags_t (), optgroup_dump_flags_t (), 0, 0, 0, false, false},
 };
 
 /* Define a name->number mapping for a dump flag value.  */
@@ -94,9 +96,7 @@  static const struct dump_option_value_info dump_options[] =
   {"slim", TDF_SLIM},
   {"raw", TDF_RAW},
   {"graph", TDF_GRAPH},
-  {"details", (TDF_DETAILS | MSG_OPTIMIZED_LOCATIONS
-               | MSG_MISSED_OPTIMIZATION
-               | MSG_NOTE)},
+  {"details", TDF_DETAILS},
   {"cselib", TDF_CSELIB},
   {"stats", TDF_STATS},
   {"blocks", TDF_BLOCKS},
@@ -112,10 +112,6 @@  static const struct dump_option_value_info dump_options[] =
   {"enumerate_locals", TDF_ENUMERATE_LOCALS},
   {"scev", TDF_SCEV},
   {"gimple", TDF_GIMPLE},
-  {"optimized", MSG_OPTIMIZED_LOCATIONS},
-  {"missed", MSG_MISSED_OPTIMIZATION},
-  {"note", MSG_NOTE},
-  {"optall", MSG_ALL},
   {"all", ~(TDF_RAW | TDF_SLIM | TDF_LINENO | TDF_TREE | TDF_RTL | TDF_IPA
 	    | TDF_STMTADDR | TDF_GRAPH | TDF_DIAGNOSTIC | TDF_VERBOSE
 	    | TDF_RHS_ONLY | TDF_NOUID | TDF_ENUMERATE_LOCALS | TDF_SCEV
@@ -123,18 +119,6 @@  static const struct dump_option_value_info dump_options[] =
   {NULL, 0}
 };
 
-/* 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[] =
-{
-  {"optimized", MSG_OPTIMIZED_LOCATIONS},
-  {"missed", MSG_MISSED_OPTIMIZATION},
-  {"note", MSG_NOTE},
-  {"all", MSG_ALL},
-  {NULL, 0}
-};
-
 template <typename E>
 dump_option_node<E>::dump_option_node (const char *name, E enum_value):
   m_name (name), m_enum_value (enum_value), m_children (), m_mask (0)
@@ -179,7 +163,7 @@  uint64_t
 dump_option_node<E>::parse (const char *token)
 {
   char *s = xstrdup (token);
-  uint64_t r = parse (s);
+  uint64_t r = parse (strtok (s, "-"));
   free (s);
 
   return r;
@@ -189,6 +173,13 @@  template <typename E>
 uint64_t
 dump_option_node<E>::parse (char *token)
 {
+  return parse_internal (strtok (token, "-"));
+}
+
+template <typename E>
+uint64_t
+dump_option_node<E>::parse_internal (char *token)
+{
   if (token == NULL)
     return m_mask;
 
@@ -202,19 +193,61 @@  dump_option_node<E>::parse (char *token)
     if (strcmp (m_children[i]->m_name, token) == 0)
     {
       token = strtok (NULL, "-");
-      return m_children[i]->parse (token);
+      return m_children[i]->parse_internal (token);
     }
 
   return 0;
 }
 
+optgroup_option_hierarchy::optgroup_option_hierarchy ()
+{
+  root = new node (NULL, OPTGROUP_NONE);
+
+  node *n = new node ("ipa", OPTGROUP_IPA);
+  n->register_suboption (new node ("optimized", OPTGROUP_IPA_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_IPA_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_IPA_NOTE));
+  root->register_suboption (n);
+
+  n = new node ("loop", OPTGROUP_LOOP);
+  n->register_suboption (new node ("optimized", OPTGROUP_LOOP_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_LOOP_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_LOOP_NOTE));
+  root->register_suboption (n);
+
+  n = new node ("inline", OPTGROUP_INLINE);
+  n->register_suboption (new node ("optimized", OPTGROUP_INLINE_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_INLINE_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_INLINE_NOTE));
+  root->register_suboption (n);
+
+  n = new node ("omp", OPTGROUP_OMP);
+  n->register_suboption (new node ("optimized", OPTGROUP_OMP_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_OMP_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_OMP_NOTE));
+  root->register_suboption (n);
+
+  n = new node ("vec", OPTGROUP_VEC);
+  n->register_suboption (new node ("optimized", OPTGROUP_VEC_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_VEC_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_VEC_NOTE));
+  root->register_suboption (n);
+
+  n = new node ("other", OPTGROUP_OTHER);
+  n->register_suboption (new node ("optimized", OPTGROUP_OTHER_OPTIMIZED));
+  n->register_suboption (new node ("missed", OPTGROUP_OTHER_MISSED));
+  n->register_suboption (new node ("note", OPTGROUP_OTHER_NOTE));
+  root->register_suboption (n);
+
+  root->initialize (optgroup_dump_flags_t::m_mask_translation);
+}
+
 gcc::dump_manager::dump_manager ():
   m_next_dump (FIRST_AUTO_NUMBERED_DUMP),
   m_extra_dump_files (NULL),
   m_extra_dump_files_in_use (0),
   m_extra_dump_files_alloced (0)
 {
-  initialize_options ();
 }
 
 gcc::dump_manager::~dump_manager ()
@@ -236,14 +269,12 @@  gcc::dump_manager::~dump_manager ()
       XDELETEVEC (const_cast <char *> (dfi->alt_filename));
     }
   XDELETEVEC (m_extra_dump_files);
-
-  delete (optgroup_options);
 }
 
 unsigned int
 gcc::dump_manager::
 dump_register (const char *suffix, const char *swtch, const char *glob,
-	       dump_flags_t flags, optgroup_dump_flags_t  optgroup_flags,
+	       dump_flags_t flags, optgroup_dump_flags_t optgroup_flags,
 	       bool take_ownership)
 {
   int num = m_next_dump++;
@@ -266,7 +297,7 @@  dump_register (const char *suffix, const char *swtch, const char *glob,
   m_extra_dump_files[count].swtch = swtch;
   m_extra_dump_files[count].glob = glob;
   m_extra_dump_files[count].pflags = flags;
-  m_extra_dump_files[count].optgroup_flags = optgroup_flags;
+  m_extra_dump_files[count].pass_optgroup_flags = optgroup_flags;
   m_extra_dump_files[count].num = num;
   m_extra_dump_files[count].owns_strings = take_ownership;
 
@@ -393,7 +424,7 @@  dump_open_alternate_stream (struct dump_file_info *dfi)
 /* Print source location on DFILE if enabled.  */
 
 void
-dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
+dump_loc (optgroup_dump_flags_t dump_kind, FILE *dfile, source_location loc)
 {
   if (dump_kind)
     {
@@ -412,29 +443,30 @@  dump_loc (dump_flags_t dump_kind, FILE *dfile, source_location loc)
    EXTRA_DUMP_FLAGS on the dump streams if DUMP_KIND is enabled.  */
 
 void
-dump_gimple_stmt (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
+dump_gimple_stmt (optgroup_dump_flags_t dump_kind,
+		  dump_flags_t extra_dump_flags,
 		  gimple *gs, int spc)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
     print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
 }
 
 /* Similar to dump_gimple_stmt, except additionally print source location.  */
 
 void
-dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
+dump_gimple_stmt_loc (optgroup_dump_flags_t dump_kind, source_location loc,
 		      dump_flags_t extra_dump_flags, gimple *gs, int spc)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
     {
       dump_loc (dump_kind, dump_file, loc);
       print_gimple_stmt (dump_file, gs, spc, dump_flags | extra_dump_flags);
     }
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     {
       dump_loc (dump_kind, alt_dump_file, loc);
       print_gimple_stmt (alt_dump_file, gs, spc, dump_flags | extra_dump_flags);
@@ -445,13 +477,14 @@  dump_gimple_stmt_loc (dump_flags_t dump_kind, source_location loc,
    DUMP_KIND is enabled.  */
 
 void
-dump_generic_expr (dump_flags_t dump_kind, dump_flags_t extra_dump_flags,
+dump_generic_expr (optgroup_dump_flags_t dump_kind,
+		   dump_flags_t extra_dump_flags,
 		   tree t)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
       print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
       print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
 }
 
@@ -460,16 +493,16 @@  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 (optgroup_dump_flags_t dump_kind, source_location loc,
 		       dump_flags_t extra_dump_flags, tree t)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
     {
       dump_loc (dump_kind, dump_file, loc);
       print_generic_expr (dump_file, t, dump_flags | extra_dump_flags);
     }
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     {
       dump_loc (dump_kind, alt_dump_file, loc);
       print_generic_expr (alt_dump_file, t, dump_flags | extra_dump_flags);
@@ -479,9 +512,9 @@  dump_generic_expr_loc (int dump_kind, source_location loc,
 /* Output a formatted message using FORMAT on appropriate dump streams.  */
 
 void
-dump_printf (dump_flags_t dump_kind, const char *format, ...)
+dump_printf (optgroup_dump_flags_t dump_kind, const char *format, ...)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
     {
       va_list ap;
       va_start (ap, format);
@@ -489,7 +522,7 @@  dump_printf (dump_flags_t dump_kind, const char *format, ...)
       va_end (ap);
     }
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     {
       va_list ap;
       va_start (ap, format);
@@ -501,10 +534,10 @@  dump_printf (dump_flags_t dump_kind, const char *format, ...)
 /* Similar to dump_printf, except source location is also printed.  */
 
 void
-dump_printf_loc (dump_flags_t dump_kind, source_location loc,
+dump_printf_loc (optgroup_dump_flags_t dump_kind, source_location loc,
 		 const char *format, ...)
 {
-  if (dump_file && (dump_kind & pflags))
+  if (dump_file)
     {
       va_list ap;
       dump_loc (dump_kind, dump_file, loc);
@@ -513,7 +546,7 @@  dump_printf_loc (dump_flags_t dump_kind, source_location loc,
       va_end (ap);
     }
 
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     {
       va_list ap;
       dump_loc (dump_kind, alt_dump_file, loc);
@@ -570,7 +603,7 @@  dump_start (int phase, dump_flags_t *flag_ptr)
       count++;
       alt_dump_file = dfi->alt_stream;
       /* Initialize current -fopt-info flags. */
-      alt_flags = dfi->alt_flags;
+      opt_info_flags = dfi->optgroup_flags;
     }
 
   if (flag_ptr)
@@ -605,7 +638,7 @@  dump_finish (int phase)
   dump_file = NULL;
   alt_dump_file = NULL;
   dump_flags = TDI_none;
-  alt_flags = 0;
+  opt_info_flags = optgroup_dump_flags_t ();
   pflags = 0;
 }
 
@@ -781,45 +814,45 @@  dump_enable_all (dump_flags_t flags, const char *filename)
 int
 gcc::dump_manager::
 opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags,
-			dump_flags_t flags, const char *filename)
+			const char *filename)
 {
   int n = 0;
   size_t i;
 
   for (i = TDI_none + 1; i < (size_t) TDI_end; i++)
     {
-      if ((dump_files[i].optgroup_flags & optgroup_flags))
-        {
-          const char *old_filename = dump_files[i].alt_filename;
-          /* Since this file is shared among different passes, it
-             should be opened in append mode.  */
-          dump_files[i].alt_state = 1;
-          dump_files[i].alt_flags |= flags;
-          n++;
-          /* Override the existing filename.  */
-          if (filename)
-            dump_files[i].alt_filename = xstrdup (filename);
-          if (old_filename && filename != old_filename)
-            free (CONST_CAST (char *, old_filename));
-        }
+      if ((dump_files[i].pass_optgroup_flags & optgroup_flags))
+	{
+	  const char *old_filename = dump_files[i].alt_filename;
+	  /* Since this file is shared among different passes, it
+	     should be opened in append mode.  */
+	  dump_files[i].alt_state = 1;
+	  dump_files[i].optgroup_flags |= optgroup_flags;
+	  n++;
+	  /* Override the existing filename.  */
+	  if (filename)
+	    dump_files[i].alt_filename = xstrdup (filename);
+	  if (old_filename && filename != old_filename)
+	    free (CONST_CAST (char *, old_filename));
+	}
     }
 
   for (i = 0; i < m_extra_dump_files_in_use; i++)
     {
-      if ((m_extra_dump_files[i].optgroup_flags & optgroup_flags))
-        {
-          const char *old_filename = m_extra_dump_files[i].alt_filename;
-          /* Since this file is shared among different passes, it
-             should be opened in append mode.  */
-          m_extra_dump_files[i].alt_state = 1;
-          m_extra_dump_files[i].alt_flags |= flags;
-          n++;
-          /* Override the existing filename.  */
-          if (filename)
-            m_extra_dump_files[i].alt_filename = xstrdup (filename);
-          if (old_filename && filename != old_filename)
-            free (CONST_CAST (char *, old_filename));
-        }
+      if ((m_extra_dump_files[i].pass_optgroup_flags & optgroup_flags))
+	{
+	  const char *old_filename = m_extra_dump_files[i].alt_filename;
+	  /* Since this file is shared among different passes, it
+	     should be opened in append mode.  */
+	  m_extra_dump_files[i].alt_state = 1;
+	  m_extra_dump_files[i].optgroup_flags |= optgroup_flags;
+	  n++;
+	  /* Override the existing filename.  */
+	  if (filename)
+	    m_extra_dump_files[i].alt_filename = xstrdup (filename);
+	  if (old_filename && filename != old_filename)
+	    free (CONST_CAST (char *, old_filename));
+	}
     }
 
   return n;
@@ -929,101 +962,49 @@  dump_switch_p (const char *arg)
   return any;
 }
 
-void
-gcc::dump_manager::
-initialize_options ()
-{
-  /* Initialize optgroup options.  */
-  typedef dump_option_node<optgroup_types> node;
-
-  optgroup_options = new node (NULL, OPTGROUP_NONE);
-  optgroup_options->register_suboption (new node ("ipa", OPTGROUP_IPA));
-  optgroup_options->register_suboption (new node ("loop", OPTGROUP_LOOP));
-  optgroup_options->register_suboption (new node ("inline", OPTGROUP_INLINE));
-  optgroup_options->register_suboption (new node ("omp", OPTGROUP_OMP));
-  optgroup_options->register_suboption (new node ("vec", OPTGROUP_VEC));
-  optgroup_options->register_suboption (new node ("other", OPTGROUP_OTHER));
-
-  optgroup_options->initialize (optgroup_dump_flags_t::m_mask_translation);
-}
+static optgroup_option_hierarchy optgroup_options __attribute__
+((init_priority((200))));
 
 /* Parse ARG as a -fopt-info switch and store flags, optgroup_flags
    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,
-		     optgroup_dump_flags_t *optgroup_flags,
+opt_info_switch_p_1 (const char *arg, optgroup_dump_flags_t *optgroup_flags,
 		     char **filename)
 {
-  const char *option_value;
-  const char *ptr;
-  optgroup_dump_flags_t f;
-  gcc::dump_manager *dumps = g->get_dumps ();
-
-  option_value = arg;
-  ptr = option_value;
-
+  char *option_value;
   *filename = NULL;
-  *flags = 0;
-  *optgroup_flags = 0;
+  *optgroup_flags = optgroup_dump_flags_t ();
 
-  if (!ptr)
+  if (!arg)
     return 1;       /* Handle '-fopt-info' without any additional options.  */
 
+  option_value = xstrdup (arg);
 
-  while (*ptr)
+  char *eq_ptr = strchr (option_value, '=');
+  if (eq_ptr)
     {
-      const struct dump_option_value_info *option_ptr;
-      const char *end_ptr;
-      const char *eq_ptr;
-      unsigned length;
-
-      while (*ptr == '-')
-	ptr++;
-      end_ptr = strchr (ptr, '-');
-      eq_ptr = strchr (ptr, '=');
-
-      if (eq_ptr && !end_ptr)
-        end_ptr = eq_ptr;
-
-      if (!end_ptr)
-	end_ptr = ptr + strlen (ptr);
-      length = end_ptr - ptr;
-
-      for (option_ptr = optinfo_verbosity_options; option_ptr->name;
-           option_ptr++)
-	if (strlen (option_ptr->name) == length
-	    && !memcmp (option_ptr->name, ptr, length))
-          {
-	    *flags |= option_ptr->value;
-	    goto found;
-	  }
+      *filename = xstrdup (eq_ptr + 1);
+      *eq_ptr = '\0';
+    }
 
-      f = dumps->get_optgroup_options ()->parse (ptr);
-      if (f)
-	{
-	  *optgroup_flags |= f;
-	  goto found;
-	}
 
-      if (*ptr == '=')
-        {
-          /* Interpret rest of the argument as a dump filename.  This
-             filename overrides other command line filenames.  */
-          *filename = xstrdup (ptr + 1);
-          break;
-        }
-      else
-        {
-          warning (0, "unknown option %q.*s in %<-fopt-info-%s%>",
-                   length, ptr, arg);
-          return 0;
-        }
-    found:;
-      ptr = end_ptr;
+  optgroup_dump_flags_t f;
+  f = optgroup_dump_flags_t::from_mask
+    (optgroup_options.root->parse (option_value));
+  if (f)
+    {
+      *optgroup_flags |= f;
+      free (option_value);
+      return 1;
+    }
+  else
+    {
+      warning (0, "unknown option %s in %<-fopt-info-%s%>",
+	       option_value, option_value);
+      free (option_value);
+      return 0;
     }
-
-  return 1;
 }
 
 /* Return non-zero if ARG is a recognized switch for
@@ -1032,13 +1013,12 @@  opt_info_switch_p_1 (const char *arg, dump_flags_t *flags,
 int
 opt_info_switch_p (const char *arg)
 {
-  dump_flags_t flags;
   optgroup_dump_flags_t optgroup_flags;
   char *filename;
   static char *file_seen = NULL;
   gcc::dump_manager *dumps = g->get_dumps ();
 
-  if (!opt_info_switch_p_1 (arg, &flags, &optgroup_flags, &filename))
+  if (!opt_info_switch_p_1 (arg, &optgroup_flags, &filename))
     return 0;
 
   if (!filename)
@@ -1053,12 +1033,10 @@  opt_info_switch_p (const char *arg)
     }
 
   file_seen = xstrdup (filename);
-  if (!flags)
-    flags = MSG_OPTIMIZED_LOCATIONS;
   if (!optgroup_flags)
     optgroup_flags = optgroup_dump_flags_t::get_all ();
 
-  return dumps->opt_info_enable_passes (optgroup_flags, flags, filename);
+  return dumps->opt_info_enable_passes (optgroup_flags, filename);
 }
 
 /* Print basic block on the dump streams.  */
@@ -1068,7 +1046,7 @@  dump_basic_block (int dump_kind, basic_block bb, int indent)
 {
   if (dump_file && (dump_kind & pflags))
     dump_bb (dump_file, bb, indent, TDF_DETAILS);
-  if (alt_dump_file && (dump_kind & alt_flags))
+  if (alt_dump_file && (dump_kind & opt_info_flags))
     dump_bb (alt_dump_file, bb, indent, TDF_DETAILS);
 }
 
diff --git a/gcc/dumpfile.h b/gcc/dumpfile.h
index 67da7003331..bcd70198901 100644
--- a/gcc/dumpfile.h
+++ b/gcc/dumpfile.h
@@ -84,11 +84,6 @@  enum tree_dump_index
 #define TDF_SCEV	(1 << 24)	/* Dump SCEV details.  */
 #define TDF_COMMENT	(1 << 25)	/* Dump lines with prefix ";;"  */
 #define TDF_GIMPLE	(1 << 26)	/* Dump in GIMPLE FE syntax  */
-#define MSG_OPTIMIZED_LOCATIONS  (1 << 27)  /* -fopt-info optimized sources */
-#define MSG_MISSED_OPTIMIZATION  (1 << 28)  /* missed opportunities */
-#define MSG_NOTE                 (1 << 29)  /* general optimization info */
-#define MSG_ALL         (MSG_OPTIMIZED_LOCATIONS | MSG_MISSED_OPTIMIZATION \
-                         | MSG_NOTE)
 
 /* Dump option node is a tree structure that implements
    parsing of suboptions and provides mapping between a given enum type E
@@ -106,6 +101,9 @@  struct dump_option_node
   /* Parse a given option string and return mask.  */
   uint64_t parse (const char *token);
 
+  /* Parse a given option string and return mask.  */
+  uint64_t parse (char *token);
+
   /* Register a SUBOPTION for a dump option node.  */
   void register_suboption (dump_option_node<E> *suboption)
   {
@@ -118,7 +116,7 @@  private:
   uint64_t initialize_masks (unsigned *current, uint64_t *mask_translation);
 
   /* Parse a given option string and return mask.  */
-  uint64_t parse (char *token);
+  uint64_t parse_internal (char *token);
 
   /* Name of the option.  */
   const char *m_name;
@@ -146,15 +144,21 @@  struct dump_flags_type
   dump_flags_type<E> (): m_mask (0)
   {}
 
-  /* Constructor for a MASK.  */
-  dump_flags_type<E> (uint64_t mask): m_mask (mask)
-  {}
-
   /* Constructor for a enum value E.  */
   dump_flags_type<E> (E enum_value)
   {
     gcc_checking_assert ((unsigned)enum_value <= OPT_MASK_SIZE);
     m_mask = m_mask_translation[enum_value];
+    gcc_checking_assert (m_mask != 0);
+  }
+
+  /* Constructor for two enum values.  */
+  dump_flags_type<E> (E enum_value, E enum_value2)
+  {
+    gcc_checking_assert ((unsigned)enum_value <= OPT_MASK_SIZE);
+    gcc_checking_assert ((unsigned)enum_value2 <= OPT_MASK_SIZE);
+    m_mask = m_mask_translation[enum_value] | m_mask_translation[enum_value2];
+    gcc_checking_assert (m_mask != 0);
   }
 
   /* OR operator for OTHER dump_flags_type.  */
@@ -181,6 +185,12 @@  struct dump_flags_type
     return m_mask;
   }
 
+  /* Return dump_flags_type for a computed mask.  */
+  static inline dump_flags_type from_mask (uint64_t mask)
+  {
+    return dump_flags_type (mask);
+  }
+
   /* Return mask that represents all selected options.  */
   static inline dump_flags_type get_all ()
   {
@@ -195,6 +205,12 @@  struct dump_flags_type
 
   /* Translation table between enum values and masks.  */
   static uint64_t m_mask_translation[OPT_MASK_SIZE];
+
+private:
+  /* Constructor.  */
+  dump_flags_type<E> (uint64_t mask): m_mask (mask)
+  {}
+
 };
 
 /* Flags used for -fopt-info groups.  */
@@ -203,11 +219,29 @@  enum optgroup_types
 {
   OPTGROUP_NONE,
   OPTGROUP_IPA,
+  OPTGROUP_IPA_OPTIMIZED,
+  OPTGROUP_IPA_MISSED,
+  OPTGROUP_IPA_NOTE,
   OPTGROUP_LOOP,
+  OPTGROUP_LOOP_OPTIMIZED,
+  OPTGROUP_LOOP_MISSED,
+  OPTGROUP_LOOP_NOTE,
   OPTGROUP_INLINE,
+  OPTGROUP_INLINE_OPTIMIZED,
+  OPTGROUP_INLINE_MISSED,
+  OPTGROUP_INLINE_NOTE,
   OPTGROUP_OMP,
+  OPTGROUP_OMP_OPTIMIZED,
+  OPTGROUP_OMP_MISSED,
+  OPTGROUP_OMP_NOTE,
   OPTGROUP_VEC,
+  OPTGROUP_VEC_OPTIMIZED,
+  OPTGROUP_VEC_MISSED,
+  OPTGROUP_VEC_NOTE,
   OPTGROUP_OTHER,
+  OPTGROUP_OTHER_OPTIMIZED,
+  OPTGROUP_OTHER_MISSED,
+  OPTGROUP_OTHER_NOTE,
   OPTGROUP_COUNT
 };
 
@@ -226,20 +260,21 @@  typedef uint64_t dump_flags_t;
 /* Define a tree dump switch.  */
 struct dump_file_info
 {
-  const char *suffix;           /* suffix to give output file.  */
-  const char *swtch;            /* command line dump switch */
-  const char *glob;             /* command line glob  */
-  const char *pfilename;        /* filename for the pass-specific stream  */
+  const char *suffix;		/* suffix to give output file.  */
+  const char *swtch;		/* command line dump switch */
+  const char *glob;		/* command line glob  */
+  const char *pfilename;	/* filename for the pass-specific stream  */
   const char *alt_filename;     /* filename for the -fopt-info stream  */
-  FILE *pstream;                /* pass-specific dump stream  */
-  FILE *alt_stream;             /* -fopt-info stream */
+  FILE *pstream;		/* pass-specific dump stream  */
+  FILE *alt_stream;		/* -fopt-info stream */
   dump_flags_t pflags;		/* dump flags */
-  optgroup_dump_flags_t optgroup_flags; /* optgroup flags for -fopt-info */
-  int alt_flags;                /* flags for opt-info */
-  int pstate;                   /* state of pass-specific stream */
-  int alt_state;                /* state of the -fopt-info stream */
-  int num;                      /* dump file number */
-  bool owns_strings;            /* fields "suffix", "swtch", "glob" can be
+  optgroup_dump_flags_t pass_optgroup_flags; /* a pass flags for -fopt-info */
+  optgroup_dump_flags_t optgroup_flags; /* flags for -fopt-info given
+					   by a user */
+  int pstate;			/* state of pass-specific stream */
+  int alt_state;		/* state of the -fopt-info stream */
+  int num;			/* dump file number */
+  bool owns_strings;		/* fields "suffix", "swtch", "glob" can be
 				   const strings, or can be dynamically
 				   allocated, needing free.  */
   bool graph_dump_initialized;  /* When a given dump file is being initialized,
@@ -253,15 +288,18 @@  extern FILE *dump_begin (int, dump_flags_t *);
 extern void dump_end (int, FILE *);
 extern int opt_info_switch_p (const char *);
 extern const char *dump_flag_name (int);
-extern void dump_printf (dump_flags_t, const char *, ...) ATTRIBUTE_PRINTF_2;
-extern void dump_printf_loc (dump_flags_t, source_location,
+extern void dump_printf (optgroup_dump_flags_t,
+			 const char *, ...) ATTRIBUTE_PRINTF_2;
+extern void dump_printf_loc (optgroup_dump_flags_t, source_location,
                              const char *, ...) ATTRIBUTE_PRINTF_3;
-extern void dump_basic_block (int, basic_block, int);
-extern void dump_generic_expr_loc (int, source_location, int, tree);
-extern void dump_generic_expr (dump_flags_t, dump_flags_t, tree);
-extern void dump_gimple_stmt_loc (dump_flags_t, source_location, dump_flags_t,
-				  gimple *, int);
-extern void dump_gimple_stmt (dump_flags_t, dump_flags_t, gimple *, int);
+extern void dump_basic_block (optgroup_dump_flags_t, basic_block, int);
+extern void dump_generic_expr_loc (optgroup_dump_flags_t, source_location,
+				   int, tree);
+extern void dump_generic_expr (optgroup_dump_flags_t, dump_flags_t, tree);
+extern void dump_gimple_stmt_loc (optgroup_dump_flags_t, source_location,
+				  dump_flags_t, gimple *, int);
+extern void dump_gimple_stmt (optgroup_dump_flags_t, dump_flags_t, gimple *,
+			      int);
 extern void print_combine_total_stats (void);
 extern bool enable_rtl_dump_file (void);
 
@@ -286,6 +324,20 @@  dump_enabled_p (void)
   return (dump_file || alt_dump_file);
 }
 
+/* Optgroup option hierarchy.  */
+
+struct optgroup_option_hierarchy
+{
+  /* Contructor.  */
+  optgroup_option_hierarchy();
+
+  /* Initialize optgroup options.  */
+  typedef dump_option_node<optgroup_types> node;
+
+  /* Root option node.  */
+  node *root;
+};
+
 namespace gcc {
 
 class dump_manager
@@ -346,12 +398,6 @@  public:
   const char *
   dump_flag_name (int phase) const;
 
-  /* Return optgroup_types dump options.  */
-  dump_option_node<optgroup_types> *get_optgroup_options ()
-  {
-    return optgroup_options;
-  }
-
 private:
 
   int
@@ -365,9 +411,7 @@  private:
 
   int
   opt_info_enable_passes (optgroup_dump_flags_t optgroup_flags,
-			  dump_flags_t flags, const char *filename);
-
-  void initialize_options ();
+			  const char *filename);
 
 private:
 
@@ -377,9 +421,6 @@  private:
   size_t m_extra_dump_files_in_use;
   size_t m_extra_dump_files_alloced;
 
-  /* Dump option node for optgroup_types enum.  */
-  dump_option_node<optgroup_types> *optgroup_options;
-
   /* Grant access to dump_enable_all.  */
   friend bool ::enable_rtl_dump_file (void);
 
diff --git a/gcc/passes.c b/gcc/passes.c
index a607e3e6bc2..ce488bc6328 100644
--- a/gcc/passes.c
+++ b/gcc/passes.c
@@ -779,7 +779,7 @@  pass_manager::register_one_dump_file (opt_pass *pass)
   char num[11];
   dump_flags_t flags;
   int id;
-  int optgroup_flags = OPTGROUP_NONE;
+  optgroup_dump_flags_t optgroup_flags;
   gcc::dump_manager *dumps = m_ctxt->get_dumps ();
 
   /* See below in next_pass_1.  */
diff --git a/gcc/tree-pass.h b/gcc/tree-pass.h
index 85bfba7ac28..1ce8a7afe8f 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_dump_flags_t optinfo_flags;
 
   /* The timevar id associated with this pass.  */
   /* ??? Ideally would be dynamically assigned.  */
-- 
2.12.2