https://gcc.gnu.org/g:6e38bef16bbfaa7743d1ec8937ed9dfba669136d

commit r16-1607-g6e38bef16bbfaa7743d1ec8937ed9dfba669136d
Author: Jan Hubicka <hubi...@ucw.cz>
Date:   Sun Jun 22 03:32:29 2025 +0200

    Prevent possible overflows in ipa-profile
    
    The bug in scaling profile of fnsplit produced clones made
    some afdo counts during gcc bootstrap very large (2^59).
    This made computations in ipa-profile to silently overflow
    which triggered hot count to be identified as 1 instead of
    sane value.
    
    While fixing the fnsplit bug prevents overflow, I think the histogram code
    should be made safe too.  sreal is not very fitting here since mantisa is 
32bit
    and not very good for many additions of many numbers which are possibly of 
very
    different order.  So I use widest_int while 128bit arithmetics would be safe
    (we are summing 60 bit counts multiplied by time estimates).  I don't think
    we have readily available 128bit type and code is not really time critical 
since
    the histogram is computed once.
    
    gcc/ChangeLog:
    
            * ipa-profile.cc (ipa_profile): Use widest_int to avoid
            possible overflows.

Diff:
---
 gcc/ipa-profile.cc | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/gcc/ipa-profile.cc b/gcc/ipa-profile.cc
index 08638667f65c..c8b8529e38b7 100644
--- a/gcc/ipa-profile.cc
+++ b/gcc/ipa-profile.cc
@@ -764,7 +764,8 @@ ipa_profile (void)
   int order_pos;
   bool something_changed = false;
   int i;
-  gcov_type overall_time = 0, cutoff = 0, cumulated = 0, overall_size = 0;
+  widest_int overall_time = 0, cumulated = 0;
+  gcov_type overall_size = 0;
   struct cgraph_node *n,*n2;
   int nindirect = 0, ncommon = 0, nunknown = 0, nuseless = 0, nconverted = 0;
   int nmismatch = 0, nimpossible = 0;
@@ -775,37 +776,44 @@ ipa_profile (void)
     dump_histogram (dump_file, histogram);
   for (i = 0; i < (int)histogram.length (); i++)
     {
-      overall_time += histogram[i]->count * histogram[i]->time;
+      overall_time += ((widest_int)histogram[i]->count) * histogram[i]->time;
+      /* Watch for overflow.  */
+      gcc_assert (overall_time >= 0);
       overall_size += histogram[i]->size;
     }
   threshold = 0;
-  if (overall_time)
+  if (overall_time != 0)
     {
       gcc_assert (overall_size);
 
-      cutoff = (overall_time * param_hot_bb_count_ws_permille + 500) / 1000;
+      widest_int cutoff = ((overall_time * param_hot_bb_count_ws_permille
+                          + 500) / 1000);
+      /* Watch for overflow.  */
+      gcc_assert (cutoff >= 0);
       for (i = 0; cumulated < cutoff; i++)
        {
-         cumulated += histogram[i]->count * histogram[i]->time;
+         cumulated += ((widest_int)histogram[i]->count) * histogram[i]->time;
           threshold = histogram[i]->count;
        }
       if (!threshold)
        threshold = 1;
       if (dump_file)
        {
-         gcov_type cumulated_time = 0, cumulated_size = 0;
+         widest_int cumulated_time = 0;
+         gcov_type cumulated_size = 0;
 
           for (i = 0;
               i < (int)histogram.length () && histogram[i]->count >= threshold;
               i++)
            {
-             cumulated_time += histogram[i]->count * histogram[i]->time;
+             cumulated_time += ((widest_int)histogram[i]->count)
+                                * histogram[i]->time;
              cumulated_size += histogram[i]->size;
            }
          fprintf (dump_file, "Determined min count: %" PRId64
                   " Time:%3.2f%% Size:%3.2f%%\n",
                   (int64_t)threshold,
-                  cumulated_time * 100.0 / overall_time,
+                  (cumulated_time * 10000 / overall_time).to_shwi () / 100.0,
                   cumulated_size * 100.0 / overall_size);
        }

Reply via email to