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
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
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/>. */
23 #include "coretypes.h"
24 #include "profile-count.h"
27 #include "basic-block.h"
31 #include "data-streamer.h"
38 profile_count::dump (FILE *f
) const
40 if (!initialized_p ())
41 fprintf (f
, "uninitialized");
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. */
61 profile_count::debug () const
64 fprintf (stderr
, "\n");
67 /* Return true if THIS differs from OTHER; tolerate small diferences. */
70 profile_count::differs_from_p (profile_count other
) const
72 gcc_checking_assert (compatible_p (other
));
73 if (!initialized_p () || !other
.initialized_p ())
75 if ((uint64_t)m_val
- (uint64_t)other
.m_val
< 100
76 || (uint64_t)other
.m_val
- (uint64_t)m_val
< 100)
80 int64_t ratio
= (int64_t)m_val
* 100 / other
.m_val
;
81 return ratio
< 99 || ratio
> 101;
84 /* Stream THIS from IB. */
87 profile_count::stream_in (struct lto_input_block
*ib
)
90 ret
.m_val
= streamer_read_gcov_count (ib
);
91 ret
.m_quality
= (profile_quality
) streamer_read_uhwi (ib
);
95 /* Stream THIS to OB. */
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. */
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. */
116 profile_probability::dump (FILE *f
) const
118 if (!initialized_p ())
119 fprintf (f
, "uninitialized");
122 /* Make difference between 0.00 as a roundoff error and actual 0.
125 fprintf (f
, "never");
126 else if (m_val
== max_probability
)
127 fprintf (f
, "always");
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. */
142 profile_probability::debug () const
145 fprintf (stderr
, "\n");
148 /* Return true if THIS differs from OTHER; tolerate small diferences. */
151 profile_probability::differs_from_p (profile_probability other
) const
153 if (!initialized_p () || !other
.initialized_p ())
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)
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. */
167 profile_probability::differs_lot_from_p (profile_probability other
) const
169 if (!initialized_p () || !other
.initialized_p ())
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. */
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
);
186 /* Stream THIS to OB. */
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. */
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. */
207 slow_safe_scale_64bit (uint64_t a
, uint64_t b
, uint64_t c
, uint64_t *res
)
209 FIXED_WIDE_INT (128) tmp
= a
;
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 ();
218 *res
= (uint64_t) -1;
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 ())
230 if (*this == profile_count::zero ())
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 ())
251 gcc_checking_assert (entry_bb_count
.initialized_p ());
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
);