xref: /dflybsd-src/contrib/gcc-4.7/gcc/statistics.c (revision 04febcfb30580676d3e95f58a16c5137ee478b32)
1*e4b17023SJohn Marino /* Optimization statistics functions.
2*e4b17023SJohn Marino    Copyright (C) 2008, 2010
3*e4b17023SJohn Marino    Free Software Foundation, Inc.
4*e4b17023SJohn Marino    Contributed by Richard Guenther  <rguenther@suse.de>
5*e4b17023SJohn Marino 
6*e4b17023SJohn Marino This file is part of GCC.
7*e4b17023SJohn Marino 
8*e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9*e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10*e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11*e4b17023SJohn Marino version.
12*e4b17023SJohn Marino 
13*e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14*e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15*e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16*e4b17023SJohn Marino for more details.
17*e4b17023SJohn Marino 
18*e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19*e4b17023SJohn Marino along with GCC; see the file COPYING3.  If not see
20*e4b17023SJohn Marino <http://www.gnu.org/licenses/>.  */
21*e4b17023SJohn Marino 
22*e4b17023SJohn Marino #include "config.h"
23*e4b17023SJohn Marino #include "system.h"
24*e4b17023SJohn Marino #include "coretypes.h"
25*e4b17023SJohn Marino #include "tree-pass.h"
26*e4b17023SJohn Marino #include "tree-dump.h"
27*e4b17023SJohn Marino #include "statistics.h"
28*e4b17023SJohn Marino #include "hashtab.h"
29*e4b17023SJohn Marino #include "function.h"
30*e4b17023SJohn Marino 
31*e4b17023SJohn Marino static int statistics_dump_nr;
32*e4b17023SJohn Marino static int statistics_dump_flags;
33*e4b17023SJohn Marino static FILE *statistics_dump_file;
34*e4b17023SJohn Marino 
35*e4b17023SJohn Marino /* Statistics entry.  A integer counter associated to a string ID
36*e4b17023SJohn Marino    and value.  */
37*e4b17023SJohn Marino 
38*e4b17023SJohn Marino typedef struct statistics_counter_s {
39*e4b17023SJohn Marino   const char *id;
40*e4b17023SJohn Marino   int val;
41*e4b17023SJohn Marino   bool histogram_p;
42*e4b17023SJohn Marino   unsigned HOST_WIDE_INT count;
43*e4b17023SJohn Marino   unsigned HOST_WIDE_INT prev_dumped_count;
44*e4b17023SJohn Marino } statistics_counter_t;
45*e4b17023SJohn Marino 
46*e4b17023SJohn Marino /* Array of statistic hashes, indexed by pass id.  */
47*e4b17023SJohn Marino static htab_t *statistics_hashes;
48*e4b17023SJohn Marino static unsigned nr_statistics_hashes;
49*e4b17023SJohn Marino 
50*e4b17023SJohn Marino /* Hash a statistic counter by its string ID.  */
51*e4b17023SJohn Marino 
52*e4b17023SJohn Marino static hashval_t
hash_statistics_hash(const void * p)53*e4b17023SJohn Marino hash_statistics_hash (const void *p)
54*e4b17023SJohn Marino {
55*e4b17023SJohn Marino   const statistics_counter_t *const c = (const statistics_counter_t *)p;
56*e4b17023SJohn Marino   return htab_hash_string (c->id) + c->val;
57*e4b17023SJohn Marino }
58*e4b17023SJohn Marino 
59*e4b17023SJohn Marino /* Compare two statistic counters by their string IDs.  */
60*e4b17023SJohn Marino 
61*e4b17023SJohn Marino static int
hash_statistics_eq(const void * p,const void * q)62*e4b17023SJohn Marino hash_statistics_eq (const void *p, const void *q)
63*e4b17023SJohn Marino {
64*e4b17023SJohn Marino   const statistics_counter_t *const c1 = (const statistics_counter_t *)p;
65*e4b17023SJohn Marino   const statistics_counter_t *const c2 = (const statistics_counter_t *)q;
66*e4b17023SJohn Marino   return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
67*e4b17023SJohn Marino }
68*e4b17023SJohn Marino 
69*e4b17023SJohn Marino /* Free a statistics entry.  */
70*e4b17023SJohn Marino 
71*e4b17023SJohn Marino static void
hash_statistics_free(void * p)72*e4b17023SJohn Marino hash_statistics_free (void *p)
73*e4b17023SJohn Marino {
74*e4b17023SJohn Marino   free (CONST_CAST(char *, ((statistics_counter_t *)p)->id));
75*e4b17023SJohn Marino   free (p);
76*e4b17023SJohn Marino }
77*e4b17023SJohn Marino 
78*e4b17023SJohn Marino /* Return the current hashtable to be used for recording or printing
79*e4b17023SJohn Marino    statistics.  */
80*e4b17023SJohn Marino 
81*e4b17023SJohn Marino static htab_t
curr_statistics_hash(void)82*e4b17023SJohn Marino curr_statistics_hash (void)
83*e4b17023SJohn Marino {
84*e4b17023SJohn Marino   unsigned idx;
85*e4b17023SJohn Marino 
86*e4b17023SJohn Marino   gcc_assert (current_pass->static_pass_number >= 0);
87*e4b17023SJohn Marino   idx = current_pass->static_pass_number;
88*e4b17023SJohn Marino 
89*e4b17023SJohn Marino   if (idx < nr_statistics_hashes
90*e4b17023SJohn Marino       && statistics_hashes[idx] != NULL)
91*e4b17023SJohn Marino     return statistics_hashes[idx];
92*e4b17023SJohn Marino 
93*e4b17023SJohn Marino   if (idx >= nr_statistics_hashes)
94*e4b17023SJohn Marino     {
95*e4b17023SJohn Marino       statistics_hashes = XRESIZEVEC (struct htab *, statistics_hashes, idx+1);
96*e4b17023SJohn Marino       memset (statistics_hashes + nr_statistics_hashes, 0,
97*e4b17023SJohn Marino 	      (idx + 1 - nr_statistics_hashes) * sizeof (htab_t));
98*e4b17023SJohn Marino       nr_statistics_hashes = idx + 1;
99*e4b17023SJohn Marino     }
100*e4b17023SJohn Marino 
101*e4b17023SJohn Marino   statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
102*e4b17023SJohn Marino 					hash_statistics_eq,
103*e4b17023SJohn Marino 					hash_statistics_free);
104*e4b17023SJohn Marino 
105*e4b17023SJohn Marino   return statistics_hashes[idx];
106*e4b17023SJohn Marino }
107*e4b17023SJohn Marino 
108*e4b17023SJohn Marino /* Helper for statistics_fini_pass.  Print the counter difference
109*e4b17023SJohn Marino    since the last dump for the pass dump files.  */
110*e4b17023SJohn Marino 
111*e4b17023SJohn Marino static int
statistics_fini_pass_1(void ** slot,void * data ATTRIBUTE_UNUSED)112*e4b17023SJohn Marino statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
113*e4b17023SJohn Marino {
114*e4b17023SJohn Marino   statistics_counter_t *counter = (statistics_counter_t *)*slot;
115*e4b17023SJohn Marino   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
116*e4b17023SJohn Marino   if (count == 0)
117*e4b17023SJohn Marino     return 1;
118*e4b17023SJohn Marino   if (counter->histogram_p)
119*e4b17023SJohn Marino     fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
120*e4b17023SJohn Marino 	     counter->id, counter->val, count);
121*e4b17023SJohn Marino   else
122*e4b17023SJohn Marino     fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
123*e4b17023SJohn Marino 	     counter->id, count);
124*e4b17023SJohn Marino   counter->prev_dumped_count = counter->count;
125*e4b17023SJohn Marino   return 1;
126*e4b17023SJohn Marino }
127*e4b17023SJohn Marino 
128*e4b17023SJohn Marino /* Helper for statistics_fini_pass.  Print the counter difference
129*e4b17023SJohn Marino    since the last dump for the statistics dump.  */
130*e4b17023SJohn Marino 
131*e4b17023SJohn Marino static int
statistics_fini_pass_2(void ** slot,void * data ATTRIBUTE_UNUSED)132*e4b17023SJohn Marino statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
133*e4b17023SJohn Marino {
134*e4b17023SJohn Marino   statistics_counter_t *counter = (statistics_counter_t *)*slot;
135*e4b17023SJohn Marino   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
136*e4b17023SJohn Marino   if (count == 0)
137*e4b17023SJohn Marino     return 1;
138*e4b17023SJohn Marino   counter->prev_dumped_count = counter->count;
139*e4b17023SJohn Marino   if (counter->histogram_p)
140*e4b17023SJohn Marino     fprintf (statistics_dump_file,
141*e4b17023SJohn Marino 	     "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
142*e4b17023SJohn Marino 	     current_pass->static_pass_number,
143*e4b17023SJohn Marino 	     current_pass->name,
144*e4b17023SJohn Marino 	     counter->id, counter->val,
145*e4b17023SJohn Marino 	     cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
146*e4b17023SJohn Marino 	     count);
147*e4b17023SJohn Marino   else
148*e4b17023SJohn Marino     fprintf (statistics_dump_file,
149*e4b17023SJohn Marino 	     "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
150*e4b17023SJohn Marino 	     current_pass->static_pass_number,
151*e4b17023SJohn Marino 	     current_pass->name,
152*e4b17023SJohn Marino 	     counter->id,
153*e4b17023SJohn Marino 	     cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
154*e4b17023SJohn Marino 	     count);
155*e4b17023SJohn Marino   counter->prev_dumped_count = counter->count;
156*e4b17023SJohn Marino   return 1;
157*e4b17023SJohn Marino }
158*e4b17023SJohn Marino 
159*e4b17023SJohn Marino /* Helper for statistics_fini_pass, reset the counters.  */
160*e4b17023SJohn Marino 
161*e4b17023SJohn Marino static int
statistics_fini_pass_3(void ** slot,void * data ATTRIBUTE_UNUSED)162*e4b17023SJohn Marino statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
163*e4b17023SJohn Marino {
164*e4b17023SJohn Marino   statistics_counter_t *counter = (statistics_counter_t *)*slot;
165*e4b17023SJohn Marino   counter->prev_dumped_count = counter->count;
166*e4b17023SJohn Marino   return 1;
167*e4b17023SJohn Marino }
168*e4b17023SJohn Marino 
169*e4b17023SJohn Marino /* Dump the current statistics incrementally.  */
170*e4b17023SJohn Marino 
171*e4b17023SJohn Marino void
statistics_fini_pass(void)172*e4b17023SJohn Marino statistics_fini_pass (void)
173*e4b17023SJohn Marino {
174*e4b17023SJohn Marino   if (current_pass->static_pass_number == -1)
175*e4b17023SJohn Marino     return;
176*e4b17023SJohn Marino 
177*e4b17023SJohn Marino   if (dump_file
178*e4b17023SJohn Marino       && dump_flags & TDF_STATS)
179*e4b17023SJohn Marino     {
180*e4b17023SJohn Marino       fprintf (dump_file, "\n");
181*e4b17023SJohn Marino       fprintf (dump_file, "Pass statistics:\n");
182*e4b17023SJohn Marino       fprintf (dump_file, "----------------\n");
183*e4b17023SJohn Marino       htab_traverse_noresize (curr_statistics_hash (),
184*e4b17023SJohn Marino 			      statistics_fini_pass_1, NULL);
185*e4b17023SJohn Marino       fprintf (dump_file, "\n");
186*e4b17023SJohn Marino     }
187*e4b17023SJohn Marino   if (statistics_dump_file
188*e4b17023SJohn Marino       && !(statistics_dump_flags & TDF_STATS
189*e4b17023SJohn Marino 	   || statistics_dump_flags & TDF_DETAILS))
190*e4b17023SJohn Marino     htab_traverse_noresize (curr_statistics_hash (),
191*e4b17023SJohn Marino 			    statistics_fini_pass_2, NULL);
192*e4b17023SJohn Marino   htab_traverse_noresize (curr_statistics_hash (),
193*e4b17023SJohn Marino 			  statistics_fini_pass_3, NULL);
194*e4b17023SJohn Marino }
195*e4b17023SJohn Marino 
196*e4b17023SJohn Marino /* Helper for printing summary information.  */
197*e4b17023SJohn Marino 
198*e4b17023SJohn Marino static int
statistics_fini_1(void ** slot,void * data)199*e4b17023SJohn Marino statistics_fini_1 (void **slot, void *data)
200*e4b17023SJohn Marino {
201*e4b17023SJohn Marino   struct opt_pass *pass = (struct opt_pass *)data;
202*e4b17023SJohn Marino   statistics_counter_t *counter = (statistics_counter_t *)*slot;
203*e4b17023SJohn Marino   if (counter->count == 0)
204*e4b17023SJohn Marino     return 1;
205*e4b17023SJohn Marino   if (counter->histogram_p)
206*e4b17023SJohn Marino     fprintf (statistics_dump_file,
207*e4b17023SJohn Marino 	     "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
208*e4b17023SJohn Marino 	     pass->static_pass_number,
209*e4b17023SJohn Marino 	     pass->name,
210*e4b17023SJohn Marino 	     counter->id, counter->val,
211*e4b17023SJohn Marino 	     counter->count);
212*e4b17023SJohn Marino   else
213*e4b17023SJohn Marino     fprintf (statistics_dump_file,
214*e4b17023SJohn Marino 	     "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
215*e4b17023SJohn Marino 	     pass->static_pass_number,
216*e4b17023SJohn Marino 	     pass->name,
217*e4b17023SJohn Marino 	     counter->id,
218*e4b17023SJohn Marino 	     counter->count);
219*e4b17023SJohn Marino   return 1;
220*e4b17023SJohn Marino }
221*e4b17023SJohn Marino 
222*e4b17023SJohn Marino /* Finish the statistics and dump summary information.  */
223*e4b17023SJohn Marino 
224*e4b17023SJohn Marino void
statistics_fini(void)225*e4b17023SJohn Marino statistics_fini (void)
226*e4b17023SJohn Marino {
227*e4b17023SJohn Marino   if (!statistics_dump_file)
228*e4b17023SJohn Marino     return;
229*e4b17023SJohn Marino 
230*e4b17023SJohn Marino   if (statistics_dump_flags & TDF_STATS)
231*e4b17023SJohn Marino     {
232*e4b17023SJohn Marino       unsigned i;
233*e4b17023SJohn Marino       for (i = 0; i < nr_statistics_hashes; ++i)
234*e4b17023SJohn Marino 	if (statistics_hashes[i] != NULL
235*e4b17023SJohn Marino 	    && get_pass_for_id (i) != NULL)
236*e4b17023SJohn Marino 	  htab_traverse_noresize (statistics_hashes[i],
237*e4b17023SJohn Marino 				  statistics_fini_1, get_pass_for_id (i));
238*e4b17023SJohn Marino     }
239*e4b17023SJohn Marino 
240*e4b17023SJohn Marino   dump_end (statistics_dump_nr, statistics_dump_file);
241*e4b17023SJohn Marino }
242*e4b17023SJohn Marino 
243*e4b17023SJohn Marino /* Register the statistics dump file.  */
244*e4b17023SJohn Marino 
245*e4b17023SJohn Marino void
statistics_early_init(void)246*e4b17023SJohn Marino statistics_early_init (void)
247*e4b17023SJohn Marino {
248*e4b17023SJohn Marino   statistics_dump_nr = dump_register (".statistics", "statistics",
249*e4b17023SJohn Marino 				      "statistics", TDF_TREE);
250*e4b17023SJohn Marino }
251*e4b17023SJohn Marino 
252*e4b17023SJohn Marino /* Init the statistics.  */
253*e4b17023SJohn Marino 
254*e4b17023SJohn Marino void
statistics_init(void)255*e4b17023SJohn Marino statistics_init (void)
256*e4b17023SJohn Marino {
257*e4b17023SJohn Marino   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
258*e4b17023SJohn Marino   statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->flags;
259*e4b17023SJohn Marino }
260*e4b17023SJohn Marino 
261*e4b17023SJohn Marino /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
262*e4b17023SJohn Marino    and HISTOGRAM_P.  */
263*e4b17023SJohn Marino 
264*e4b17023SJohn Marino static statistics_counter_t *
lookup_or_add_counter(htab_t hash,const char * id,int val,bool histogram_p)265*e4b17023SJohn Marino lookup_or_add_counter (htab_t hash, const char *id, int val,
266*e4b17023SJohn Marino 		       bool histogram_p)
267*e4b17023SJohn Marino {
268*e4b17023SJohn Marino   statistics_counter_t **counter;
269*e4b17023SJohn Marino   statistics_counter_t c;
270*e4b17023SJohn Marino   c.id = id;
271*e4b17023SJohn Marino   c.val = val;
272*e4b17023SJohn Marino   counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
273*e4b17023SJohn Marino   if (!*counter)
274*e4b17023SJohn Marino     {
275*e4b17023SJohn Marino       *counter = XNEW (struct statistics_counter_s);
276*e4b17023SJohn Marino       (*counter)->id = xstrdup (id);
277*e4b17023SJohn Marino       (*counter)->val = val;
278*e4b17023SJohn Marino       (*counter)->histogram_p = histogram_p;
279*e4b17023SJohn Marino       (*counter)->prev_dumped_count = 0;
280*e4b17023SJohn Marino       (*counter)->count = 0;
281*e4b17023SJohn Marino     }
282*e4b17023SJohn Marino   return *counter;
283*e4b17023SJohn Marino }
284*e4b17023SJohn Marino 
285*e4b17023SJohn Marino /* Add statistics information about event ID in function FN.
286*e4b17023SJohn Marino    This will increment the counter associated with ID by INCR.
287*e4b17023SJohn Marino    It will also dump the event to the global statistics file if requested.  */
288*e4b17023SJohn Marino 
289*e4b17023SJohn Marino void
statistics_counter_event(struct function * fn,const char * id,int incr)290*e4b17023SJohn Marino statistics_counter_event (struct function *fn, const char *id, int incr)
291*e4b17023SJohn Marino {
292*e4b17023SJohn Marino   statistics_counter_t *counter;
293*e4b17023SJohn Marino 
294*e4b17023SJohn Marino   if ((!(dump_flags & TDF_STATS)
295*e4b17023SJohn Marino        && !statistics_dump_file)
296*e4b17023SJohn Marino       || incr == 0)
297*e4b17023SJohn Marino     return;
298*e4b17023SJohn Marino 
299*e4b17023SJohn Marino   if (current_pass->static_pass_number != -1)
300*e4b17023SJohn Marino     {
301*e4b17023SJohn Marino       counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
302*e4b17023SJohn Marino       gcc_assert (!counter->histogram_p);
303*e4b17023SJohn Marino       counter->count += incr;
304*e4b17023SJohn Marino     }
305*e4b17023SJohn Marino 
306*e4b17023SJohn Marino   if (!statistics_dump_file
307*e4b17023SJohn Marino       || !(statistics_dump_flags & TDF_DETAILS))
308*e4b17023SJohn Marino     return;
309*e4b17023SJohn Marino 
310*e4b17023SJohn Marino   fprintf (statistics_dump_file,
311*e4b17023SJohn Marino 	   "%d %s \"%s\" \"%s\" %d\n",
312*e4b17023SJohn Marino 	   current_pass->static_pass_number,
313*e4b17023SJohn Marino 	   current_pass->name,
314*e4b17023SJohn Marino 	   id,
315*e4b17023SJohn Marino 	   fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)",
316*e4b17023SJohn Marino 	   incr);
317*e4b17023SJohn Marino }
318*e4b17023SJohn Marino 
319*e4b17023SJohn Marino /* Add statistics information about event ID in function FN with the
320*e4b17023SJohn Marino    histogram value VAL.
321*e4b17023SJohn Marino    It will dump the event to the global statistics file if requested.  */
322*e4b17023SJohn Marino 
323*e4b17023SJohn Marino void
statistics_histogram_event(struct function * fn,const char * id,int val)324*e4b17023SJohn Marino statistics_histogram_event (struct function *fn, const char *id, int val)
325*e4b17023SJohn Marino {
326*e4b17023SJohn Marino   statistics_counter_t *counter;
327*e4b17023SJohn Marino 
328*e4b17023SJohn Marino   if (!(dump_flags & TDF_STATS)
329*e4b17023SJohn Marino       && !statistics_dump_file)
330*e4b17023SJohn Marino     return;
331*e4b17023SJohn Marino 
332*e4b17023SJohn Marino   counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
333*e4b17023SJohn Marino   gcc_assert (counter->histogram_p);
334*e4b17023SJohn Marino   counter->count += 1;
335*e4b17023SJohn Marino 
336*e4b17023SJohn Marino   if (!statistics_dump_file
337*e4b17023SJohn Marino       || !(statistics_dump_flags & TDF_DETAILS))
338*e4b17023SJohn Marino     return;
339*e4b17023SJohn Marino 
340*e4b17023SJohn Marino   fprintf (statistics_dump_file,
341*e4b17023SJohn Marino 	   "%d %s \"%s == %d\" \"%s\" 1\n",
342*e4b17023SJohn Marino 	   current_pass->static_pass_number,
343*e4b17023SJohn Marino 	   current_pass->name,
344*e4b17023SJohn Marino 	   id, val,
345*e4b17023SJohn Marino 	   fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)");
346*e4b17023SJohn Marino }
347