]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Cleanup max of profile_count
authorJan Hubicka <hubicka@ucw.cz>
Wed, 15 Oct 2025 07:49:21 +0000 (09:49 +0200)
committerJan Hubicka <hubicka@ucw.cz>
Wed, 15 Oct 2025 07:55:17 +0000 (09:55 +0200)
profile_count::max is not implemented same way as other arithmetics on
profile counts which generally require counts to be compatible and
returns minimum of qualities of input counts.  Reason is that originally
it was used to compute statistics of whole callgraph profile so inliner
weights can be scaled to reasonable integers interprocedurally.  It also
combines qulities weird way so the same counter could be used to
determine what quality of profile is available.  That code had roundoff
error issues and was replaced by sreals.

Now max is mostly used to determine cfg->max_count which is used to
scale counts to reasonable integers intraprocedurally and is still being
used i.e. by IRA.  There are also few places where max is used for
normal arithmetics when updating profile.

For computing max_count we need max to still be a bit special so max
(uninitialized, initialized) returns initialized rather then
uninitialized. Partial profiles are later handled specially.

This patch renames max to max_prefer_initialized to make it clear and updates
implementation to require compatible profiles.  I checked this behaviour is good
for other places using it as well.
I also turned function to static, since a = a->max (b) looks odd.

gcc/ChangeLog:

* auto-profile.cc (scale_bb_profile): Use
profile_count::max_prefer_initialized.
(afdo_adjust_guessed_profile): Likewise.
* bb-reorder.cc (edge_order): Do not use max.
* cfghooks.cc (merge_blocks): Likewise.
* ipa-fnsummary.cc (param_change_prob): Likewise.
* ipa-inline-transform.cc (inline_transform): Likewise.
* predict.cc (update_max_bb_count): Likewise.
(estimate_bb_frequencies): Likewise.
(rebuild_frequencies): Likewise.
* tree-ssa-loop-unswitch.cc (struct unswitch_predicate): Likewise.
* profile-count.h (profile_count::max): Rename to
(profile_count::max_prefer_initialized): this; update handling
of qualities.

gcc/auto-profile.cc
gcc/bb-reorder.cc
gcc/cfghooks.cc
gcc/ipa-fnsummary.cc
gcc/ipa-inline-transform.cc
gcc/predict.cc
gcc/profile-count.h
gcc/tree-ssa-loop-unswitch.cc

index 6971204ddf552ff96a3ec253bb20555cbbcfea02..cf7a219133617dcd63330d3c06a3c6ac6b1e05a4 100644 (file)
@@ -3600,11 +3600,12 @@ scale_bb_profile ()
     {
       profile_count cnt = bb->count;
       bbs.safe_push (bb);
-      max_count = max_count.max (bb->count);
+      max_count = profile_count::max_prefer_initialized (max_count, cnt);
       if (afdo_set_bb_count (bb, zero_bbs))
        {
          std::swap (cnt, bb->count);
-         max_count_in_fn = max_count_in_fn.max (cnt);
+         max_count_in_fn
+           = profile_count::max_prefer_initialized (max_count_in_fn, cnt);
          add_scale (&scales, cnt, bb->count);
        }
     }
@@ -3646,7 +3647,8 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb)
     if (is_bb_annotated (seed_bb, *annotated_bb))
       {
        component[seed_bb->index] = 1;
-       max_count_in_fn = max_count_in_fn.max (seed_bb->count);
+       max_count_in_fn
+         = profile_count::max_prefer_initialized (max_count_in_fn, seed_bb->count);
       }
     else
       component[seed_bb->index] = 0;
@@ -3669,7 +3671,7 @@ afdo_adjust_guessed_profile (bb_set *annotated_bb)
           basic_block b = stack.pop ();
 
           bbs.quick_push (b);
-          max_count = max_count.max (b->count);
+          max_count = profile_count::max_prefer_initialized (max_count, b->count);
 
           for (edge e: b->preds)
             if (!component[e->src->index])
index 641b4928ffbaf137ebec51b644f76c00425cc127..e4efdee0b16e879074d551537d683a11dd28df58 100644 (file)
@@ -2389,8 +2389,10 @@ edge_order (const void *ve1, const void *ve2)
   /* Since profile_count::operator< does not establish a strict weak order
      in presence of uninitialized counts, use 'max': this makes them appear
      as if having execution frequency less than any initialized count.  */
-  profile_count m = c1.max (c2);
-  return (m == c2) - (m == c1);
+  gcov_type gc1 = c1.initialized_p () ? c1.to_gcov_type () : 0;
+  gcov_type gc2 = c2.initialized_p () ? c2.to_gcov_type () : 0;
+  gcov_type m = MAX (gc1, gc2);
+  return (m == gc1) - (m == gc2);
 }
 
 /* Reorder basic blocks using the "simple" algorithm.  This tries to
index 25bc5d4b2732f16903255c24b1cd2d41a7659bc9..01169e22fbb946b3f5a964f9c2eee4c12b078f76 100644 (file)
@@ -824,7 +824,7 @@ merge_blocks (basic_block a, basic_block b)
   else if (a->count.quality () < b->count.quality ())
     a->count = b->count;
   else if (a->count.quality () == b->count.quality ())
-    a->count = a->count.max (b->count);
+    a->count = profile_count::max_prefer_initialized (a->count, b->count);
 
   cfg_hooks->merge_blocks (a, b);
 
index dd41de98ff1a345aee5418afc98e88fbd4165859..28f79aad29e90dd227ea4ee36286729890809f9a 100644 (file)
@@ -2356,7 +2356,8 @@ param_change_prob (ipa_func_body_info *fbi, gimple *stmt, int i)
       /* Lookup the most frequent update of the value and believe that
         it dominates all the other; precise analysis here is difficult.  */
       EXECUTE_IF_SET_IN_BITMAP (info.bb_set, 0, index, bi)
-       max = max.max (BASIC_BLOCK_FOR_FN (cfun, index)->count);
+       max = profile_count::max_prefer_initialized
+               (max, BASIC_BLOCK_FOR_FN (cfun, index)->count);
       if (dump_file)
        {
           fprintf (dump_file, "     Set with count ");
index a20485496654fef4a2c8fb09efd9dd916ca698a7..99969aae1891d1bca5c17fd8a9a84003b4f18127 100644 (file)
@@ -833,7 +833,8 @@ inline_transform (struct cgraph_node *node)
       FOR_ALL_BB_FN (bb, cfun)
        {
          bb->count = bb->count.apply_scale (num, den);
-         cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count);
+         cfun->cfg->count_max = profile_count::max_prefer_initialized
+                 (cfun->cfg->count_max, bb->count);
        }
       ENTRY_BLOCK_PTR_FOR_FN (cfun)->count = node->count;
     }
index 895c5f959d02f1c8dedcf61e9c69c1f0fab70d83..d937cc699b0754fc6edf47d0ec3c719bf62945c8 100644 (file)
@@ -3849,7 +3849,7 @@ update_max_bb_count (void)
   basic_block bb;
 
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
-    true_count_max = true_count_max.max (bb->count);
+    true_count_max = profile_count::max_prefer_initialized (true_count_max, bb->count);
 
   cfun->cfg->count_max = true_count_max;
 
@@ -4162,7 +4162,9 @@ estimate_bb_frequencies ()
         executed, then preserve this info.  */
       if (!(bb->count == profile_count::zero ()))
        bb->count = count.guessed_local ().combine_with_ipa_count (ipa_count);
-      cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count);
+      cfun->cfg->count_max
+       = profile_count::max_prefer_initialized (cfun->cfg->count_max,
+                                                bb->count);
     }
 
   free_aux_for_blocks ();
@@ -4473,7 +4475,9 @@ rebuild_frequencies (void)
   cfun->cfg->count_max = profile_count::uninitialized ();
   FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR_FOR_FN (cfun), NULL, next_bb)
     {
-      cfun->cfg->count_max = cfun->cfg->count_max.max (bb->count);
+      cfun->cfg->count_max
+             = profile_count::max_prefer_initialized (cfun->cfg->count_max,
+                                                      bb->count);
       if (bb->count.nonzero_p () && bb->count.quality () >= AFDO)
        feedback_found = true;
       /* Uninitialized count may be result of inlining or an omision in an
index 89746c6749fdf67b3b8d269ef49568dca1d3ea20..85e601e5001f7a719794aa8c1a83552fa26a8471 100644 (file)
@@ -1109,30 +1109,23 @@ public:
   /* Make counter forcibly nonzero.  */
   profile_count force_nonzero () const;
 
-  profile_count max (profile_count other) const
-    {
-      profile_count val = *this;
 
-      /* Always prefer nonzero IPA counts over local counts.  */
-      if (ipa ().nonzero_p () || other.ipa ().nonzero_p ())
-       {
-         val = ipa ();
-         other = other.ipa ();
-       }
-      if (!initialized_p ())
-       return other;
-      if (!other.initialized_p ())
-       return *this;
-      if (*this == zero ())
-       return other;
-      if (other == zero ())
-       return *this;
-      gcc_checking_assert (compatible_p (other));
-      if (val.m_val < other.m_val || (m_val == other.m_val
-                                     && val.m_quality < other.m_quality))
-       return other;
-      return *this;
-    }
+  /* Return maximum of A and B.  If one of values is uninitialized return the
+     other.  */
+
+  static profile_count
+  max_prefer_initialized (const profile_count a, const profile_count b)
+  {
+    if (!a.initialized_p ())
+      return b;
+    if (!b.initialized_p ())
+      return a;
+    profile_count ret;
+    gcc_checking_assert (a.compatible_p (b));
+    ret.m_val = MAX (a.m_val, b.m_val);
+    ret.m_quality = MIN (a.m_quality, b.m_quality);
+    return ret;
+  }
 
   /* PROB is a probability in scale 0...REG_BR_PROB_BASE.  Scale counter
      accordingly.  */
index c5ca4ff894521d313ac42bbc789ed6f92f4a84cb..dc0cb245754c9cfd0e90b21dff674748a53cebe0 100644 (file)
@@ -136,7 +136,8 @@ struct unswitch_predicate
     tree rhs = gimple_cond_rhs (stmt);
     enum tree_code code = gimple_cond_code (stmt);
     condition = build2 (code, boolean_type_node, lhs, rhs);
-    count = EDGE_SUCC (bb, 0)->count ().max (EDGE_SUCC (bb, 1)->count ());
+    count = profile_count::max_prefer_initialized (EDGE_SUCC (bb, 0)->count (),
+                                                  EDGE_SUCC (bb, 1)->count ());
     if (irange::supports_p (TREE_TYPE (lhs)))
       {
        auto range_op = range_op_handler (code);