annotate gcc/profile-count.h @ 132:d34655255c78

update gcc-8.2
author mir3636
date Thu, 25 Oct 2018 10:21:07 +0900
parents 84e7813d76e9
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 /* Profile counter container type.
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
2 Copyright (C) 2017-2018 Free Software Foundation, Inc.
111
kono
parents:
diff changeset
3 Contributed by Jan Hubicka
kono
parents:
diff changeset
4
kono
parents:
diff changeset
5 This file is part of GCC.
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it under
kono
parents:
diff changeset
8 the terms of the GNU General Public License as published by the Free
kono
parents:
diff changeset
9 Software Foundation; either version 3, or (at your option) any later
kono
parents:
diff changeset
10 version.
kono
parents:
diff changeset
11
kono
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
kono
parents:
diff changeset
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
kono
parents:
diff changeset
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
kono
parents:
diff changeset
15 for more details.
kono
parents:
diff changeset
16
kono
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
kono
parents:
diff changeset
20
kono
parents:
diff changeset
21 #ifndef GCC_PROFILE_COUNT_H
kono
parents:
diff changeset
22 #define GCC_PROFILE_COUNT_H
kono
parents:
diff changeset
23
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
24 struct function;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
25 class profile_count;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
26
111
kono
parents:
diff changeset
27 /* Quality of the profile count. Because gengtype does not support enums
kono
parents:
diff changeset
28 inside of classes, this is in global namespace. */
kono
parents:
diff changeset
29 enum profile_quality {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
30 /* Uninitialized value. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
31 profile_uninitialized,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
32 /* Profile is based on static branch prediction heuristics and may
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
33 or may not match reality. It is local to function and can not be compared
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
34 inter-procedurally. Never used by probabilities (they are always local).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
35 */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
36 profile_guessed_local,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
37 /* Profile was read by feedback and was 0, we used local heuristics to guess
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
38 better. This is the case of functions not run in profile fedback.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
39 Never used by probabilities. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
40 profile_guessed_global0,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
41
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
42 /* Same as profile_guessed_global0 but global count is adjusted 0. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
43 profile_guessed_global0adjusted,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
44
111
kono
parents:
diff changeset
45 /* Profile is based on static branch prediction heuristics. It may or may
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
46 not reflect the reality but it can be compared interprocedurally
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
47 (for example, we inlined function w/o profile feedback into function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
48 with feedback and propagated from that).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
49 Never used by probablities. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
50 profile_guessed,
111
kono
parents:
diff changeset
51 /* Profile was determined by autofdo. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
52 profile_afdo,
111
kono
parents:
diff changeset
53 /* Profile was originally based on feedback but it was adjusted
kono
parents:
diff changeset
54 by code duplicating optimization. It may not precisely reflect the
kono
parents:
diff changeset
55 particular code path. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
56 profile_adjusted,
111
kono
parents:
diff changeset
57 /* Profile was read from profile feedback or determined by accurate static
kono
parents:
diff changeset
58 method. */
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
59 profile_precise
111
kono
parents:
diff changeset
60 };
kono
parents:
diff changeset
61
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
62 extern const char *profile_quality_as_string (enum profile_quality);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
63
111
kono
parents:
diff changeset
64 /* The base value for branch probability notes and edge probabilities. */
kono
parents:
diff changeset
65 #define REG_BR_PROB_BASE 10000
kono
parents:
diff changeset
66
kono
parents:
diff changeset
67 #define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
kono
parents:
diff changeset
68
kono
parents:
diff changeset
69 bool slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res);
kono
parents:
diff changeset
70
kono
parents:
diff changeset
71 /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
kono
parents:
diff changeset
72
kono
parents:
diff changeset
73 inline bool
kono
parents:
diff changeset
74 safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
kono
parents:
diff changeset
75 {
kono
parents:
diff changeset
76 #if (GCC_VERSION >= 5000)
kono
parents:
diff changeset
77 uint64_t tmp;
kono
parents:
diff changeset
78 if (!__builtin_mul_overflow (a, b, &tmp)
kono
parents:
diff changeset
79 && !__builtin_add_overflow (tmp, c/2, &tmp))
kono
parents:
diff changeset
80 {
kono
parents:
diff changeset
81 *res = tmp / c;
kono
parents:
diff changeset
82 return true;
kono
parents:
diff changeset
83 }
kono
parents:
diff changeset
84 if (c == 1)
kono
parents:
diff changeset
85 {
kono
parents:
diff changeset
86 *res = (uint64_t) -1;
kono
parents:
diff changeset
87 return false;
kono
parents:
diff changeset
88 }
kono
parents:
diff changeset
89 #else
kono
parents:
diff changeset
90 if (a < ((uint64_t)1 << 31)
kono
parents:
diff changeset
91 && b < ((uint64_t)1 << 31)
kono
parents:
diff changeset
92 && c < ((uint64_t)1 << 31))
kono
parents:
diff changeset
93 {
kono
parents:
diff changeset
94 *res = (a * b + (c / 2)) / c;
kono
parents:
diff changeset
95 return true;
kono
parents:
diff changeset
96 }
kono
parents:
diff changeset
97 #endif
kono
parents:
diff changeset
98 return slow_safe_scale_64bit (a, b, c, res);
kono
parents:
diff changeset
99 }
kono
parents:
diff changeset
100
kono
parents:
diff changeset
101 /* Data type to hold probabilities. It implements fixed point arithmetics
kono
parents:
diff changeset
102 with capping so probability is always in range [0,1] and scaling requiring
kono
parents:
diff changeset
103 values greater than 1 needs to be represented otherwise.
kono
parents:
diff changeset
104
kono
parents:
diff changeset
105 In addition to actual value the quality of profile is tracked and propagated
kono
parents:
diff changeset
106 through all operations. Special value UNINITIALIZED is used for probabilities
kono
parents:
diff changeset
107 that has not been determined yet (for example bacause of
kono
parents:
diff changeset
108 -fno-guess-branch-probability)
kono
parents:
diff changeset
109
kono
parents:
diff changeset
110 Typically probabilities are derived from profile feedback (via
kono
parents:
diff changeset
111 probability_in_gcov_type), autoFDO or guessed statically and then propagated
kono
parents:
diff changeset
112 thorough the compilation.
kono
parents:
diff changeset
113
kono
parents:
diff changeset
114 Named probabilities are available:
kono
parents:
diff changeset
115 - never (0 probability)
kono
parents:
diff changeset
116 - guessed_never
kono
parents:
diff changeset
117 - very_unlikely (1/2000 probability)
kono
parents:
diff changeset
118 - unlikely (1/5 probablity)
kono
parents:
diff changeset
119 - even (1/2 probability)
kono
parents:
diff changeset
120 - likely (4/5 probability)
kono
parents:
diff changeset
121 - very_likely (1999/2000 probability)
kono
parents:
diff changeset
122 - guessed_always
kono
parents:
diff changeset
123 - always
kono
parents:
diff changeset
124
kono
parents:
diff changeset
125 Named probabilities except for never/always are assumed to be statically
kono
parents:
diff changeset
126 guessed and thus not necessarily accurate. The difference between never
kono
parents:
diff changeset
127 and guessed_never is that the first one should be used only in case that
kono
parents:
diff changeset
128 well behaving program will very likely not execute the "never" path.
kono
parents:
diff changeset
129 For example if the path is going to abort () call or it exception handling.
kono
parents:
diff changeset
130
kono
parents:
diff changeset
131 Always and guessed_always probabilities are symmetric.
kono
parents:
diff changeset
132
kono
parents:
diff changeset
133 For legacy code we support conversion to/from REG_BR_PROB_BASE based fixpoint
kono
parents:
diff changeset
134 integer arithmetics. Once the code is converted to branch probabilities,
kono
parents:
diff changeset
135 these conversions will probably go away because they are lossy.
kono
parents:
diff changeset
136 */
kono
parents:
diff changeset
137
kono
parents:
diff changeset
138 class GTY((user)) profile_probability
kono
parents:
diff changeset
139 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
140 static const int n_bits = 29;
111
kono
parents:
diff changeset
141 /* We can technically use ((uint32_t) 1 << (n_bits - 1)) - 2 but that
kono
parents:
diff changeset
142 will lead to harder multiplication sequences. */
kono
parents:
diff changeset
143 static const uint32_t max_probability = (uint32_t) 1 << (n_bits - 2);
kono
parents:
diff changeset
144 static const uint32_t uninitialized_probability
kono
parents:
diff changeset
145 = ((uint32_t) 1 << (n_bits - 1)) - 1;
kono
parents:
diff changeset
146
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
147 uint32_t m_val : 29;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
148 enum profile_quality m_quality : 3;
111
kono
parents:
diff changeset
149
kono
parents:
diff changeset
150 friend class profile_count;
kono
parents:
diff changeset
151 public:
kono
parents:
diff changeset
152
kono
parents:
diff changeset
153 /* Named probabilities. */
kono
parents:
diff changeset
154 static profile_probability never ()
kono
parents:
diff changeset
155 {
kono
parents:
diff changeset
156 profile_probability ret;
kono
parents:
diff changeset
157 ret.m_val = 0;
kono
parents:
diff changeset
158 ret.m_quality = profile_precise;
kono
parents:
diff changeset
159 return ret;
kono
parents:
diff changeset
160 }
kono
parents:
diff changeset
161 static profile_probability guessed_never ()
kono
parents:
diff changeset
162 {
kono
parents:
diff changeset
163 profile_probability ret;
kono
parents:
diff changeset
164 ret.m_val = 0;
kono
parents:
diff changeset
165 ret.m_quality = profile_guessed;
kono
parents:
diff changeset
166 return ret;
kono
parents:
diff changeset
167 }
kono
parents:
diff changeset
168 static profile_probability very_unlikely ()
kono
parents:
diff changeset
169 {
kono
parents:
diff changeset
170 /* Be consistent with PROB_VERY_UNLIKELY in predict.h. */
kono
parents:
diff changeset
171 profile_probability r
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
172 = profile_probability::guessed_always ().apply_scale (1, 2000);
111
kono
parents:
diff changeset
173 r.m_val--;
kono
parents:
diff changeset
174 return r;
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176 static profile_probability unlikely ()
kono
parents:
diff changeset
177 {
kono
parents:
diff changeset
178 /* Be consistent with PROB_VERY_LIKELY in predict.h. */
kono
parents:
diff changeset
179 profile_probability r
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
180 = profile_probability::guessed_always ().apply_scale (1, 5);
111
kono
parents:
diff changeset
181 r.m_val--;
kono
parents:
diff changeset
182 return r;
kono
parents:
diff changeset
183 }
kono
parents:
diff changeset
184 static profile_probability even ()
kono
parents:
diff changeset
185 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
186 return profile_probability::guessed_always ().apply_scale (1, 2);
111
kono
parents:
diff changeset
187 }
kono
parents:
diff changeset
188 static profile_probability very_likely ()
kono
parents:
diff changeset
189 {
kono
parents:
diff changeset
190 return profile_probability::always () - very_unlikely ();
kono
parents:
diff changeset
191 }
kono
parents:
diff changeset
192 static profile_probability likely ()
kono
parents:
diff changeset
193 {
kono
parents:
diff changeset
194 return profile_probability::always () - unlikely ();
kono
parents:
diff changeset
195 }
kono
parents:
diff changeset
196 static profile_probability guessed_always ()
kono
parents:
diff changeset
197 {
kono
parents:
diff changeset
198 profile_probability ret;
kono
parents:
diff changeset
199 ret.m_val = max_probability;
kono
parents:
diff changeset
200 ret.m_quality = profile_guessed;
kono
parents:
diff changeset
201 return ret;
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203 static profile_probability always ()
kono
parents:
diff changeset
204 {
kono
parents:
diff changeset
205 profile_probability ret;
kono
parents:
diff changeset
206 ret.m_val = max_probability;
kono
parents:
diff changeset
207 ret.m_quality = profile_precise;
kono
parents:
diff changeset
208 return ret;
kono
parents:
diff changeset
209 }
kono
parents:
diff changeset
210 /* Probabilities which has not been initialized. Either because
kono
parents:
diff changeset
211 initialization did not happen yet or because profile is unknown. */
kono
parents:
diff changeset
212 static profile_probability uninitialized ()
kono
parents:
diff changeset
213 {
kono
parents:
diff changeset
214 profile_probability c;
kono
parents:
diff changeset
215 c.m_val = uninitialized_probability;
kono
parents:
diff changeset
216 c.m_quality = profile_guessed;
kono
parents:
diff changeset
217 return c;
kono
parents:
diff changeset
218 }
kono
parents:
diff changeset
219
kono
parents:
diff changeset
220
kono
parents:
diff changeset
221 /* Return true if value has been initialized. */
kono
parents:
diff changeset
222 bool initialized_p () const
kono
parents:
diff changeset
223 {
kono
parents:
diff changeset
224 return m_val != uninitialized_probability;
kono
parents:
diff changeset
225 }
kono
parents:
diff changeset
226 /* Return true if value can be trusted. */
kono
parents:
diff changeset
227 bool reliable_p () const
kono
parents:
diff changeset
228 {
kono
parents:
diff changeset
229 return m_quality >= profile_adjusted;
kono
parents:
diff changeset
230 }
kono
parents:
diff changeset
231
kono
parents:
diff changeset
232 /* Conversion from and to REG_BR_PROB_BASE integer fixpoint arithmetics.
kono
parents:
diff changeset
233 this is mostly to support legacy code and should go away. */
kono
parents:
diff changeset
234 static profile_probability from_reg_br_prob_base (int v)
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 profile_probability ret;
kono
parents:
diff changeset
237 gcc_checking_assert (v >= 0 && v <= REG_BR_PROB_BASE);
kono
parents:
diff changeset
238 ret.m_val = RDIV (v * (uint64_t) max_probability, REG_BR_PROB_BASE);
kono
parents:
diff changeset
239 ret.m_quality = profile_guessed;
kono
parents:
diff changeset
240 return ret;
kono
parents:
diff changeset
241 }
kono
parents:
diff changeset
242 int to_reg_br_prob_base () const
kono
parents:
diff changeset
243 {
kono
parents:
diff changeset
244 gcc_checking_assert (initialized_p ());
kono
parents:
diff changeset
245 return RDIV (m_val * (uint64_t) REG_BR_PROB_BASE, max_probability);
kono
parents:
diff changeset
246 }
kono
parents:
diff changeset
247
kono
parents:
diff changeset
248 /* Conversion to and from RTL representation of profile probabilities. */
kono
parents:
diff changeset
249 static profile_probability from_reg_br_prob_note (int v)
kono
parents:
diff changeset
250 {
kono
parents:
diff changeset
251 profile_probability ret;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
252 ret.m_val = ((unsigned int)v) / 8;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
253 ret.m_quality = (enum profile_quality)(v & 7);
111
kono
parents:
diff changeset
254 return ret;
kono
parents:
diff changeset
255 }
kono
parents:
diff changeset
256 int to_reg_br_prob_note () const
kono
parents:
diff changeset
257 {
kono
parents:
diff changeset
258 gcc_checking_assert (initialized_p ());
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
259 int ret = m_val * 8 + m_quality;
111
kono
parents:
diff changeset
260 gcc_checking_assert (profile_probability::from_reg_br_prob_note (ret)
kono
parents:
diff changeset
261 == *this);
kono
parents:
diff changeset
262 return ret;
kono
parents:
diff changeset
263 }
kono
parents:
diff changeset
264
kono
parents:
diff changeset
265 /* Return VAL1/VAL2. */
kono
parents:
diff changeset
266 static profile_probability probability_in_gcov_type
kono
parents:
diff changeset
267 (gcov_type val1, gcov_type val2)
kono
parents:
diff changeset
268 {
kono
parents:
diff changeset
269 profile_probability ret;
kono
parents:
diff changeset
270 gcc_checking_assert (val1 >= 0 && val2 > 0);
kono
parents:
diff changeset
271 if (val1 > val2)
kono
parents:
diff changeset
272 ret.m_val = max_probability;
kono
parents:
diff changeset
273 else
kono
parents:
diff changeset
274 {
kono
parents:
diff changeset
275 uint64_t tmp;
kono
parents:
diff changeset
276 safe_scale_64bit (val1, max_probability, val2, &tmp);
kono
parents:
diff changeset
277 gcc_checking_assert (tmp <= max_probability);
kono
parents:
diff changeset
278 ret.m_val = tmp;
kono
parents:
diff changeset
279 }
kono
parents:
diff changeset
280 ret.m_quality = profile_precise;
kono
parents:
diff changeset
281 return ret;
kono
parents:
diff changeset
282 }
kono
parents:
diff changeset
283
kono
parents:
diff changeset
284 /* Basic operations. */
kono
parents:
diff changeset
285 bool operator== (const profile_probability &other) const
kono
parents:
diff changeset
286 {
kono
parents:
diff changeset
287 return m_val == other.m_val && m_quality == other.m_quality;
kono
parents:
diff changeset
288 }
kono
parents:
diff changeset
289 profile_probability operator+ (const profile_probability &other) const
kono
parents:
diff changeset
290 {
kono
parents:
diff changeset
291 if (other == profile_probability::never ())
kono
parents:
diff changeset
292 return *this;
kono
parents:
diff changeset
293 if (*this == profile_probability::never ())
kono
parents:
diff changeset
294 return other;
kono
parents:
diff changeset
295 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
296 return profile_probability::uninitialized ();
kono
parents:
diff changeset
297
kono
parents:
diff changeset
298 profile_probability ret;
kono
parents:
diff changeset
299 ret.m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
kono
parents:
diff changeset
300 ret.m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
301 return ret;
kono
parents:
diff changeset
302 }
kono
parents:
diff changeset
303 profile_probability &operator+= (const profile_probability &other)
kono
parents:
diff changeset
304 {
kono
parents:
diff changeset
305 if (other == profile_probability::never ())
kono
parents:
diff changeset
306 return *this;
kono
parents:
diff changeset
307 if (*this == profile_probability::never ())
kono
parents:
diff changeset
308 {
kono
parents:
diff changeset
309 *this = other;
kono
parents:
diff changeset
310 return *this;
kono
parents:
diff changeset
311 }
kono
parents:
diff changeset
312 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
313 return *this = profile_probability::uninitialized ();
kono
parents:
diff changeset
314 else
kono
parents:
diff changeset
315 {
kono
parents:
diff changeset
316 m_val = MIN ((uint32_t)(m_val + other.m_val), max_probability);
kono
parents:
diff changeset
317 m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
318 }
kono
parents:
diff changeset
319 return *this;
kono
parents:
diff changeset
320 }
kono
parents:
diff changeset
321 profile_probability operator- (const profile_probability &other) const
kono
parents:
diff changeset
322 {
kono
parents:
diff changeset
323 if (*this == profile_probability::never ()
kono
parents:
diff changeset
324 || other == profile_probability::never ())
kono
parents:
diff changeset
325 return *this;
kono
parents:
diff changeset
326 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
327 return profile_probability::uninitialized ();
kono
parents:
diff changeset
328 profile_probability ret;
kono
parents:
diff changeset
329 ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
kono
parents:
diff changeset
330 ret.m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
331 return ret;
kono
parents:
diff changeset
332 }
kono
parents:
diff changeset
333 profile_probability &operator-= (const profile_probability &other)
kono
parents:
diff changeset
334 {
kono
parents:
diff changeset
335 if (*this == profile_probability::never ()
kono
parents:
diff changeset
336 || other == profile_probability::never ())
kono
parents:
diff changeset
337 return *this;
kono
parents:
diff changeset
338 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
339 return *this = profile_probability::uninitialized ();
kono
parents:
diff changeset
340 else
kono
parents:
diff changeset
341 {
kono
parents:
diff changeset
342 m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
kono
parents:
diff changeset
343 m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
344 }
kono
parents:
diff changeset
345 return *this;
kono
parents:
diff changeset
346 }
kono
parents:
diff changeset
347 profile_probability operator* (const profile_probability &other) const
kono
parents:
diff changeset
348 {
kono
parents:
diff changeset
349 if (*this == profile_probability::never ()
kono
parents:
diff changeset
350 || other == profile_probability::never ())
kono
parents:
diff changeset
351 return profile_probability::never ();
kono
parents:
diff changeset
352 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
353 return profile_probability::uninitialized ();
kono
parents:
diff changeset
354 profile_probability ret;
kono
parents:
diff changeset
355 ret.m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
356 ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
111
kono
parents:
diff changeset
357 return ret;
kono
parents:
diff changeset
358 }
kono
parents:
diff changeset
359 profile_probability &operator*= (const profile_probability &other)
kono
parents:
diff changeset
360 {
kono
parents:
diff changeset
361 if (*this == profile_probability::never ()
kono
parents:
diff changeset
362 || other == profile_probability::never ())
kono
parents:
diff changeset
363 return *this = profile_probability::never ();
kono
parents:
diff changeset
364 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
365 return *this = profile_probability::uninitialized ();
kono
parents:
diff changeset
366 else
kono
parents:
diff changeset
367 {
kono
parents:
diff changeset
368 m_val = RDIV ((uint64_t)m_val * other.m_val, max_probability);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
369 m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
111
kono
parents:
diff changeset
370 }
kono
parents:
diff changeset
371 return *this;
kono
parents:
diff changeset
372 }
kono
parents:
diff changeset
373 profile_probability operator/ (const profile_probability &other) const
kono
parents:
diff changeset
374 {
kono
parents:
diff changeset
375 if (*this == profile_probability::never ())
kono
parents:
diff changeset
376 return profile_probability::never ();
kono
parents:
diff changeset
377 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
378 return profile_probability::uninitialized ();
kono
parents:
diff changeset
379 profile_probability ret;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
380 /* If we get probability above 1, mark it as unreliable and return 1. */
111
kono
parents:
diff changeset
381 if (m_val >= other.m_val)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
382 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
383 ret.m_val = max_probability;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
384 ret.m_quality = MIN (MIN (m_quality, other.m_quality),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
385 profile_guessed);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
386 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
387 }
111
kono
parents:
diff changeset
388 else if (!m_val)
kono
parents:
diff changeset
389 ret.m_val = 0;
kono
parents:
diff changeset
390 else
kono
parents:
diff changeset
391 {
kono
parents:
diff changeset
392 gcc_checking_assert (other.m_val);
kono
parents:
diff changeset
393 ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
kono
parents:
diff changeset
394 other.m_val),
kono
parents:
diff changeset
395 max_probability);
kono
parents:
diff changeset
396 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
397 ret.m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
111
kono
parents:
diff changeset
398 return ret;
kono
parents:
diff changeset
399 }
kono
parents:
diff changeset
400 profile_probability &operator/= (const profile_probability &other)
kono
parents:
diff changeset
401 {
kono
parents:
diff changeset
402 if (*this == profile_probability::never ())
kono
parents:
diff changeset
403 return *this = profile_probability::never ();
kono
parents:
diff changeset
404 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
405 return *this = profile_probability::uninitialized ();
kono
parents:
diff changeset
406 else
kono
parents:
diff changeset
407 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
408 /* If we get probability above 1, mark it as unreliable
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
409 and return 1. */
111
kono
parents:
diff changeset
410 if (m_val > other.m_val)
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
411 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
412 m_val = max_probability;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
413 m_quality = MIN (MIN (m_quality, other.m_quality),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
414 profile_guessed);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
415 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
416 }
111
kono
parents:
diff changeset
417 else if (!m_val)
kono
parents:
diff changeset
418 ;
kono
parents:
diff changeset
419 else
kono
parents:
diff changeset
420 {
kono
parents:
diff changeset
421 gcc_checking_assert (other.m_val);
kono
parents:
diff changeset
422 m_val = MIN (RDIV ((uint64_t)m_val * max_probability,
kono
parents:
diff changeset
423 other.m_val),
kono
parents:
diff changeset
424 max_probability);
kono
parents:
diff changeset
425 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
426 m_quality = MIN (MIN (m_quality, other.m_quality), profile_adjusted);
111
kono
parents:
diff changeset
427 }
kono
parents:
diff changeset
428 return *this;
kono
parents:
diff changeset
429 }
kono
parents:
diff changeset
430
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
431 /* Split *THIS (ORIG) probability into 2 probabilities, such that
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
432 the returned one (FIRST) is *THIS * CPROB and *THIS is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
433 adjusted (SECOND) so that FIRST + FIRST.invert () * SECOND
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
434 == ORIG. This is useful e.g. when splitting a conditional
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
435 branch like:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
436 if (cond)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
437 goto lab; // ORIG probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
438 into
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
439 if (cond1)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
440 goto lab; // FIRST = ORIG * CPROB probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
441 if (cond2)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
442 goto lab; // SECOND probability
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
443 such that the overall probability of jumping to lab remains
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
444 the same. CPROB gives the relative probability between the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
445 branches. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
446 profile_probability split (const profile_probability &cprob)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
447 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
448 profile_probability ret = *this * cprob;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
449 /* The following is equivalent to:
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
450 *this = cprob.invert () * *this / ret.invert (); */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
451 *this = (*this - ret) / ret.invert ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
452 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
453 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
454
111
kono
parents:
diff changeset
455 gcov_type apply (gcov_type val) const
kono
parents:
diff changeset
456 {
kono
parents:
diff changeset
457 if (*this == profile_probability::uninitialized ())
kono
parents:
diff changeset
458 return val / 2;
kono
parents:
diff changeset
459 return RDIV (val * m_val, max_probability);
kono
parents:
diff changeset
460 }
kono
parents:
diff changeset
461
kono
parents:
diff changeset
462 /* Return 1-*THIS. */
kono
parents:
diff changeset
463 profile_probability invert () const
kono
parents:
diff changeset
464 {
kono
parents:
diff changeset
465 return profile_probability::always() - *this;
kono
parents:
diff changeset
466 }
kono
parents:
diff changeset
467
kono
parents:
diff changeset
468 /* Return THIS with quality dropped to GUESSED. */
kono
parents:
diff changeset
469 profile_probability guessed () const
kono
parents:
diff changeset
470 {
kono
parents:
diff changeset
471 profile_probability ret = *this;
kono
parents:
diff changeset
472 ret.m_quality = profile_guessed;
kono
parents:
diff changeset
473 return ret;
kono
parents:
diff changeset
474 }
kono
parents:
diff changeset
475
kono
parents:
diff changeset
476 /* Return THIS with quality dropped to AFDO. */
kono
parents:
diff changeset
477 profile_probability afdo () const
kono
parents:
diff changeset
478 {
kono
parents:
diff changeset
479 profile_probability ret = *this;
kono
parents:
diff changeset
480 ret.m_quality = profile_afdo;
kono
parents:
diff changeset
481 return ret;
kono
parents:
diff changeset
482 }
kono
parents:
diff changeset
483
kono
parents:
diff changeset
484 /* Return *THIS * NUM / DEN. */
kono
parents:
diff changeset
485 profile_probability apply_scale (int64_t num, int64_t den) const
kono
parents:
diff changeset
486 {
kono
parents:
diff changeset
487 if (*this == profile_probability::never ())
kono
parents:
diff changeset
488 return *this;
kono
parents:
diff changeset
489 if (!initialized_p ())
kono
parents:
diff changeset
490 return profile_probability::uninitialized ();
kono
parents:
diff changeset
491 profile_probability ret;
kono
parents:
diff changeset
492 uint64_t tmp;
kono
parents:
diff changeset
493 safe_scale_64bit (m_val, num, den, &tmp);
kono
parents:
diff changeset
494 ret.m_val = MIN (tmp, max_probability);
kono
parents:
diff changeset
495 ret.m_quality = MIN (m_quality, profile_adjusted);
kono
parents:
diff changeset
496 return ret;
kono
parents:
diff changeset
497 }
kono
parents:
diff changeset
498
kono
parents:
diff changeset
499 /* Return true when the probability of edge is reliable.
kono
parents:
diff changeset
500
kono
parents:
diff changeset
501 The profile guessing code is good at predicting branch outcome (ie.
kono
parents:
diff changeset
502 taken/not taken), that is predicted right slightly over 75% of time.
kono
parents:
diff changeset
503 It is however notoriously poor on predicting the probability itself.
kono
parents:
diff changeset
504 In general the profile appear a lot flatter (with probabilities closer
kono
parents:
diff changeset
505 to 50%) than the reality so it is bad idea to use it to drive optimization
kono
parents:
diff changeset
506 such as those disabling dynamic branch prediction for well predictable
kono
parents:
diff changeset
507 branches.
kono
parents:
diff changeset
508
kono
parents:
diff changeset
509 There are two exceptions - edges leading to noreturn edges and edges
kono
parents:
diff changeset
510 predicted by number of iterations heuristics are predicted well. This macro
kono
parents:
diff changeset
511 should be able to distinguish those, but at the moment it simply check for
kono
parents:
diff changeset
512 noreturn heuristic that is only one giving probability over 99% or bellow
kono
parents:
diff changeset
513 1%. In future we might want to propagate reliability information across the
kono
parents:
diff changeset
514 CFG if we find this information useful on multiple places. */
kono
parents:
diff changeset
515
kono
parents:
diff changeset
516 bool probably_reliable_p () const
kono
parents:
diff changeset
517 {
kono
parents:
diff changeset
518 if (m_quality >= profile_adjusted)
kono
parents:
diff changeset
519 return true;
kono
parents:
diff changeset
520 if (!initialized_p ())
kono
parents:
diff changeset
521 return false;
kono
parents:
diff changeset
522 return m_val < max_probability / 100
kono
parents:
diff changeset
523 || m_val > max_probability - max_probability / 100;
kono
parents:
diff changeset
524 }
kono
parents:
diff changeset
525
kono
parents:
diff changeset
526 /* Return false if profile_probability is bogus. */
kono
parents:
diff changeset
527 bool verify () const
kono
parents:
diff changeset
528 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
529 gcc_checking_assert (m_quality != profile_uninitialized);
111
kono
parents:
diff changeset
530 if (m_val == uninitialized_probability)
kono
parents:
diff changeset
531 return m_quality == profile_guessed;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
532 else if (m_quality < profile_guessed)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
533 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
534 return m_val <= max_probability;
111
kono
parents:
diff changeset
535 }
kono
parents:
diff changeset
536
kono
parents:
diff changeset
537 /* Comparsions are three-state and conservative. False is returned if
kono
parents:
diff changeset
538 the inequality can not be decided. */
kono
parents:
diff changeset
539 bool operator< (const profile_probability &other) const
kono
parents:
diff changeset
540 {
kono
parents:
diff changeset
541 return initialized_p () && other.initialized_p () && m_val < other.m_val;
kono
parents:
diff changeset
542 }
kono
parents:
diff changeset
543 bool operator> (const profile_probability &other) const
kono
parents:
diff changeset
544 {
kono
parents:
diff changeset
545 return initialized_p () && other.initialized_p () && m_val > other.m_val;
kono
parents:
diff changeset
546 }
kono
parents:
diff changeset
547
kono
parents:
diff changeset
548 bool operator<= (const profile_probability &other) const
kono
parents:
diff changeset
549 {
kono
parents:
diff changeset
550 return initialized_p () && other.initialized_p () && m_val <= other.m_val;
kono
parents:
diff changeset
551 }
kono
parents:
diff changeset
552 bool operator>= (const profile_probability &other) const
kono
parents:
diff changeset
553 {
kono
parents:
diff changeset
554 return initialized_p () && other.initialized_p () && m_val >= other.m_val;
kono
parents:
diff changeset
555 }
kono
parents:
diff changeset
556
kono
parents:
diff changeset
557 /* Output THIS to F. */
kono
parents:
diff changeset
558 void dump (FILE *f) const;
kono
parents:
diff changeset
559
kono
parents:
diff changeset
560 /* Print THIS to stderr. */
kono
parents:
diff changeset
561 void debug () const;
kono
parents:
diff changeset
562
kono
parents:
diff changeset
563 /* Return true if THIS is known to differ significantly from OTHER. */
kono
parents:
diff changeset
564 bool differs_from_p (profile_probability other) const;
kono
parents:
diff changeset
565 /* Return if difference is greater than 50%. */
kono
parents:
diff changeset
566 bool differs_lot_from_p (profile_probability other) const;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
567 /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
568 happens with COUNT2 probablity. Return probablity that either *THIS or
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
569 OTHER happens. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
570 profile_probability combine_with_count (profile_count count1,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
571 profile_probability other,
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
572 profile_count count2) const;
111
kono
parents:
diff changeset
573
kono
parents:
diff changeset
574 /* LTO streaming support. */
kono
parents:
diff changeset
575 static profile_probability stream_in (struct lto_input_block *);
kono
parents:
diff changeset
576 void stream_out (struct output_block *);
kono
parents:
diff changeset
577 void stream_out (struct lto_output_stream *);
kono
parents:
diff changeset
578 };
kono
parents:
diff changeset
579
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
580 /* Main data type to hold profile counters in GCC. Profile counts originate
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
581 either from profile feedback, static profile estimation or both. We do not
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
582 perform whole program profile propagation and thus profile estimation
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
583 counters are often local to function, while counters from profile feedback
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
584 (or special cases of profile estimation) can be used inter-procedurally.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
585
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
586 There are 3 basic types
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
587 1) local counters which are result of intra-procedural static profile
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
588 estimation.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
589 2) ipa counters which are result of profile feedback or special case
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
590 of static profile estimation (such as in function main).
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
591 3) counters which counts as 0 inter-procedurally (beause given function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
592 was never run in train feedback) but they hold local static profile
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
593 estimate.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
594
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
595 Counters of type 1 and 3 can not be mixed with counters of different type
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
596 within operation (because whole function should use one type of counter)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
597 with exception that global zero mix in most operations where outcome is
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
598 well defined.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
599
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
600 To take local counter and use it inter-procedurally use ipa member function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
601 which strips information irelevant at the inter-procedural level.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
602
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
603 Counters are 61bit integers representing number of executions during the
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
604 train run or normalized frequency within the function.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
605
111
kono
parents:
diff changeset
606 As the profile is maintained during the compilation, many adjustments are
kono
parents:
diff changeset
607 made. Not all transformations can be made precisely, most importantly
kono
parents:
diff changeset
608 when code is being duplicated. It also may happen that part of CFG has
kono
parents:
diff changeset
609 profile counts known while other do not - for example when LTO optimizing
kono
parents:
diff changeset
610 partly profiled program or when profile was lost due to COMDAT merging.
kono
parents:
diff changeset
611
kono
parents:
diff changeset
612 For this reason profile_count tracks more information than
kono
parents:
diff changeset
613 just unsigned integer and it is also ready for profile mismatches.
kono
parents:
diff changeset
614 The API of this data type represent operations that are natural
kono
parents:
diff changeset
615 on profile counts - sum, difference and operation with scales and
kono
parents:
diff changeset
616 probabilities. All operations are safe by never getting negative counts
kono
parents:
diff changeset
617 and they do end up in uninitialized scale if any of the parameters is
kono
parents:
diff changeset
618 uninitialized.
kono
parents:
diff changeset
619
kono
parents:
diff changeset
620 All comparsions that are three state and handling of probabilities. Thus
kono
parents:
diff changeset
621 a < b is not equal to !(a >= b).
kono
parents:
diff changeset
622
kono
parents:
diff changeset
623 The following pre-defined counts are available:
kono
parents:
diff changeset
624
kono
parents:
diff changeset
625 profile_count::zero () for code that is known to execute zero times at
kono
parents:
diff changeset
626 runtime (this can be detected statically i.e. for paths leading to
kono
parents:
diff changeset
627 abort ();
kono
parents:
diff changeset
628 profile_count::one () for code that is known to execute once (such as
kono
parents:
diff changeset
629 main () function
kono
parents:
diff changeset
630 profile_count::uninitialized () for unknown execution count.
kono
parents:
diff changeset
631
kono
parents:
diff changeset
632 */
kono
parents:
diff changeset
633
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
634 class sreal;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
635
111
kono
parents:
diff changeset
636 class GTY(()) profile_count
kono
parents:
diff changeset
637 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
638 public:
111
kono
parents:
diff changeset
639 /* Use 62bit to hold basic block counters. Should be at least
kono
parents:
diff changeset
640 64bit. Although a counter cannot be negative, we use a signed
kono
parents:
diff changeset
641 type to hold various extra stages. */
kono
parents:
diff changeset
642
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
643 static const int n_bits = 61;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
644 private:
111
kono
parents:
diff changeset
645 static const uint64_t max_count = ((uint64_t) 1 << n_bits) - 2;
kono
parents:
diff changeset
646 static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
kono
parents:
diff changeset
647
kono
parents:
diff changeset
648 uint64_t m_val : n_bits;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
649 enum profile_quality m_quality : 3;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
650
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
651 /* Return true if both values can meaningfully appear in single function
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
652 body. We have either all counters in function local or global, otherwise
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
653 operations between them are not really defined well. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
654 bool compatible_p (const profile_count other) const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
655 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
656 if (!initialized_p () || !other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
657 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
658 if (*this == profile_count::zero ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
659 || other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
660 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
661 return ipa_p () == other.ipa_p ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
662 }
111
kono
parents:
diff changeset
663 public:
kono
parents:
diff changeset
664
kono
parents:
diff changeset
665 /* Used for counters which are expected to be never executed. */
kono
parents:
diff changeset
666 static profile_count zero ()
kono
parents:
diff changeset
667 {
kono
parents:
diff changeset
668 return from_gcov_type (0);
kono
parents:
diff changeset
669 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
670 static profile_count adjusted_zero ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
671 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
672 profile_count c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
673 c.m_val = 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
674 c.m_quality = profile_adjusted;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
675 return c;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
676 }
111
kono
parents:
diff changeset
677 static profile_count guessed_zero ()
kono
parents:
diff changeset
678 {
kono
parents:
diff changeset
679 profile_count c;
kono
parents:
diff changeset
680 c.m_val = 0;
kono
parents:
diff changeset
681 c.m_quality = profile_guessed;
kono
parents:
diff changeset
682 return c;
kono
parents:
diff changeset
683 }
kono
parents:
diff changeset
684 static profile_count one ()
kono
parents:
diff changeset
685 {
kono
parents:
diff changeset
686 return from_gcov_type (1);
kono
parents:
diff changeset
687 }
kono
parents:
diff changeset
688 /* Value of counters which has not been initialized. Either because
kono
parents:
diff changeset
689 initialization did not happen yet or because profile is unknown. */
kono
parents:
diff changeset
690 static profile_count uninitialized ()
kono
parents:
diff changeset
691 {
kono
parents:
diff changeset
692 profile_count c;
kono
parents:
diff changeset
693 c.m_val = uninitialized_count;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
694 c.m_quality = profile_guessed_local;
111
kono
parents:
diff changeset
695 return c;
kono
parents:
diff changeset
696 }
kono
parents:
diff changeset
697
kono
parents:
diff changeset
698 /* Conversion to gcov_type is lossy. */
kono
parents:
diff changeset
699 gcov_type to_gcov_type () const
kono
parents:
diff changeset
700 {
kono
parents:
diff changeset
701 gcc_checking_assert (initialized_p ());
kono
parents:
diff changeset
702 return m_val;
kono
parents:
diff changeset
703 }
kono
parents:
diff changeset
704
kono
parents:
diff changeset
705 /* Return true if value has been initialized. */
kono
parents:
diff changeset
706 bool initialized_p () const
kono
parents:
diff changeset
707 {
kono
parents:
diff changeset
708 return m_val != uninitialized_count;
kono
parents:
diff changeset
709 }
kono
parents:
diff changeset
710 /* Return true if value can be trusted. */
kono
parents:
diff changeset
711 bool reliable_p () const
kono
parents:
diff changeset
712 {
kono
parents:
diff changeset
713 return m_quality >= profile_adjusted;
kono
parents:
diff changeset
714 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
715 /* Return true if vlaue can be operated inter-procedurally. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
716 bool ipa_p () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
717 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
718 return !initialized_p () || m_quality >= profile_guessed_global0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
719 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
720 /* Return true if quality of profile is precise. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
721 bool precise_p () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
722 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
723 return m_quality == profile_precise;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
724 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
725
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
726 /* Get the quality of the count. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
727 enum profile_quality quality () const { return m_quality; }
111
kono
parents:
diff changeset
728
kono
parents:
diff changeset
729 /* When merging basic blocks, the two different profile counts are unified.
kono
parents:
diff changeset
730 Return true if this can be done without losing info about profile.
kono
parents:
diff changeset
731 The only case we care about here is when first BB contains something
kono
parents:
diff changeset
732 that makes it terminate in a way not visible in CFG. */
kono
parents:
diff changeset
733 bool ok_for_merging (profile_count other) const
kono
parents:
diff changeset
734 {
kono
parents:
diff changeset
735 if (m_quality < profile_adjusted
kono
parents:
diff changeset
736 || other.m_quality < profile_adjusted)
kono
parents:
diff changeset
737 return true;
kono
parents:
diff changeset
738 return !(other < *this);
kono
parents:
diff changeset
739 }
kono
parents:
diff changeset
740
kono
parents:
diff changeset
741 /* When merging two BBs with different counts, pick common count that looks
kono
parents:
diff changeset
742 most representative. */
kono
parents:
diff changeset
743 profile_count merge (profile_count other) const
kono
parents:
diff changeset
744 {
kono
parents:
diff changeset
745 if (*this == other || !other.initialized_p ()
kono
parents:
diff changeset
746 || m_quality > other.m_quality)
kono
parents:
diff changeset
747 return *this;
kono
parents:
diff changeset
748 if (other.m_quality > m_quality
kono
parents:
diff changeset
749 || other > *this)
kono
parents:
diff changeset
750 return other;
kono
parents:
diff changeset
751 return *this;
kono
parents:
diff changeset
752 }
kono
parents:
diff changeset
753
kono
parents:
diff changeset
754 /* Basic operations. */
kono
parents:
diff changeset
755 bool operator== (const profile_count &other) const
kono
parents:
diff changeset
756 {
kono
parents:
diff changeset
757 return m_val == other.m_val && m_quality == other.m_quality;
kono
parents:
diff changeset
758 }
kono
parents:
diff changeset
759 profile_count operator+ (const profile_count &other) const
kono
parents:
diff changeset
760 {
kono
parents:
diff changeset
761 if (other == profile_count::zero ())
kono
parents:
diff changeset
762 return *this;
kono
parents:
diff changeset
763 if (*this == profile_count::zero ())
kono
parents:
diff changeset
764 return other;
kono
parents:
diff changeset
765 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
766 return profile_count::uninitialized ();
kono
parents:
diff changeset
767
kono
parents:
diff changeset
768 profile_count ret;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
769 gcc_checking_assert (compatible_p (other));
111
kono
parents:
diff changeset
770 ret.m_val = m_val + other.m_val;
kono
parents:
diff changeset
771 ret.m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
772 return ret;
kono
parents:
diff changeset
773 }
kono
parents:
diff changeset
774 profile_count &operator+= (const profile_count &other)
kono
parents:
diff changeset
775 {
kono
parents:
diff changeset
776 if (other == profile_count::zero ())
kono
parents:
diff changeset
777 return *this;
kono
parents:
diff changeset
778 if (*this == profile_count::zero ())
kono
parents:
diff changeset
779 {
kono
parents:
diff changeset
780 *this = other;
kono
parents:
diff changeset
781 return *this;
kono
parents:
diff changeset
782 }
kono
parents:
diff changeset
783 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
784 return *this = profile_count::uninitialized ();
kono
parents:
diff changeset
785 else
kono
parents:
diff changeset
786 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
787 gcc_checking_assert (compatible_p (other));
111
kono
parents:
diff changeset
788 m_val += other.m_val;
kono
parents:
diff changeset
789 m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
790 }
kono
parents:
diff changeset
791 return *this;
kono
parents:
diff changeset
792 }
kono
parents:
diff changeset
793 profile_count operator- (const profile_count &other) const
kono
parents:
diff changeset
794 {
kono
parents:
diff changeset
795 if (*this == profile_count::zero () || other == profile_count::zero ())
kono
parents:
diff changeset
796 return *this;
kono
parents:
diff changeset
797 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
798 return profile_count::uninitialized ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
799 gcc_checking_assert (compatible_p (other));
111
kono
parents:
diff changeset
800 profile_count ret;
kono
parents:
diff changeset
801 ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
kono
parents:
diff changeset
802 ret.m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
803 return ret;
kono
parents:
diff changeset
804 }
kono
parents:
diff changeset
805 profile_count &operator-= (const profile_count &other)
kono
parents:
diff changeset
806 {
kono
parents:
diff changeset
807 if (*this == profile_count::zero () || other == profile_count::zero ())
kono
parents:
diff changeset
808 return *this;
kono
parents:
diff changeset
809 if (!initialized_p () || !other.initialized_p ())
kono
parents:
diff changeset
810 return *this = profile_count::uninitialized ();
kono
parents:
diff changeset
811 else
kono
parents:
diff changeset
812 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
813 gcc_checking_assert (compatible_p (other));
111
kono
parents:
diff changeset
814 m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
kono
parents:
diff changeset
815 m_quality = MIN (m_quality, other.m_quality);
kono
parents:
diff changeset
816 }
kono
parents:
diff changeset
817 return *this;
kono
parents:
diff changeset
818 }
kono
parents:
diff changeset
819
kono
parents:
diff changeset
820 /* Return false if profile_count is bogus. */
kono
parents:
diff changeset
821 bool verify () const
kono
parents:
diff changeset
822 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
823 gcc_checking_assert (m_quality != profile_uninitialized);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
824 return m_val != uninitialized_count || m_quality == profile_guessed_local;
111
kono
parents:
diff changeset
825 }
kono
parents:
diff changeset
826
kono
parents:
diff changeset
827 /* Comparsions are three-state and conservative. False is returned if
kono
parents:
diff changeset
828 the inequality can not be decided. */
kono
parents:
diff changeset
829 bool operator< (const profile_count &other) const
kono
parents:
diff changeset
830 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
831 if (!initialized_p () || !other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
832 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
833 if (*this == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
834 return !(other == profile_count::zero ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
835 if (other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
836 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
837 gcc_checking_assert (compatible_p (other));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
838 return m_val < other.m_val;
111
kono
parents:
diff changeset
839 }
kono
parents:
diff changeset
840 bool operator> (const profile_count &other) const
kono
parents:
diff changeset
841 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
842 if (!initialized_p () || !other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
843 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
844 if (*this == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
845 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
846 if (other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
847 return !(*this == profile_count::zero ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
848 gcc_checking_assert (compatible_p (other));
111
kono
parents:
diff changeset
849 return initialized_p () && other.initialized_p () && m_val > other.m_val;
kono
parents:
diff changeset
850 }
kono
parents:
diff changeset
851 bool operator< (const gcov_type other) const
kono
parents:
diff changeset
852 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
853 gcc_checking_assert (ipa_p ());
111
kono
parents:
diff changeset
854 gcc_checking_assert (other >= 0);
kono
parents:
diff changeset
855 return initialized_p () && m_val < (uint64_t) other;
kono
parents:
diff changeset
856 }
kono
parents:
diff changeset
857 bool operator> (const gcov_type other) const
kono
parents:
diff changeset
858 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
859 gcc_checking_assert (ipa_p ());
111
kono
parents:
diff changeset
860 gcc_checking_assert (other >= 0);
kono
parents:
diff changeset
861 return initialized_p () && m_val > (uint64_t) other;
kono
parents:
diff changeset
862 }
kono
parents:
diff changeset
863
kono
parents:
diff changeset
864 bool operator<= (const profile_count &other) const
kono
parents:
diff changeset
865 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
866 if (!initialized_p () || !other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
867 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
868 if (*this == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
869 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
870 if (other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
871 return (*this == profile_count::zero ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
872 gcc_checking_assert (compatible_p (other));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
873 return m_val <= other.m_val;
111
kono
parents:
diff changeset
874 }
kono
parents:
diff changeset
875 bool operator>= (const profile_count &other) const
kono
parents:
diff changeset
876 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
877 if (!initialized_p () || !other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
878 return false;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
879 if (other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
880 return true;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
881 if (*this == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
882 return !(other == profile_count::zero ());
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
883 gcc_checking_assert (compatible_p (other));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
884 return m_val >= other.m_val;
111
kono
parents:
diff changeset
885 }
kono
parents:
diff changeset
886 bool operator<= (const gcov_type other) const
kono
parents:
diff changeset
887 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
888 gcc_checking_assert (ipa_p ());
111
kono
parents:
diff changeset
889 gcc_checking_assert (other >= 0);
kono
parents:
diff changeset
890 return initialized_p () && m_val <= (uint64_t) other;
kono
parents:
diff changeset
891 }
kono
parents:
diff changeset
892 bool operator>= (const gcov_type other) const
kono
parents:
diff changeset
893 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
894 gcc_checking_assert (ipa_p ());
111
kono
parents:
diff changeset
895 gcc_checking_assert (other >= 0);
kono
parents:
diff changeset
896 return initialized_p () && m_val >= (uint64_t) other;
kono
parents:
diff changeset
897 }
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
898 /* Return true when value is not zero and can be used for scaling.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
899 This is different from *this > 0 because that requires counter to
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
900 be IPA. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
901 bool nonzero_p () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
902 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
903 return initialized_p () && m_val != 0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
904 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
905
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
906 /* Make counter forcingly nonzero. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
907 profile_count force_nonzero () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
908 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
909 if (!initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
910 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
911 profile_count ret = *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
912 if (ret.m_val == 0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
913 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
914 ret.m_val = 1;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
915 ret.m_quality = MIN (m_quality, profile_adjusted);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
916 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
917 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
918 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
919
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
920 profile_count max (profile_count other) const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
921 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
922 if (!initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
923 return other;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
924 if (!other.initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
925 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
926 if (*this == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
927 return other;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
928 if (other == profile_count::zero ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
929 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
930 gcc_checking_assert (compatible_p (other));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
931 if (m_val < other.m_val || (m_val == other.m_val
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
932 && m_quality < other.m_quality))
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
933 return other;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
934 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
935 }
111
kono
parents:
diff changeset
936
kono
parents:
diff changeset
937 /* PROB is a probability in scale 0...REG_BR_PROB_BASE. Scale counter
kono
parents:
diff changeset
938 accordingly. */
kono
parents:
diff changeset
939 profile_count apply_probability (int prob) const
kono
parents:
diff changeset
940 {
kono
parents:
diff changeset
941 gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
kono
parents:
diff changeset
942 if (m_val == 0)
kono
parents:
diff changeset
943 return *this;
kono
parents:
diff changeset
944 if (!initialized_p ())
kono
parents:
diff changeset
945 return profile_count::uninitialized ();
kono
parents:
diff changeset
946 profile_count ret;
kono
parents:
diff changeset
947 ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
kono
parents:
diff changeset
948 ret.m_quality = MIN (m_quality, profile_adjusted);
kono
parents:
diff changeset
949 return ret;
kono
parents:
diff changeset
950 }
kono
parents:
diff changeset
951
kono
parents:
diff changeset
952 /* Scale counter according to PROB. */
kono
parents:
diff changeset
953 profile_count apply_probability (profile_probability prob) const
kono
parents:
diff changeset
954 {
kono
parents:
diff changeset
955 if (*this == profile_count::zero ())
kono
parents:
diff changeset
956 return *this;
kono
parents:
diff changeset
957 if (prob == profile_probability::never ())
kono
parents:
diff changeset
958 return profile_count::zero ();
kono
parents:
diff changeset
959 if (!initialized_p ())
kono
parents:
diff changeset
960 return profile_count::uninitialized ();
kono
parents:
diff changeset
961 profile_count ret;
kono
parents:
diff changeset
962 uint64_t tmp;
kono
parents:
diff changeset
963 safe_scale_64bit (m_val, prob.m_val, profile_probability::max_probability,
kono
parents:
diff changeset
964 &tmp);
kono
parents:
diff changeset
965 ret.m_val = tmp;
kono
parents:
diff changeset
966 ret.m_quality = MIN (m_quality, prob.m_quality);
kono
parents:
diff changeset
967 return ret;
kono
parents:
diff changeset
968 }
kono
parents:
diff changeset
969 /* Return *THIS * NUM / DEN. */
kono
parents:
diff changeset
970 profile_count apply_scale (int64_t num, int64_t den) const
kono
parents:
diff changeset
971 {
kono
parents:
diff changeset
972 if (m_val == 0)
kono
parents:
diff changeset
973 return *this;
kono
parents:
diff changeset
974 if (!initialized_p ())
kono
parents:
diff changeset
975 return profile_count::uninitialized ();
kono
parents:
diff changeset
976 profile_count ret;
kono
parents:
diff changeset
977 uint64_t tmp;
kono
parents:
diff changeset
978
kono
parents:
diff changeset
979 gcc_checking_assert (num >= 0 && den > 0);
kono
parents:
diff changeset
980 safe_scale_64bit (m_val, num, den, &tmp);
kono
parents:
diff changeset
981 ret.m_val = MIN (tmp, max_count);
kono
parents:
diff changeset
982 ret.m_quality = MIN (m_quality, profile_adjusted);
kono
parents:
diff changeset
983 return ret;
kono
parents:
diff changeset
984 }
kono
parents:
diff changeset
985 profile_count apply_scale (profile_count num, profile_count den) const
kono
parents:
diff changeset
986 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
987 if (*this == profile_count::zero ())
111
kono
parents:
diff changeset
988 return *this;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
989 if (num == profile_count::zero ())
111
kono
parents:
diff changeset
990 return num;
kono
parents:
diff changeset
991 if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
kono
parents:
diff changeset
992 return profile_count::uninitialized ();
kono
parents:
diff changeset
993 if (num == den)
kono
parents:
diff changeset
994 return *this;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
995 gcc_checking_assert (den.m_val);
111
kono
parents:
diff changeset
996
kono
parents:
diff changeset
997 profile_count ret;
kono
parents:
diff changeset
998 uint64_t val;
kono
parents:
diff changeset
999 safe_scale_64bit (m_val, num.m_val, den.m_val, &val);
kono
parents:
diff changeset
1000 ret.m_val = MIN (val, max_count);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1001 ret.m_quality = MIN (MIN (MIN (m_quality, profile_adjusted),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1002 num.m_quality), den.m_quality);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1003 if (num.ipa_p () && !ret.ipa_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1004 ret.m_quality = MIN (num.m_quality, profile_guessed);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1005 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1006 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1007
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1008 /* Return THIS with quality dropped to GUESSED_LOCAL. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1009 profile_count guessed_local () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1010 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1011 profile_count ret = *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1012 if (!initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1013 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1014 ret.m_quality = profile_guessed_local;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1015 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1016 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1017
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1018 /* We know that profile is globally 0 but keep local profile if present. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1019 profile_count global0 () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1020 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1021 profile_count ret = *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1022 if (!initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1023 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1024 ret.m_quality = profile_guessed_global0;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1025 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1026 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1027
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1028 /* We know that profile is globally adjusted 0 but keep local profile
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1029 if present. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1030 profile_count global0adjusted () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1031 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1032 profile_count ret = *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1033 if (!initialized_p ())
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1034 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1035 ret.m_quality = profile_guessed_global0adjusted;
111
kono
parents:
diff changeset
1036 return ret;
kono
parents:
diff changeset
1037 }
kono
parents:
diff changeset
1038
kono
parents:
diff changeset
1039 /* Return THIS with quality dropped to GUESSED. */
kono
parents:
diff changeset
1040 profile_count guessed () const
kono
parents:
diff changeset
1041 {
kono
parents:
diff changeset
1042 profile_count ret = *this;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1043 ret.m_quality = MIN (ret.m_quality, profile_guessed);
111
kono
parents:
diff changeset
1044 return ret;
kono
parents:
diff changeset
1045 }
kono
parents:
diff changeset
1046
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1047 /* Return variant of profile counte which is always safe to compare
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1048 acorss functions. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1049 profile_count ipa () const
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1050 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1051 if (m_quality > profile_guessed_global0adjusted)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1052 return *this;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1053 if (m_quality == profile_guessed_global0)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1054 return profile_count::zero ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1055 if (m_quality == profile_guessed_global0adjusted)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1056 return profile_count::adjusted_zero ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1057 return profile_count::uninitialized ();
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1058 }
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1059
111
kono
parents:
diff changeset
1060 /* Return THIS with quality dropped to AFDO. */
kono
parents:
diff changeset
1061 profile_count afdo () const
kono
parents:
diff changeset
1062 {
kono
parents:
diff changeset
1063 profile_count ret = *this;
kono
parents:
diff changeset
1064 ret.m_quality = profile_afdo;
kono
parents:
diff changeset
1065 return ret;
kono
parents:
diff changeset
1066 }
kono
parents:
diff changeset
1067
kono
parents:
diff changeset
1068 /* Return probability of event with counter THIS within event with counter
kono
parents:
diff changeset
1069 OVERALL. */
kono
parents:
diff changeset
1070 profile_probability probability_in (const profile_count overall) const
kono
parents:
diff changeset
1071 {
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1072 if (*this == profile_count::zero ()
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1073 && !(overall == profile_count::zero ()))
111
kono
parents:
diff changeset
1074 return profile_probability::never ();
kono
parents:
diff changeset
1075 if (!initialized_p () || !overall.initialized_p ()
kono
parents:
diff changeset
1076 || !overall.m_val)
kono
parents:
diff changeset
1077 return profile_probability::uninitialized ();
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1078 if (*this == overall && m_quality == profile_precise)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1079 return profile_probability::always ();
111
kono
parents:
diff changeset
1080 profile_probability ret;
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1081 gcc_checking_assert (compatible_p (overall));
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1082
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1083 if (overall.m_val < m_val)
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1084 {
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1085 ret.m_val = profile_probability::max_probability;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1086 ret.m_quality = profile_guessed;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1087 return ret;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1088 }
111
kono
parents:
diff changeset
1089 else
kono
parents:
diff changeset
1090 ret.m_val = RDIV (m_val * profile_probability::max_probability,
kono
parents:
diff changeset
1091 overall.m_val);
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1092 ret.m_quality = MIN (MAX (MIN (m_quality, overall.m_quality),
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1093 profile_guessed), profile_adjusted);
111
kono
parents:
diff changeset
1094 return ret;
kono
parents:
diff changeset
1095 }
kono
parents:
diff changeset
1096
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1097 int to_frequency (struct function *fun) const;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1098 int to_cgraph_frequency (profile_count entry_bb_count) const;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1099 sreal to_sreal_scale (profile_count in, bool *known = NULL) const;
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1100
111
kono
parents:
diff changeset
1101 /* Output THIS to F. */
kono
parents:
diff changeset
1102 void dump (FILE *f) const;
kono
parents:
diff changeset
1103
kono
parents:
diff changeset
1104 /* Print THIS to stderr. */
kono
parents:
diff changeset
1105 void debug () const;
kono
parents:
diff changeset
1106
kono
parents:
diff changeset
1107 /* Return true if THIS is known to differ significantly from OTHER. */
kono
parents:
diff changeset
1108 bool differs_from_p (profile_count other) const;
kono
parents:
diff changeset
1109
131
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1110 /* We want to scale profile across function boundary from NUM to DEN.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1111 Take care of the side case when NUM and DEN are zeros of incompatible
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1112 kinds. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1113 static void adjust_for_ipa_scaling (profile_count *num, profile_count *den);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1114
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1115 /* THIS is a count of bb which is known to be executed IPA times.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1116 Combine this information into bb counter. This means returning IPA
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1117 if it is nonzero, not changing anything if IPA is uninitialized
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1118 and if IPA is zero, turning THIS into corresponding local profile with
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1119 global0. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1120 profile_count combine_with_ipa_count (profile_count ipa);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1121
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1122 /* The profiling runtime uses gcov_type, which is usually 64bit integer.
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1123 Conversions back and forth are used to read the coverage and get it
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1124 into internal representation. */
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1125 static profile_count from_gcov_type (gcov_type v);
84e7813d76e9 gcc-8.2
mir3636
parents: 111
diff changeset
1126
111
kono
parents:
diff changeset
1127 /* LTO streaming support. */
kono
parents:
diff changeset
1128 static profile_count stream_in (struct lto_input_block *);
kono
parents:
diff changeset
1129 void stream_out (struct output_block *);
kono
parents:
diff changeset
1130 void stream_out (struct lto_output_stream *);
kono
parents:
diff changeset
1131 };
kono
parents:
diff changeset
1132 #endif