Home | History | Annotate | Line # | Download | only in gcc
      1 /* Profile counter container type.
      2    Copyright (C) 2017-2022 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 
     36 /* Names from profile_quality enum values.  */
     37 
     38 const char *profile_quality_names[] =
     39 {
     40   "uninitialized",
     41   "guessed_local",
     42   "guessed_global0",
     43   "guessed_global0adjusted",
     44   "guessed",
     45   "afdo",
     46   "adjusted",
     47   "precise"
     48 };
     49 
     50 /* Get a string describing QUALITY.  */
     51 
     52 const char *
     53 profile_quality_as_string (enum profile_quality quality)
     54 {
     55   return profile_quality_names[quality];
     56 }
     57 
     58 /* Parse VALUE as profile quality and return true when a valid QUALITY.  */
     59 
     60 bool
     61 parse_profile_quality (const char *value, profile_quality *quality)
     62 {
     63   for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
     64     if (strcmp (profile_quality_names[i], value) == 0)
     65       {
     66 	*quality = (profile_quality)i;
     67 	return true;
     68       }
     69 
     70   return false;
     71 }
     72 
     73 /* Display names from profile_quality enum values.  */
     74 
     75 const char *profile_quality_display_names[] =
     76 {
     77   NULL,
     78   "estimated locally",
     79   "estimated locally, globally 0",
     80   "estimated locally, globally 0 adjusted",
     81   "guessed",
     82   "auto FDO",
     83   "adjusted",
     84   "precise"
     85 };
     86 
     87 /* Dump THIS to BUFFER.  */
     88 
     89 void
     90 profile_count::dump (char *buffer) const
     91 {
     92   if (!initialized_p ())
     93     sprintf (buffer, "uninitialized");
     94   else
     95     sprintf (buffer, "%" PRId64 " (%s)", m_val,
     96 	     profile_quality_display_names[m_quality]);
     97 }
     98 
     99 /* Dump THIS to F.  */
    100 
    101 void
    102 profile_count::dump (FILE *f) const
    103 {
    104   char buffer[64];
    105   dump (buffer);
    106   fputs (buffer, f);
    107 }
    108 
    109 /* Dump THIS to stderr.  */
    110 
    111 void
    112 profile_count::debug () const
    113 {
    114   dump (stderr);
    115   fprintf (stderr, "\n");
    116 }
    117 
    118 /* Return true if THIS differs from OTHER; tolerate small differences.  */
    119 
    120 bool
    121 profile_count::differs_from_p (profile_count other) const
    122 {
    123   gcc_checking_assert (compatible_p (other));
    124   if (!initialized_p () || !other.initialized_p ())
    125     return false;
    126   if ((uint64_t)m_val - (uint64_t)other.m_val < 100
    127       || (uint64_t)other.m_val - (uint64_t)m_val < 100)
    128     return false;
    129   if (!other.m_val)
    130     return true;
    131   int64_t ratio = (int64_t)m_val * 100 / other.m_val;
    132   return ratio < 99 || ratio > 101;
    133 }
    134 
    135 /* Stream THIS from IB.  */
    136 
    137 profile_count
    138 profile_count::stream_in (class lto_input_block *ib)
    139 {
    140   profile_count ret;
    141   ret.m_val = streamer_read_gcov_count (ib);
    142   ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
    143   return ret;
    144 }
    145 
    146 /* Stream THIS to OB.  */
    147 
    148 void
    149 profile_count::stream_out (struct output_block *ob)
    150 {
    151   streamer_write_gcov_count (ob, m_val);
    152   streamer_write_uhwi (ob, m_quality);
    153 }
    154 
    155 /* Stream THIS to OB.  */
    156 
    157 void
    158 profile_count::stream_out (struct lto_output_stream *ob)
    159 {
    160   streamer_write_gcov_count_stream (ob, m_val);
    161   streamer_write_uhwi_stream (ob, m_quality);
    162 }
    163 
    164 
    165 /* Output THIS to BUFFER.  */
    166 
    167 void
    168 profile_probability::dump (char *buffer) const
    169 {
    170   if (!initialized_p ())
    171     sprintf (buffer, "uninitialized");
    172   else
    173     {
    174       /* Make difference between 0.00 as a roundoff error and actual 0.
    175 	 Similarly for 1.  */
    176       if (m_val == 0)
    177 	buffer += sprintf (buffer, "never");
    178       else if (m_val == max_probability)
    179 	buffer += sprintf (buffer, "always");
    180       else
    181 	buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability);
    182 
    183       if (m_quality == ADJUSTED)
    184 	sprintf (buffer, " (adjusted)");
    185       else if (m_quality == AFDO)
    186 	sprintf (buffer, " (auto FDO)");
    187       else if (m_quality == GUESSED)
    188 	sprintf (buffer, " (guessed)");
    189     }
    190 }
    191 
    192 /* Dump THIS to F.  */
    193 
    194 void
    195 profile_probability::dump (FILE *f) const
    196 {
    197   char buffer[64];
    198   dump (buffer);
    199   fputs (buffer, f);
    200 }
    201 
    202 /* Dump THIS to stderr.  */
    203 
    204 void
    205 profile_probability::debug () const
    206 {
    207   dump (stderr);
    208   fprintf (stderr, "\n");
    209 }
    210 
    211 /* Return true if THIS differs from OTHER; tolerate small differences.  */
    212 
    213 bool
    214 profile_probability::differs_from_p (profile_probability other) const
    215 {
    216   if (!initialized_p () || !other.initialized_p ())
    217     return false;
    218   if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
    219       || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
    220     return false;
    221   if (!other.m_val)
    222     return true;
    223   int64_t ratio = (int64_t)m_val * 100 / other.m_val;
    224   return ratio < 99 || ratio > 101;
    225 }
    226 
    227 /* Return true if THIS differs significantly from OTHER.  */
    228 
    229 bool
    230 profile_probability::differs_lot_from_p (profile_probability other) const
    231 {
    232   if (!initialized_p () || !other.initialized_p ())
    233     return false;
    234   uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
    235   return d > max_probability / 2;
    236 }
    237 
    238 /* Stream THIS from IB.  */
    239 
    240 profile_probability
    241 profile_probability::stream_in (class lto_input_block *ib)
    242 {
    243   profile_probability ret;
    244   ret.m_val = streamer_read_uhwi (ib);
    245   ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
    246   return ret;
    247 }
    248 
    249 /* Stream THIS to OB.  */
    250 
    251 void
    252 profile_probability::stream_out (struct output_block *ob)
    253 {
    254   streamer_write_uhwi (ob, m_val);
    255   streamer_write_uhwi (ob, m_quality);
    256 }
    257 
    258 /* Stream THIS to OB.  */
    259 
    260 void
    261 profile_probability::stream_out (struct lto_output_stream *ob)
    262 {
    263   streamer_write_uhwi_stream (ob, m_val);
    264   streamer_write_uhwi_stream (ob, m_quality);
    265 }
    266 
    267 /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened.  */
    268 
    269 bool
    270 slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
    271 {
    272   FIXED_WIDE_INT (128) tmp = a;
    273   wi::overflow_type overflow;
    274   tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
    275   gcc_checking_assert (!overflow);
    276   if (wi::fits_uhwi_p (tmp))
    277     {
    278       *res = tmp.to_uhwi ();
    279       return true;
    280     }
    281   *res = (uint64_t) -1;
    282   return false;
    283 }
    284 
    285 /* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
    286    Used for legacy code and should not be used anymore.  */
    287 
    288 int
    289 profile_count::to_frequency (struct function *fun) const
    290 {
    291   if (!initialized_p ())
    292     return BB_FREQ_MAX;
    293   if (*this == zero ())
    294     return 0;
    295   STATIC_ASSERT (REG_BR_PROB_BASE == BB_FREQ_MAX);
    296   gcc_assert (fun->cfg->count_max.initialized_p ());
    297   profile_probability prob = probability_in (fun->cfg->count_max);
    298   if (!prob.initialized_p ())
    299     return REG_BR_PROB_BASE;
    300   return prob.to_reg_br_prob_base ();
    301 }
    302 
    303 /* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
    304    where CGRAPH_FREQ_BASE means that count equals to entry block count.
    305    Used for legacy code and should not be used anymore.  */
    306 
    307 int
    308 profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
    309 {
    310   if (!initialized_p () || !entry_bb_count.initialized_p ())
    311     return CGRAPH_FREQ_BASE;
    312   if (*this == zero ())
    313     return 0;
    314   gcc_checking_assert (entry_bb_count.initialized_p ());
    315   uint64_t scale;
    316   gcc_checking_assert (compatible_p (entry_bb_count));
    317   if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
    318 			 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
    319     return CGRAPH_FREQ_MAX;
    320   return MIN (scale, CGRAPH_FREQ_MAX);
    321 }
    322 
    323 /* Return THIS/IN as sreal value.  */
    324 
    325 sreal
    326 profile_count::to_sreal_scale (profile_count in, bool *known) const
    327 {
    328   if (!initialized_p () || !in.initialized_p ())
    329     {
    330       if (known)
    331 	*known = false;
    332       return 1;
    333     }
    334   if (known)
    335     *known = true;
    336   /* Watch for cases where one count is IPA and other is not.  */
    337   if (in.ipa ().initialized_p ())
    338     {
    339       gcc_checking_assert (ipa ().initialized_p ());
    340       /* If current count is inter-procedurally 0 and IN is inter-procedurally
    341 	 non-zero, return 0.  */
    342       if (in.ipa ().nonzero_p ()
    343 	  && !ipa().nonzero_p ())
    344 	return 0;
    345     }
    346   else
    347     /* We can handle correctly 0 IPA count within locally estimated
    348        profile, but otherwise we are lost and this should not happen.   */
    349     gcc_checking_assert (!ipa ().initialized_p () || !ipa ().nonzero_p ());
    350   if (*this == zero ())
    351     return 0;
    352   if (m_val == in.m_val)
    353     return 1;
    354   gcc_checking_assert (compatible_p (in));
    355 
    356   if (!in.m_val)
    357     {
    358       if (!m_val)
    359 	return 1;
    360       return m_val * 4;
    361     }
    362   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 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   if (*num == *den)
    378     return;
    379   /* Scaling to zero is always zero.  */
    380   if (*num == zero ())
    381     return;
    382   /* If den is non-zero we are safe.  */
    383   if (den->force_nonzero () == *den)
    384     return;
    385   /* Force both to non-zero so we do not push profiles to 0 when
    386      both num == 0 and den == 0.  */
    387   *den = den->force_nonzero ();
    388   *num = num->force_nonzero ();
    389 }
    390 
    391 /* THIS is a count of bb which is known to be executed IPA times.
    392    Combine this information into bb counter.  This means returning IPA
    393    if it is nonzero, not changing anything if IPA is uninitialized
    394    and if IPA is zero, turning THIS into corresponding local profile with
    395    global0.  */
    396 
    397 profile_count
    398 profile_count::combine_with_ipa_count (profile_count ipa)
    399 {
    400   if (!initialized_p ())
    401     return *this;
    402   ipa = ipa.ipa ();
    403   if (ipa.nonzero_p ())
    404     return ipa;
    405   if (!ipa.initialized_p () || *this == zero ())
    406     return *this;
    407   if (ipa == zero ())
    408     return this->global0 ();
    409   return this->global0adjusted ();
    410 }
    411 
    412 /* Sae as profile_count::combine_with_ipa_count but within function with count
    413    IPA2.  */
    414 profile_count
    415 profile_count::combine_with_ipa_count_within (profile_count ipa,
    416 					      profile_count ipa2)
    417 {
    418   profile_count ret;
    419   if (!initialized_p ())
    420     return *this;
    421   if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
    422     ret = ipa;
    423   else
    424     ret = combine_with_ipa_count (ipa);
    425   gcc_checking_assert (ret.compatible_p (ipa2));
    426   return ret;
    427 }
    428 
    429 /* The profiling runtime uses gcov_type, which is usually 64bit integer.
    430    Conversions back and forth are used to read the coverage and get it
    431    into internal representation.  */
    432 
    433 profile_count
    434 profile_count::from_gcov_type (gcov_type v, profile_quality quality)
    435   {
    436     profile_count ret;
    437     gcc_checking_assert (v >= 0);
    438     if (dump_file && v >= (gcov_type)max_count)
    439       fprintf (dump_file,
    440 	       "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
    441 	       (int64_t) v, (int64_t) max_count);
    442     ret.m_val = MIN (v, (gcov_type)max_count);
    443     ret.m_quality = quality;
    444     return ret;
    445   }
    446 
    447 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
    448    happens with COUNT2 probability.  Return probability that either *THIS or
    449    OTHER happens.  */
    450 
    451 profile_probability
    452 profile_probability::combine_with_count (profile_count count1,
    453 					 profile_probability other,
    454 					 profile_count count2) const
    455 {
    456   /* If probabilities are same, we are done.
    457      If counts are nonzero we can distribute accordingly. In remaining
    458      cases just average the values and hope for the best.  */
    459   if (*this == other || count1 == count2
    460       || (count2 == profile_count::zero ()
    461 	  && !(count1 == profile_count::zero ())))
    462     return *this;
    463   if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
    464     return other;
    465   else if (count1.nonzero_p () || count2.nonzero_p ())
    466     return *this * count1.probability_in (count1 + count2)
    467 	   + other * count2.probability_in (count1 + count2);
    468   else
    469     return *this * even () + other * even ();
    470 }
    471 
    472 /* Return probability as sreal in range [0, 1].  */
    473 
    474 sreal
    475 profile_probability::to_sreal () const
    476 {
    477   gcc_checking_assert (initialized_p ());
    478   return ((sreal)m_val) >> (n_bits - 2);
    479 }
    480