]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Handle auto-fdo 0 more carefully
authorJan Hubicka <hubicka@ucw.cz>
Wed, 28 May 2025 12:26:11 +0000 (14:26 +0200)
committerJan Hubicka <hubicka@ucw.cz>
Wed, 28 May 2025 12:26:11 +0000 (14:26 +0200)
This patch fixes few other places where auto-fdo 0 should be be treated as
actual 0 (i.e. probably never executed).  Overall I think we should end up
combining static profile with auto-fdo profile where auto-fdo has 0 counts,
but that is something that should be benchmarked and first it is neccessary to
get something benchmarkeable out of auto-FDO.

gcc/ChangeLog:

* cgraph.cc (cgraph_edge::maybe_hot_p): For auto-fdo turn 0
to non-zero.
* ipa-cp.cc (cs_interesting_for_ipcp_p): Do not trust
auto-fdo 0.
* profile-count.cc (profile_count::adjust_for_ipa_scaling): Likewise.
(profile_count::from_gcov_type): Fix formating.

gcc/cgraph.cc
gcc/ipa-cp.cc
gcc/profile-count.cc

index ac0f2519361b4cdb9643950a69615d1e05e4bc08..3f95ca1fa85c33962c5e46ce4c48f3aaf8efe211 100644 (file)
@@ -3019,7 +3019,14 @@ cgraph_edge::maybe_hot_p (sreal scale)
 
   /* Use IPA count and if it s not available appy local heuristics.  */
   if (c.initialized_p ())
-    return maybe_hot_count_p (NULL, c * scale);
+    {
+      /* A special case; AFDO zero means that function may quite possibly
+        be executed few times per execution.  If scale is large, we still
+        want to consider the call hot.  */
+      if (c.quality () == AFDO)
+       c = c.force_nonzero ();
+      return maybe_hot_count_p (NULL, c * scale);
+    }
   if (!count.initialized_p ())
     return true;
   cgraph_node *where = caller->inlined_to ? caller->inlined_to : caller;
index f06ac46dfffbe7eb1ed2a7b5350dc0b5ac2a0489..73cf9040fad7fecb16ba1418872e85ee07fdc71c 100644 (file)
@@ -544,8 +544,12 @@ cs_interesting_for_ipcp_p (cgraph_edge *e)
   if (e->count.ipa ().nonzero_p ())
     return true;
   /* If local (possibly guseed or adjusted 0 profile) claims edge is
-     not executed, do not propagate.  */
-  if (e->count.initialized_p () && !e->count.nonzero_p ())
+     not executed, do not propagate.
+     Do not trust AFDO since branch needs to be executed multiple
+     time to count while we want to propagate even call called
+     once during the train run if callee is important.  */
+  if (e->count.initialized_p () && !e->count.nonzero_p ()
+      && e->count.quality () != AFDO)
     return false;
   /* If we have zero IPA profile, still consider edge for cloning
      in case we do partial training.  */
index 374f06f4c0834421d06396e3171079b7cf11808f..2d9c778b3758b27bd62c03e475c3d6dc93cd2160 100644 (file)
@@ -364,8 +364,12 @@ profile_count::adjust_for_ipa_scaling (profile_count *num,
   /* Scaling to zero is always zero.  */
   if (*num == zero ())
     return;
-  /* If den is non-zero we are safe.  */
-  if (den->force_nonzero () == *den)
+  /* If den is non-zero we are safe.
+     However take care of zeros in AFDO profiles since
+     they simply means that no useful samples were collected.
+     Called function still may contain important loop.  */
+  if (den->force_nonzero () == *den
+      && num->quality () != AFDO)
     return;
   /* Force both to non-zero so we do not push profiles to 0 when
      both num == 0 and den == 0.  */
@@ -417,17 +421,17 @@ profile_count::combine_with_ipa_count_within (profile_count ipa,
 
 profile_count
 profile_count::from_gcov_type (gcov_type v, profile_quality quality)
-  {
-    profile_count ret;
-    gcc_checking_assert (v >= 0);
-    if (dump_file && v >= (gcov_type)max_count)
-      fprintf (dump_file,
-              "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 = quality;
-    return ret;
-  }
+{
+  profile_count ret;
+  gcc_checking_assert (v >= 0);
+  if (dump_file && v >= (gcov_type)max_count)
+    fprintf (dump_file,
+            "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 = quality;
+  return ret;
+}
 
 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
    happens with COUNT2 probability.  Return probability that either *THIS or