2010-11-11 Jakub Jelinek <jakub@redhat.com>
[official-gcc.git] / gcc / statistics.c
blobb7bfd45dd975027371aa4957302095123b3eaabb
1 /* Optimization statistics functions.
2 Copyright (C) 2008
3 Free Software Foundation, Inc.
4 Contributed by Richard Guenther <rguenther@suse.de>
6 This file is part of GCC.
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.
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.
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/>. */
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"
32 static int statistics_dump_nr;
33 static int statistics_dump_flags;
34 static FILE *statistics_dump_file;
36 /* Statistics entry. A integer counter associated to a string ID
37 and value. */
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;
47 /* Array of statistic hashes, indexed by pass id. */
48 static htab_t *statistics_hashes;
49 static unsigned nr_statistics_hashes;
51 /* Hash a statistic counter by its string ID. */
53 static hashval_t
54 hash_statistics_hash (const void *p)
56 const statistics_counter_t *const c = (const statistics_counter_t *)p;
57 return htab_hash_string (c->id) + c->val;
60 /* Compare two statistic counters by their string IDs. */
62 static int
63 hash_statistics_eq (const void *p, const void *q)
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;
70 /* Free a statistics entry. */
72 static void
73 hash_statistics_free (void *p)
75 free (CONST_CAST(char *, ((statistics_counter_t *)p)->id));
76 free (p);
79 /* Return the current hashtable to be used for recording or printing
80 statistics. */
82 static htab_t
83 curr_statistics_hash (void)
85 unsigned idx;
87 gcc_assert (current_pass->static_pass_number >= 0);
88 idx = current_pass->static_pass_number;
90 if (idx < nr_statistics_hashes
91 && statistics_hashes[idx] != NULL)
92 return statistics_hashes[idx];
94 if (idx >= nr_statistics_hashes)
96 statistics_hashes = XRESIZEVEC (struct htab *, statistics_hashes, idx+1);
97 memset (statistics_hashes + nr_statistics_hashes, 0,
98 (idx + 1 - nr_statistics_hashes) * sizeof (htab_t));
99 nr_statistics_hashes = idx + 1;
102 statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
103 hash_statistics_eq,
104 hash_statistics_free);
106 return statistics_hashes[idx];
109 /* Helper for statistics_fini_pass. Print the counter difference
110 since the last dump for the pass dump files. */
112 static int
113 statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
115 statistics_counter_t *counter = (statistics_counter_t *)*slot;
116 unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
117 if (count == 0)
118 return 1;
119 if (counter->histogram_p)
120 fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
121 counter->id, counter->val, count);
122 else
123 fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
124 counter->id, count);
125 counter->prev_dumped_count = counter->count;
126 return 1;
129 /* Helper for statistics_fini_pass. Print the counter difference
130 since the last dump for the statistics dump. */
132 static int
133 statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
135 statistics_counter_t *counter = (statistics_counter_t *)*slot;
136 unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
137 if (count == 0)
138 return 1;
139 counter->prev_dumped_count = counter->count;
140 if (counter->histogram_p)
141 fprintf (statistics_dump_file,
142 "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
143 current_pass->static_pass_number,
144 current_pass->name,
145 counter->id, counter->val,
146 cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
147 count);
148 else
149 fprintf (statistics_dump_file,
150 "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
151 current_pass->static_pass_number,
152 current_pass->name,
153 counter->id,
154 cfun ? IDENTIFIER_POINTER (DECL_NAME (cfun->decl)) : "(nofn)",
155 count);
156 counter->prev_dumped_count = counter->count;
157 return 1;
160 /* Helper for statistics_fini_pass, reset the counters. */
162 static int
163 statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
165 statistics_counter_t *counter = (statistics_counter_t *)*slot;
166 counter->prev_dumped_count = counter->count;
167 return 1;
170 /* Dump the current statistics incrementally. */
172 void
173 statistics_fini_pass (void)
175 if (current_pass->static_pass_number == -1)
176 return;
178 if (dump_file
179 && dump_flags & TDF_STATS)
181 fprintf (dump_file, "\n");
182 fprintf (dump_file, "Pass statistics:\n");
183 fprintf (dump_file, "----------------\n");
184 htab_traverse_noresize (curr_statistics_hash (),
185 statistics_fini_pass_1, NULL);
186 fprintf (dump_file, "\n");
188 if (statistics_dump_file
189 && !(statistics_dump_flags & TDF_STATS
190 || statistics_dump_flags & TDF_DETAILS))
191 htab_traverse_noresize (curr_statistics_hash (),
192 statistics_fini_pass_2, NULL);
193 htab_traverse_noresize (curr_statistics_hash (),
194 statistics_fini_pass_3, NULL);
197 /* Helper for printing summary information. */
199 static int
200 statistics_fini_1 (void **slot, void *data)
202 struct opt_pass *pass = (struct opt_pass *)data;
203 statistics_counter_t *counter = (statistics_counter_t *)*slot;
204 if (counter->count == 0)
205 return 1;
206 if (counter->histogram_p)
207 fprintf (statistics_dump_file,
208 "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
209 pass->static_pass_number,
210 pass->name,
211 counter->id, counter->val,
212 counter->count);
213 else
214 fprintf (statistics_dump_file,
215 "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
216 pass->static_pass_number,
217 pass->name,
218 counter->id,
219 counter->count);
220 return 1;
223 /* Finish the statistics and dump summary information. */
225 void
226 statistics_fini (void)
228 if (!statistics_dump_file)
229 return;
231 if (statistics_dump_flags & TDF_STATS)
233 unsigned i;
234 for (i = 0; i < nr_statistics_hashes; ++i)
235 if (statistics_hashes[i] != NULL
236 && get_pass_for_id (i) != NULL)
237 htab_traverse_noresize (statistics_hashes[i],
238 statistics_fini_1, get_pass_for_id (i));
241 dump_end (statistics_dump_nr, statistics_dump_file);
244 /* Register the statistics dump file. */
246 void
247 statistics_early_init (void)
249 statistics_dump_nr = dump_register (".statistics", "statistics",
250 "statistics", TDF_TREE);
253 /* Init the statistics. */
255 void
256 statistics_init (void)
258 statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
259 statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->flags;
262 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
263 and HISTOGRAM_P. */
265 static statistics_counter_t *
266 lookup_or_add_counter (htab_t hash, const char *id, int val,
267 bool histogram_p)
269 statistics_counter_t **counter;
270 statistics_counter_t c;
271 c.id = id;
272 c.val = val;
273 counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
274 if (!*counter)
276 *counter = XNEW (struct statistics_counter_s);
277 (*counter)->id = xstrdup (id);
278 (*counter)->val = val;
279 (*counter)->histogram_p = histogram_p;
280 (*counter)->prev_dumped_count = 0;
281 (*counter)->count = 0;
283 return *counter;
286 /* Add statistics information about event ID in function FN.
287 This will increment the counter associated with ID by INCR.
288 It will also dump the event to the global statistics file if requested. */
290 void
291 statistics_counter_event (struct function *fn, const char *id, int incr)
293 statistics_counter_t *counter;
295 if ((!(dump_flags & TDF_STATS)
296 && !statistics_dump_file)
297 || incr == 0)
298 return;
300 if (current_pass->static_pass_number != -1)
302 counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
303 gcc_assert (!counter->histogram_p);
304 counter->count += incr;
307 if (!statistics_dump_file
308 || !(statistics_dump_flags & TDF_DETAILS))
309 return;
311 fprintf (statistics_dump_file,
312 "%d %s \"%s\" \"%s\" %d\n",
313 current_pass->static_pass_number,
314 current_pass->name,
316 fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)",
317 incr);
320 /* Add statistics information about event ID in function FN with the
321 histogram value VAL.
322 It will dump the event to the global statistics file if requested. */
324 void
325 statistics_histogram_event (struct function *fn, const char *id, int val)
327 statistics_counter_t *counter;
329 if (!(dump_flags & TDF_STATS)
330 && !statistics_dump_file)
331 return;
333 counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
334 gcc_assert (counter->histogram_p);
335 counter->count += 1;
337 if (!statistics_dump_file
338 || !(statistics_dump_flags & TDF_DETAILS))
339 return;
341 fprintf (statistics_dump_file,
342 "%d %s \"%s == %d\" \"%s\" 1\n",
343 current_pass->static_pass_number,
344 current_pass->name,
345 id, val,
346 fn ? IDENTIFIER_POINTER (DECL_NAME (fn->decl)) : "(nofn)");