comparison gcc/profile-count.c @ 145:1830386684a0

gcc-9.2.0
author anatofuz
date Thu, 13 Feb 2020 11:34:05 +0900
parents 84e7813d76e9
children
comparison
equal deleted inserted replaced
131:84e7813d76e9 145:1830386684a0
1 /* Profile counter container type. 1 /* Profile counter container type.
2 Copyright (C) 2017-2018 Free Software Foundation, Inc. 2 Copyright (C) 2017-2020 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka 3 Contributed by Jan Hubicka
4 4
5 This file is part of GCC. 5 This file is part of GCC.
6 6
7 GCC is free software; you can redistribute it and/or modify it under 7 GCC is free software; you can redistribute it and/or modify it under
31 #include "data-streamer.h" 31 #include "data-streamer.h"
32 #include "cgraph.h" 32 #include "cgraph.h"
33 #include "wide-int.h" 33 #include "wide-int.h"
34 #include "sreal.h" 34 #include "sreal.h"
35 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
36 /* Get a string describing QUALITY. */ 50 /* Get a string describing QUALITY. */
37 51
38 const char * 52 const char *
39 profile_quality_as_string (enum profile_quality quality) 53 profile_quality_as_string (enum profile_quality quality)
40 { 54 {
41 switch (quality) 55 return profile_quality_names[quality];
42 { 56 }
43 default: 57
44 gcc_unreachable (); 58 /* Parse VALUE as profile quality and return true when a valid QUALITY. */
45 case profile_uninitialized: 59
46 return "uninitialized"; 60 bool
47 case profile_guessed_local: 61 parse_profile_quality (const char *value, profile_quality *quality)
48 return "guessed_local"; 62 {
49 case profile_guessed_global0: 63 for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
50 return "guessed_global0"; 64 if (strcmp (profile_quality_names[i], value) == 0)
51 case profile_guessed_global0adjusted: 65 {
52 return "guessed_global0adjusted"; 66 *quality = (profile_quality)i;
53 case profile_guessed: 67 return true;
54 return "guessed"; 68 }
55 case profile_afdo: 69
56 return "afdo"; 70 return false;
57 case profile_adjusted: 71 }
58 return "adjusted"; 72
59 case profile_precise: 73 /* Display names from profile_quality enum values. */
60 return "precise"; 74
61 } 75 const char *profile_quality_display_names[] =
62 } 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 };
63 86
64 /* Dump THIS to F. */ 87 /* Dump THIS to F. */
65 88
66 void 89 void
67 profile_count::dump (FILE *f) const 90 profile_count::dump (FILE *f) const
68 { 91 {
69 if (!initialized_p ()) 92 if (!initialized_p ())
70 fprintf (f, "uninitialized"); 93 fprintf (f, "uninitialized");
71 else 94 else
72 { 95 fprintf (f, "%" PRId64 " (%s)", m_val,
73 fprintf (f, "%" PRId64, m_val); 96 profile_quality_display_names[m_quality]);
74 if (m_quality == profile_guessed_local)
75 fprintf (f, " (estimated locally)");
76 else if (m_quality == profile_guessed_global0)
77 fprintf (f, " (estimated locally, globally 0)");
78 else if (m_quality == profile_guessed_global0adjusted)
79 fprintf (f, " (estimated locally, globally 0 adjusted)");
80 else if (m_quality == profile_adjusted)
81 fprintf (f, " (adjusted)");
82 else if (m_quality == profile_afdo)
83 fprintf (f, " (auto FDO)");
84 else if (m_quality == profile_guessed)
85 fprintf (f, " (guessed)");
86 }
87 } 97 }
88 98
89 /* Dump THIS to stderr. */ 99 /* Dump THIS to stderr. */
90 100
91 void 101 void
93 { 103 {
94 dump (stderr); 104 dump (stderr);
95 fprintf (stderr, "\n"); 105 fprintf (stderr, "\n");
96 } 106 }
97 107
98 /* Return true if THIS differs from OTHER; tolerate small diferences. */ 108 /* Return true if THIS differs from OTHER; tolerate small differences. */
99 109
100 bool 110 bool
101 profile_count::differs_from_p (profile_count other) const 111 profile_count::differs_from_p (profile_count other) const
102 { 112 {
103 gcc_checking_assert (compatible_p (other)); 113 gcc_checking_assert (compatible_p (other));
113 } 123 }
114 124
115 /* Stream THIS from IB. */ 125 /* Stream THIS from IB. */
116 126
117 profile_count 127 profile_count
118 profile_count::stream_in (struct lto_input_block *ib) 128 profile_count::stream_in (class lto_input_block *ib)
119 { 129 {
120 profile_count ret; 130 profile_count ret;
121 ret.m_val = streamer_read_gcov_count (ib); 131 ret.m_val = streamer_read_gcov_count (ib);
122 ret.m_quality = (profile_quality) streamer_read_uhwi (ib); 132 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
123 return ret; 133 return ret;
156 fprintf (f, "never"); 166 fprintf (f, "never");
157 else if (m_val == max_probability) 167 else if (m_val == max_probability)
158 fprintf (f, "always"); 168 fprintf (f, "always");
159 else 169 else
160 fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability); 170 fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
161 if (m_quality == profile_adjusted) 171 if (m_quality == ADJUSTED)
162 fprintf (f, " (adjusted)"); 172 fprintf (f, " (adjusted)");
163 else if (m_quality == profile_afdo) 173 else if (m_quality == AFDO)
164 fprintf (f, " (auto FDO)"); 174 fprintf (f, " (auto FDO)");
165 else if (m_quality == profile_guessed) 175 else if (m_quality == GUESSED)
166 fprintf (f, " (guessed)"); 176 fprintf (f, " (guessed)");
167 } 177 }
168 } 178 }
169 179
170 /* Dump THIS to stderr. */ 180 /* Dump THIS to stderr. */
174 { 184 {
175 dump (stderr); 185 dump (stderr);
176 fprintf (stderr, "\n"); 186 fprintf (stderr, "\n");
177 } 187 }
178 188
179 /* Return true if THIS differs from OTHER; tolerate small diferences. */ 189 /* Return true if THIS differs from OTHER; tolerate small differences. */
180 190
181 bool 191 bool
182 profile_probability::differs_from_p (profile_probability other) const 192 profile_probability::differs_from_p (profile_probability other) const
183 { 193 {
184 if (!initialized_p () || !other.initialized_p ()) 194 if (!initialized_p () || !other.initialized_p ())
204 } 214 }
205 215
206 /* Stream THIS from IB. */ 216 /* Stream THIS from IB. */
207 217
208 profile_probability 218 profile_probability
209 profile_probability::stream_in (struct lto_input_block *ib) 219 profile_probability::stream_in (class lto_input_block *ib)
210 { 220 {
211 profile_probability ret; 221 profile_probability ret;
212 ret.m_val = streamer_read_uhwi (ib); 222 ret.m_val = streamer_read_uhwi (ib);
213 ret.m_quality = (profile_quality) streamer_read_uhwi (ib); 223 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
214 return ret; 224 return ret;
256 int 266 int
257 profile_count::to_frequency (struct function *fun) const 267 profile_count::to_frequency (struct function *fun) const
258 { 268 {
259 if (!initialized_p ()) 269 if (!initialized_p ())
260 return BB_FREQ_MAX; 270 return BB_FREQ_MAX;
261 if (*this == profile_count::zero ()) 271 if (*this == zero ())
262 return 0; 272 return 0;
263 gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX 273 gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX
264 && fun->cfg->count_max.initialized_p ()); 274 && fun->cfg->count_max.initialized_p ());
265 profile_probability prob = probability_in (fun->cfg->count_max); 275 profile_probability prob = probability_in (fun->cfg->count_max);
266 if (!prob.initialized_p ()) 276 if (!prob.initialized_p ())
275 int 285 int
276 profile_count::to_cgraph_frequency (profile_count entry_bb_count) const 286 profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
277 { 287 {
278 if (!initialized_p () || !entry_bb_count.initialized_p ()) 288 if (!initialized_p () || !entry_bb_count.initialized_p ())
279 return CGRAPH_FREQ_BASE; 289 return CGRAPH_FREQ_BASE;
280 if (*this == profile_count::zero ()) 290 if (*this == zero ())
281 return 0; 291 return 0;
282 gcc_checking_assert (entry_bb_count.initialized_p ()); 292 gcc_checking_assert (entry_bb_count.initialized_p ());
283 uint64_t scale; 293 uint64_t scale;
294 gcc_checking_assert (compatible_p (entry_bb_count));
284 if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val, 295 if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
285 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale)) 296 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
286 return CGRAPH_FREQ_MAX; 297 return CGRAPH_FREQ_MAX;
287 return MIN (scale, CGRAPH_FREQ_MAX); 298 return MIN (scale, CGRAPH_FREQ_MAX);
288 } 299 }
298 *known = false; 309 *known = false;
299 return 1; 310 return 1;
300 } 311 }
301 if (known) 312 if (known)
302 *known = true; 313 *known = true;
303 if (*this == profile_count::zero ()) 314 /* Watch for cases where one count is IPA and other is not. */
315 if (in.ipa ().initialized_p ())
316 {
317 gcc_checking_assert (ipa ().initialized_p ());
318 /* If current count is inter-procedurally 0 and IN is inter-procedurally
319 non-zero, return 0. */
320 if (in.ipa ().nonzero_p ()
321 && !ipa().nonzero_p ())
322 return 0;
323 }
324 else
325 /* We can handle correctly 0 IPA count within locally estimated
326 profile, but otherwise we are lost and this should not happen. */
327 gcc_checking_assert (!ipa ().initialized_p () || !ipa ().nonzero_p ());
328 if (*this == zero ())
304 return 0; 329 return 0;
330 if (m_val == in.m_val)
331 return 1;
332 gcc_checking_assert (compatible_p (in));
305 333
306 if (!in.m_val) 334 if (!in.m_val)
307 { 335 {
308 if (!m_val) 336 if (!m_val)
309 return 1; 337 return 1;
325 { 353 {
326 /* Scaling is no-op if NUM and DEN are the same. */ 354 /* Scaling is no-op if NUM and DEN are the same. */
327 if (*num == *den) 355 if (*num == *den)
328 return; 356 return;
329 /* Scaling to zero is always zero. */ 357 /* Scaling to zero is always zero. */
330 if (*num == profile_count::zero ()) 358 if (*num == zero ())
331 return; 359 return;
332 /* If den is non-zero we are safe. */ 360 /* If den is non-zero we are safe. */
333 if (den->force_nonzero () == *den) 361 if (den->force_nonzero () == *den)
334 return; 362 return;
335 /* Force both to non-zero so we do not push profiles to 0 when 363 /* Force both to non-zero so we do not push profiles to 0 when
341 /* THIS is a count of bb which is known to be executed IPA times. 369 /* THIS is a count of bb which is known to be executed IPA times.
342 Combine this information into bb counter. This means returning IPA 370 Combine this information into bb counter. This means returning IPA
343 if it is nonzero, not changing anything if IPA is uninitialized 371 if it is nonzero, not changing anything if IPA is uninitialized
344 and if IPA is zero, turning THIS into corresponding local profile with 372 and if IPA is zero, turning THIS into corresponding local profile with
345 global0. */ 373 global0. */
374
346 profile_count 375 profile_count
347 profile_count::combine_with_ipa_count (profile_count ipa) 376 profile_count::combine_with_ipa_count (profile_count ipa)
348 { 377 {
378 if (!initialized_p ())
379 return *this;
349 ipa = ipa.ipa (); 380 ipa = ipa.ipa ();
350 if (ipa.nonzero_p ()) 381 if (ipa.nonzero_p ())
351 return ipa; 382 return ipa;
352 if (!ipa.initialized_p () || *this == profile_count::zero ()) 383 if (!ipa.initialized_p () || *this == zero ())
353 return *this; 384 return *this;
354 if (ipa == profile_count::zero ()) 385 if (ipa == zero ())
355 return this->global0 (); 386 return this->global0 ();
356 return this->global0adjusted (); 387 return this->global0adjusted ();
388 }
389
390 /* Sae as profile_count::combine_with_ipa_count but within function with count
391 IPA2. */
392 profile_count
393 profile_count::combine_with_ipa_count_within (profile_count ipa,
394 profile_count ipa2)
395 {
396 profile_count ret;
397 if (!initialized_p ())
398 return *this;
399 if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
400 ret = ipa;
401 else
402 ret = combine_with_ipa_count (ipa);
403 gcc_checking_assert (ret.compatible_p (ipa2));
404 return ret;
357 } 405 }
358 406
359 /* The profiling runtime uses gcov_type, which is usually 64bit integer. 407 /* The profiling runtime uses gcov_type, which is usually 64bit integer.
360 Conversions back and forth are used to read the coverage and get it 408 Conversions back and forth are used to read the coverage and get it
361 into internal representation. */ 409 into internal representation. */
410
362 profile_count 411 profile_count
363 profile_count::from_gcov_type (gcov_type v) 412 profile_count::from_gcov_type (gcov_type v, profile_quality quality)
364 { 413 {
365 profile_count ret; 414 profile_count ret;
366 gcc_checking_assert (v >= 0); 415 gcc_checking_assert (v >= 0);
367 if (dump_file && v >= (gcov_type)max_count) 416 if (dump_file && v >= (gcov_type)max_count)
368 fprintf (dump_file, 417 fprintf (dump_file,
369 "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n", 418 "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
370 (int64_t) v, (int64_t) max_count); 419 (int64_t) v, (int64_t) max_count);
371 ret.m_val = MIN (v, (gcov_type)max_count); 420 ret.m_val = MIN (v, (gcov_type)max_count);
372 ret.m_quality = profile_precise; 421 ret.m_quality = quality;
373 return ret; 422 return ret;
374 } 423 }
375 424
376
377 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER 425 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
378 happens with COUNT2 probablity. Return probablity that either *THIS or 426 happens with COUNT2 probability. Return probability that either *THIS or
379 OTHER happens. */ 427 OTHER happens. */
380 428
381 profile_probability 429 profile_probability
382 profile_probability::combine_with_count (profile_count count1, 430 profile_probability::combine_with_count (profile_count count1,
383 profile_probability other, 431 profile_probability other,
384 profile_count count2) const 432 profile_count count2) const
385 { 433 {
386 /* If probabilities are same, we are done. 434 /* If probabilities are same, we are done.
387 If counts are nonzero we can distribute accordingly. In remaining 435 If counts are nonzero we can distribute accordingly. In remaining
388 cases just avreage the values and hope for the best. */ 436 cases just average the values and hope for the best. */
389 if (*this == other || count1 == count2 437 if (*this == other || count1 == count2
390 || (count2 == profile_count::zero () 438 || (count2 == profile_count::zero ()
391 && !(count1 == profile_count::zero ()))) 439 && !(count1 == profile_count::zero ())))
392 return *this; 440 return *this;
393 if (count1 == profile_count::zero () && !(count2 == profile_count::zero ())) 441 if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
394 return other; 442 return other;
395 else if (count1.nonzero_p () || count2.nonzero_p ()) 443 else if (count1.nonzero_p () || count2.nonzero_p ())
396 return *this * count1.probability_in (count1 + count2) 444 return *this * count1.probability_in (count1 + count2)
397 + other * count2.probability_in (count1 + count2); 445 + other * count2.probability_in (count1 + count2);
398 else 446 else
399 return *this * profile_probability::even () 447 return *this * even () + other * even ();
400 + other * profile_probability::even (); 448 }
401 } 449
450 /* Return probability as sreal in range [0, 1]. */
451
452 sreal
453 profile_probability::to_sreal () const
454 {
455 gcc_checking_assert (initialized_p ());
456 return ((sreal)m_val) >> (n_bits - 2);
457 }