Support profile (BB counts and edge probabilities) in GIMPLE FE.
authorMartin Liska <mliska@suse.cz>
Thu, 9 May 2019 13:03:28 +0000 (15:03 +0200)
committerMartin Liska <marxin@gcc.gnu.org>
Thu, 9 May 2019 13:03:28 +0000 (13:03 +0000)
2019-05-09  Martin Liska  <mliska@suse.cz>

* tree-cfg.c (dump_function_to_file): Dump entry BB count.
* gimple-pretty-print.c (dump_gimple_bb_header):
Dump BB count.
(pp_cfg_jump): Dump edge probability.
* profile-count.c (profile_quality_as_string): Simplify
with a static array.
(parse_profile_quality): New function.
(profile_count::dump): Simplify with a static array.
(profile_count::from_gcov_type): Add new argument.
* profile-count.h (parse_profile_quality): Likewise.
* predict.h (set_hot_bb_threshold): New.
* params.def (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD):
New param.
* predict.c (get_hot_bb_threshold): Set from the new param.
(set_hot_bb_threshold): New.
2019-05-09  Martin Liska  <mliska@suse.cz>

* gimple-parser.c (struct gimple_parser): Add probability.
for gimple_parser_edge.
(gimple_parser::push_edge): Add new argument probability.
(c_parser_gimple_parse_bb_spec): Parse also probability
if present.
(c_parser_parse_gimple_body): Set edge probability.
(c_parser_gimple_compound_statement): Consume token
before calling c_parser_gimple_goto_stmt.
Parse BB counts.
(c_parser_gimple_statement): Pass new argument.
(c_parser_gimple_goto_stmt): Likewise.
(c_parser_gimple_if_stmt): Likewise.
(c_parser_gimple_or_rtl_pass_list): Parse hot_bb_threshold.
* c-parser.c (c_parser_declaration_or_fndef): Pass
hot_bb_threshold argument.
* c-tree.h (struct c_declspecs): Add hot_bb_threshold
field.
(c_parser_gimple_parse_bb_spec_edge_probability): New.
2019-05-09  Martin Liska  <mliska@suse.cz>

* gcc.dg/gimplefe-37.c: New test.
* gcc.dg/gimplefe-33.c: Likewise.

From-SVN: r271034

15 files changed:
gcc/ChangeLog
gcc/c/ChangeLog
gcc/c/c-parser.c
gcc/c/c-tree.h
gcc/c/gimple-parser.c
gcc/c/gimple-parser.h
gcc/gimple-pretty-print.c
gcc/params.def
gcc/predict.c
gcc/profile-count.c
gcc/profile-count.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/gimplefe-37.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gimplefe-38.c [new file with mode: 0644]
gcc/tree-cfg.c

index 35badb9..45360fa 100644 (file)
@@ -1,3 +1,21 @@
+2019-05-09  Martin Liska  <mliska@suse.cz>
+
+       * tree-cfg.c (dump_function_to_file): Dump entry BB count.
+       * gimple-pretty-print.c (dump_gimple_bb_header):
+       Dump BB count.
+       (pp_cfg_jump): Dump edge probability.
+       * profile-count.c (profile_quality_as_string): Simplify
+       with a static array.
+       (parse_profile_quality): New function.
+       (profile_count::dump): Simplify with a static array.
+       (profile_count::from_gcov_type): Add new argument.
+       * profile-count.h (parse_profile_quality): Likewise.
+       * predict.h (set_hot_bb_threshold): New.
+       * params.def (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD):
+       New param.
+       * predict.c (get_hot_bb_threshold): Set from the new param.
+       (set_hot_bb_threshold): New.
+
 2019-05-09  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/90395
index ef192bf..67f0e08 100644 (file)
@@ -1,3 +1,24 @@
+2019-05-09  Martin Liska  <mliska@suse.cz>
+
+       * gimple-parser.c (struct gimple_parser): Add probability.
+       for gimple_parser_edge.
+       (gimple_parser::push_edge): Add new argument probability.
+       (c_parser_gimple_parse_bb_spec): Parse also probability
+       if present.
+       (c_parser_parse_gimple_body): Set edge probability.
+       (c_parser_gimple_compound_statement): Consume token
+       before calling c_parser_gimple_goto_stmt.
+       Parse BB counts.
+       (c_parser_gimple_statement): Pass new argument.
+       (c_parser_gimple_goto_stmt): Likewise.
+       (c_parser_gimple_if_stmt): Likewise.
+       (c_parser_gimple_or_rtl_pass_list): Parse hot_bb_threshold.
+       * c-parser.c (c_parser_declaration_or_fndef): Pass
+       hot_bb_threshold argument.
+       * c-tree.h (struct c_declspecs): Add hot_bb_threshold
+       field.
+       (c_parser_gimple_parse_bb_spec_edge_probability): New.
+
 2019-04-26  Jakub Jelinek  <jakub@redhat.com>
 
        PR debug/90197
index 854cd6c..3aa8512 100644 (file)
@@ -2347,7 +2347,8 @@ c_parser_declaration_or_fndef (c_parser *parser, bool fndef_ok,
          bool saved = in_late_binary_op;
          in_late_binary_op = true;
          c_parser_parse_gimple_body (parser, specs->gimple_or_rtl_pass,
-                                     specs->declspec_il);
+                                     specs->declspec_il,
+                                     specs->entry_bb_count);
          in_late_binary_op = saved;
        }
       else
index 7e35ab1..346f46a 100644 (file)
@@ -317,6 +317,8 @@ struct c_declspecs {
   tree attrs;
   /* The pass to start compiling a __GIMPLE or __RTL function with.  */
   char *gimple_or_rtl_pass;
+  /* ENTRY BB count.  */
+  profile_count entry_bb_count;
   /* The base-2 log of the greatest alignment required by an _Alignas
      specifier, in bytes, or -1 if no such specifiers with nonzero
      alignment.  */
index fff3460..ede5a92 100644 (file)
@@ -63,6 +63,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "tree-phinodes.h"
 #include "tree-into-ssa.h"
 #include "bitmap.h"
+#include "params.h"
 
 
 /* GIMPLE parser state.  */
@@ -81,20 +82,23 @@ struct gimple_parser
     int src;
     int dest;
     int flags;
+    profile_probability probability;
   };
   auto_vec<gimple_parser_edge> edges;
   basic_block current_bb;
 
-  void push_edge (int, int, int);
+  void push_edge (int, int, int, profile_probability);
 };
 
 void
-gimple_parser::push_edge (int src, int dest, int flags)
+gimple_parser::push_edge (int src, int dest, int flags,
+                         profile_probability prob)
 {
   gimple_parser_edge e;
   e.src = src;
   e.dest = dest;
   e.flags = flags;
+  e.probability = prob;
   edges.safe_push (e);
 }
 
@@ -120,7 +124,7 @@ static void c_parser_gimple_expr_list (gimple_parser &, vec<tree> *);
 
 
 /* See if VAL is an identifier matching __BB<num> and return <num>
-   in *INDEX.  Return true if so.  */
+   in *INDEX.  */
 
 static bool
 c_parser_gimple_parse_bb_spec (tree val, int *index)
@@ -134,11 +138,77 @@ c_parser_gimple_parse_bb_spec (tree val, int *index)
   return *index > 0;
 }
 
+/* See if VAL is an identifier matching __BB<num> and return <num>
+   in *INDEX.  Return true if so and parse also FREQUENCY of
+   the edge.  */
+
+
+static bool
+c_parser_gimple_parse_bb_spec_edge_probability (tree val,
+                                               gimple_parser &parser,
+                                               int *index,
+                                               profile_probability *probablity)
+{
+  bool return_p = c_parser_gimple_parse_bb_spec (val, index);
+  if (return_p)
+    {
+      *probablity = profile_probability::uninitialized ();
+      /* Parse frequency if provided.  */
+      if (c_parser_next_token_is (parser, CPP_OPEN_PAREN))
+       {
+         tree f;
+         c_parser_consume_token (parser);
+         if (!c_parser_next_token_is (parser, CPP_NAME))
+           {
+             c_parser_error (parser, "expected frequency quality");
+             return false;
+           }
+
+         profile_quality quality;
+         const char *v
+           = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
+         if (!parse_profile_quality (v, &quality))
+           {
+             c_parser_error (parser, "unknown profile quality");
+             return false;
+           }
+
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           return false;
+
+         if (!c_parser_next_token_is (parser, CPP_NUMBER)
+             || (TREE_CODE (f = c_parser_peek_token (parser)->value)
+                 != INTEGER_CST))
+           {
+             c_parser_error (parser, "expected frequency value");
+             return false;
+           }
+
+         unsigned int value = TREE_INT_CST_LOW (f);
+         *probablity = profile_probability (value, quality);
+
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+           return false;
+
+         if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+           return false;
+       }
+
+      return true;
+    }
+
+  return false;
+
+}
+
 /* Parse the body of a function declaration marked with "__GIMPLE".  */
 
 void
 c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
-                           enum c_declspec_il cdil)
+                           enum c_declspec_il cdil,
+                           profile_count entry_bb_count)
 {
   gimple_parser parser (cparser);
   gimple_seq seq = NULL;
@@ -209,9 +279,12 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
          add_local_decl (cfun, var);
       /* We have a CFG.  Build the edges.  */
       for (unsigned i = 0; i < parser.edges.length (); ++i)
-       make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
-                  BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
-                  parser.edges[i].flags);
+       {
+         edge e = make_edge (BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].src),
+                             BASIC_BLOCK_FOR_FN (cfun, parser.edges[i].dest),
+                             parser.edges[i].flags);
+         e->probability = parser.edges[i].probability;
+       }
       /* Add edges for case labels.  */
       basic_block bb;
       FOR_EACH_BB_FN (bb, cfun)
@@ -274,6 +347,13 @@ c_parser_parse_gimple_body (c_parser *cparser, char *gimple_pass,
       fix_loop_structure (NULL);
     }
 
+  if (cfun->curr_properties & PROP_cfg)
+    {
+      ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = entry_bb_count;
+      gcov_type t = PARAM_VALUE (PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD);
+      set_hot_bb_threshold (t);
+      update_max_bb_count ();
+    }
   dump_function (TDI_gimple, current_function_decl);
 }
 
@@ -337,11 +417,9 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                c_parser_consume_token (parser);
                if (c_parser_next_token_is (parser, CPP_NAME))
                  {
-                   c_parser_gimple_goto_stmt (parser, loc,
-                                              c_parser_peek_token
-                                              (parser)->value,
-                                              seq);
+                   tree label = c_parser_peek_token (parser)->value;
                    c_parser_consume_token (parser);
+                   c_parser_gimple_goto_stmt (parser, loc, label, seq);
                    if (! c_parser_require (parser, CPP_SEMICOLON,
                                            "expected %<;%>"))
                      return return_p;
@@ -355,7 +433,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                                      "expected %<;%>"))
                return return_p;
              if (cfun->curr_properties & PROP_cfg)
-               parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0);
+               parser.push_edge (parser.current_bb->index, EXIT_BLOCK, 0,
+                                 profile_probability::uninitialized ());
              break;
            default:
              goto expr_stmt;
@@ -397,6 +476,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                  return return_p;
                }
              int is_loop_header_of = -1;
+             profile_count bb_count = profile_count::uninitialized ();
              c_parser_consume_token (parser);
              while (c_parser_next_token_is (parser, CPP_COMMA))
                {
@@ -430,10 +510,39 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                                              "expected %<)%>"))
                        return return_p;
                    }
+                 /* Parse profile: quality(value) */
                  else
                    {
-                     c_parser_error (parser, "unknown block specifier");
-                     return return_p;
+                     tree q;
+                     profile_quality quality;
+                     tree v = c_parser_peek_token (parser)->value;
+                     if (!parse_profile_quality (IDENTIFIER_POINTER (v),
+                                                 &quality))
+                       {
+                         c_parser_error (parser, "unknown block specifier");
+                         return false;
+                       }
+
+                     c_parser_consume_token (parser);
+                     if (!c_parser_require (parser, CPP_OPEN_PAREN,
+                                            "expected %<(%>"))
+                       return false;
+
+                     if (!c_parser_next_token_is (parser, CPP_NUMBER)
+                         || (TREE_CODE (q = c_parser_peek_token (parser)->value)
+                             != INTEGER_CST))
+                       {
+                         c_parser_error (parser, "expected count value");
+                         return false;
+                       }
+
+                     bb_count
+                       = profile_count::from_gcov_type (TREE_INT_CST_LOW (q),
+                                                        quality);
+                     c_parser_consume_token (parser);
+                     if (! c_parser_require (parser, CPP_CLOSE_PAREN,
+                                             "expected %<)%>"))
+                       return return_p;
                    }
                }
              if (! c_parser_require (parser, CPP_CLOSE_PAREN,
@@ -470,7 +579,8 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                last_basic_block_for_fn (cfun) = index + 1;
              n_basic_blocks_for_fn (cfun)++;
              if (!parser.current_bb)
-               parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU);
+               parser.push_edge (ENTRY_BLOCK, bb->index, EDGE_FALLTHRU,
+                                 profile_probability::always ());
 
              /* We leave the proper setting to fixup.  */
              struct loop *loop_father = loops_for_fn (cfun)->tree_root;
@@ -498,6 +608,7 @@ c_parser_gimple_compound_statement (gimple_parser &parser, gimple_seq *seq)
                  loop_father = get_loop (cfun, is_loop_header_of);
                }
              bb->loop_father = loop_father;
+             bb->count = bb_count;
 
              /* Stmts now go to the new block.  */
              parser.current_bb = bb;
@@ -1609,8 +1720,10 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
     return;
   c_parser_consume_token (parser);
 
+  specs->entry_bb_count = profile_count::uninitialized ();
   while (c_parser_next_token_is (parser, CPP_NAME))
     {
+      profile_quality quality;
       const char *op = IDENTIFIER_POINTER (c_parser_peek_token (parser)->value);
       c_parser_consume_token (parser);
       if (! strcmp (op, "startwith"))
@@ -1629,6 +1742,26 @@ c_parser_gimple_or_rtl_pass_list (c_parser *parser, c_declspecs *specs)
          if (! c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<(%>"))
            return;
        }
+      else if (parse_profile_quality (op, &quality))
+       {
+         tree q;
+         if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+           return;
+
+         if (!c_parser_next_token_is (parser, CPP_NUMBER)
+             || (TREE_CODE (q = c_parser_peek_token (parser)->value)
+                 != INTEGER_CST))
+           {
+             c_parser_error (parser, "expected count value");
+             return;
+           }
+
+         specs->entry_bb_count
+           = profile_count::from_gcov_type (TREE_INT_CST_LOW (q), quality);
+         c_parser_consume_token (parser);
+         if (!c_parser_require (parser, CPP_CLOSE_PAREN, "expected %<)%>"))
+           return;
+       }
       else if (specs->declspec_il != cdil_gimple)
        /* Allow only one IL specifier and none on RTL.  */
        ;
@@ -1757,10 +1890,12 @@ c_parser_gimple_goto_stmt (gimple_parser &parser,
   if (cfun->curr_properties & PROP_cfg)
     {
       int dest_index;
-      if (c_parser_gimple_parse_bb_spec (label, &dest_index))
+      profile_probability prob;
+      if (c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
+                                                         &dest_index, &prob))
        {
          parser.push_edge (parser.current_bb->index, dest_index,
-                           EDGE_FALLTHRU);
+                           EDGE_FALLTHRU, prob);
          return;
        }
     }
@@ -1811,10 +1946,12 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
       label = c_parser_peek_token (parser)->value;
       c_parser_consume_token (parser);
       int dest_index;
+      profile_probability prob;
       if ((cfun->curr_properties & PROP_cfg)
-         && c_parser_gimple_parse_bb_spec (label, &dest_index))
+         && c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
+                                                            &dest_index, &prob))
        parser.push_edge (parser.current_bb->index, dest_index,
-                         EDGE_TRUE_VALUE);
+                         EDGE_TRUE_VALUE, prob);
       else
        t_label = lookup_label_for_goto (loc, label);
       if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
@@ -1844,14 +1981,16 @@ c_parser_gimple_if_stmt (gimple_parser &parser, gimple_seq *seq)
          return;
        }
       label = c_parser_peek_token (parser)->value;
+      c_parser_consume_token (parser);
       int dest_index;
+      profile_probability prob;
       if ((cfun->curr_properties & PROP_cfg)
-         && c_parser_gimple_parse_bb_spec (label, &dest_index))
+         && c_parser_gimple_parse_bb_spec_edge_probability (label, parser,
+                                                            &dest_index, &prob))
        parser.push_edge (parser.current_bb->index, dest_index,
-                         EDGE_FALSE_VALUE);
+                         EDGE_FALSE_VALUE, prob);
       else
        f_label = lookup_label_for_goto (loc, label);
-      c_parser_consume_token (parser);
       if (! c_parser_require (parser, CPP_SEMICOLON, "expected %<;%>"))
        return;
     }
index 383ad76..cc28c0f 100644 (file)
@@ -22,7 +22,8 @@ along with GCC; see the file COPYING3.  If not see
 
 /* Gimple parsing functions.  */
 extern void c_parser_parse_gimple_body (c_parser *, char *,
-                                       enum c_declspec_il);
+                                       enum c_declspec_il,
+                                       profile_count);
 extern void c_parser_gimple_or_rtl_pass_list (c_parser *, c_declspecs *);
 
 #endif
index 69bae0d..7e3916b 100644 (file)
@@ -2704,6 +2704,10 @@ dump_gimple_bb_header (FILE *outf, basic_block bb, int indent,
          fprintf (outf, "%*s__BB(%d", indent, "", bb->index);
          if (bb->loop_father->header == bb)
            fprintf (outf, ",loop_header(%d)", bb->loop_father->num);
+         if (bb->count.initialized_p ())
+           fprintf (outf, ",%s(%d)",
+                    profile_quality_as_string (bb->count.quality ()),
+                    bb->count.value ());
          fprintf (outf, "):\n");
        }
       else
@@ -2760,6 +2764,15 @@ pp_cfg_jump (pretty_printer *buffer, edge e, dump_flags_t flags)
     {
       pp_string (buffer, "goto __BB");
       pp_decimal_int (buffer, e->dest->index);
+      if (e->probability.initialized_p ())
+       {
+         pp_string (buffer, "(");
+         pp_string (buffer,
+                    profile_quality_as_string (e->probability.quality ()));
+         pp_string (buffer, "(");
+         pp_decimal_int (buffer, e->probability.value ());
+         pp_string (buffer, "))");
+       }
       pp_semicolon (buffer);
     }
   else
index 904b3cb..5830cb5 100644 (file)
@@ -1419,6 +1419,12 @@ DEFPARAM(PARAM_LOOP_VERSIONING_MAX_OUTER_INSNS,
         " loops.",
         100, 0, 0)
 
+DEFPARAM(PARAM_GIMPLE_FE_COMPUTED_HOT_BB_THRESHOLD,
+        "gimple-fe-computed-hot-bb-threshold",
+        "The number of executions of a basic block which is considered hot."
+        " The parameters is used only in GIMPLE FE.",
+        0, 0, 0)
+
 /*
 
 Local variables:
index b010c20..ad19d12 100644 (file)
@@ -132,8 +132,8 @@ get_hot_bb_threshold ()
 {
   if (min_count == -1)
     {
-      min_count
-       = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
+      gcov_type t = profile_info->sum_max / PARAM_VALUE (HOT_BB_COUNT_FRACTION);
+      set_hot_bb_threshold (t);
       if (dump_file)
        fprintf (dump_file, "Setting hotness threshold to %" PRId64 ".\n",
                 min_count);
index 8c58f86..4f0bac0 100644 (file)
@@ -33,34 +33,57 @@ along with GCC; see the file COPYING3.  If not see
 #include "wide-int.h"
 #include "sreal.h"
 
+/* Names from profile_quality enum values.  */
+
+const char *profile_quality_names[] =
+{
+  "uninitialized",
+  "guessed_local",
+  "guessed_global0",
+  "guessed_global0adjusted",
+  "guessed",
+  "afdo",
+  "adjusted",
+  "precise"
+};
+
 /* Get a string describing QUALITY.  */
 
 const char *
 profile_quality_as_string (enum profile_quality quality)
 {
-  switch (quality)
-    {
-    default:
-      gcc_unreachable ();
-    case profile_uninitialized:
-      return "uninitialized";
-    case profile_guessed_local:
-      return "guessed_local";
-    case profile_guessed_global0:
-      return "guessed_global0";
-    case profile_guessed_global0adjusted:
-      return "guessed_global0adjusted";
-    case profile_guessed:
-      return "guessed";
-    case profile_afdo:
-      return "afdo";
-    case profile_adjusted:
-      return "adjusted";
-    case profile_precise:
-      return "precise";
-    }
+  return profile_quality_names[quality];
+}
+
+/* Parse VALUE as profile quality and return true when a valid QUALITY.  */
+
+bool
+parse_profile_quality (const char *value, profile_quality *quality)
+{
+  for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
+    if (strcmp (profile_quality_names[i], value) == 0)
+      {
+       *quality = (profile_quality)i;
+       return true;
+      }
+
+  return false;
 }
 
+/* Display names from profile_quality enum values.  */
+
+const char *profile_quality_display_names[] =
+{
+  NULL,
+  "estimated locally",
+  "estimated locally, globally 0",
+  "estimated locally, globally 0 adjusted",
+  "adjusted",
+  "auto FDO",
+  "guessed",
+  "precise"
+};
+
 /* Dump THIS to F.  */
 
 void
@@ -69,23 +92,8 @@ profile_count::dump (FILE *f) const
   if (!initialized_p ())
     fprintf (f, "uninitialized");
   else
-    {
-      fprintf (f, "%" PRId64, m_val);
-      if (m_quality == profile_guessed_local)
-       fprintf (f, " (estimated locally)");
-      else if (m_quality == profile_guessed_global0)
-       fprintf (f, " (estimated locally, globally 0)");
-      else if (m_quality == profile_guessed_global0adjusted)
-       fprintf (f, " (estimated locally, globally 0 adjusted)");
-      else if (m_quality == profile_adjusted)
-       fprintf (f, " (adjusted)");
-      else if (m_quality == profile_afdo)
-       fprintf (f, " (auto FDO)");
-      else if (m_quality == profile_guessed)
-       fprintf (f, " (guessed)");
-      else if (m_quality == profile_precise)
-       fprintf (f, " (precise)");
-    }
+    fprintf (f, "%" PRId64 " (%s)", m_val,
+            profile_quality_display_names[m_quality]);
 }
 
 /* Dump THIS to stderr.  */
@@ -362,7 +370,7 @@ profile_count::combine_with_ipa_count (profile_count ipa)
    Conversions back and forth are used to read the coverage and get it
    into internal representation.  */
 profile_count
-profile_count::from_gcov_type (gcov_type v)
+profile_count::from_gcov_type (gcov_type v, profile_quality quality)
   {
     profile_count ret;
     gcc_checking_assert (v >= 0);
@@ -371,7 +379,7 @@ profile_count::from_gcov_type (gcov_type v)
               "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
               (int64_t) v, (int64_t) max_count);
     ret.m_val = MIN (v, (gcov_type)max_count);
-    ret.m_quality = profile_precise;
+    ret.m_quality = quality;
     return ret;
   }
 
index d6de61f..2669f0d 100644 (file)
@@ -60,6 +60,8 @@ enum profile_quality {
 };
 
 extern const char *profile_quality_as_string (enum profile_quality);
+extern bool parse_profile_quality (const char *value,
+                                  profile_quality *quality);
 
 /* The base value for branch probability notes and edge probabilities.  */
 #define REG_BR_PROB_BASE  10000
@@ -149,6 +151,13 @@ class GTY((user)) profile_probability
 
   friend class profile_count;
 public:
+  profile_probability (): m_val (uninitialized_probability),
+    m_quality (profile_guessed)
+  {}
+
+  profile_probability (uint32_t val, profile_quality quality):
+    m_val (val), m_quality (quality)
+  {}
 
   /* Named probabilities.  */
   static profile_probability never ()
@@ -558,6 +567,12 @@ public:
       return initialized_p () && other.initialized_p () && m_val >= other.m_val;
     }
 
+  /* Get the value of the count.  */
+  uint32_t value () const { return m_val; }
+
+  /* Get the quality of the count.  */
+  enum profile_quality quality () const { return m_quality; }
+
   /* Output THIS to F.  */
   void dump (FILE *f) const;
 
@@ -675,7 +690,6 @@ private:
       return ipa_p () == other.ipa_p ();
     }
 public:
-
   /* Used for counters which are expected to be never executed.  */
   static profile_count zero ()
     {
@@ -737,6 +751,9 @@ public:
       return m_quality == profile_precise;
     }
 
+  /* Get the value of the count.  */
+  uint32_t value () const { return m_val; }
+
   /* Get the quality of the count.  */
   enum profile_quality quality () const { return m_quality; }
 
@@ -1136,7 +1153,8 @@ public:
   /* The profiling runtime uses gcov_type, which is usually 64bit integer.
      Conversions back and forth are used to read the coverage and get it
      into internal representation.  */
-  static profile_count from_gcov_type (gcov_type v);
+  static profile_count from_gcov_type (gcov_type v,
+                                      profile_quality quality = profile_precise);
 
   /* LTO streaming support.  */
   static profile_count stream_in (struct lto_input_block *);
index 53c210f..4c384ea 100644 (file)
@@ -1,3 +1,8 @@
+2019-05-09  Martin Liska  <mliska@suse.cz>
+
+       * gcc.dg/gimplefe-37.c: New test.
+       * gcc.dg/gimplefe-33.c: Likewise.
+
 2019-05-09  Paolo Carlini  <paolo.carlini@oracle.com>
 
        PR c++/90382
diff --git a/gcc/testsuite/gcc.dg/gimplefe-37.c b/gcc/testsuite/gcc.dg/gimplefe-37.c
new file mode 100644 (file)
index 0000000..d3ea186
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-optimized --param=gimple-fe-computed-hot-bb-threshold=10 " } */
+
+int __GIMPLE (ssa,startwith("slsr"),precise(3))
+main (int argc)
+{
+  int _1;
+
+  __BB(2,precise(3)):
+  if (argc_2(D) == 2)
+    goto __BB3(precise(44739243));
+  else
+    goto __BB4(precise(89478485));
+
+  __BB(3,precise(1)):
+  goto __BB4(precise(134217728));
+
+  __BB(4,precise(3)):
+  _1 = __PHI (__BB2: 0, __BB3: 12);
+  return _1;
+}
+
+
+/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[count: 3" 2 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[count: 2" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[33\\\.33%\\\]" 1 "optimized" } } */
+/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[66\\\.67%\\\]" 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.dg/gimplefe-38.c b/gcc/testsuite/gcc.dg/gimplefe-38.c
new file mode 100644 (file)
index 0000000..64532d8
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fgimple -fdump-tree-slsr" } */
+
+int __GIMPLE (ssa,startwith("slsr"),guessed_local(1073741824))
+main (int argc)
+{
+  int _1;
+
+  __BB(2,guessed_local(1073741824)):
+  if (argc_2(D) == 2)
+    goto __BB3(guessed(16777216));
+  else
+    goto __BB4(guessed(117440512));
+
+  __BB(3,guessed_local(134217728)):
+  goto __BB4(precise(134217728));
+
+  __BB(4,guessed_local(1073741824)):
+  _1 = __PHI (__BB2: 0, __BB3: 12);
+  return _1;
+}
+
+
+/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local count: 1073741824" 2 "slsr" } } */
+/* { dg-final { scan-tree-dump-times "<bb \[0-9\]> \\\[local count: 134217728" 1 "slsr" } } */
+/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[12\\\.50%\\\]" 1 "slsr" } } */
+/* { dg-final { scan-tree-dump-times "goto <bb \[0-9\]>; \\\[87\\\.50%\\\]" 1 "slsr" } } */
index 5874081..966ce5a 100644 (file)
@@ -62,6 +62,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "selftest.h"
 #include "opts.h"
 #include "asan.h"
+#include "profile.h"
 
 /* This file contains functions for building the Control Flow Graph (CFG)
    for a function tree.  */
@@ -7872,13 +7873,32 @@ dump_function_to_file (tree fndecl, FILE *file, dump_flags_t flags)
   current_function_decl = fndecl;
   if (flags & TDF_GIMPLE)
     {
+      static bool hotness_bb_param_printed = false;
+      if (profile_info != NULL
+         && !hotness_bb_param_printed)
+       {
+         hotness_bb_param_printed = true;
+         fprintf (file,
+                  "/* --param=gimple-fe-computed-hot-bb-threshold=%" PRId64
+                  " */\n", get_hot_bb_threshold ());
+       }
+
       print_generic_expr (file, TREE_TYPE (TREE_TYPE (fndecl)),
                          dump_flags | TDF_SLIM);
-      fprintf (file, " __GIMPLE (%s)\n%s (",
+      fprintf (file, " __GIMPLE (%s",
               (fun->curr_properties & PROP_ssa) ? "ssa"
               : (fun->curr_properties & PROP_cfg) ? "cfg"
-              : "",
-              function_name (fun));
+              : "");
+
+      if (cfun->cfg)
+       {
+         basic_block bb = ENTRY_BLOCK_PTR_FOR_FN (cfun);
+         if (bb->count.initialized_p ())
+           fprintf (file, ",%s(%d)",
+                    profile_quality_as_string (bb->count.quality ()),
+                    bb->count.value ());
+         fprintf (file, ")\n%s (", function_name (fun));
+       }
     }
   else
     fprintf (file, "%s %s(", function_name (fun), tmclone ? "[tm-clone] " : "");