2015-05-05 Yvan Roux <yvan.roux@linaro.org>
[official-gcc.git] / gcc / statistics.c
blob8cbe88d4a906d554feea8bc6596aeafd8cf5408a
1 /* Optimization statistics functions.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 Contributed by Richard Guenther <rguenther@suse.de>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tree-pass.h"
25 #include "tree-dump.h"
26 #include "statistics.h"
27 #include "hash-table.h"
28 #include "hashtab.h"
29 #include "hash-set.h"
30 #include "vec.h"
31 #include "machmode.h"
32 #include "tm.h"
33 #include "hard-reg-set.h"
34 #include "input.h"
35 #include "function.h"
36 #include "context.h"
37 #include "pass_manager.h"
39 static int statistics_dump_nr;
40 static int statistics_dump_flags;
41 static FILE *statistics_dump_file;
43 /* Statistics entry. A integer counter associated to a string ID
44 and value. */
46 typedef struct statistics_counter_s {
47 const char *id;
48 int val;
49 bool histogram_p;
50 unsigned HOST_WIDE_INT count;
51 unsigned HOST_WIDE_INT prev_dumped_count;
52 } statistics_counter_t;
54 /* Hashtable helpers. */
56 struct stats_counter_hasher
58 typedef statistics_counter_t *value_type;
59 typedef statistics_counter_t *compare_type;
60 static inline hashval_t hash (const statistics_counter_t *);
61 static inline bool equal (const statistics_counter_t *,
62 const statistics_counter_t *);
63 static inline void remove (statistics_counter_t *);
66 /* Hash a statistic counter by its string ID. */
68 inline hashval_t
69 stats_counter_hasher::hash (const statistics_counter_t *c)
71 return htab_hash_string (c->id) + c->val;
74 /* Compare two statistic counters by their string IDs. */
76 inline bool
77 stats_counter_hasher::equal (const statistics_counter_t *c1,
78 const statistics_counter_t *c2)
80 return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
83 /* Free a statistics entry. */
85 inline void
86 stats_counter_hasher::remove (statistics_counter_t *v)
88 free (CONST_CAST (char *, v->id));
89 free (v);
92 typedef hash_table<stats_counter_hasher> stats_counter_table_type;
94 /* Array of statistic hashes, indexed by pass id. */
95 static stats_counter_table_type **statistics_hashes;
96 static unsigned nr_statistics_hashes;
98 /* Return the current hashtable to be used for recording or printing
99 statistics. */
101 static stats_counter_table_type *
102 curr_statistics_hash (void)
104 unsigned idx;
106 gcc_assert (current_pass->static_pass_number >= 0);
107 idx = current_pass->static_pass_number;
109 if (idx < nr_statistics_hashes
110 && statistics_hashes[idx])
111 return statistics_hashes[idx];
113 if (idx >= nr_statistics_hashes)
115 statistics_hashes = XRESIZEVEC (stats_counter_table_type *,
116 statistics_hashes, idx+1);
117 memset (statistics_hashes + nr_statistics_hashes, 0,
118 (idx + 1 - nr_statistics_hashes)
119 * sizeof (stats_counter_table_type *));
120 nr_statistics_hashes = idx + 1;
123 statistics_hashes[idx] = new stats_counter_table_type (15);
125 return statistics_hashes[idx];
128 /* Helper for statistics_fini_pass. Print the counter difference
129 since the last dump for the pass dump files. */
132 statistics_fini_pass_1 (statistics_counter_t **slot,
133 void *data ATTRIBUTE_UNUSED)
135 statistics_counter_t *counter = *slot;
136 unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
137 if (count == 0)
138 return 1;
139 if (counter->histogram_p)
140 fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
141 counter->id, counter->val, count);
142 else
143 fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
144 counter->id, count);
145 counter->prev_dumped_count = counter->count;
146 return 1;
149 /* Helper for statistics_fini_pass. Print the counter difference
150 since the last dump for the statistics dump. */
153 statistics_fini_pass_2 (statistics_counter_t **slot,
154 void *data ATTRIBUTE_UNUSED)
156 statistics_counter_t *counter = *slot;
157 unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
158 if (count == 0)
159 return 1;
160 counter->prev_dumped_count = counter->count;
161 if (counter->histogram_p)
162 fprintf (statistics_dump_file,
163 "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
164 current_pass->static_pass_number,
165 current_pass->name,
166 counter->id, counter->val,
167 current_function_name (),
168 count);
169 else
170 fprintf (statistics_dump_file,
171 "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
172 current_pass->static_pass_number,
173 current_pass->name,
174 counter->id,
175 current_function_name (),
176 count);
177 counter->prev_dumped_count = counter->count;
178 return 1;
181 /* Helper for statistics_fini_pass, reset the counters. */
184 statistics_fini_pass_3 (statistics_counter_t **slot,
185 void *data ATTRIBUTE_UNUSED)
187 statistics_counter_t *counter = *slot;
188 counter->prev_dumped_count = counter->count;
189 return 1;
192 /* Dump the current statistics incrementally. */
194 void
195 statistics_fini_pass (void)
197 if (current_pass->static_pass_number == -1)
198 return;
200 if (dump_file
201 && dump_flags & TDF_STATS)
203 fprintf (dump_file, "\n");
204 fprintf (dump_file, "Pass statistics:\n");
205 fprintf (dump_file, "----------------\n");
206 curr_statistics_hash ()
207 ->traverse_noresize <void *, statistics_fini_pass_1> (NULL);
208 fprintf (dump_file, "\n");
210 if (statistics_dump_file
211 && !(statistics_dump_flags & TDF_STATS
212 || statistics_dump_flags & TDF_DETAILS))
213 curr_statistics_hash ()
214 ->traverse_noresize <void *, statistics_fini_pass_2> (NULL);
215 curr_statistics_hash ()
216 ->traverse_noresize <void *, statistics_fini_pass_3> (NULL);
219 /* Helper for printing summary information. */
222 statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
224 statistics_counter_t *counter = *slot;
225 if (counter->count == 0)
226 return 1;
227 if (counter->histogram_p)
228 fprintf (statistics_dump_file,
229 "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
230 pass->static_pass_number,
231 pass->name,
232 counter->id, counter->val,
233 counter->count);
234 else
235 fprintf (statistics_dump_file,
236 "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
237 pass->static_pass_number,
238 pass->name,
239 counter->id,
240 counter->count);
241 return 1;
244 /* Finish the statistics and dump summary information. */
246 void
247 statistics_fini (void)
249 gcc::pass_manager *passes = g->get_passes ();
250 if (!statistics_dump_file)
251 return;
253 if (statistics_dump_flags & TDF_STATS)
255 unsigned i;
256 for (i = 0; i < nr_statistics_hashes; ++i)
257 if (statistics_hashes[i]
258 && passes->get_pass_for_id (i) != NULL)
259 statistics_hashes[i]
260 ->traverse_noresize <opt_pass *, statistics_fini_1>
261 (passes->get_pass_for_id (i));
264 dump_end (statistics_dump_nr, statistics_dump_file);
267 /* Register the statistics dump file. */
269 void
270 statistics_early_init (void)
272 gcc::dump_manager *dumps = g->get_dumps ();
273 statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
274 "statistics", TDF_TREE,
275 OPTGROUP_NONE,
276 false);
279 /* Init the statistics. */
281 void
282 statistics_init (void)
284 gcc::dump_manager *dumps = g->get_dumps ();
285 statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
286 statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
289 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
290 and HISTOGRAM_P. */
292 static statistics_counter_t *
293 lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
294 bool histogram_p)
296 statistics_counter_t **counter;
297 statistics_counter_t c;
298 c.id = id;
299 c.val = val;
300 counter = hash->find_slot (&c, INSERT);
301 if (!*counter)
303 *counter = XNEW (struct statistics_counter_s);
304 (*counter)->id = xstrdup (id);
305 (*counter)->val = val;
306 (*counter)->histogram_p = histogram_p;
307 (*counter)->prev_dumped_count = 0;
308 (*counter)->count = 0;
310 return *counter;
313 /* Add statistics information about event ID in function FN.
314 This will increment the counter associated with ID by INCR.
315 It will also dump the event to the global statistics file if requested. */
317 void
318 statistics_counter_event (struct function *fn, const char *id, int incr)
320 statistics_counter_t *counter;
322 if ((!(dump_flags & TDF_STATS)
323 && !statistics_dump_file)
324 || incr == 0)
325 return;
327 if (current_pass->static_pass_number != -1)
329 counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
330 gcc_assert (!counter->histogram_p);
331 counter->count += incr;
334 if (!statistics_dump_file
335 || !(statistics_dump_flags & TDF_DETAILS))
336 return;
338 fprintf (statistics_dump_file,
339 "%d %s \"%s\" \"%s\" %d\n",
340 current_pass->static_pass_number,
341 current_pass->name,
343 function_name (fn),
344 incr);
347 /* Add statistics information about event ID in function FN with the
348 histogram value VAL.
349 It will dump the event to the global statistics file if requested. */
351 void
352 statistics_histogram_event (struct function *fn, const char *id, int val)
354 statistics_counter_t *counter;
356 if (!(dump_flags & TDF_STATS)
357 && !statistics_dump_file)
358 return;
360 counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
361 gcc_assert (counter->histogram_p);
362 counter->count += 1;
364 if (!statistics_dump_file
365 || !(statistics_dump_flags & TDF_DETAILS))
366 return;
368 fprintf (statistics_dump_file,
369 "%d %s \"%s == %d\" \"%s\" 1\n",
370 current_pass->static_pass_number,
371 current_pass->name,
372 id, val,
373 function_name (fn));