xref: /dflybsd-src/contrib/gcc-8.0/libgcc/libgcov-merge.c (revision 38fd149817dfbff97799f62fcb70be98c4e32523)
1*38fd1498Szrj /* Routines required for instrumenting a program.  */
2*38fd1498Szrj /* Compile this one with gcc.  */
3*38fd1498Szrj /* Copyright (C) 1989-2018 Free Software Foundation, Inc.
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 Under Section 7 of GPL version 3, you are granted additional
18*38fd1498Szrj permissions described in the GCC Runtime Library Exception, version
19*38fd1498Szrj 3.1, as published by the Free Software Foundation.
20*38fd1498Szrj 
21*38fd1498Szrj You should have received a copy of the GNU General Public License and
22*38fd1498Szrj a copy of the GCC Runtime Library Exception along with this program;
23*38fd1498Szrj see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
24*38fd1498Szrj <http://www.gnu.org/licenses/>.  */
25*38fd1498Szrj 
26*38fd1498Szrj #include "libgcov.h"
27*38fd1498Szrj 
28*38fd1498Szrj #if defined(inhibit_libc)
29*38fd1498Szrj /* If libc and its header files are not available, provide dummy functions.  */
30*38fd1498Szrj 
31*38fd1498Szrj #ifdef L_gcov_merge_add
__gcov_merge_add(gcov_type * counters,unsigned n_counters)32*38fd1498Szrj void __gcov_merge_add (gcov_type *counters  __attribute__ ((unused)),
33*38fd1498Szrj                        unsigned n_counters __attribute__ ((unused))) {}
34*38fd1498Szrj #endif
35*38fd1498Szrj 
36*38fd1498Szrj #ifdef L_gcov_merge_single
__gcov_merge_single(gcov_type * counters,unsigned n_counters)37*38fd1498Szrj void __gcov_merge_single (gcov_type *counters  __attribute__ ((unused)),
38*38fd1498Szrj                           unsigned n_counters __attribute__ ((unused))) {}
39*38fd1498Szrj #endif
40*38fd1498Szrj 
41*38fd1498Szrj #else
42*38fd1498Szrj 
43*38fd1498Szrj #ifdef L_gcov_merge_add
44*38fd1498Szrj /* The profile merging function that just adds the counters.  It is given
45*38fd1498Szrj    an array COUNTERS of N_COUNTERS old counters and it reads the same number
46*38fd1498Szrj    of counters from the gcov file.  */
47*38fd1498Szrj void
__gcov_merge_add(gcov_type * counters,unsigned n_counters)48*38fd1498Szrj __gcov_merge_add (gcov_type *counters, unsigned n_counters)
49*38fd1498Szrj {
50*38fd1498Szrj   for (; n_counters; counters++, n_counters--)
51*38fd1498Szrj     *counters += gcov_get_counter ();
52*38fd1498Szrj }
53*38fd1498Szrj #endif /* L_gcov_merge_add */
54*38fd1498Szrj 
55*38fd1498Szrj #ifdef L_gcov_merge_ior
56*38fd1498Szrj /* The profile merging function that just adds the counters.  It is given
57*38fd1498Szrj    an array COUNTERS of N_COUNTERS old counters and it reads the same number
58*38fd1498Szrj    of counters from the gcov file.  */
59*38fd1498Szrj void
__gcov_merge_ior(gcov_type * counters,unsigned n_counters)60*38fd1498Szrj __gcov_merge_ior (gcov_type *counters, unsigned n_counters)
61*38fd1498Szrj {
62*38fd1498Szrj   for (; n_counters; counters++, n_counters--)
63*38fd1498Szrj     *counters |= gcov_get_counter_target ();
64*38fd1498Szrj }
65*38fd1498Szrj #endif
66*38fd1498Szrj 
67*38fd1498Szrj #ifdef L_gcov_merge_time_profile
68*38fd1498Szrj /* Time profiles are merged so that minimum from all valid (greater than zero)
69*38fd1498Szrj    is stored. There could be a fork that creates new counters. To have
70*38fd1498Szrj    the profile stable, we chosen to pick the smallest function visit time.  */
71*38fd1498Szrj void
__gcov_merge_time_profile(gcov_type * counters,unsigned n_counters)72*38fd1498Szrj __gcov_merge_time_profile (gcov_type *counters, unsigned n_counters)
73*38fd1498Szrj {
74*38fd1498Szrj   unsigned int i;
75*38fd1498Szrj   gcov_type value;
76*38fd1498Szrj 
77*38fd1498Szrj   for (i = 0; i < n_counters; i++)
78*38fd1498Szrj     {
79*38fd1498Szrj       value = gcov_get_counter_target ();
80*38fd1498Szrj 
81*38fd1498Szrj       if (value && (!counters[i] || value < counters[i]))
82*38fd1498Szrj         counters[i] = value;
83*38fd1498Szrj     }
84*38fd1498Szrj }
85*38fd1498Szrj #endif /* L_gcov_merge_time_profile */
86*38fd1498Szrj 
87*38fd1498Szrj #ifdef L_gcov_merge_single
88*38fd1498Szrj /* The profile merging function for choosing the most common value.
89*38fd1498Szrj    It is given an array COUNTERS of N_COUNTERS old counters and it
90*38fd1498Szrj    reads the same number of counters from the gcov file.  The counters
91*38fd1498Szrj    are split into 3-tuples where the members of the tuple have
92*38fd1498Szrj    meanings:
93*38fd1498Szrj 
94*38fd1498Szrj    -- the stored candidate on the most common value of the measured entity
95*38fd1498Szrj    -- counter
96*38fd1498Szrj    -- total number of evaluations of the value  */
97*38fd1498Szrj void
__gcov_merge_single(gcov_type * counters,unsigned n_counters)98*38fd1498Szrj __gcov_merge_single (gcov_type *counters, unsigned n_counters)
99*38fd1498Szrj {
100*38fd1498Szrj   unsigned i, n_measures;
101*38fd1498Szrj   gcov_type value, counter, all;
102*38fd1498Szrj 
103*38fd1498Szrj   gcc_assert (!(n_counters % 3));
104*38fd1498Szrj   n_measures = n_counters / 3;
105*38fd1498Szrj   for (i = 0; i < n_measures; i++, counters += 3)
106*38fd1498Szrj     {
107*38fd1498Szrj       value = gcov_get_counter_target ();
108*38fd1498Szrj       counter = gcov_get_counter ();
109*38fd1498Szrj       all = gcov_get_counter ();
110*38fd1498Szrj 
111*38fd1498Szrj       if (counters[0] == value)
112*38fd1498Szrj         counters[1] += counter;
113*38fd1498Szrj       else if (counter > counters[1])
114*38fd1498Szrj         {
115*38fd1498Szrj           counters[0] = value;
116*38fd1498Szrj           counters[1] = counter - counters[1];
117*38fd1498Szrj         }
118*38fd1498Szrj       else
119*38fd1498Szrj         counters[1] -= counter;
120*38fd1498Szrj       counters[2] += all;
121*38fd1498Szrj     }
122*38fd1498Szrj }
123*38fd1498Szrj #endif /* L_gcov_merge_single */
124*38fd1498Szrj 
125*38fd1498Szrj #ifdef L_gcov_merge_icall_topn
126*38fd1498Szrj /* The profile merging function used for merging indirect call counts
127*38fd1498Szrj    This function is given array COUNTERS of N_COUNTERS old counters and it
128*38fd1498Szrj    reads the same number of counters from the gcov file.  */
129*38fd1498Szrj 
130*38fd1498Szrj void
__gcov_merge_icall_topn(gcov_type * counters,unsigned n_counters)131*38fd1498Szrj __gcov_merge_icall_topn (gcov_type *counters, unsigned n_counters)
132*38fd1498Szrj {
133*38fd1498Szrj   unsigned i, j, k, m;
134*38fd1498Szrj 
135*38fd1498Szrj   gcc_assert (!(n_counters % GCOV_ICALL_TOPN_NCOUNTS));
136*38fd1498Szrj   for (i = 0; i < n_counters; i += GCOV_ICALL_TOPN_NCOUNTS)
137*38fd1498Szrj     {
138*38fd1498Szrj       gcov_type *value_array = &counters[i + 1];
139*38fd1498Szrj       unsigned tmp_size = 2 * (GCOV_ICALL_TOPN_NCOUNTS - 1);
140*38fd1498Szrj       gcov_type *tmp_array
141*38fd1498Szrj           = (gcov_type *) alloca (tmp_size * sizeof (gcov_type));
142*38fd1498Szrj 
143*38fd1498Szrj       for (j = 0; j < tmp_size; j++)
144*38fd1498Szrj         tmp_array[j] = 0;
145*38fd1498Szrj 
146*38fd1498Szrj       for (j = 0; j < GCOV_ICALL_TOPN_NCOUNTS - 1; j += 2)
147*38fd1498Szrj         {
148*38fd1498Szrj           tmp_array[j] = value_array[j];
149*38fd1498Szrj           tmp_array[j + 1] = value_array [j + 1];
150*38fd1498Szrj         }
151*38fd1498Szrj 
152*38fd1498Szrj       /* Skip the number_of_eviction entry.  */
153*38fd1498Szrj       gcov_get_counter ();
154*38fd1498Szrj       for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
155*38fd1498Szrj         {
156*38fd1498Szrj           int found = 0;
157*38fd1498Szrj           gcov_type global_id = gcov_get_counter_target ();
158*38fd1498Szrj           gcov_type call_count = gcov_get_counter ();
159*38fd1498Szrj           for (m = 0; m < j; m += 2)
160*38fd1498Szrj             {
161*38fd1498Szrj               if (tmp_array[m] == global_id)
162*38fd1498Szrj                 {
163*38fd1498Szrj                   found = 1;
164*38fd1498Szrj                   tmp_array[m + 1] += call_count;
165*38fd1498Szrj                   break;
166*38fd1498Szrj                 }
167*38fd1498Szrj             }
168*38fd1498Szrj           if (!found)
169*38fd1498Szrj             {
170*38fd1498Szrj               tmp_array[j] = global_id;
171*38fd1498Szrj               tmp_array[j + 1] = call_count;
172*38fd1498Szrj               j += 2;
173*38fd1498Szrj             }
174*38fd1498Szrj         }
175*38fd1498Szrj       /* Now sort the temp array */
176*38fd1498Szrj       gcov_sort_n_vals (tmp_array, j);
177*38fd1498Szrj 
178*38fd1498Szrj       /* Now copy back the top half of the temp array */
179*38fd1498Szrj       for (k = 0; k < GCOV_ICALL_TOPN_NCOUNTS - 1; k += 2)
180*38fd1498Szrj         {
181*38fd1498Szrj           value_array[k] = tmp_array[k];
182*38fd1498Szrj           value_array[k + 1] = tmp_array[k + 1];
183*38fd1498Szrj         }
184*38fd1498Szrj     }
185*38fd1498Szrj }
186*38fd1498Szrj #endif /* L_gcov_merge_icall_topn */
187*38fd1498Szrj #endif /* inhibit_libc */
188