1 /* Profile counter container type.
2 Copyright (C) 2017-2023 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
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
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
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/>. */
23 #include "coretypes.h"
24 #include "profile-count.h"
27 #include "basic-block.h"
31 #include "data-streamer.h"
36 /* Names from profile_quality enum values. */
38 const char *profile_quality_names
[] =
43 "guessed_global0adjusted",
50 /* Get a string describing QUALITY. */
53 profile_quality_as_string (enum profile_quality quality
)
55 return profile_quality_names
[quality
];
58 /* Parse VALUE as profile quality and return true when a valid QUALITY. */
61 parse_profile_quality (const char *value
, profile_quality
*quality
)
63 for (unsigned i
= 0; i
< ARRAY_SIZE (profile_quality_names
); i
++)
64 if (strcmp (profile_quality_names
[i
], value
) == 0)
66 *quality
= (profile_quality
)i
;
73 /* Display names from profile_quality enum values. */
75 const char *profile_quality_display_names
[] =
79 "estimated locally, globally 0",
80 "estimated locally, globally 0 adjusted",
87 /* Dump THIS to BUFFER. */
90 profile_count::dump (char *buffer
, struct function
*fun
) const
92 if (!initialized_p ())
93 sprintf (buffer
, "uninitialized");
94 else if (fun
&& initialized_p ()
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 ());
101 sprintf (buffer
, "%" PRId64
" (%s)", m_val
,
102 profile_quality_display_names
[m_quality
]);
105 /* Dump THIS to F. */
108 profile_count::dump (FILE *f
, struct function
*fun
) const
115 /* Dump THIS to stderr. */
118 profile_count::debug () const
121 fprintf (stderr
, "\n");
124 /* Return true if THIS differs from OTHER; tolerate small differences. */
127 profile_count::differs_from_p (profile_count other
) const
129 gcc_checking_assert (compatible_p (other
));
130 if (!initialized_p () || !other
.initialized_p ())
132 if ((uint64_t)m_val
- (uint64_t)other
.m_val
< 100
133 || (uint64_t)other
.m_val
- (uint64_t)m_val
< 100)
137 int64_t ratio
= (int64_t)m_val
* 100 / other
.m_val
;
138 return ratio
< 99 || ratio
> 101;
141 /* Stream THIS from IB. */
144 profile_count::stream_in (class lto_input_block
*ib
)
147 ret
.m_val
= streamer_read_gcov_count (ib
);
148 ret
.m_quality
= (profile_quality
) streamer_read_uhwi (ib
);
152 /* Stream THIS to OB. */
155 profile_count::stream_out (struct output_block
*ob
)
157 streamer_write_gcov_count (ob
, m_val
);
158 streamer_write_uhwi (ob
, m_quality
);
161 /* Stream THIS to OB. */
164 profile_count::stream_out (struct lto_output_stream
*ob
)
166 streamer_write_gcov_count_stream (ob
, m_val
);
167 streamer_write_uhwi_stream (ob
, m_quality
);
171 /* Output THIS to BUFFER. */
174 profile_probability::dump (char *buffer
) const
176 if (!initialized_p ())
177 sprintf (buffer
, "uninitialized");
180 /* Make difference between 0.00 as a roundoff error and actual 0.
183 buffer
+= sprintf (buffer
, "never");
184 else if (m_val
== max_probability
)
185 buffer
+= sprintf (buffer
, "always");
187 buffer
+= sprintf (buffer
, "%3.1f%%", (double)m_val
* 100 / max_probability
);
189 if (m_quality
== ADJUSTED
)
190 sprintf (buffer
, " (adjusted)");
191 else if (m_quality
== AFDO
)
192 sprintf (buffer
, " (auto FDO)");
193 else if (m_quality
== GUESSED
)
194 sprintf (buffer
, " (guessed)");
198 /* Dump THIS to F. */
201 profile_probability::dump (FILE *f
) const
208 /* Dump THIS to stderr. */
211 profile_probability::debug () const
214 fprintf (stderr
, "\n");
217 /* Return true if THIS differs from OTHER; tolerate small differences. */
220 profile_probability::differs_from_p (profile_probability other
) const
222 if (!initialized_p () || !other
.initialized_p ())
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)
229 int64_t ratio
= (int64_t)m_val
* 100 / other
.m_val
;
230 return ratio
< 99 || ratio
> 101;
233 /* Return true if THIS differs significantly from OTHER. */
236 profile_probability::differs_lot_from_p (profile_probability other
) const
238 if (!initialized_p () || !other
.initialized_p ())
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;
244 /* Stream THIS from IB. */
247 profile_probability::stream_in (class lto_input_block
*ib
)
249 profile_probability ret
;
250 ret
.m_val
= streamer_read_uhwi (ib
);
251 ret
.m_quality
= (profile_quality
) streamer_read_uhwi (ib
);
255 /* Stream THIS to OB. */
258 profile_probability::stream_out (struct output_block
*ob
)
260 streamer_write_uhwi (ob
, m_val
);
261 streamer_write_uhwi (ob
, m_quality
);
264 /* Stream THIS to OB. */
267 profile_probability::stream_out (struct lto_output_stream
*ob
)
269 streamer_write_uhwi_stream (ob
, m_val
);
270 streamer_write_uhwi_stream (ob
, m_quality
);
273 /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
276 slow_safe_scale_64bit (uint64_t a
, uint64_t b
, uint64_t c
, uint64_t *res
)
278 FIXED_WIDE_INT (128) tmp
= a
;
279 wi::overflow_type overflow
;
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
))
284 *res
= tmp
.to_uhwi ();
287 *res
= (uint64_t) -1;
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. */
295 profile_count::to_frequency (struct function
*fun
) const
297 if (!initialized_p ())
299 if (*this == zero ())
301 STATIC_ASSERT (REG_BR_PROB_BASE
== BB_FREQ_MAX
);
302 gcc_assert (fun
->cfg
->count_max
.initialized_p ());
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 ();
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. */
314 profile_count::to_cgraph_frequency (profile_count entry_bb_count
) const
316 if (!initialized_p () || !entry_bb_count
.initialized_p ())
317 return CGRAPH_FREQ_BASE
;
318 if (*this == zero ())
320 gcc_checking_assert (entry_bb_count
.initialized_p ());
322 gcc_checking_assert (compatible_p (entry_bb_count
));
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
);
329 /* Return THIS/IN as sreal value. */
332 profile_count::to_sreal_scale (profile_count in
, bool *known
) const
341 if (!initialized_p () || !in
.initialized_p ())
351 gcc_checking_assert (compatible_p (in
));
352 if (m_val
== in
.m_val
)
356 return (sreal
)m_val
/ (sreal
)in
.m_val
;
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. */
367 profile_count::adjust_for_ipa_scaling (profile_count
*num
,
370 /* Scaling is no-op if NUM and DEN are the same. */
373 /* Scaling to zero is always zero. */
376 /* If den is non-zero we are safe. */
377 if (den
->force_nonzero () == *den
)
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 ();
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
392 profile_count::combine_with_ipa_count (profile_count ipa
)
394 if (!initialized_p ())
397 if (ipa
.nonzero_p ())
399 if (!ipa
.initialized_p () || *this == zero ())
402 return this->global0 ();
403 return this->global0adjusted ();
406 /* Sae as profile_count::combine_with_ipa_count but within function with count
409 profile_count::combine_with_ipa_count_within (profile_count ipa
,
413 if (!initialized_p ())
415 if (ipa2
.ipa () == ipa2
&& ipa
.initialized_p ())
418 ret
= combine_with_ipa_count (ipa
);
419 gcc_checking_assert (ret
.compatible_p (ipa2
));
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. */
428 profile_count::from_gcov_type (gcov_type v
, profile_quality quality
)
431 gcc_checking_assert (v
>= 0);
432 if (dump_file
&& v
>= (gcov_type
)max_count
)
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
);
437 ret
.m_quality
= quality
;
441 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
442 happens with COUNT2 probability. Return probability that either *THIS or
446 profile_probability::combine_with_count (profile_count count1
,
447 profile_probability other
,
448 profile_count count2
) const
450 /* If probabilities are same, we are done.
451 If counts are nonzero we can distribute accordingly. In remaining
452 cases just average the values and hope for the best. */
453 if (*this == other
|| count1
== count2
454 || (count2
== profile_count::zero ()
455 && !(count1
== profile_count::zero ())))
457 if (count1
== profile_count::zero () && !(count2
== profile_count::zero ()))
459 else if (count1
.nonzero_p () || count2
.nonzero_p ())
460 return *this * count1
.probability_in (count1
+ count2
)
461 + other
* count2
.probability_in (count1
+ count2
);
463 return *this * even () + other
* even ();
466 /* Return probability as sreal in range [0, 1]. */
469 profile_probability::to_sreal () const
471 gcc_checking_assert (initialized_p ());
472 return ((sreal
)m_val
) >> (n_bits
- 2);