xref: /dflybsd-src/contrib/gcc-8.0/gcc/profile-count.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Profile counter container type.
2*38fd1498Szrj    Copyright (C) 2017-2018 Free Software Foundation, Inc.
3*38fd1498Szrj    Contributed by Jan Hubicka
4*38fd1498Szrj 
5*38fd1498Szrj This file is part of GCC.
6*38fd1498Szrj 
7*38fd1498Szrj GCC is free software; you can redistribute it and/or modify it under
8*38fd1498Szrj the terms of the GNU General Public License as published by the Free
9*38fd1498Szrj Software Foundation; either version 3, or (at your option) any later
10*38fd1498Szrj version.
11*38fd1498Szrj 
12*38fd1498Szrj GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13*38fd1498Szrj WARRANTY; without even the implied warranty of MERCHANTABILITY or
14*38fd1498Szrj FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15*38fd1498Szrj for more details.
16*38fd1498Szrj 
17*38fd1498Szrj You should have received a copy of the GNU General Public License
18*38fd1498Szrj along with GCC; see the file COPYING3.  If not see
19*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
20*38fd1498Szrj 
21*38fd1498Szrj #include "config.h"
22*38fd1498Szrj #include "system.h"
23*38fd1498Szrj #include "coretypes.h"
24*38fd1498Szrj #include "profile-count.h"
25*38fd1498Szrj #include "options.h"
26*38fd1498Szrj #include "tree.h"
27*38fd1498Szrj #include "basic-block.h"
28*38fd1498Szrj #include "cfg.h"
29*38fd1498Szrj #include "function.h"
30*38fd1498Szrj #include "gimple.h"
31*38fd1498Szrj #include "data-streamer.h"
32*38fd1498Szrj #include "cgraph.h"
33*38fd1498Szrj #include "wide-int.h"
34*38fd1498Szrj #include "sreal.h"
35*38fd1498Szrj 
36*38fd1498Szrj /* Dump THIS to F.  */
37*38fd1498Szrj 
38*38fd1498Szrj void
dump(FILE * f)39*38fd1498Szrj profile_count::dump (FILE *f) const
40*38fd1498Szrj {
41*38fd1498Szrj   if (!initialized_p ())
42*38fd1498Szrj     fprintf (f, "uninitialized");
43*38fd1498Szrj   else
44*38fd1498Szrj     {
45*38fd1498Szrj       fprintf (f, "%" PRId64, m_val);
46*38fd1498Szrj       if (m_quality == profile_guessed_local)
47*38fd1498Szrj 	fprintf (f, " (estimated locally)");
48*38fd1498Szrj       else if (m_quality == profile_guessed_global0)
49*38fd1498Szrj 	fprintf (f, " (estimated locally, globally 0)");
50*38fd1498Szrj       else if (m_quality == profile_guessed_global0adjusted)
51*38fd1498Szrj 	fprintf (f, " (estimated locally, globally 0 adjusted)");
52*38fd1498Szrj       else if (m_quality == profile_adjusted)
53*38fd1498Szrj 	fprintf (f, " (adjusted)");
54*38fd1498Szrj       else if (m_quality == profile_afdo)
55*38fd1498Szrj 	fprintf (f, " (auto FDO)");
56*38fd1498Szrj       else if (m_quality == profile_guessed)
57*38fd1498Szrj 	fprintf (f, " (guessed)");
58*38fd1498Szrj     }
59*38fd1498Szrj }
60*38fd1498Szrj 
61*38fd1498Szrj /* Dump THIS to stderr.  */
62*38fd1498Szrj 
63*38fd1498Szrj void
debug()64*38fd1498Szrj profile_count::debug () const
65*38fd1498Szrj {
66*38fd1498Szrj   dump (stderr);
67*38fd1498Szrj   fprintf (stderr, "\n");
68*38fd1498Szrj }
69*38fd1498Szrj 
70*38fd1498Szrj /* Return true if THIS differs from OTHER; tolerate small diferences.  */
71*38fd1498Szrj 
72*38fd1498Szrj bool
differs_from_p(profile_count other)73*38fd1498Szrj profile_count::differs_from_p (profile_count other) const
74*38fd1498Szrj {
75*38fd1498Szrj   gcc_checking_assert (compatible_p (other));
76*38fd1498Szrj   if (!initialized_p () || !other.initialized_p ())
77*38fd1498Szrj     return false;
78*38fd1498Szrj   if ((uint64_t)m_val - (uint64_t)other.m_val < 100
79*38fd1498Szrj       || (uint64_t)other.m_val - (uint64_t)m_val < 100)
80*38fd1498Szrj     return false;
81*38fd1498Szrj   if (!other.m_val)
82*38fd1498Szrj     return true;
83*38fd1498Szrj   int64_t ratio = (int64_t)m_val * 100 / other.m_val;
84*38fd1498Szrj   return ratio < 99 || ratio > 101;
85*38fd1498Szrj }
86*38fd1498Szrj 
87*38fd1498Szrj /* Stream THIS from IB.  */
88*38fd1498Szrj 
89*38fd1498Szrj profile_count
stream_in(struct lto_input_block * ib)90*38fd1498Szrj profile_count::stream_in (struct lto_input_block *ib)
91*38fd1498Szrj {
92*38fd1498Szrj   profile_count ret;
93*38fd1498Szrj   ret.m_val = streamer_read_gcov_count (ib);
94*38fd1498Szrj   ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
95*38fd1498Szrj   return ret;
96*38fd1498Szrj }
97*38fd1498Szrj 
98*38fd1498Szrj /* Stream THIS to OB.  */
99*38fd1498Szrj 
100*38fd1498Szrj void
stream_out(struct output_block * ob)101*38fd1498Szrj profile_count::stream_out (struct output_block *ob)
102*38fd1498Szrj {
103*38fd1498Szrj   streamer_write_gcov_count (ob, m_val);
104*38fd1498Szrj   streamer_write_uhwi (ob, m_quality);
105*38fd1498Szrj }
106*38fd1498Szrj 
107*38fd1498Szrj /* Stream THIS to OB.  */
108*38fd1498Szrj 
109*38fd1498Szrj void
stream_out(struct lto_output_stream * ob)110*38fd1498Szrj profile_count::stream_out (struct lto_output_stream *ob)
111*38fd1498Szrj {
112*38fd1498Szrj   streamer_write_gcov_count_stream (ob, m_val);
113*38fd1498Szrj   streamer_write_uhwi_stream (ob, m_quality);
114*38fd1498Szrj }
115*38fd1498Szrj 
116*38fd1498Szrj /* Dump THIS to F.  */
117*38fd1498Szrj 
118*38fd1498Szrj void
dump(FILE * f)119*38fd1498Szrj profile_probability::dump (FILE *f) const
120*38fd1498Szrj {
121*38fd1498Szrj   if (!initialized_p ())
122*38fd1498Szrj     fprintf (f, "uninitialized");
123*38fd1498Szrj   else
124*38fd1498Szrj     {
125*38fd1498Szrj       /* Make difference between 0.00 as a roundoff error and actual 0.
126*38fd1498Szrj 	 Similarly for 1.  */
127*38fd1498Szrj       if (m_val == 0)
128*38fd1498Szrj         fprintf (f, "never");
129*38fd1498Szrj       else if (m_val == max_probability)
130*38fd1498Szrj         fprintf (f, "always");
131*38fd1498Szrj       else
132*38fd1498Szrj         fprintf (f, "%3.1f%%", (double)m_val * 100 / max_probability);
133*38fd1498Szrj       if (m_quality == profile_adjusted)
134*38fd1498Szrj 	fprintf (f, " (adjusted)");
135*38fd1498Szrj       else if (m_quality == profile_afdo)
136*38fd1498Szrj 	fprintf (f, " (auto FDO)");
137*38fd1498Szrj       else if (m_quality == profile_guessed)
138*38fd1498Szrj 	fprintf (f, " (guessed)");
139*38fd1498Szrj     }
140*38fd1498Szrj }
141*38fd1498Szrj 
142*38fd1498Szrj /* Dump THIS to stderr.  */
143*38fd1498Szrj 
144*38fd1498Szrj void
debug()145*38fd1498Szrj profile_probability::debug () const
146*38fd1498Szrj {
147*38fd1498Szrj   dump (stderr);
148*38fd1498Szrj   fprintf (stderr, "\n");
149*38fd1498Szrj }
150*38fd1498Szrj 
151*38fd1498Szrj /* Return true if THIS differs from OTHER; tolerate small diferences.  */
152*38fd1498Szrj 
153*38fd1498Szrj bool
differs_from_p(profile_probability other)154*38fd1498Szrj profile_probability::differs_from_p (profile_probability other) const
155*38fd1498Szrj {
156*38fd1498Szrj   if (!initialized_p () || !other.initialized_p ())
157*38fd1498Szrj     return false;
158*38fd1498Szrj   if ((uint64_t)m_val - (uint64_t)other.m_val < max_probability / 1000
159*38fd1498Szrj       || (uint64_t)other.m_val - (uint64_t)max_probability < 1000)
160*38fd1498Szrj     return false;
161*38fd1498Szrj   if (!other.m_val)
162*38fd1498Szrj     return true;
163*38fd1498Szrj   int64_t ratio = (int64_t)m_val * 100 / other.m_val;
164*38fd1498Szrj   return ratio < 99 || ratio > 101;
165*38fd1498Szrj }
166*38fd1498Szrj 
167*38fd1498Szrj /* Return true if THIS differs significantly from OTHER.  */
168*38fd1498Szrj 
169*38fd1498Szrj bool
differs_lot_from_p(profile_probability other)170*38fd1498Szrj profile_probability::differs_lot_from_p (profile_probability other) const
171*38fd1498Szrj {
172*38fd1498Szrj   if (!initialized_p () || !other.initialized_p ())
173*38fd1498Szrj     return false;
174*38fd1498Szrj   uint32_t d = m_val > other.m_val ? m_val - other.m_val : other.m_val - m_val;
175*38fd1498Szrj   return d > max_probability / 2;
176*38fd1498Szrj }
177*38fd1498Szrj 
178*38fd1498Szrj /* Stream THIS from IB.  */
179*38fd1498Szrj 
180*38fd1498Szrj profile_probability
stream_in(struct lto_input_block * ib)181*38fd1498Szrj profile_probability::stream_in (struct lto_input_block *ib)
182*38fd1498Szrj {
183*38fd1498Szrj   profile_probability ret;
184*38fd1498Szrj   ret.m_val = streamer_read_uhwi (ib);
185*38fd1498Szrj   ret.m_quality = (profile_quality) streamer_read_uhwi (ib);
186*38fd1498Szrj   return ret;
187*38fd1498Szrj }
188*38fd1498Szrj 
189*38fd1498Szrj /* Stream THIS to OB.  */
190*38fd1498Szrj 
191*38fd1498Szrj void
stream_out(struct output_block * ob)192*38fd1498Szrj profile_probability::stream_out (struct output_block *ob)
193*38fd1498Szrj {
194*38fd1498Szrj   streamer_write_uhwi (ob, m_val);
195*38fd1498Szrj   streamer_write_uhwi (ob, m_quality);
196*38fd1498Szrj }
197*38fd1498Szrj 
198*38fd1498Szrj /* Stream THIS to OB.  */
199*38fd1498Szrj 
200*38fd1498Szrj void
stream_out(struct lto_output_stream * ob)201*38fd1498Szrj profile_probability::stream_out (struct lto_output_stream *ob)
202*38fd1498Szrj {
203*38fd1498Szrj   streamer_write_uhwi_stream (ob, m_val);
204*38fd1498Szrj   streamer_write_uhwi_stream (ob, m_quality);
205*38fd1498Szrj }
206*38fd1498Szrj 
207*38fd1498Szrj /* Compute RES=(a*b + c/2)/c capping and return false if overflow happened.  */
208*38fd1498Szrj 
209*38fd1498Szrj bool
slow_safe_scale_64bit(uint64_t a,uint64_t b,uint64_t c,uint64_t * res)210*38fd1498Szrj slow_safe_scale_64bit (uint64_t a, uint64_t b, uint64_t c, uint64_t *res)
211*38fd1498Szrj {
212*38fd1498Szrj   FIXED_WIDE_INT (128) tmp = a;
213*38fd1498Szrj   bool overflow;
214*38fd1498Szrj   tmp = wi::udiv_floor (wi::umul (tmp, b, &overflow) + (c / 2), c);
215*38fd1498Szrj   gcc_checking_assert (!overflow);
216*38fd1498Szrj   if (wi::fits_uhwi_p (tmp))
217*38fd1498Szrj     {
218*38fd1498Szrj       *res = tmp.to_uhwi ();
219*38fd1498Szrj       return true;
220*38fd1498Szrj     }
221*38fd1498Szrj   *res = (uint64_t) -1;
222*38fd1498Szrj   return false;
223*38fd1498Szrj }
224*38fd1498Szrj 
225*38fd1498Szrj /* Return count as frequency within FUN scaled in range 0 to REG_FREQ_MAX
226*38fd1498Szrj    Used for legacy code and should not be used anymore.  */
227*38fd1498Szrj 
228*38fd1498Szrj int
to_frequency(struct function * fun)229*38fd1498Szrj profile_count::to_frequency (struct function *fun) const
230*38fd1498Szrj {
231*38fd1498Szrj   if (!initialized_p ())
232*38fd1498Szrj     return BB_FREQ_MAX;
233*38fd1498Szrj   if (*this == profile_count::zero ())
234*38fd1498Szrj     return 0;
235*38fd1498Szrj   gcc_assert (REG_BR_PROB_BASE == BB_FREQ_MAX
236*38fd1498Szrj 	      && fun->cfg->count_max.initialized_p ());
237*38fd1498Szrj   profile_probability prob = probability_in (fun->cfg->count_max);
238*38fd1498Szrj   if (!prob.initialized_p ())
239*38fd1498Szrj     return REG_BR_PROB_BASE;
240*38fd1498Szrj   return prob.to_reg_br_prob_base ();
241*38fd1498Szrj }
242*38fd1498Szrj 
243*38fd1498Szrj /* Return count as frequency within FUN scaled in range 0 to CGRAPH_FREQ_MAX
244*38fd1498Szrj    where CGRAPH_FREQ_BASE means that count equals to entry block count.
245*38fd1498Szrj    Used for legacy code and should not be used anymore.  */
246*38fd1498Szrj 
247*38fd1498Szrj int
to_cgraph_frequency(profile_count entry_bb_count)248*38fd1498Szrj profile_count::to_cgraph_frequency (profile_count entry_bb_count) const
249*38fd1498Szrj {
250*38fd1498Szrj   if (!initialized_p () || !entry_bb_count.initialized_p ())
251*38fd1498Szrj     return CGRAPH_FREQ_BASE;
252*38fd1498Szrj   if (*this == profile_count::zero ())
253*38fd1498Szrj     return 0;
254*38fd1498Szrj   gcc_checking_assert (entry_bb_count.initialized_p ());
255*38fd1498Szrj   uint64_t scale;
256*38fd1498Szrj   if (!safe_scale_64bit (!entry_bb_count.m_val ? m_val + 1 : m_val,
257*38fd1498Szrj 			 CGRAPH_FREQ_BASE, MAX (1, entry_bb_count.m_val), &scale))
258*38fd1498Szrj     return CGRAPH_FREQ_MAX;
259*38fd1498Szrj   return MIN (scale, CGRAPH_FREQ_MAX);
260*38fd1498Szrj }
261*38fd1498Szrj 
262*38fd1498Szrj /* Return THIS/IN as sreal value.  */
263*38fd1498Szrj 
264*38fd1498Szrj sreal
to_sreal_scale(profile_count in,bool * known)265*38fd1498Szrj profile_count::to_sreal_scale (profile_count in, bool *known) const
266*38fd1498Szrj {
267*38fd1498Szrj   if (!initialized_p () || !in.initialized_p ())
268*38fd1498Szrj     {
269*38fd1498Szrj       if (known)
270*38fd1498Szrj 	*known = false;
271*38fd1498Szrj       return 1;
272*38fd1498Szrj     }
273*38fd1498Szrj   if (known)
274*38fd1498Szrj     *known = true;
275*38fd1498Szrj   if (*this == profile_count::zero ())
276*38fd1498Szrj     return 0;
277*38fd1498Szrj 
278*38fd1498Szrj   if (!in.m_val)
279*38fd1498Szrj     {
280*38fd1498Szrj       if (!m_val)
281*38fd1498Szrj 	return 1;
282*38fd1498Szrj       return m_val * 4;
283*38fd1498Szrj     }
284*38fd1498Szrj   return (sreal)m_val / (sreal)in.m_val;
285*38fd1498Szrj }
286*38fd1498Szrj 
287*38fd1498Szrj /* We want to scale profile across function boundary from NUM to DEN.
288*38fd1498Szrj    Take care of the side case when DEN is zeros.  We still want to behave
289*38fd1498Szrj    sanely here which means
290*38fd1498Szrj      - scale to profile_count::zero () if NUM is profile_count::zero
291*38fd1498Szrj      - do not affect anything if NUM == DEN
292*38fd1498Szrj      - preserve counter value but adjust quality in other cases.  */
293*38fd1498Szrj 
294*38fd1498Szrj void
adjust_for_ipa_scaling(profile_count * num,profile_count * den)295*38fd1498Szrj profile_count::adjust_for_ipa_scaling (profile_count *num,
296*38fd1498Szrj 				       profile_count *den)
297*38fd1498Szrj {
298*38fd1498Szrj   /* Scaling is no-op if NUM and DEN are the same.  */
299*38fd1498Szrj   if (*num == *den)
300*38fd1498Szrj     return;
301*38fd1498Szrj   /* Scaling to zero is always zero.  */
302*38fd1498Szrj   if (*num == profile_count::zero ())
303*38fd1498Szrj     return;
304*38fd1498Szrj   /* If den is non-zero we are safe.  */
305*38fd1498Szrj   if (den->force_nonzero () == *den)
306*38fd1498Szrj     return;
307*38fd1498Szrj   /* Force both to non-zero so we do not push profiles to 0 when
308*38fd1498Szrj      both num == 0 and den == 0.  */
309*38fd1498Szrj   *den = den->force_nonzero ();
310*38fd1498Szrj   *num = num->force_nonzero ();
311*38fd1498Szrj }
312*38fd1498Szrj 
313*38fd1498Szrj /* THIS is a count of bb which is known to be executed IPA times.
314*38fd1498Szrj    Combine this information into bb counter.  This means returning IPA
315*38fd1498Szrj    if it is nonzero, not changing anything if IPA is uninitialized
316*38fd1498Szrj    and if IPA is zero, turning THIS into corresponding local profile with
317*38fd1498Szrj    global0.  */
318*38fd1498Szrj profile_count
combine_with_ipa_count(profile_count ipa)319*38fd1498Szrj profile_count::combine_with_ipa_count (profile_count ipa)
320*38fd1498Szrj {
321*38fd1498Szrj   ipa = ipa.ipa ();
322*38fd1498Szrj   if (ipa.nonzero_p ())
323*38fd1498Szrj     return ipa;
324*38fd1498Szrj   if (!ipa.initialized_p () || *this == profile_count::zero ())
325*38fd1498Szrj     return *this;
326*38fd1498Szrj   if (ipa == profile_count::zero ())
327*38fd1498Szrj     return this->global0 ();
328*38fd1498Szrj   return this->global0adjusted ();
329*38fd1498Szrj }
330*38fd1498Szrj 
331*38fd1498Szrj /* The profiling runtime uses gcov_type, which is usually 64bit integer.
332*38fd1498Szrj    Conversions back and forth are used to read the coverage and get it
333*38fd1498Szrj    into internal representation.  */
334*38fd1498Szrj profile_count
from_gcov_type(gcov_type v)335*38fd1498Szrj profile_count::from_gcov_type (gcov_type v)
336*38fd1498Szrj   {
337*38fd1498Szrj     profile_count ret;
338*38fd1498Szrj     gcc_checking_assert (v >= 0);
339*38fd1498Szrj     if (dump_file && v >= (gcov_type)max_count)
340*38fd1498Szrj       fprintf (dump_file,
341*38fd1498Szrj 	       "Capping gcov count %" PRId64 " to max_count %" PRId64 "\n",
342*38fd1498Szrj 	       (int64_t) v, (int64_t) max_count);
343*38fd1498Szrj     ret.m_val = MIN (v, (gcov_type)max_count);
344*38fd1498Szrj     ret.m_quality = profile_precise;
345*38fd1498Szrj     return ret;
346*38fd1498Szrj   }
347*38fd1498Szrj 
348*38fd1498Szrj 
349*38fd1498Szrj /* COUNT1 times event happens with *THIS probability, COUNT2 times OTHER
350*38fd1498Szrj    happens with COUNT2 probablity. Return probablity that either *THIS or
351*38fd1498Szrj    OTHER happens.  */
352*38fd1498Szrj 
353*38fd1498Szrj profile_probability
combine_with_count(profile_count count1,profile_probability other,profile_count count2)354*38fd1498Szrj profile_probability::combine_with_count (profile_count count1,
355*38fd1498Szrj 					 profile_probability other,
356*38fd1498Szrj 					 profile_count count2) const
357*38fd1498Szrj {
358*38fd1498Szrj   /* If probabilities are same, we are done.
359*38fd1498Szrj      If counts are nonzero we can distribute accordingly. In remaining
360*38fd1498Szrj      cases just avreage the values and hope for the best.  */
361*38fd1498Szrj   if (*this == other || count1 == count2
362*38fd1498Szrj       || (count2 == profile_count::zero ()
363*38fd1498Szrj 	  && !(count1 == profile_count::zero ())))
364*38fd1498Szrj     return *this;
365*38fd1498Szrj   if (count1 == profile_count::zero () && !(count2 == profile_count::zero ()))
366*38fd1498Szrj     return other;
367*38fd1498Szrj   else if (count1.nonzero_p () || count2.nonzero_p ())
368*38fd1498Szrj     return *this * count1.probability_in (count1 + count2)
369*38fd1498Szrj 	   + other * count2.probability_in (count1 + count2);
370*38fd1498Szrj   else
371*38fd1498Szrj     return *this * profile_probability::even ()
372*38fd1498Szrj 	   + other * profile_probability::even ();
373*38fd1498Szrj }
374