* asan.c (create_cond_insert_point): Maintain profile.
[official-gcc.git] / gcc / profile-count.c
blobd70314046452db2e15345de25d7d5ae58746ad12
1 /* Profile counter container type.
2 Copyright (C) 2017 Free Software Foundation, Inc.
3 Contributed by Jan Hubicka
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "profile-count.h"
25 #include "options.h"
26 #include "tree.h"
27 #include "basic-block.h"
28 #include "cfg.h"
29 #include "function.h"
30 #include "gimple.h"
31 #include "data-streamer.h"
32 #include "cgraph.h"
33 #include "wide-int.h"
35 /* Dump THIS to F. */
37 void
38 profile_count::dump (FILE *f) const
40 if (!initialized_p ())
41 fprintf (f, "uninitialized");
42 else
44 fprintf (f, "%" PRId64, m_val);
45 if (m_quality == profile_guessed_local)
46 fprintf (f, " (estimated locally)");
47 else if (m_quality == profile_guessed_global0)
48 fprintf (f, " (estimated locally, globally 0)");
49 else if (m_quality == profile_adjusted)
50 fprintf (f, " (adjusted)");
51 else if (m_quality == profile_afdo)
52 fprintf (f, " (auto FDO)");
53 else if (m_quality == profile_guessed)
54 fprintf (f, " (guessed)");
58 /* Dump THIS to stderr. */
60 void
61 profile_count::debug () const
63 dump (stderr);
64 fprintf (stderr, "\n");
67 /* Return true if THIS differs from OTHER; tolerate small diferences. */
69 bool
70 profile_count::differs_from_p (profile_count other) const
72 gcc_checking_assert (compatible_p (other));
73 if (!initialized_p () || !other.initialized_p ())
74 return false;
75 if ((uint64_t)m_val - (uint64_t)other.m_val < 100
76 || (uint64_t)other.m_val - (uint64_t)m_val < 100)
77 return false;
78 if (!other.m_val)
79 return true;
80 int64_t ratio = (int64_t)m_val * 100 / other.m_val;
81 return ratio < 99 || ratio > 101;
84 /* Stream THIS from IB. */
86 profile_count
87 profile_count::stream_in (struct lto_input_block *ib)
89 profile_count ret;
90 ret.m_val = streamer_read_gcov_count (ib);
91 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
92 return ret;
95 /* Stream THIS to OB. */
97 void
98 profile_count::stream_out (struct output_block *ob)
100 streamer_write_gcov_count (ob, m_val);
101 streamer_write_uhwi (ob, m_quality);
104 /* Stream THIS to OB. */
106 void
107 profile_count::stream_out (struct lto_output_stream *ob)
109 streamer_write_gcov_count_stream (ob, m_val);
110 streamer_write_uhwi_stream (ob, m_quality);
113 /* Dump THIS to F. */
115 void
116 profile_probability::dump (FILE *f) const
118 if (!initialized_p ())
119 fprintf (f, "uninitialized");
120 else
122 /* Make difference between 0.00 as a roundoff error and actual 0.
123 Similarly for 1. */
124 if (m_val == 0)
125 fprintf (f, "never");
126 else if (m_val == max_probability)
127 fprintf (f, "always");
128 else
129 fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
130 if (m_quality == profile_adjusted)
131 fprintf (f, " (adjusted)");
132 else if (m_quality == profile_afdo)
133 fprintf (f, " (auto FDO)");
134 else if (m_quality == profile_guessed)
135 fprintf (f, " (guessed)");
139 /* Dump THIS to stderr. */
141 void
142 profile_probability::debug () const
144 dump (stderr);
145 fprintf (stderr, "\n");
148 /* Return true if THIS differs from OTHER; tolerate small diferences. */
150 bool
151 profile_probability::differs_from_p (profile_probability other) const
153 if (!initialized_p () || !other.initialized_p ())
154 return false;
155 if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
156 || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
157 return false;
158 if (!other.m_val)
159 return true;
160 int64_t ratio = (int64_t)m_val * 100 / other.m_val;
161 return ratio < 99 || ratio > 101;
164 /* Return true if THIS differs significantly from OTHER. */
166 bool
167 profile_probability::differs_lot_from_p (profile_probability other) const
169 if (!initialized_p () || !other.initialized_p ())
170 return false;
171 uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
172 return d > max_probability / 2;
175 /* Stream THIS from IB. */
177 profile_probability
178 profile_probability::stream_in (struct lto_input_block *ib)
180 profile_probability ret;
181 ret.m_val = streamer_read_uhwi (ib);
182 ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
183 return ret;
186 /* Stream THIS to OB. */
188 void
189 profile_probability::stream_out (struct output_block *ob)
191 streamer_write_uhwi (ob, m_val);
192 streamer_write_uhwi (ob, m_quality);
195 /* Stream THIS to OB. */
197 void
198 profile_probability::stream_out (struct lto_output_stream *ob)
200 streamer_write_uhwi_stream (ob, m_val);
201 streamer_write_uhwi_stream (ob, m_quality);
204 /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened. */
206 bool
207 slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
209 FIXED_WIDE_INT (128) tmp = a;
210 bool overflow;
211 tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
212 gcc_checking_assert (!overflow);
213 if (wi::fits_uhwi_p (tmp))
215 *res = tmp.to_uhwi ();
216 return true;
218 *res = (uint64_t) -1;
219 return false;
222 /* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
223 Used for legacy code and should not be used anymore. */
226 profile_count::to_frequency (struct function *fun) const
228 if (!initialized_p ())
229 return BB_FREQ_MAX;
230 if (*this == profile_count::zero ())
231 return 0;
232 gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX
233 && fun->cfg->count_max.initialized_p ());
234 profile_probability prob = probability_in (fun->cfg->count_max);
235 if (!prob.initialized_p ())
236 return REG_BR_PROB_BASE;
237 return prob.to_reg_br_prob_base ();
240 /* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
241 where CGRAPH_FREQ_BASE means that count equals to entry block count.
242 Used for legacy code and should not be used anymore. */
245 profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
247 if (!initialized_p ())
248 return CGRAPH_FREQ_BASE;
249 if (*this == profile_count::zero ())
250 return 0;
251 gcc_checking_assert (entry_bb_count.initialized_p ());
252 uint64_t scale;
253 if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
254 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
255 return CGRAPH_FREQ_MAX;
256 return MIN (scale, CGRAPH_FREQ_MAX);