]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/profile-count.h
runtime: don't assume that _ = *s will panic if s is nil
[thirdparty/gcc.git] / gcc / profile-count.h
CommitLineData
3995f3a2
JH
1/* Profile counter container type.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
4
5This file is part of GCC.
6
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 3, or (at your option) any later
10version.
11
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
16
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING3. If not see
19<http://www.gnu.org/licenses/>. */
20
21#ifndef GCC_PROFILE_COUNT_H
22#define GCC_PROFILE_COUNT_H
23
4e9a497f
JH
24/* Quality of the proflie count. Because gengtype does not support enums
25 inside of clases, this is in global namespace. */
26enum profile_count_quality {
27 /* Profile is based on static branch prediction heuristics. It may or may
28 not reflect the reality. */
29 count_guessed = 0,
30 /* Profile was determined by autofdo. */
b2c2a7e4 31 count_afdo = 1,
4e9a497f
JH
32 /* Profile was originally based on feedback but it was adjusted
33 by code duplicating optimization. It may not precisely reflect the
34 particular code path. */
b2c2a7e4 35 count_adjusted = 2,
4e9a497f
JH
36 /* Profile was read from profile feedback or determined by accurate static
37 method. */
38 count_read = 3
39};
3995f3a2
JH
40
41/* The base value for branch probability notes and edge probabilities. */
42#define REG_BR_PROB_BASE 10000
43
44#define RDIV(X,Y) (((X) + (Y) / 2) / (Y))
45
46/* Main data type to hold profile counters in GCC. In most cases profile
47 counts originate from profile feedback. They are 64bit integers
48 representing number of executions during the train run.
49 As the profile is maintained during the compilation, many adjustments are
50 made. Not all transformations can be made precisely, most importantly
51 when code is being duplicated. It also may happen that part of CFG has
52 profile counts known while other do not - for example when LTO optimizing
53 partly profiled program or when profile was lost due to COMDAT merging.
54
b69d9ac6 55 For this reason profile_count tracks more information than
3995f3a2
JH
56 just unsigned integer and it is also ready for profile mismatches.
57 The API of this data type represent operations that are natural
58 on profile counts - sum, difference and operation with scales and
59 probabilities. All operations are safe by never getting negative counts
60 and they do end up in uninitialized scale if any of the parameters is
61 uninitialized.
62
63 All comparsions that are three state and handling of probabilities. Thus
64 a < b is not equal to !(a >= b).
65
66 The following pre-defined counts are available:
67
68 profile_count::zero () for code that is known to execute zero times at
69 runtime (this can be detected statically i.e. for paths leading to
70 abort ();
71 profile_count::one () for code that is known to execute once (such as
72 main () function
73 profile_count::uninitialized () for unknown execution count.
74
75 */
76
3995f3a2
JH
77class GTY(()) profile_count
78{
4e9a497f 79 /* Use 62bit to hold basic block counters. Should be at least
3995f3a2
JH
80 64bit. Although a counter cannot be negative, we use a signed
81 type to hold various extra stages. */
82
4e9a497f
JH
83 static const int n_bits = 62;
84 static const uint64_t max_count = ((uint64_t) 1 << n_bits) - 2;
85 static const uint64_t uninitialized_count = ((uint64_t) 1 << n_bits) - 1;
86
87 uint64_t m_val : n_bits;
88 enum profile_count_quality m_quality : 2;
3995f3a2
JH
89
90 /* Assume numbers smaller than this to multiply. This is set to make
4e9a497f 91 testsuite pass, in future we may implement precise multiplication in higer
3995f3a2
JH
92 rangers. */
93 static const int64_t max_safe_multiplier = 131072;
94public:
95
96 /* Used for counters which are expected to be never executed. */
97 static profile_count zero ()
98 {
99 return from_gcov_type (0);
100 }
101 static profile_count one ()
102 {
103 return from_gcov_type (1);
104 }
105 /* Value of counters which has not been initialized. Either because
106 initialization did not happen yet or because profile is unknown. */
107 static profile_count uninitialized ()
108 {
109 profile_count c;
4e9a497f
JH
110 c.m_val = uninitialized_count;
111 c.m_quality = count_guessed;
3995f3a2
JH
112 return c;
113 }
114
115 /* The profiling runtime uses gcov_type, which is usually 64bit integer.
116 Conversions back and forth are used to read the coverage and get it
117 into internal representation. */
118 static profile_count from_gcov_type (gcov_type v)
119 {
120 profile_count ret;
4e9a497f 121 gcc_checking_assert (v >= 0 && (uint64_t) v <= max_count);
3995f3a2 122 ret.m_val = v;
4e9a497f 123 ret.m_quality = count_read;
3995f3a2
JH
124 return ret;
125 }
126
127 /* Conversion to gcov_type is lossy. */
128 gcov_type to_gcov_type () const
129 {
130 gcc_checking_assert (initialized_p ());
131 return m_val;
132 }
133
134 /* Return true if value has been initialized. */
135 bool initialized_p () const
136 {
4e9a497f 137 return m_val != uninitialized_count;
3995f3a2
JH
138 }
139 /* Return true if value can be trusted. */
140 bool reliable_p () const
141 {
142 return initialized_p ();
143 }
144
145 /* Basic operations. */
146 bool operator== (const profile_count &other) const
147 {
4e9a497f 148 return m_val == other.m_val && m_quality == other.m_quality;
3995f3a2
JH
149 }
150 profile_count operator+ (const profile_count &other) const
151 {
152 if (other == profile_count::zero ())
153 return *this;
154 if (*this == profile_count::zero ())
155 return other;
156 if (!initialized_p () || !other.initialized_p ())
157 return profile_count::uninitialized ();
158
159 profile_count ret;
160 ret.m_val = m_val + other.m_val;
4e9a497f 161 ret.m_quality = MIN (m_quality, other.m_quality);
3995f3a2
JH
162 return ret;
163 }
164 profile_count &operator+= (const profile_count &other)
165 {
166 if (other == profile_count::zero ())
167 return *this;
168 if (*this == profile_count::zero ())
169 {
170 *this = other;
171 return *this;
172 }
173 if (!initialized_p () || !other.initialized_p ())
174 return *this = profile_count::uninitialized ();
175 else
4e9a497f
JH
176 {
177 m_val += other.m_val;
178 m_quality = MIN (m_quality, other.m_quality);
179 }
3995f3a2
JH
180 return *this;
181 }
182 profile_count operator- (const profile_count &other) const
183 {
184 if (*this == profile_count::zero () || other == profile_count::zero ())
185 return *this;
186 if (!initialized_p () || !other.initialized_p ())
187 return profile_count::uninitialized ();
188 profile_count ret;
4e9a497f
JH
189 ret.m_val = m_val >= other.m_val ? m_val - other.m_val : 0;
190 ret.m_quality = MIN (m_quality, other.m_quality);
3995f3a2
JH
191 return ret;
192 }
193 profile_count &operator-= (const profile_count &other)
194 {
195 if (*this == profile_count::zero () || other == profile_count::zero ())
196 return *this;
197 if (!initialized_p () || !other.initialized_p ())
198 return *this = profile_count::uninitialized ();
199 else
4e9a497f
JH
200 {
201 m_val = m_val >= other.m_val ? m_val - other.m_val: 0;
202 m_quality = MIN (m_quality, other.m_quality);
203 }
3995f3a2
JH
204 return *this;
205 }
206
207 /* Return false if profile_count is bogus. */
208 bool verify () const
209 {
4e9a497f 210 return m_val != uninitialized_count || m_quality == count_guessed;
3995f3a2
JH
211 }
212
213 /* Comparsions are three-state and conservative. False is returned if
214 the inequality can not be decided. */
215 bool operator< (const profile_count &other) const
216 {
217 return initialized_p () && other.initialized_p () && m_val < other.m_val;
218 }
219 bool operator> (const profile_count &other) const
220 {
221 return initialized_p () && other.initialized_p () && m_val > other.m_val;
222 }
223 bool operator< (const gcov_type other) const
224 {
4e9a497f
JH
225 gcc_checking_assert (other >= 0);
226 return initialized_p () && m_val < (uint64_t) other;
3995f3a2
JH
227 }
228 bool operator> (const gcov_type other) const
229 {
4e9a497f
JH
230 gcc_checking_assert (other >= 0);
231 return initialized_p () && m_val > (uint64_t) other;
3995f3a2
JH
232 }
233
234 bool operator<= (const profile_count &other) const
235 {
236 return initialized_p () && other.initialized_p () && m_val <= other.m_val;
237 }
238 bool operator>= (const profile_count &other) const
239 {
240 return initialized_p () && m_val >= other.m_val;
241 }
242 bool operator<= (const gcov_type other) const
243 {
4e9a497f
JH
244 gcc_checking_assert (other >= 0);
245 return initialized_p () && m_val <= (uint64_t) other;
3995f3a2
JH
246 }
247 bool operator>= (const gcov_type other) const
248 {
4e9a497f
JH
249 gcc_checking_assert (other >= 0);
250 return initialized_p () && m_val >= (uint64_t) other;
3995f3a2
JH
251 }
252
253 /* PROB is a probability in scale 0...REG_BR_PROB_BASE. Scale counter
254 accordingly. */
255 profile_count apply_probability (int prob) const
256 {
257 gcc_checking_assert (prob >= 0 && prob <= REG_BR_PROB_BASE);
aea5e79a
JH
258 if (*this == profile_count::zero ())
259 return *this;
3995f3a2
JH
260 if (!initialized_p ())
261 return profile_count::uninitialized ();
262 profile_count ret;
263 ret.m_val = RDIV (m_val * prob, REG_BR_PROB_BASE);
4e9a497f 264 ret.m_quality = MIN (m_quality, count_adjusted);
3995f3a2
JH
265 return ret;
266 }
267 /* Return *THIS * NUM / DEN. */
268 profile_count apply_scale (int64_t num, int64_t den) const
269 {
aea5e79a
JH
270 if (*this == profile_count::zero ())
271 return *this;
3995f3a2
JH
272 if (!initialized_p ())
273 return profile_count::uninitialized ();
274 profile_count ret;
275 /* FIXME: shrink wrapping violates this sanity check. */
276 gcc_checking_assert ((num >= 0
277 && (num <= REG_BR_PROB_BASE
278 || den <= REG_BR_PROB_BASE)
279 && den > 0) || 1);
280 ret.m_val = RDIV (m_val * num, den);
4e9a497f 281 ret.m_quality = MIN (m_quality, count_adjusted);
3995f3a2
JH
282 return ret;
283 }
284 profile_count apply_scale (profile_count num, profile_count den) const
285 {
aea5e79a 286 if (*this == profile_count::zero () || num == profile_count::zero ())
3995f3a2
JH
287 return profile_count::zero ();
288 if (!initialized_p () || !num.initialized_p () || !den.initialized_p ())
289 return profile_count::uninitialized ();
3995f3a2 290 gcc_checking_assert (den > 0);
4e9a497f
JH
291 if (num == den)
292 return *this;
293
294 profile_count ret;
3995f3a2
JH
295 /* Take care for overflows! */
296 if (num.m_val < max_safe_multiplier || m_val < max_safe_multiplier)
297 ret.m_val = RDIV (m_val * num.m_val, den.m_val);
298 else
299 ret.m_val = RDIV (m_val * RDIV (num.m_val * max_safe_multiplier,
300 den.m_val), max_safe_multiplier);
4e9a497f 301 ret.m_quality = MIN (m_quality, count_adjusted);
3995f3a2
JH
302 return ret;
303 }
304
305 /* Return probability of event with counter THIS within event with counter
306 OVERALL. */
307 int probability_in (profile_count overall)
308 {
309 if (*this == profile_count::zero ())
310 return 0;
311 if (!initialized_p () || !overall.initialized_p ())
312 return REG_BR_PROB_BASE / 2;
313 if (overall < *this)
314 return REG_BR_PROB_BASE;
315 if (!overall.m_val)
316 return REG_BR_PROB_BASE / 2;
317 return RDIV (m_val * REG_BR_PROB_BASE, overall.m_val);
318 }
319
320 /* Output THIS to F. */
321 void dump (FILE *f) const;
322
323 /* Print THIS to stderr. */
324 void debug () const;
325
326 /* Return true if THIS is known to differ significantly from OTHER. */
327 bool differs_from_p (profile_count other) const;
328
329 /* LTO streaming support. */
330 static profile_count stream_in (struct lto_input_block *);
331 void stream_out (struct output_block *);
332 void stream_out (struct lto_output_stream *);
333};
334#endif