Mercurial > hg > CbC > CbC_gcc
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 } |