Hi,
This patch makes auto-fdo more careful about keeping info we have
from static profile prediction.

If all counters in function are 0, we can keep original auto-fdo profile.
Having all 0 profile is not very useful especially becuase 0 in autofdo is not
very informative and the code still may have been executed in the train run.
I added comment about adding GUESSED_GLOBAL0_AFDO which would still preserve
info that the function is not hot in the profile, but I would like to do this
incrementally.

If function has non-zero counters, we can still keep info about zero being
reliable from static prediction (i.e. after EH or with cold attribute).

Bootstrapped/regtested x86_64-linux, comitted.

gcc/ChangeLog:

        * auto-profile.cc (update_count_by_afdo_count): New function.
        (afdo_set_bb_count): Add debug output; only set count if it is
        non-zero.
        (afdo_find_equiv_class): Add debug output.
        (afdo_calculate_branch_prob): Fix formating.
        (afdo_annotate_cfg): Add debug output; do not erase static
        profile if autofdo profile is all 0.

diff --git a/gcc/auto-profile.cc b/gcc/auto-profile.cc
index 91d829908d2..3eefb970fde 100644
--- a/gcc/auto-profile.cc
+++ b/gcc/auto-profile.cc
@@ -1061,6 +1061,19 @@ set_bb_annotated (basic_block bb, bb_set *annotated)
   annotated->insert (bb);
 }
 
+/* Update profile_count by known autofdo count.  */
+void
+update_count_by_afdo_count (profile_count *count, gcov_type c)
+{
+  if (c)
+    *count = profile_count::from_gcov_type (c).afdo ();
+  /* In case we have guessed profile which is already zero, preserve
+     quality info.  */
+  else if (count->nonzero_p ()
+          || count->quality () == GUESSED)
+    *count = profile_count::zero ().afdo ();
+}
+
 /* For a given BB, set its execution count. Attach value profile if a stmt
    is not in PROMOTED, because we only want to promote an indirect call once.
    Return TRUE if BB is annotated.  */
@@ -1071,6 +1084,8 @@ afdo_set_bb_count (basic_block bb, const stmt_set 
&promoted)
   gimple_stmt_iterator gsi;
   gcov_type max_count = 0;
   bool has_annotated = false;
+  if (dump_file)
+    fprintf (dump_file, " Looking up AFDO count of bb %i\n", bb->index);
 
   for (gsi = gsi_start_bb (bb); !gsi_end_p (gsi); gsi_next (&gsi))
     {
@@ -1082,6 +1097,12 @@ afdo_set_bb_count (basic_block bb, const stmt_set 
&promoted)
         {
           if (info.count > max_count)
             max_count = info.count;
+         if (dump_file && info.count)
+           {
+             fprintf (dump_file, "  count %" PRIu64 " in stmt: ",
+                      (int64_t)info.count);
+             print_gimple_stmt (dump_file, stmt, 0, TDF_SLIM);
+           }
           has_annotated = true;
           if (info.targets.size () > 0
               && promoted.find (stmt) == promoted.end ())
@@ -1112,6 +1133,13 @@ afdo_set_bb_count (basic_block bb, const stmt_set 
&promoted)
                {
                  if (info.count > max_count)
                    max_count = info.count;
+                 if (dump_file && info.count)
+                   {
+                     fprintf (dump_file,
+                              "  phi op in BB %i with count %" PRIu64": ",
+                              bb_succ->index, (int64_t)info.count);
+                     print_gimple_stmt (dump_file, phi, 0, TDF_SLIM);
+                   }
                  has_annotated = true;
                }
            }
@@ -1121,7 +1149,14 @@ afdo_set_bb_count (basic_block bb, const stmt_set 
&promoted)
        return false;
     }
 
-  bb->count = profile_count::from_gcov_type (max_count).afdo ();
+  if (max_count)
+    {
+      update_count_by_afdo_count (&bb->count, max_count);
+      if (dump_file)
+       fprintf (dump_file,
+                " Annotated bb %i with count %" PRId64 "\n",
+                bb->index, (int64_t)max_count);
+    }
   return true;
 }
 
@@ -1154,6 +1189,14 @@ afdo_find_equiv_class (bb_set *annotated_bb)
          bb1->aux = bb;
          if (bb1->count > bb->count && is_bb_annotated (bb1, *annotated_bb))
            {
+             if (dump_file)
+               {
+                 fprintf (dump_file,
+                          "  Copying count of bb %i to bb %i; count is:",
+                          bb1->index,
+                          bb->index);
+                 bb1->count.dump (dump_file);
+               }
              bb->count = bb1->count;
              set_bb_annotated (bb, annotated_bb);
            }
@@ -1166,6 +1209,14 @@ afdo_find_equiv_class (bb_set *annotated_bb)
          bb1->aux = bb;
          if (bb1->count > bb->count && is_bb_annotated (bb1, *annotated_bb))
            {
+             if (dump_file)
+               {
+                 fprintf (dump_file,
+                          "  Copying count of bb %i to bb %i; count is:",
+                          bb1->index,
+                          bb->index);
+                 bb1->count.dump (dump_file);
+               }
              bb->count = bb1->count;
              set_bb_annotated (bb, annotated_bb);
            }
@@ -1411,7 +1462,7 @@ afdo_calculate_branch_prob (bb_set *annotated_bb)
       else
         total_count += AFDO_EINFO (e)->get_count ();
     }
-    if (num_unknown_succ == 0 && total_count.nonzero_p())
+    if (num_unknown_succ == 0 && total_count.nonzero_p ())
       {
        FOR_EACH_EDGE (e, ei, bb->succs)
          e->probability
@@ -1512,22 +1563,55 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts)
           current_function_decl);
 
   if (s == NULL)
-    return;
-  ENTRY_BLOCK_PTR_FOR_FN (cfun)->count
-     = profile_count::from_gcov_type (s->head_count ()).afdo ();
-  EXIT_BLOCK_PTR_FOR_FN (cfun)->count = profile_count::zero ().afdo ();
-  profile_count max_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+    {
+      if (dump_file)
+       fprintf (dump_file, "No afdo profile for %s",
+                cgraph_node::get (current_function_decl)->dump_name ());
+      return;
+    }
 
+  if (dump_file)
+    fprintf (dump_file, "\n\nAnnotating BB profile of %s\n",
+            cgraph_node::get (current_function_decl)->dump_name ());
+
+  /* In the first pass only store non-zero counts.  */
+  gcov_type head_count = s->head_count ();
+  bool profile_found = head_count > 0;
   FOR_EACH_BB_FN (bb, cfun)
     {
-      /* As autoFDO uses sampling approach, we have to assume that all
-        counters are zero when not seen by autoFDO.  */
-      bb->count = profile_count::zero ().afdo ();
       if (afdo_set_bb_count (bb, promoted_stmts))
-       set_bb_annotated (bb, &annotated_bb);
-      if (bb->count > max_count)
-       max_count = bb->count;
+       {
+         if (bb->count.quality () == AFDO)
+           {
+             gcc_assert (bb->count.nonzero_p ());
+             profile_found = true;
+           }
+         set_bb_annotated (bb, &annotated_bb);
+       }
+    }
+  /* Exit without clobbering static profile if there was no
+     non-zero count.
+     ??? Instead of keeping guessed profile we can introduce
+     GUESSED_GLOBAL0_AFDO.  */
+  if (!profile_found)
+    {
+      if (dump_file)
+       fprintf (dump_file, "No afdo samples found; keeping original profile");
+      return;
     }
+
+  /* Update profile.  */
+  update_count_by_afdo_count (&ENTRY_BLOCK_PTR_FOR_FN (cfun)->count,
+                             head_count);
+  update_count_by_afdo_count (&EXIT_BLOCK_PTR_FOR_FN (cfun)->count, 0);
+  profile_count max_count = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
+
+  FOR_EACH_BB_FN (bb, cfun)
+    if (bb->count.quality () != AFDO)
+      update_count_by_afdo_count (&bb->count, 0);
+    else
+      max_count = max_count.max (bb->count);
+
   if (ENTRY_BLOCK_PTR_FOR_FN (cfun)->count
       > ENTRY_BLOCK_PTR_FOR_FN (cfun)->next_bb->count)
     {
@@ -1542,11 +1626,10 @@ afdo_annotate_cfg (const stmt_set &promoted_stmts)
           = ENTRY_BLOCK_PTR_FOR_FN (cfun)->count;
       set_bb_annotated (EXIT_BLOCK_PTR_FOR_FN (cfun)->prev_bb, &annotated_bb);
     }
-  if (max_count.nonzero_p())
-    {
-      /* Calculate, propagate count and probability information on CFG.  */
-      afdo_calculate_branch_prob (&annotated_bb);
-    }
+  gcc_assert (max_count.nonzero_p ());
+  /* Calculate, propagate count and probability information on CFG.  */
+  afdo_calculate_branch_prob (&annotated_bb);
+
   cgraph_node::get(current_function_decl)->count
       = ENTRY_BLOCK_PTR_FOR_FN(cfun)->count;
   update_max_bb_count ();

Reply via email to