]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/profile-count.cc
Dump profile_count along with relative frequency
[thirdparty/gcc.git] / gcc / profile-count.cc
CommitLineData
3995f3a2 1/* Profile counter container type.
aeee4812 2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3995f3a2
JH
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along 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"
3995f3a2 28#include "function.h"
e144a2b3 29#include "cfg.h"
3995f3a2
JH
30#include "gimple.h"
31#include "data-streamer.h"
32#include "cgraph.h"
9588ea78 33#include "wide-int.h"
41f0e819 34#include "sreal.h"
3995f3a2 35
d276406a
ML
36/* Names from profile_quality enum values. */
37
38const 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
4a4412b9
DM
50/* Get a string describing QUALITY. */
51
52const char *
53profile_quality_as_string (enum profile_quality quality)
54{
d276406a
ML
55 return profile_quality_names[quality];
56}
57
58/* Parse VALUE as profile quality and return true when a valid QUALITY. */
59
60bool
61parse_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;
4a4412b9
DM
71}
72
d276406a
ML
73/* Display names from profile_quality enum values. */
74
75const char *profile_quality_display_names[] =
76{
77 NULL,
78 "estimated locally",
79 "estimated locally, globally 0",
80 "estimated locally, globally 0 adjusted",
d276406a 81 "guessed",
f7a7839c
JH
82 "auto FDO",
83 "adjusted",
d276406a
ML
84 "precise"
85};
86
df704591 87/* Dump THIS to BUFFER. */
357067f2 88
3995f3a2 89void
3cce8d98 90profile_count::dump (char *buffer, struct function *fun) const
3995f3a2
JH
91{
92 if (!initialized_p ())
df704591 93 sprintf (buffer, "uninitialized");
3cce8d98
JH
94 else if (fun && initialized_p ()
95 && fun->cfg
96 && ENTRY_BLOCK_PTR_FOR_FN (fun)->count.initialized_p ())
97 sprintf (buffer, "%" PRId64 " (%s freq %.4f)", m_val,
98 profile_quality_display_names[m_quality],
99 to_sreal_scale (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ());
3995f3a2 100 else
df704591 101 sprintf (buffer, "%" PRId64 " (%s)", m_val,
d276406a 102 profile_quality_display_names[m_quality]);
3995f3a2
JH
103}
104
df704591
ML
105/* Dump THIS to F. */
106
107void
3cce8d98 108profile_count::dump (FILE *f, struct function *fun) const
df704591
ML
109{
110 char buffer[64];
3cce8d98 111 dump (buffer, fun);
df704591
ML
112 fputs (buffer, f);
113}
114
357067f2
JH
115/* Dump THIS to stderr. */
116
3995f3a2
JH
117void
118profile_count::debug () const
119{
3cce8d98 120 dump (stderr, cfun);
357067f2 121 fprintf (stderr, "\n");
3995f3a2
JH
122}
123
956d615d 124/* Return true if THIS differs from OTHER; tolerate small differences. */
357067f2 125
3995f3a2
JH
126bool
127profile_count::differs_from_p (profile_count other) const
128{
e7a74006 129 gcc_checking_assert (compatible_p (other));
3995f3a2
JH
130 if (!initialized_p () || !other.initialized_p ())
131 return false;
357067f2
JH
132 if ((uint64_t)m_val - (uint64_t)other.m_val < 100
133 || (uint64_t)other.m_val - (uint64_t)m_val < 100)
3995f3a2
JH
134 return false;
135 if (!other.m_val)
136 return true;
357067f2 137 int64_t ratio = (int64_t)m_val * 100 / other.m_val;
3995f3a2
JH
138 return ratio < 99 || ratio > 101;
139}
140
357067f2
JH
141/* Stream THIS from IB. */
142
3995f3a2 143profile_count
99b1c316 144profile_count::stream_in (class lto_input_block *ib)
3995f3a2
JH
145{
146 profile_count ret;
147 ret.m_val = streamer_read_gcov_count (ib);
357067f2 148 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
3995f3a2
JH
149 return ret;
150}
151
357067f2
JH
152/* Stream THIS to OB. */
153
3995f3a2
JH
154void
155profile_count::stream_out (struct output_block *ob)
156{
157 streamer_write_gcov_count (ob, m_val);
4e9a497f 158 streamer_write_uhwi (ob, m_quality);
3995f3a2
JH
159}
160
357067f2
JH
161/* Stream THIS to OB. */
162
3995f3a2
JH
163void
164profile_count::stream_out (struct lto_output_stream *ob)
165{
166 streamer_write_gcov_count_stream (ob, m_val);
4e9a497f 167 streamer_write_uhwi_stream (ob, m_quality);
3995f3a2 168}
357067f2 169
df704591
ML
170
171/* Output THIS to BUFFER. */
357067f2
JH
172
173void
df704591 174profile_probability::dump (char *buffer) const
357067f2
JH
175{
176 if (!initialized_p ())
df704591 177 sprintf (buffer, "uninitialized");
357067f2
JH
178 else
179 {
180 /* Make difference between 0.00 as a roundoff error and actual 0.
181 Similarly for 1. */
182 if (m_val == 0)
df704591 183 buffer += sprintf (buffer, "never");
357067f2 184 else if (m_val == max_probability)
df704591 185 buffer += sprintf (buffer, "always");
357067f2 186 else
df704591
ML
187 buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability);
188
e48dc99e 189 if (m_quality == ADJUSTED)
df704591 190 sprintf (buffer, " (adjusted)");
e48dc99e 191 else if (m_quality == AFDO)
df704591 192 sprintf (buffer, " (auto FDO)");
e48dc99e 193 else if (m_quality == GUESSED)
df704591 194 sprintf (buffer, " (guessed)");
357067f2
JH
195 }
196}
197
df704591
ML
198/* Dump THIS to F. */
199
200void
201profile_probability::dump (FILE *f) const
202{
203 char buffer[64];
204 dump (buffer);
205 fputs (buffer, f);
206}
207
357067f2
JH
208/* Dump THIS to stderr. */
209
210void
211profile_probability::debug () const
212{
213 dump (stderr);
214 fprintf (stderr, "\n");
215}
216
956d615d 217/* Return true if THIS differs from OTHER; tolerate small differences. */
357067f2
JH
218
219bool
220profile_probability::differs_from_p (profile_probability other) const
221{
222 if (!initialized_p () || !other.initialized_p ())
223 return false;
83d502cf
JH
224 if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
225 || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
357067f2
JH
226 return false;
227 if (!other.m_val)
228 return true;
83d502cf 229 int64_t ratio = (int64_t)m_val * 100 / other.m_val;
357067f2
JH
230 return ratio < 99 || ratio > 101;
231}
232
233/* Return true if THIS differs significantly from OTHER. */
234
235bool
236profile_probability::differs_lot_from_p (profile_probability other) const
237{
238 if (!initialized_p () || !other.initialized_p ())
239 return false;
240 uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
241 return d > max_probability / 2;
242}
243
244/* Stream THIS from IB. */
245
246profile_probability
99b1c316 247profile_probability::stream_in (class lto_input_block *ib)
357067f2
JH
248{
249 profile_probability ret;
250 ret.m_val = streamer_read_uhwi (ib);
251 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
252 return ret;
253}
254
255/* Stream THIS to OB. */
256
257void
258profile_probability::stream_out (struct output_block *ob)
259{
260 streamer_write_uhwi (ob, m_val);
261 streamer_write_uhwi (ob, m_quality);
262}
263
264/* Stream THIS to OB. */
265
266void
267profile_probability::stream_out (struct lto_output_stream *ob)
268{
269 streamer_write_uhwi_stream (ob, m_val);
270 streamer_write_uhwi_stream (ob, m_quality);
271}
9588ea78
JH
272
273/* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
274
275bool
276slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
277{
278 FIXED_WIDE_INT (128) tmp = a;
4a669ac3 279 wi::overflow_type overflow;
9588ea78
JH
280 tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
281 gcc_checking_assert (!overflow);
282 if (wi::fits_uhwi_p (tmp))
283 {
284 *res = tmp.to_uhwi ();
285 return true;
286 }
287 *res = (uint64_t) -1;
288 return false;
289}
e7a74006
JH
290
291/* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
292 Used for legacy code and should not be used anymore. */
293
294int
295profile_count::to_frequency (struct function *fun) const
296{
297 if (!initialized_p ())
298 return BB_FREQ_MAX;
a4c3f08d 299 if (*this == zero ())
e7a74006 300 return 0;
508e2d88
ML
301 STATIC_ASSERT (REG_BR_PROB_BASE == BB_FREQ_MAX);
302 gcc_assert (fun->cfg->count_max.initialized_p ());
e7a74006
JH
303 profile_probability prob = probability_in (fun->cfg->count_max);
304 if (!prob.initialized_p ())
305 return REG_BR_PROB_BASE;
306 return prob.to_reg_br_prob_base ();
307}
308
309/* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
310 where CGRAPH_FREQ_BASE means that count equals to entry block count.
311 Used for legacy code and should not be used anymore. */
312
313int
314profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
315{
517048ce 316 if (!initialized_p () || !entry_bb_count.initialized_p ())
e7a74006 317 return CGRAPH_FREQ_BASE;
a4c3f08d 318 if (*this == zero ())
e7a74006
JH
319 return 0;
320 gcc_checking_assert (entry_bb_count.initialized_p ());
321 uint64_t scale;
db51f624 322 gcc_checking_assert (compatible_p (entry_bb_count));
e7a74006
JH
323 if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
324 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
325 return CGRAPH_FREQ_MAX;
326 return MIN (scale, CGRAPH_FREQ_MAX);
327}
e4373d41 328
41f0e819
JH
329/* Return THIS/IN as sreal value. */
330
331sreal
332profile_count::to_sreal_scale (profile_count in, bool *known) const
333{
5159a1f1
JH
334 if (*this == zero ()
335 && !(in == zero ()))
336 {
337 if (known)
338 *known = true;
339 return 0;
340 }
517048ce 341 if (!initialized_p () || !in.initialized_p ())
41f0e819
JH
342 {
343 if (known)
344 *known = false;
77459763 345 return 1;
41f0e819
JH
346 }
347 if (known)
348 *known = true;
5159a1f1 349 if (*this == in)
65eaab18 350 return 1;
db51f624 351 gcc_checking_assert (compatible_p (in));
5159a1f1
JH
352 if (m_val == in.m_val)
353 return 1;
41f0e819 354 if (!in.m_val)
5159a1f1 355 return m_val * 4;
41f0e819
JH
356 return (sreal)m_val / (sreal)in.m_val;
357}
358
e4373d41
JH
359/* We want to scale profile across function boundary from NUM to DEN.
360 Take care of the side case when DEN is zeros. We still want to behave
361 sanely here which means
362 - scale to profile_count::zero () if NUM is profile_count::zero
363 - do not affect anything if NUM == DEN
364 - preserve counter value but adjust quality in other cases. */
365
366void
367profile_count::adjust_for_ipa_scaling (profile_count *num,
368 profile_count *den)
369{
370 /* Scaling is no-op if NUM and DEN are the same. */
371 if (*num == *den)
372 return;
517048ce 373 /* Scaling to zero is always zero. */
a4c3f08d 374 if (*num == zero ())
e4373d41
JH
375 return;
376 /* If den is non-zero we are safe. */
377 if (den->force_nonzero () == *den)
378 return;
379 /* Force both to non-zero so we do not push profiles to 0 when
380 both num == 0 and den == 0. */
381 *den = den->force_nonzero ();
382 *num = num->force_nonzero ();
383}
517048ce
JH
384
385/* THIS is a count of bb which is known to be executed IPA times.
386 Combine this information into bb counter. This means returning IPA
387 if it is nonzero, not changing anything if IPA is uninitialized
388 and if IPA is zero, turning THIS into corresponding local profile with
389 global0. */
03105885 390
517048ce
JH
391profile_count
392profile_count::combine_with_ipa_count (profile_count ipa)
393{
b225a29b
JH
394 if (!initialized_p ())
395 return *this;
517048ce
JH
396 ipa = ipa.ipa ();
397 if (ipa.nonzero_p ())
398 return ipa;
a4c3f08d 399 if (!ipa.initialized_p () || *this == zero ())
517048ce 400 return *this;
a4c3f08d 401 if (ipa == zero ())
517048ce
JH
402 return this->global0 ();
403 return this->global0adjusted ();
404}
f6422f23 405
b49d29d7
JH
406/* Sae as profile_count::combine_with_ipa_count but within function with count
407 IPA2. */
408profile_count
409profile_count::combine_with_ipa_count_within (profile_count ipa,
410 profile_count ipa2)
411{
412 profile_count ret;
413 if (!initialized_p ())
414 return *this;
415 if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
416 ret = ipa;
417 else
418 ret = combine_with_ipa_count (ipa);
419 gcc_checking_assert (ret.compatible_p (ipa2));
420 return ret;
421}
422
f6422f23
JH
423/* The profiling runtime uses gcov_type, which is usually 64bit integer.
424 Conversions back and forth are used to read the coverage and get it
425 into internal representation. */
03105885 426
f6422f23 427profile_count
d276406a 428profile_count::from_gcov_type (gcov_type v, profile_quality quality)
f6422f23
JH
429 {
430 profile_count ret;
431 gcc_checking_assert (v >= 0);
432 if (dump_file && v >= (gcov_type)max_count)
433 fprintf (dump_file,
434 "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
435 (int64_t) v, (int64_t) max_count);
436 ret.m_val = MIN (v, (gcov_type)max_count);
d276406a 437 ret.m_quality = quality;
f6422f23
JH
438 return ret;
439 }
440
97c07987 441/* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
956d615d 442 happens with COUNT2 probability. Return probability that either *THIS or
97c07987
JH
443 OTHER happens. */
444
445profile_probability
446profile_probability::combine_with_count (profile_count count1,
447 profile_probability other,
448 profile_count count2) const
449{
450 /* If probabilities are same, we are done.
451 If counts are nonzero we can distribute accordingly. In remaining
956d615d 452 cases just average the values and hope for the best. */
97c07987
JH
453 if (*this == other || count1 == count2
454 || (count2 == profile_count::zero ()
455 && !(count1 == profile_count::zero ())))
456 return *this;
457 if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
458 return other;
459 else if (count1.nonzero_p () || count2.nonzero_p ())
460 return *this * count1.probability_in (count1 + count2)
461 + other * count2.probability_in (count1 + count2);
462 else
a4c3f08d 463 return *this * even () + other * even ();
97c07987 464}
f5b25e15
JH
465
466/* Return probability as sreal in range [0, 1]. */
467
468sreal
469profile_probability::to_sreal () const
470{
471 gcc_checking_assert (initialized_p ());
472 return ((sreal)m_val) >> (n_bits - 2);
473}