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