LCOV - code coverage report
Current view: top level - gcc - profile-count.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.0 % 289 240
Test Date: 2026-08-22 16:33:35 Functions: 84.8 % 33 28
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Profile counter container type.
       2              :    Copyright (C) 2017-2026 Free Software Foundation, Inc.
       3              :    Contributed by Jan Hubicka
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "profile-count.h"
      25              : #include "options.h"
      26              : #include "tree.h"
      27              : #include "basic-block.h"
      28              : #include "function.h"
      29              : #include "cfg.h"
      30              : #include "gimple.h"
      31              : #include "data-streamer.h"
      32              : #include "cgraph.h"
      33              : #include "wide-int.h"
      34              : #include "sreal.h"
      35              : #include "profile.h"
      36              : #include "selftest.h"
      37              : 
      38              : /* Names from profile_quality enum values.  */
      39              : 
      40              : const char *profile_quality_names[] =
      41              : {
      42              :   "uninitialized",
      43              :   "guessed_local",
      44              :   "guessed_global0afdo",
      45              :   "guessed_global0adjusted",
      46              :   "guessed_global0",
      47              :   "guessed",
      48              :   "afdo",
      49              :   "adjusted",
      50              :   "precise"
      51              : };
      52              : 
      53              : /* Get a string describing QUALITY.  */
      54              : 
      55              : const char *
      56        47980 : profile_quality_as_string (enum profile_quality quality)
      57              : {
      58        47980 :   return profile_quality_names[quality];
      59              : }
      60              : 
      61              : /* Parse VALUE as profile quality and return true when a valid QUALITY.  */
      62              : 
      63              : bool
      64         1195 : parse_profile_quality (const char *value, profile_quality *quality)
      65              : {
      66         6918 :   for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
      67         6641 :     if (strcmp (profile_quality_names[i], value) == 0)
      68              :       {
      69          918 :         *quality = (profile_quality)i;
      70          918 :         return true;
      71              :       }
      72              : 
      73              :   return false;
      74              : }
      75              : 
      76              : /* Display names from profile_quality enum values.  */
      77              : 
      78              : const char *profile_quality_display_names[] =
      79              : {
      80              :   NULL,
      81              :   "estimated locally",
      82              :   "estimated locally, globally 0 auto FDO",
      83              :   "estimated locally, globally 0 adjusted",
      84              :   "estimated locally, globally 0",
      85              :   "guessed",
      86              :   "auto FDO",
      87              :   "adjusted",
      88              :   "precise"
      89              : };
      90              : 
      91              : /* Dump THIS to F.  */
      92              : 
      93              : void
      94        79106 : profile_count::dump (FILE *f, struct function *fun) const
      95              : {
      96        79106 :   if (!initialized_p ())
      97           17 :     fprintf (f, "uninitialized");
      98       130405 :   else if (fun && initialized_p ()
      99        51316 :            && fun->cfg
     100       130405 :            && ENTRY_BLOCK_PTR_FOR_FN (fun)->count.initialized_p ())
     101              :     {
     102        51316 :       if (compatible_p (ENTRY_BLOCK_PTR_FOR_FN (fun)->count))
     103        51316 :         fprintf (f, "%" PRId64 " (%s, freq %.4f)", m_val,
     104        51316 :                  profile_quality_display_names[m_quality],
     105              :                  to_sreal_scale
     106       102632 :                    (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ());
     107              :       else
     108            0 :         fprintf (f, "%" PRId64 " (%s, incompatible with entry block count)",
     109            0 :                  m_val, profile_quality_display_names[m_quality]);
     110              :     }
     111              :   else
     112        27773 :     fprintf (f, "%" PRId64 " (%s)", m_val,
     113        27773 :              profile_quality_display_names[m_quality]);
     114        79106 : }
     115              : 
     116              : /* Dump THIS to stderr.  */
     117              : 
     118              : void
     119            0 : profile_count::debug () const
     120              : {
     121            0 :   dump (stderr, cfun);
     122            0 :   fprintf (stderr, "\n");
     123            0 : }
     124              : 
     125              : /* Return true if THIS differs from OTHER; tolerate small differences.  */
     126              : 
     127              : bool
     128     54648640 : profile_count::differs_from_p (profile_count other) const
     129              : {
     130     54648640 :   gcc_checking_assert (compatible_p (other));
     131     54648640 :   if (!initialized_p () || !other.initialized_p ())
     132           47 :     return initialized_p () != other.initialized_p ();
     133     54648593 :   if ((uint64_t)m_val - (uint64_t)other.m_val < 100
     134       997657 :       || (uint64_t)other.m_val - (uint64_t)m_val < 100)
     135              :     return false;
     136       318339 :   if (!other.m_val)
     137              :     return true;
     138       317246 :   uint64_t ratio;
     139       317246 :   safe_scale_64bit (m_val, 100, other.m_val, &ratio);
     140       317246 :   return ratio < 99 || ratio > 101;
     141              : }
     142              : 
     143              : /* Stream THIS from IB.  */
     144              : 
     145              : profile_count
     146      1548855 : profile_count::stream_in (class lto_input_block *ib)
     147              : {
     148      1548855 :   profile_count ret;
     149      1548855 :   ret.m_val = streamer_read_gcov_count (ib);
     150      1548855 :   ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
     151      1548855 :   return ret;
     152              : }
     153              : 
     154              : /* Stream THIS to OB.  */
     155              : 
     156              : void
     157       916873 : profile_count::stream_out (struct output_block *ob)
     158              : {
     159       916873 :   streamer_write_gcov_count (ob, m_val);
     160       916873 :   streamer_write_uhwi (ob, m_quality);
     161       916873 : }
     162              : 
     163              : /* Stream THIS to OB.  */
     164              : 
     165              : void
     166      1055528 : profile_count::stream_out (struct lto_output_stream *ob)
     167              : {
     168      1055528 :   streamer_write_gcov_count_stream (ob, m_val);
     169      1055528 :   streamer_write_uhwi_stream (ob, m_quality);
     170      1055528 : }
     171              : 
     172              : 
     173              : /* Output THIS to BUFFER.  */
     174              : 
     175              : void
     176        60452 : profile_probability::dump (char *buffer) const
     177              : {
     178        60452 :   if (!initialized_p ())
     179            0 :     sprintf (buffer, "uninitialized");
     180              :   else
     181              :     {
     182              :       /* Make difference between 0.00 as a roundoff error and actual 0.
     183              :          Similarly for 1.  */
     184        60452 :       if (m_val == 0)
     185         3096 :         buffer += sprintf (buffer, "never");
     186        57356 :       else if (m_val == max_probability)
     187        19899 :         buffer += sprintf (buffer, "always");
     188              :       else
     189        37457 :         buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability);
     190              : 
     191        60452 :       if (quality () == ADJUSTED)
     192         5837 :         sprintf (buffer, " (adjusted)");
     193        54615 :       else if (quality () == AFDO)
     194            0 :         sprintf (buffer, " (auto FDO)");
     195        54615 :       else if (quality () == GUESSED)
     196        33059 :         sprintf (buffer, " (guessed)");
     197              :     }
     198        60452 : }
     199              : 
     200              : /* Dump THIS to F.  */
     201              : 
     202              : void
     203        60438 : profile_probability::dump (FILE *f) const
     204              : {
     205        60438 :   char buffer[64];
     206        60438 :   dump (buffer);
     207        60438 :   fputs (buffer, f);
     208        60438 : }
     209              : 
     210              : /* Dump THIS to stderr.  */
     211              : 
     212              : void
     213            0 : profile_probability::debug () const
     214              : {
     215            0 :   dump (stderr);
     216            0 :   fprintf (stderr, "\n");
     217            0 : }
     218              : 
     219              : /* Return true if THIS differs from OTHER; tolerate small differences.  */
     220              : 
     221              : bool
     222        10767 : profile_probability::differs_from_p (profile_probability other) const
     223              : {
     224        10767 :   if (!initialized_p () || !other.initialized_p ())
     225              :     return false;
     226        10767 :   if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
     227            9 :       || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
     228              :     return false;
     229            0 :   if (!other.m_val)
     230              :     return true;
     231            0 :   int64_t ratio = (int64_t)m_val * 100 / other.m_val;
     232            0 :   return ratio < 99 || ratio > 101;
     233              : }
     234              : 
     235              : /* Return true if THIS differs significantly from OTHER.  */
     236              : 
     237              : bool
     238       255466 : profile_probability::differs_lot_from_p (profile_probability other) const
     239              : {
     240       255466 :   if (!initialized_p () || !other.initialized_p ())
     241              :     return false;
     242       255370 :   uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
     243       255370 :   return d > max_probability / 2;
     244              : }
     245              : 
     246              : /* Stream THIS from IB.  */
     247              : 
     248              : profile_probability
     249       862290 : profile_probability::stream_in (class lto_input_block *ib)
     250              : {
     251       862290 :   profile_probability ret;
     252       862290 :   ret.m_val = streamer_read_uhwi (ib);
     253       862290 :   ret.m_adjusted_quality = streamer_read_uhwi (ib);
     254       862290 :   return ret;
     255              : }
     256              : 
     257              : /* Stream THIS to OB.  */
     258              : 
     259              : void
     260      1042293 : profile_probability::stream_out (struct output_block *ob)
     261              : {
     262      1042293 :   streamer_write_uhwi (ob, m_val);
     263      1042293 :   streamer_write_uhwi (ob, m_adjusted_quality);
     264      1042293 : }
     265              : 
     266              : /* Stream THIS to OB.  */
     267              : 
     268              : void
     269            0 : profile_probability::stream_out (struct lto_output_stream *ob)
     270              : {
     271            0 :   streamer_write_uhwi_stream (ob, m_val);
     272            0 :   streamer_write_uhwi_stream (ob, m_adjusted_quality);
     273            0 : }
     274              : 
     275              : /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened.  */
     276              : 
     277              : bool
     278      2277497 : slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
     279              : {
     280      2277497 :   FIXED_WIDE_INT (128) tmp = a;
     281      2277497 :   wi::overflow_type overflow;
     282      2277497 :   tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
     283      2277497 :   gcc_checking_assert (!overflow);
     284      2277497 :   if (wi::fits_uhwi_p (tmp))
     285              :     {
     286      2276784 :       *res = tmp.to_uhwi ();
     287      2276784 :       return true;
     288              :     }
     289              :   *res = (uint64_t) -1;
     290              :   return false;
     291              : }
     292              : 
     293              : /* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
     294              :    Used for legacy code and should not be used anymore.  */
     295              : 
     296              : int
     297   1118273320 : profile_count::to_frequency (struct function *fun) const
     298              : {
     299   1118273320 :   if (!initialized_p ())
     300              :     return BB_FREQ_MAX;
     301   1116124286 :   if (*this == zero ())
     302     17042298 :     return 0;
     303   1099081988 :   STATIC_ASSERT (REG_BR_PROB_BASE == BB_FREQ_MAX);
     304   1099081988 :   gcc_assert (fun->cfg->count_max.initialized_p ());
     305   1099081988 :   profile_probability prob = probability_in (fun->cfg->count_max);
     306   1099081988 :   if (!prob.initialized_p ())
     307              :     return REG_BR_PROB_BASE;
     308   1099081600 :   return prob.to_reg_br_prob_base ();
     309              : }
     310              : 
     311              : /* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
     312              :    where CGRAPH_FREQ_BASE means that count equals to entry block count.
     313              :    Used for legacy code and should not be used anymore.  */
     314              : 
     315              : int
     316       187664 : profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
     317              : {
     318       187664 :   if (!initialized_p () || !entry_bb_count.initialized_p ())
     319              :     return CGRAPH_FREQ_BASE;
     320       187389 :   if (*this == zero ())
     321          198 :     return 0;
     322       187191 :   gcc_checking_assert (entry_bb_count.initialized_p ());
     323       187191 :   uint64_t scale;
     324       187191 :   gcc_checking_assert (compatible_p (entry_bb_count));
     325       374382 :   if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
     326       187191 :                          CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
     327              :     return CGRAPH_FREQ_MAX;
     328       187191 :   return MIN (scale, CGRAPH_FREQ_MAX);
     329              : }
     330              : 
     331              : /* Return THIS/IN as sreal value.  */
     332              : 
     333              : sreal
     334    335120930 : profile_count::to_sreal_scale (profile_count in, bool *known) const
     335              : {
     336    363536225 :   if (*this == zero ()
     337     28415295 :       && !(in == zero ()))
     338              :   {
     339     28241186 :     if (known)
     340            5 :       *known = true;
     341     28241186 :     return 0;
     342              :   }
     343    306879744 :   if (!initialized_p () || !in.initialized_p ())
     344              :     {
     345     39448642 :       if (known)
     346            0 :         *known = false;
     347     39448642 :       return 1;
     348              :     }
     349    267431102 :   if (known)
     350      9095260 :     *known = in.m_val != 0;
     351    267431102 :   if (*this == in)
     352     47538111 :     return 1;
     353    219892991 :   gcc_checking_assert (compatible_p (in));
     354    219892991 :   if (m_val == in.m_val)
     355          397 :     return 1;
     356    219892594 :   if (!in.m_val)
     357        11495 :     return m_val * 4;
     358              :   /* Auto-FDO 0 really just means that we have no samples.
     359              :      Treat it as small non-zero frequency.  */
     360    219881099 :   if (!m_val && quality () == AFDO)
     361            0 :     return (sreal)1 / (sreal)in.m_val;
     362    219881099 :   return (sreal)m_val / (sreal)in.m_val;
     363              : }
     364              : 
     365              : /* We want to scale profile across function boundary from NUM to DEN.
     366              :    Take care of the side case when DEN is zeros.  We still want to behave
     367              :    sanely here which means
     368              :      - scale to profile_count::zero () if NUM is profile_count::zero
     369              :      - do not affect anything if NUM == DEN
     370              :      - preserve counter value but adjust quality in other cases.  */
     371              : 
     372              : void
     373     29632529 : profile_count::adjust_for_ipa_scaling (profile_count *num,
     374              :                                        profile_count *den)
     375              : {
     376              :   /* Scaling is no-op if NUM and DEN are the same.  */
     377     29632529 :   if (*num == *den)
     378              :     return;
     379              :   /* Scaling to zero is always zero.  */
     380     22879051 :   if (*num == zero ())
     381       112618 :     return;
     382              :   /* If den is non-zero we are safe.
     383              :      However take care of zeros in AFDO profiles since
     384              :      they simply means that no useful samples were collected.
     385              :      Called function still may contain important loop.  */
     386     45517510 :   if (den->force_nonzero () == *den
     387     22751077 :       && num->quality () != AFDO)
     388     22751077 :     return;
     389              :   /* Force both to non-zero so we do not push profiles to 0 when
     390              :      both num == 0 and den == 0.  */
     391        15356 :   *den = den->force_nonzero ();
     392        15356 :   *num = num->force_nonzero ();
     393              : }
     394              : 
     395              : /* THIS is a count of bb which is known to be executed IPA times.
     396              :    Combine this information into bb counter.  This means returning IPA
     397              :    if it is nonzero, not changing anything if IPA is uninitialized
     398              :    and if IPA is zero, turning THIS into corresponding local profile with
     399              :    global0.  */
     400              : 
     401              : profile_count
     402     27684795 : profile_count::combine_with_ipa_count (profile_count ipa)
     403              : {
     404     27684795 :   if (!initialized_p ())
     405        19929 :     return *this;
     406     27664866 :   ipa = ipa.ipa ();
     407     27664866 :   if (ipa.nonzero_p ())
     408           91 :     return ipa;
     409     30095650 :   if (!ipa.initialized_p () || *this == zero ())
     410     27664668 :     return *this;
     411          107 :   if (ipa == zero ())
     412           47 :     return this->global0 ();
     413           60 :   if (ipa == afdo_zero ())
     414            0 :     return this->global0afdo ();
     415           60 :   return this->global0adjusted ();
     416              : }
     417              : 
     418              : /* Same as profile_count::combine_with_ipa_count but within function with count
     419              :    IPA2.  */
     420              : profile_count
     421      7708266 : profile_count::combine_with_ipa_count_within (profile_count ipa,
     422              :                                               profile_count ipa2)
     423              : {
     424      7708266 :   profile_count ret;
     425      7708266 :   if (!initialized_p ())
     426       992476 :     return *this;
     427      6959852 :   if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
     428       244062 :     ret = ipa;
     429              :   else
     430              :     {
     431              :       /* For inconsistent profiles we may end up having ipa2 of GLOBAL0
     432              :          while ipa is non-zero (i.e. non-zero IPA counters within function
     433              :          executed 0 times).  Be sure we produce GLOBAL0 as well
     434              :          so counters remain compatible.  */
     435      6471728 :       if (ipa.nonzero_p ()
     436      6471728 :           && ipa2.ipa ().initialized_p ())
     437            0 :         ipa = ipa2.ipa ();
     438      6471728 :       ret = combine_with_ipa_count (ipa);
     439              :     }
     440      6715790 :   gcc_checking_assert (ret.compatible_p (ipa2));
     441      6715790 :   return ret;
     442              : }
     443              : 
     444              : /* The profiling runtime uses gcov_type, which is usually 64bit integer.
     445              :    Conversions back and forth are used to read the coverage and get it
     446              :    into internal representation.  */
     447              : 
     448              : profile_count
     449  18818683616 : profile_count::from_gcov_type (gcov_type v, profile_quality quality)
     450              : {
     451  18818683616 :   profile_count ret;
     452  18818683616 :   gcc_checking_assert (v >= 0);
     453  18818683616 :   if (dump_file && v >= (gcov_type)max_count)
     454            0 :     fprintf (dump_file,
     455              :              "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
     456              :              (int64_t) v, (int64_t) max_count);
     457  18818683616 :   ret.m_val = MIN (v, (gcov_type)max_count);
     458  18818683616 :   ret.m_quality = quality;
     459  18818683616 :   return ret;
     460              : }
     461              : 
     462              : /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
     463              :    happens with COUNT2 probability.  Return probability that either *THIS or
     464              :    OTHER happens.  */
     465              : 
     466              : profile_probability
     467      1336045 : profile_probability::combine_with_count (profile_count count1,
     468              :                                          profile_probability other,
     469              :                                          profile_count count2) const
     470              : {
     471              :   /* If probabilities are same, we are done.
     472              :      If counts are nonzero we can distribute accordingly. In remaining
     473              :      cases just average the values and hope for the best.  */
     474        44287 :   if (*this == other || count1 == count2
     475      1380346 :       || (count2 == profile_count::zero ()
     476      1291772 :           && !(count1 == profile_count::zero ())))
     477      1291772 :     return *this;
     478        44875 :   if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
     479          602 :     return other;
     480        44314 :   else if (count1.nonzero_p () || count2.nonzero_p ())
     481        43671 :     return *this * count1.probability_in (count1 + count2)
     482        87342 :            + other * count2.probability_in (count1 + count2);
     483              :   else
     484            0 :     return *this * even () + other * even ();
     485              : }
     486              : 
     487              : /* Return probability as sreal in range [0, 1].  */
     488              : 
     489              : sreal
     490     50673721 : profile_probability::to_sreal () const
     491              : {
     492     50673721 :   gcc_checking_assert (initialized_p ());
     493     50673721 :   return ((sreal)m_val) >> (n_bits - 2);
     494              : }
     495              : 
     496              : /* Compute square root.  */
     497              : 
     498              : profile_probability
     499         2627 : profile_probability::sqrt () const
     500              : {
     501         2627 :   if (!initialized_p () || *this == never () || *this == always ())
     502            0 :     return *this;
     503         2627 :   profile_probability ret = *this;
     504         5254 :   ret.set_quality (MIN (ret.quality (), ADJUSTED));
     505         2627 :   uint32_t min_range = m_val;
     506         2627 :   uint32_t max_range = max_probability;
     507         2627 :   if (!m_val)
     508            0 :     max_range = 0;
     509         2627 :   if (m_val == max_probability)
     510            0 :     min_range = max_probability;
     511        65675 :   while (min_range != max_range)
     512              :     {
     513        63048 :       uint32_t val = (min_range + max_range) / 2;
     514        63048 :       uint32_t val2 = RDIV ((uint64_t)val * val, max_probability);
     515        63048 :       if (val2 == m_val)
     516              :         min_range = max_range = m_val;
     517        63048 :       else if (val2 > m_val)
     518        23643 :         max_range = val - 1;
     519        39405 :       else if (val2 < m_val)
     520        39405 :         min_range = val + 1;
     521              :     }
     522         2627 :   ret.m_val = min_range;
     523         2627 :   return ret;
     524              : }
     525              : 
     526              : /* Compute n-th power of THIS.  */
     527              : 
     528              : profile_probability
     529            0 : profile_probability::pow (int n) const
     530              : {
     531            0 :   if (n == 1 || !initialized_p ())
     532            0 :     return *this;
     533            0 :   if (!n)
     534            0 :     return profile_probability::always ();
     535            0 :   if (!nonzero_p ()
     536            0 :       || !(profile_probability::always () - *this).nonzero_p ())
     537            0 :     return *this;
     538            0 :   profile_probability ret = profile_probability::always ();
     539            0 :   profile_probability v = *this;
     540            0 :   int p = 1;
     541            0 :   while (true)
     542              :     {
     543            0 :       if (n & p)
     544            0 :         ret = ret * v;
     545            0 :       p <<= 1;
     546            0 :       if (p > n)
     547              :         break;
     548            0 :       v = v * v;
     549              :     }
     550            0 :   return ret;
     551              : }
     552              : profile_count
     553      4300157 : profile_count::operator* (const sreal &num) const
     554              : {
     555      4300157 :   if (m_val == 0)
     556      1017097 :     return *this;
     557      3283060 :   if (!initialized_p ())
     558            0 :     return uninitialized ();
     559      3283060 :   sreal scaled = num * m_val;
     560      3283060 :   gcc_checking_assert (scaled >= 0);
     561      3283060 :   profile_count ret;
     562      3283060 :   if (scaled > max_count)
     563              :     ret.m_val = max_count;
     564              :   else
     565      3283060 :     ret.m_val = scaled.to_nearest_int ();
     566      3283060 :   ret.m_quality = MIN (m_quality, ADJUSTED);
     567      3283060 :   return ret;
     568              : }
     569              : 
     570              : profile_count
     571            0 : profile_count::operator*= (const sreal &num)
     572              : {
     573            0 :   return *this * num;
     574              : }
     575              : 
     576              : /* Make counter forcibly nonzero.  */
     577              : profile_count
     578     26996997 : profile_count::force_nonzero () const
     579              : {
     580     26996997 :   if (!initialized_p ())
     581      4205228 :     return *this;
     582     22791769 :   profile_count ret = *this;
     583              :   /* Generally values are forced non-zero to handle inconsistent profile 
     584              :      where count 0 needs to be scaled up to non-zero.
     585              : 
     586              :      Use cutoff value here to avoid situation where profile has large
     587              :      cutoff and we perform count = count * num / den where num is non-zero
     588              :      and den is 0.   If profile was scaled by large factor, forcing value
     589              :      to 1 would lead to large scale factor.  */
     590     22791769 :   gcov_unsigned_t small = profile_info ? profile_info->cutoff / 2 + 1
     591              :                           : 1;
     592     22791769 :   if (ret.m_val < small)
     593              :     {
     594        40567 :       ret.m_val = small;
     595        40567 :       ret.m_quality = MIN (m_quality, ADJUSTED);
     596              :     }
     597     22791769 :   return ret;
     598              : }
     599              : 
     600              : #if CHECKING_P
     601              : 
     602              : namespace selftest {
     603              : 
     604              : /* Verify profile_probability::apply.  */
     605              : 
     606              : static void
     607            4 : test_profile_probability_apply ()
     608              : {
     609            4 :   const gcov_type min = INTTYPE_MINIMUM (gcov_type);
     610            4 :   const gcov_type max = INTTYPE_MAXIMUM (gcov_type);
     611            4 :   profile_probability quarter = profile_probability::guessed_always () / 4;
     612            4 :   profile_probability even = profile_probability::even ();
     613              : 
     614            4 :   ASSERT_EQ (1, quarter.apply (3));
     615            4 :   ASSERT_EQ (-1, quarter.apply (-3));
     616            4 :   ASSERT_EQ (2, even.apply (3));
     617            4 :   ASSERT_EQ (-2, even.apply (-3));
     618            4 :   ASSERT_EQ (0, even.apply (0));
     619              : 
     620            4 :   ASSERT_EQ (0, profile_probability::never ().apply (min));
     621            4 :   ASSERT_EQ (min, profile_probability::always ().apply (min));
     622            4 :   ASSERT_EQ (max, profile_probability::always ().apply (max));
     623            4 :   ASSERT_EQ (min, profile_probability::guessed_always ().apply (min));
     624            4 :   ASSERT_EQ (min / 2, even.apply (min));
     625            4 :   ASSERT_EQ (max / 2 + 1, even.apply (max));
     626              : 
     627            4 :   profile_probability uninitialized = profile_probability::uninitialized ();
     628            4 :   ASSERT_EQ (1, uninitialized.apply (3));
     629            4 :   ASSERT_EQ (-1, uninitialized.apply (-3));
     630            4 :   ASSERT_EQ (min / 2, uninitialized.apply (min));
     631            4 :   ASSERT_EQ (max / 2, uninitialized.apply (max));
     632            4 : }
     633              : 
     634              : /* Run all of the selftests within this file.  */
     635              : 
     636              : void
     637            4 : profile_count_cc_tests ()
     638              : {
     639            4 :   test_profile_probability_apply ();
     640            4 : }
     641              : 
     642              : } // namespace selftest
     643              : 
     644              : #endif
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.