OSDN Git Service

Daily bump.
[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   const statistics_counter_t *const c = (const 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   const statistics_counter_t *const c1 = (const statistics_counter_t *)p;
66   const statistics_counter_t *const c2 = (const 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 (CONST_CAST(char *, ((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 = XRESIZEVEC (struct htab *, statistics_hashes, idx+1);
94       memset (statistics_hashes + nr_statistics_hashes, 0,
95               (idx + 1 - nr_statistics_hashes) * sizeof (htab_t));
96       nr_statistics_hashes = idx + 1;
97     }
98
99   statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
100                                         hash_statistics_eq,
101                                         hash_statistics_free);
102
103   return statistics_hashes[idx];
104 }
105
106 /* Helper for statistics_fini_pass.  Print the counter difference
107    since the last dump for the pass dump files.  */
108
109 static int
110 statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
111 {
112   statistics_counter_t *counter = (statistics_counter_t *)*slot;
113   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
114   if (count == 0)
115     return 1;
116   if (counter->histogram_p)
117     fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
118              counter->id, counter->val, count);
119   else
120     fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
121              counter->id, count);
122   counter->prev_dumped_count = counter->count;
123   return 1;
124 }
125
126 /* Helper for statistics_fini_pass.  Print the counter difference
127    since the last dump for the statistics dump.  */
128
129 static int
130 statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
131 {
132   statistics_counter_t *counter = (statistics_counter_t *)*slot;
133   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
134   if (count == 0)
135     return 1;
136   counter->prev_dumped_count = counter->count;
137   if (counter->histogram_p)
138     fprintf (statistics_dump_file,
139              "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
140              current_pass->static_pass_number,
141              current_pass->name,
142              counter->id, counter->val,
143              cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
144              count);
145   else
146     fprintf (statistics_dump_file,
147              "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
148              current_pass->static_pass_number,
149              current_pass->name,
150              counter->id,
151              cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
152              count);
153   counter->prev_dumped_count = counter->count;
154   return 1;
155 }
156
157 /* Helper for statistics_fini_pass, reset the counters.  */
158
159 static int
160 statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
161 {
162   statistics_counter_t *counter = (statistics_counter_t *)*slot;
163   counter->prev_dumped_count = counter->count;
164   return 1;
165 }
166
167 /* Dump the current statistics incrementally.  */
168
169 void
170 statistics_fini_pass (void)
171 {
172   if (current_pass->static_pass_number == -1)
173     return;
174
175   if (dump_file
176       && dump_flags & TDF_STATS)
177     {
178       fprintf (dump_file, "\n");
179       fprintf (dump_file, "Pass statistics:\n");
180       fprintf (dump_file, "----------------\n");
181       htab_traverse_noresize (curr_statistics_hash (),
182                               statistics_fini_pass_1, NULL);
183       fprintf (dump_file, "\n");
184     }
185   if (statistics_dump_file
186       && !(statistics_dump_flags & TDF_STATS
187            || statistics_dump_flags & TDF_DETAILS))
188     htab_traverse_noresize (curr_statistics_hash (),
189                             statistics_fini_pass_2, NULL);
190   htab_traverse_noresize (curr_statistics_hash (),
191                           statistics_fini_pass_3, NULL);
192 }
193
194 /* Helper for printing summary information.  */
195
196 static int
197 statistics_fini_1 (void **slot, void *data)
198 {
199   struct opt_pass *pass = (struct opt_pass *)data;
200   statistics_counter_t *counter = (statistics_counter_t *)*slot;
201   if (counter->count == 0)
202     return 1;
203   if (counter->histogram_p)
204     fprintf (statistics_dump_file,
205              "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
206              pass->static_pass_number,
207              pass->name,
208              counter->id, counter->val,
209              counter->count);
210   else
211     fprintf (statistics_dump_file,
212              "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
213              pass->static_pass_number,
214              pass->name,
215              counter->id,
216              counter->count);
217   return 1;
218 }
219
220 /* Finish the statistics and dump summary information.  */
221
222 void
223 statistics_fini (void)
224 {
225   if (!statistics_dump_file)
226     return;
227
228   if (statistics_dump_flags & TDF_STATS)
229     {
230       unsigned i;
231       for (i = 0; i < nr_statistics_hashes; ++i)
232         if (statistics_hashes[i] != NULL
233             && get_pass_for_id (i) != NULL)
234           htab_traverse_noresize (statistics_hashes[i],
235                                   statistics_fini_1, get_pass_for_id (i));
236     }
237
238   dump_end (statistics_dump_nr, statistics_dump_file);
239 }
240
241 /* Register the statistics dump file.  */
242
243 void
244 statistics_early_init (void)
245 {
246   statistics_dump_nr = dump_register (".statistics", "statistics",
247                                       "statistics", TDF_TREE);
248 }
249
250 /* Init the statistics.  */
251
252 void
253 statistics_init (void)
254 {
255   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
256   statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->flags;
257 }
258
259 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
260    and HISTOGRAM_P.  */
261
262 static statistics_counter_t *
263 lookup_or_add_counter (htab_t hash, const char *id, int val,
264                        bool histogram_p)
265 {
266   statistics_counter_t **counter;
267   statistics_counter_t c;
268   c.id = id;
269   c.val = val;
270   counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
271   if (!*counter)
272     {
273       *counter = XNEW (struct statistics_counter_s);
274       (*counter)->id = xstrdup (id);
275       (*counter)->val = val;
276       (*counter)->histogram_p = histogram_p;
277       (*counter)->prev_dumped_count = 0;
278       (*counter)->count = 0;
279     }
280   return *counter;
281 }
282
283 /* Add statistics information about event ID in function FN.
284    This will increment the counter associated with ID by INCR.
285    It will also dump the event to the global statistics file if requested.  */
286
287 void
288 statistics_counter_event (struct function *fn, const char *id, int incr)
289 {
290   statistics_counter_t *counter;
291
292   if ((!(dump_flags & TDF_STATS)
293        && !statistics_dump_file)
294       || incr == 0)
295     return;
296
297   counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
298   gcc_assert (!counter->histogram_p);
299   counter->count += incr;
300
301   if (!statistics_dump_file
302       || !(statistics_dump_flags & TDF_DETAILS))
303     return;
304
305   fprintf (statistics_dump_file,
306            "%d %s \"%s\" \"%s\" %d\n",
307            current_pass->static_pass_number,
308            current_pass->name,
309            id,
310            fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)",
311            incr);
312 }
313
314 /* Add statistics information about event ID in function FN with the
315    histogram value VAL.
316    It will dump the event to the global statistics file if requested.  */
317
318 void
319 statistics_histogram_event (struct function *fn, const char *id, int val)
320 {
321   statistics_counter_t *counter;
322
323   if (!(dump_flags & TDF_STATS)
324       && !statistics_dump_file)
325     return;
326
327   counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
328   gcc_assert (counter->histogram_p);
329   counter->count += 1;
330
331   if (!statistics_dump_file
332       || !(statistics_dump_flags & TDF_DETAILS))
333     return;
334
335   fprintf (statistics_dump_file,
336            "%d %s \"%s == %d\" \"%s\" 1\n",
337            current_pass->static_pass_number,
338            current_pass->name,
339            id, val,
340            fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)");
341 }