]> gcc.gnu.org Git - gcc.git/blame - gcc/statistics.c
Remove a layer of indirection from hash_table
[gcc.git] / gcc / statistics.c
CommitLineData
82e6d02f 1/* Optimization statistics functions.
23a5b65a 2 Copyright (C) 2008-2014 Free Software Foundation, Inc.
82e6d02f
RB
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"
24#include "tree-pass.h"
25#include "tree-dump.h"
26#include "statistics.h"
bf190e8d 27#include "hash-table.h"
82e6d02f 28#include "function.h"
315f8c0e
DM
29#include "context.h"
30#include "pass_manager.h"
82e6d02f
RB
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
39typedef 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
bf190e8d
LC
47/* Hashtable helpers. */
48
49struct stats_counter_hasher
50{
51 typedef statistics_counter_t value_type;
52 typedef statistics_counter_t compare_type;
53 static inline hashval_t hash (const value_type *);
54 static inline bool equal (const value_type *, const compare_type *);
55 static inline void remove (value_type *);
56};
82e6d02f
RB
57
58/* Hash a statistic counter by its string ID. */
59
bf190e8d
LC
60inline hashval_t
61stats_counter_hasher::hash (const value_type *c)
82e6d02f 62{
82e6d02f
RB
63 return htab_hash_string (c->id) + c->val;
64}
65
66/* Compare two statistic counters by their string IDs. */
67
bf190e8d
LC
68inline bool
69stats_counter_hasher::equal (const value_type *c1, const compare_type *c2)
82e6d02f 70{
82e6d02f
RB
71 return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
72}
73
74/* Free a statistics entry. */
75
bf190e8d
LC
76inline void
77stats_counter_hasher::remove (value_type *v)
82e6d02f 78{
c3284718 79 free (CONST_CAST (char *, v->id));
bf190e8d 80 free (v);
82e6d02f
RB
81}
82
c203e8a7 83typedef hash_table<stats_counter_hasher> stats_counter_table_type;
bf190e8d
LC
84
85/* Array of statistic hashes, indexed by pass id. */
c203e8a7 86static stats_counter_table_type **statistics_hashes;
bf190e8d
LC
87static unsigned nr_statistics_hashes;
88
82e6d02f
RB
89/* Return the current hashtable to be used for recording or printing
90 statistics. */
91
c203e8a7 92static stats_counter_table_type *
82e6d02f
RB
93curr_statistics_hash (void)
94{
5e1b50f6
AB
95 unsigned idx;
96
97 gcc_assert (current_pass->static_pass_number >= 0);
98 idx = current_pass->static_pass_number;
82e6d02f
RB
99
100 if (idx < nr_statistics_hashes
c203e8a7 101 && statistics_hashes[idx])
82e6d02f
RB
102 return statistics_hashes[idx];
103
104 if (idx >= nr_statistics_hashes)
105 {
c203e8a7 106 statistics_hashes = XRESIZEVEC (stats_counter_table_type *,
bf190e8d 107 statistics_hashes, idx+1);
82e6d02f 108 memset (statistics_hashes + nr_statistics_hashes, 0,
bf190e8d 109 (idx + 1 - nr_statistics_hashes)
c203e8a7 110 * sizeof (stats_counter_table_type *));
82e6d02f
RB
111 nr_statistics_hashes = idx + 1;
112 }
113
c203e8a7 114 statistics_hashes[idx] = new stats_counter_table_type (15);
82e6d02f
RB
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
bf190e8d
LC
122int
123statistics_fini_pass_1 (statistics_counter_t **slot,
124 void *data ATTRIBUTE_UNUSED)
82e6d02f 125{
bf190e8d 126 statistics_counter_t *counter = *slot;
82e6d02f
RB
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
bf190e8d
LC
143int
144statistics_fini_pass_2 (statistics_counter_t **slot,
145 void *data ATTRIBUTE_UNUSED)
82e6d02f 146{
bf190e8d 147 statistics_counter_t *counter = *slot;
82e6d02f
RB
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,
532aafad 158 current_function_name (),
82e6d02f
RB
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,
532aafad 166 current_function_name (),
82e6d02f
RB
167 count);
168 counter->prev_dumped_count = counter->count;
169 return 1;
170}
171
172/* Helper for statistics_fini_pass, reset the counters. */
173
bf190e8d
LC
174int
175statistics_fini_pass_3 (statistics_counter_t **slot,
176 void *data ATTRIBUTE_UNUSED)
82e6d02f 177{
bf190e8d 178 statistics_counter_t *counter = *slot;
82e6d02f
RB
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");
195 fprintf (dump_file, "Pass statistics:\n");
196 fprintf (dump_file, "----------------\n");
bf190e8d 197 curr_statistics_hash ()
c203e8a7 198 ->traverse_noresize <void *, statistics_fini_pass_1> (NULL);
82e6d02f
RB
199 fprintf (dump_file, "\n");
200 }
201 if (statistics_dump_file
202 && !(statistics_dump_flags & TDF_STATS
203 || statistics_dump_flags & TDF_DETAILS))
bf190e8d 204 curr_statistics_hash ()
c203e8a7 205 ->traverse_noresize <void *, statistics_fini_pass_2> (NULL);
bf190e8d 206 curr_statistics_hash ()
c203e8a7 207 ->traverse_noresize <void *, statistics_fini_pass_3> (NULL);
82e6d02f
RB
208}
209
210/* Helper for printing summary information. */
211
bf190e8d
LC
212int
213statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
82e6d02f 214{
bf190e8d 215 statistics_counter_t *counter = *slot;
82e6d02f
RB
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{
315f8c0e 240 gcc::pass_manager *passes = g->get_passes ();
82e6d02f
RB
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)
c203e8a7 248 if (statistics_hashes[i]
315f8c0e 249 && passes->get_pass_for_id (i) != NULL)
bf190e8d 250 statistics_hashes[i]
c203e8a7 251 ->traverse_noresize <opt_pass *, statistics_fini_1>
315f8c0e 252 (passes->get_pass_for_id (i));
82e6d02f
RB
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{
47e0da37
DM
263 gcc::dump_manager *dumps = g->get_dumps ();
264 statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
265 "statistics", TDF_TREE,
266 OPTGROUP_NONE);
82e6d02f
RB
267}
268
269/* Init the statistics. */
270
271void
272statistics_init (void)
273{
47e0da37 274 gcc::dump_manager *dumps = g->get_dumps ();
82e6d02f 275 statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
47e0da37 276 statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
82e6d02f
RB
277}
278
279/* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
280 and HISTOGRAM_P. */
281
282static statistics_counter_t *
c203e8a7 283lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
82e6d02f
RB
284 bool histogram_p)
285{
286 statistics_counter_t **counter;
287 statistics_counter_t c;
288 c.id = id;
289 c.val = val;
c203e8a7 290 counter = hash->find_slot (&c, INSERT);
82e6d02f
RB
291 if (!*counter)
292 {
293 *counter = XNEW (struct statistics_counter_s);
294 (*counter)->id = xstrdup (id);
295 (*counter)->val = val;
296 (*counter)->histogram_p = histogram_p;
297 (*counter)->prev_dumped_count = 0;
298 (*counter)->count = 0;
299 }
300 return *counter;
301}
302
303/* Add statistics information about event ID in function FN.
304 This will increment the counter associated with ID by INCR.
305 It will also dump the event to the global statistics file if requested. */
306
307void
308statistics_counter_event (struct function *fn, const char *id, int incr)
309{
310 statistics_counter_t *counter;
311
312 if ((!(dump_flags & TDF_STATS)
313 && !statistics_dump_file)
314 || incr == 0)
315 return;
316
5e1b50f6
AB
317 if (current_pass->static_pass_number != -1)
318 {
319 counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
320 gcc_assert (!counter->histogram_p);
321 counter->count += incr;
322 }
82e6d02f
RB
323
324 if (!statistics_dump_file
325 || !(statistics_dump_flags & TDF_DETAILS))
326 return;
327
328 fprintf (statistics_dump_file,
329 "%d %s \"%s\" \"%s\" %d\n",
330 current_pass->static_pass_number,
331 current_pass->name,
332 id,
532aafad 333 function_name (fn),
82e6d02f
RB
334 incr);
335}
336
337/* Add statistics information about event ID in function FN with the
338 histogram value VAL.
339 It will dump the event to the global statistics file if requested. */
340
341void
342statistics_histogram_event (struct function *fn, const char *id, int val)
343{
344 statistics_counter_t *counter;
345
346 if (!(dump_flags & TDF_STATS)
347 && !statistics_dump_file)
348 return;
349
350 counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
351 gcc_assert (counter->histogram_p);
352 counter->count += 1;
353
354 if (!statistics_dump_file
355 || !(statistics_dump_flags & TDF_DETAILS))
356 return;
357
358 fprintf (statistics_dump_file,
359 "%d %s \"%s == %d\" \"%s\" 1\n",
360 current_pass->static_pass_number,
361 current_pass->name,
362 id, val,
532aafad 363 function_name (fn));
82e6d02f 364}
This page took 2.860128 seconds and 5 git commands to generate.