OSDN Git Service

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