Branch data Line data Source code
1 : : /* Profile counter container type.
2 : : Copyright (C) 2017-2025 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 : : #include "profile.h"
36 : :
37 : : /* Names from profile_quality enum values. */
38 : :
39 : : const char *profile_quality_names[] =
40 : : {
41 : : "uninitialized",
42 : : "guessed_local",
43 : : "guessed_global0afdo",
44 : : "guessed_global0adjusted",
45 : : "guessed_global0",
46 : : "guessed",
47 : : "afdo",
48 : : "adjusted",
49 : : "precise"
50 : : };
51 : :
52 : : /* Get a string describing QUALITY. */
53 : :
54 : : const char *
55 : 47013 : profile_quality_as_string (enum profile_quality quality)
56 : : {
57 : 47013 : return profile_quality_names[quality];
58 : : }
59 : :
60 : : /* Parse VALUE as profile quality and return true when a valid QUALITY. */
61 : :
62 : : bool
63 : 434 : parse_profile_quality (const char *value, profile_quality *quality)
64 : : {
65 : 2897 : for (unsigned i = 0; i < ARRAY_SIZE (profile_quality_names); i++)
66 : 2736 : if (strcmp (profile_quality_names[i], value) == 0)
67 : : {
68 : 273 : *quality = (profile_quality)i;
69 : 273 : return true;
70 : : }
71 : :
72 : : return false;
73 : : }
74 : :
75 : : /* Display names from profile_quality enum values. */
76 : :
77 : : const char *profile_quality_display_names[] =
78 : : {
79 : : NULL,
80 : : "estimated locally",
81 : : "estimated locally, globally 0 auto FDO",
82 : : "estimated locally, globally 0 adjusted",
83 : : "estimated locally, globally 0",
84 : : "guessed",
85 : : "auto FDO",
86 : : "adjusted",
87 : : "precise"
88 : : };
89 : :
90 : : /* Dump THIS to F. */
91 : :
92 : : void
93 : 79626 : profile_count::dump (FILE *f, struct function *fun) const
94 : : {
95 : 79626 : if (!initialized_p ())
96 : 17 : fprintf (f, "uninitialized");
97 : 131657 : else if (fun && initialized_p ()
98 : 52048 : && fun->cfg
99 : 131657 : && ENTRY_BLOCK_PTR_FOR_FN (fun)->count.initialized_p ())
100 : : {
101 : 52048 : if (compatible_p (ENTRY_BLOCK_PTR_FOR_FN (fun)->count))
102 : 52048 : fprintf (f, "%" PRId64 " (%s, freq %.4f)", m_val,
103 : 52048 : profile_quality_display_names[m_quality],
104 : : to_sreal_scale
105 : 104096 : (ENTRY_BLOCK_PTR_FOR_FN (fun)->count).to_double ());
106 : : else
107 : 0 : fprintf (f, "%" PRId64 " (%s, incompatible with entry block count)",
108 : 0 : m_val, profile_quality_display_names[m_quality]);
109 : : }
110 : : else
111 : 27561 : fprintf (f, "%" PRId64 " (%s)", m_val,
112 : 27561 : profile_quality_display_names[m_quality]);
113 : 79626 : }
114 : :
115 : : /* Dump THIS to stderr. */
116 : :
117 : : void
118 : 0 : profile_count::debug () const
119 : : {
120 : 0 : dump (stderr, cfun);
121 : 0 : fprintf (stderr, "\n");
122 : 0 : }
123 : :
124 : : /* Return true if THIS differs from OTHER; tolerate small differences. */
125 : :
126 : : bool
127 : 55529952 : profile_count::differs_from_p (profile_count other) const
128 : : {
129 : 55529952 : gcc_checking_assert (compatible_p (other));
130 : 55529952 : if (!initialized_p () || !other.initialized_p ())
131 : 52 : return initialized_p () != other.initialized_p ();
132 : 55529900 : if ((uint64_t)m_val - (uint64_t)other.m_val < 100
133 : 1207643 : || (uint64_t)other.m_val - (uint64_t)m_val < 100)
134 : : return false;
135 : 473778 : if (!other.m_val)
136 : : return true;
137 : 472819 : uint64_t ratio;
138 : 472819 : safe_scale_64bit (m_val, 100, other.m_val, &ratio);
139 : 472819 : return ratio < 99 || ratio > 101;
140 : : }
141 : :
142 : : /* Stream THIS from IB. */
143 : :
144 : : profile_count
145 : 1536966 : profile_count::stream_in (class lto_input_block *ib)
146 : : {
147 : 1536966 : profile_count ret;
148 : 1536966 : ret.m_val = streamer_read_gcov_count (ib);
149 : 1536966 : ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
150 : 1536966 : return ret;
151 : : }
152 : :
153 : : /* Stream THIS to OB. */
154 : :
155 : : void
156 : 903271 : profile_count::stream_out (struct output_block *ob)
157 : : {
158 : 903271 : streamer_write_gcov_count (ob, m_val);
159 : 903271 : streamer_write_uhwi (ob, m_quality);
160 : 903271 : }
161 : :
162 : : /* Stream THIS to OB. */
163 : :
164 : : void
165 : 1048231 : profile_count::stream_out (struct lto_output_stream *ob)
166 : : {
167 : 1048231 : streamer_write_gcov_count_stream (ob, m_val);
168 : 1048231 : streamer_write_uhwi_stream (ob, m_quality);
169 : 1048231 : }
170 : :
171 : :
172 : : /* Output THIS to BUFFER. */
173 : :
174 : : void
175 : 59521 : profile_probability::dump (char *buffer) const
176 : : {
177 : 59521 : if (!initialized_p ())
178 : 0 : sprintf (buffer, "uninitialized");
179 : : else
180 : : {
181 : : /* Make difference between 0.00 as a roundoff error and actual 0.
182 : : Similarly for 1. */
183 : 59521 : if (m_val == 0)
184 : 2948 : buffer += sprintf (buffer, "never");
185 : 56573 : else if (m_val == max_probability)
186 : 20451 : buffer += sprintf (buffer, "always");
187 : : else
188 : 36122 : buffer += sprintf (buffer, "%3.1f%%", (double)m_val * 100 / max_probability);
189 : :
190 : 59521 : if (quality () == ADJUSTED)
191 : 5435 : sprintf (buffer, " (adjusted)");
192 : 54086 : else if (quality () == AFDO)
193 : 0 : sprintf (buffer, " (auto FDO)");
194 : 54086 : else if (quality () == GUESSED)
195 : 32150 : sprintf (buffer, " (guessed)");
196 : : }
197 : 59521 : }
198 : :
199 : : /* Dump THIS to F. */
200 : :
201 : : void
202 : 59507 : profile_probability::dump (FILE *f) const
203 : : {
204 : 59507 : char buffer[64];
205 : 59507 : dump (buffer);
206 : 59507 : fputs (buffer, f);
207 : 59507 : }
208 : :
209 : : /* Dump THIS to stderr. */
210 : :
211 : : void
212 : 0 : profile_probability::debug () const
213 : : {
214 : 0 : dump (stderr);
215 : 0 : fprintf (stderr, "\n");
216 : 0 : }
217 : :
218 : : /* Return true if THIS differs from OTHER; tolerate small differences. */
219 : :
220 : : bool
221 : 10944 : profile_probability::differs_from_p (profile_probability other) const
222 : : {
223 : 10944 : if (!initialized_p () || !other.initialized_p ())
224 : : return false;
225 : 10944 : if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
226 : 0 : || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
227 : : return false;
228 : 0 : if (!other.m_val)
229 : : return true;
230 : 0 : int64_t ratio = (int64_t)m_val * 100 / other.m_val;
231 : 0 : return ratio < 99 || ratio > 101;
232 : : }
233 : :
234 : : /* Return true if THIS differs significantly from OTHER. */
235 : :
236 : : bool
237 : 228698 : profile_probability::differs_lot_from_p (profile_probability other) const
238 : : {
239 : 228698 : if (!initialized_p () || !other.initialized_p ())
240 : : return false;
241 : 228590 : uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
242 : 228590 : return d > max_probability / 2;
243 : : }
244 : :
245 : : /* Stream THIS from IB. */
246 : :
247 : : profile_probability
248 : 855397 : profile_probability::stream_in (class lto_input_block *ib)
249 : : {
250 : 855397 : profile_probability ret;
251 : 855397 : ret.m_val = streamer_read_uhwi (ib);
252 : 855397 : ret.m_adjusted_quality = streamer_read_uhwi (ib);
253 : 855397 : return ret;
254 : : }
255 : :
256 : : /* Stream THIS to OB. */
257 : :
258 : : void
259 : 1028356 : profile_probability::stream_out (struct output_block *ob)
260 : : {
261 : 1028356 : streamer_write_uhwi (ob, m_val);
262 : 1028356 : streamer_write_uhwi (ob, m_adjusted_quality);
263 : 1028356 : }
264 : :
265 : : /* Stream THIS to OB. */
266 : :
267 : : void
268 : 0 : profile_probability::stream_out (struct lto_output_stream *ob)
269 : : {
270 : 0 : streamer_write_uhwi_stream (ob, m_val);
271 : 0 : streamer_write_uhwi_stream (ob, m_adjusted_quality);
272 : 0 : }
273 : :
274 : : /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
275 : :
276 : : bool
277 : 560483 : slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
278 : : {
279 : 560483 : FIXED_WIDE_INT (128) tmp = a;
280 : 560483 : wi::overflow_type overflow;
281 : 560483 : tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
282 : 560483 : gcc_checking_assert (!overflow);
283 : 560483 : if (wi::fits_uhwi_p (tmp))
284 : : {
285 : 559923 : *res = tmp.to_uhwi ();
286 : 559923 : return true;
287 : : }
288 : 560 : *res = (uint64_t) -1;
289 : 560 : return false;
290 : : }
291 : :
292 : : /* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
293 : : Used for legacy code and should not be used anymore. */
294 : :
295 : : int
296 : 1105761997 : profile_count::to_frequency (struct function *fun) const
297 : : {
298 : 1105761997 : if (!initialized_p ())
299 : : return BB_FREQ_MAX;
300 : 1103951454 : if (*this == zero ())
301 : 16826054 : return 0;
302 : 1087125400 : STATIC_ASSERT (REG_BR_PROB_BASE == BB_FREQ_MAX);
303 : 1087125400 : gcc_assert (fun->cfg->count_max.initialized_p ());
304 : 1087125400 : profile_probability prob = probability_in (fun->cfg->count_max);
305 : 1087125400 : if (!prob.initialized_p ())
306 : : return REG_BR_PROB_BASE;
307 : 1087125012 : return prob.to_reg_br_prob_base ();
308 : : }
309 : :
310 : : /* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
311 : : where CGRAPH_FREQ_BASE means that count equals to entry block count.
312 : : Used for legacy code and should not be used anymore. */
313 : :
314 : : int
315 : 188095 : profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
316 : : {
317 : 188095 : if (!initialized_p () || !entry_bb_count.initialized_p ())
318 : : return CGRAPH_FREQ_BASE;
319 : 184721 : if (*this == zero ())
320 : 176 : return 0;
321 : 184545 : gcc_checking_assert (entry_bb_count.initialized_p ());
322 : 184545 : uint64_t scale;
323 : 184545 : gcc_checking_assert (compatible_p (entry_bb_count));
324 : 369090 : if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
325 : 184545 : CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
326 : : return CGRAPH_FREQ_MAX;
327 : 184545 : return MIN (scale, CGRAPH_FREQ_MAX);
328 : : }
329 : :
330 : : /* Return THIS/IN as sreal value. */
331 : :
332 : : sreal
333 : 326638297 : profile_count::to_sreal_scale (profile_count in, bool *known) const
334 : : {
335 : 351329602 : if (*this == zero ()
336 : 24691305 : && !(in == zero ()))
337 : : {
338 : 24536916 : if (known)
339 : 5 : *known = true;
340 : 24536916 : return 0;
341 : : }
342 : 302101381 : if (!initialized_p () || !in.initialized_p ())
343 : : {
344 : 38861315 : if (known)
345 : 14 : *known = false;
346 : 38861315 : return 1;
347 : : }
348 : 263240066 : if (known)
349 : 8960785 : *known = in.m_val != 0;
350 : 263240066 : if (*this == in)
351 : 43248047 : return 1;
352 : 219992019 : gcc_checking_assert (compatible_p (in));
353 : 219992019 : if (m_val == in.m_val)
354 : 410 : return 1;
355 : 219991609 : if (!in.m_val)
356 : 10911 : return m_val * 4;
357 : : /* Auto-FDO 0 really just means that we have no samples.
358 : : Treat it as small non-zero frequency. */
359 : 219980698 : if (!m_val && quality () == AFDO)
360 : 0 : return (sreal)1 / (sreal)in.m_val;
361 : 219980698 : return (sreal)m_val / (sreal)in.m_val;
362 : : }
363 : :
364 : : /* We want to scale profile across function boundary from NUM to DEN.
365 : : Take care of the side case when DEN is zeros. We still want to behave
366 : : sanely here which means
367 : : - scale to profile_count::zero () if NUM is profile_count::zero
368 : : - do not affect anything if NUM == DEN
369 : : - preserve counter value but adjust quality in other cases. */
370 : :
371 : : void
372 : 27575429 : profile_count::adjust_for_ipa_scaling (profile_count *num,
373 : : profile_count *den)
374 : : {
375 : : /* Scaling is no-op if NUM and DEN are the same. */
376 : 27575429 : if (*num == *den)
377 : : return;
378 : : /* Scaling to zero is always zero. */
379 : 21685069 : if (*num == zero ())
380 : 105679 : return;
381 : : /* If den is non-zero we are safe.
382 : : However take care of zeros in AFDO profiles since
383 : : they simply means that no useful samples were collected.
384 : : Called function still may contain important loop. */
385 : 43150168 : if (den->force_nonzero () == *den
386 : 21570778 : && num->quality () != AFDO)
387 : 21570778 : return;
388 : : /* Force both to non-zero so we do not push profiles to 0 when
389 : : both num == 0 and den == 0. */
390 : 8612 : *den = den->force_nonzero ();
391 : 8612 : *num = num->force_nonzero ();
392 : : }
393 : :
394 : : /* THIS is a count of bb which is known to be executed IPA times.
395 : : Combine this information into bb counter. This means returning IPA
396 : : if it is nonzero, not changing anything if IPA is uninitialized
397 : : and if IPA is zero, turning THIS into corresponding local profile with
398 : : global0. */
399 : :
400 : : profile_count
401 : 26994570 : profile_count::combine_with_ipa_count (profile_count ipa)
402 : : {
403 : 26994570 : if (!initialized_p ())
404 : 18431 : return *this;
405 : 26976139 : ipa = ipa.ipa ();
406 : 26976139 : if (ipa.nonzero_p ())
407 : 110 : return ipa;
408 : 27463707 : if (!ipa.initialized_p () || *this == zero ())
409 : 26975946 : return *this;
410 : 83 : if (ipa == zero ())
411 : 46 : return this->global0 ();
412 : 37 : if (ipa == afdo_zero ())
413 : 0 : return this->global0afdo ();
414 : 37 : return this->global0adjusted ();
415 : : }
416 : :
417 : : /* Same as profile_count::combine_with_ipa_count but within function with count
418 : : IPA2. */
419 : : profile_count
420 : 6870888 : profile_count::combine_with_ipa_count_within (profile_count ipa,
421 : : profile_count ipa2)
422 : : {
423 : 6870888 : profile_count ret;
424 : 6870888 : if (!initialized_p ())
425 : 964561 : return *this;
426 : 5987305 : if (ipa2.ipa () == ipa2 && ipa.initialized_p ())
427 : 80978 : ret = ipa;
428 : : else
429 : : {
430 : : /* For inconsistent profiles we may end up having ipa2 of GLOBAL0
431 : : while ipa is non-zero (i.e. non-zero IPA counters within function
432 : : executed 0 times). Be sure we produce GLOBAL0 as well
433 : : so counters remain compatible. */
434 : 5825349 : if (ipa.nonzero_p ()
435 : 5825349 : && ipa2.ipa ().initialized_p ())
436 : 0 : ipa = ipa2.ipa ();
437 : 5825349 : ret = combine_with_ipa_count (ipa);
438 : : }
439 : 5906327 : gcc_checking_assert (ret.compatible_p (ipa2));
440 : 5906327 : return ret;
441 : : }
442 : :
443 : : /* The profiling runtime uses gcov_type, which is usually 64bit integer.
444 : : Conversions back and forth are used to read the coverage and get it
445 : : into internal representation. */
446 : :
447 : : profile_count
448 : 18731633537 : profile_count::from_gcov_type (gcov_type v, profile_quality quality)
449 : : {
450 : 18731633537 : profile_count ret;
451 : 18731633537 : gcc_checking_assert (v >= 0);
452 : 18731633537 : if (dump_file && v >= (gcov_type)max_count)
453 : 0 : fprintf (dump_file,
454 : : "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
455 : : (int64_t) v, (int64_t) max_count);
456 : 18731633537 : ret.m_val = MIN (v, (gcov_type)max_count);
457 : 18731633537 : ret.m_quality = quality;
458 : 18731633537 : return ret;
459 : : }
460 : :
461 : : /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
462 : : happens with COUNT2 probability. Return probability that either *THIS or
463 : : OTHER happens. */
464 : :
465 : : profile_probability
466 : 1328106 : profile_probability::combine_with_count (profile_count count1,
467 : : profile_probability other,
468 : : profile_count count2) const
469 : : {
470 : : /* If probabilities are same, we are done.
471 : : If counts are nonzero we can distribute accordingly. In remaining
472 : : cases just average the values and hope for the best. */
473 : 39184 : if (*this == other || count1 == count2
474 : 1367326 : || (count2 == profile_count::zero ()
475 : 36 : && !(count1 == profile_count::zero ())))
476 : 1288958 : return *this;
477 : 39770 : if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
478 : 622 : return other;
479 : 41470 : else if (count1.nonzero_p () || count2.nonzero_p ())
480 : 38526 : return *this * count1.probability_in (count1 + count2)
481 : 77052 : + other * count2.probability_in (count1 + count2);
482 : : else
483 : 0 : return *this * even () + other * even ();
484 : : }
485 : :
486 : : /* Return probability as sreal in range [0, 1]. */
487 : :
488 : : sreal
489 : 49481534 : profile_probability::to_sreal () const
490 : : {
491 : 49481534 : gcc_checking_assert (initialized_p ());
492 : 49481534 : return ((sreal)m_val) >> (n_bits - 2);
493 : : }
494 : :
495 : : /* Compute square root. */
496 : :
497 : : profile_probability
498 : 2532 : profile_probability::sqrt () const
499 : : {
500 : 2532 : if (!initialized_p () || *this == never () || *this == always ())
501 : 0 : return *this;
502 : 2532 : profile_probability ret = *this;
503 : 5064 : ret.set_quality (MIN (ret.quality (), ADJUSTED));
504 : 2532 : uint32_t min_range = m_val;
505 : 2532 : uint32_t max_range = max_probability;
506 : 2532 : if (!m_val)
507 : 0 : max_range = 0;
508 : 2532 : if (m_val == max_probability)
509 : 0 : min_range = max_probability;
510 : 63300 : while (min_range != max_range)
511 : : {
512 : 60768 : uint32_t val = (min_range + max_range) / 2;
513 : 60768 : uint32_t val2 = RDIV ((uint64_t)val * val, max_probability);
514 : 60768 : if (val2 == m_val)
515 : : min_range = max_range = m_val;
516 : 60768 : else if (val2 > m_val)
517 : 22788 : max_range = val - 1;
518 : 37980 : else if (val2 < m_val)
519 : 37980 : min_range = val + 1;
520 : : }
521 : 2532 : ret.m_val = min_range;
522 : 2532 : return ret;
523 : : }
524 : :
525 : : /* Compute n-th power of THIS. */
526 : :
527 : : profile_probability
528 : 0 : profile_probability::pow (int n) const
529 : : {
530 : 0 : if (n == 1 || !initialized_p ())
531 : 0 : return *this;
532 : 0 : if (!n)
533 : 0 : return profile_probability::always ();
534 : 0 : if (!nonzero_p ()
535 : 0 : || !(profile_probability::always () - *this).nonzero_p ())
536 : 0 : return *this;
537 : 0 : profile_probability ret = profile_probability::always ();
538 : 0 : profile_probability v = *this;
539 : 0 : int p = 1;
540 : 0 : while (true)
541 : : {
542 : 0 : if (n & p)
543 : 0 : ret = ret * v;
544 : 0 : p <<= 1;
545 : 0 : if (p > n)
546 : : break;
547 : 0 : v = v * v;
548 : : }
549 : 0 : return ret;
550 : : }
551 : : profile_count
552 : 4030925 : profile_count::operator* (const sreal &num) const
553 : : {
554 : 4030925 : if (m_val == 0)
555 : 1035019 : return *this;
556 : 2995906 : if (!initialized_p ())
557 : 0 : return uninitialized ();
558 : 2995906 : sreal scaled = num * m_val;
559 : 2995906 : gcc_checking_assert (scaled >= 0);
560 : 2995906 : profile_count ret;
561 : 2995906 : if (scaled > max_count)
562 : : ret.m_val = max_count;
563 : : else
564 : 2995906 : ret.m_val = scaled.to_nearest_int ();
565 : 2995906 : ret.m_quality = MIN (m_quality, ADJUSTED);
566 : 2995906 : return ret;
567 : : }
568 : :
569 : : profile_count
570 : 0 : profile_count::operator*= (const sreal &num)
571 : : {
572 : 0 : return *this * num;
573 : : }
574 : :
575 : : /* Make counter forcibly nonzero. */
576 : : profile_count
577 : 21596614 : profile_count::force_nonzero () const
578 : : {
579 : 21596614 : if (!initialized_p ())
580 : 8666 : return *this;
581 : 21587948 : profile_count ret = *this;
582 : : /* Generally values are forced non-zero to handle inconsistent profile
583 : : where count 0 needs to be scaled up to non-zero.
584 : :
585 : : Use cutoff value here to avoid situation where profile has large
586 : : cutoff and we perform count = count * num / den where num is non-zero
587 : : and den is 0. If profile was scaled by large factor, forcing value
588 : : to 1 would lead to large scale factor. */
589 : 21587948 : gcov_unsigned_t small = profile_info ? profile_info->cutoff / 2 + 1
590 : : : 1;
591 : 21587948 : if (ret.m_val < small)
592 : : {
593 : 17224 : ret.m_val = small;
594 : 17224 : ret.m_quality = MIN (m_quality, ADJUSTED);
595 : : }
596 : 21587948 : return ret;
597 : : }
|