]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/statistics.c
remove need for store_values_directly
[thirdparty/gcc.git] / gcc / statistics.c
1 /* Optimization statistics functions.
2 Copyright (C) 2008-2015 Free Software Foundation, Inc.
3 Contributed by Richard Guenther <rguenther@suse.de>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
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"
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"
38
39 static int statistics_dump_nr;
40 static int statistics_dump_flags;
41 static FILE *statistics_dump_file;
42
43 /* Statistics entry. A integer counter associated to a string ID
44 and value. */
45
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;
53
54 /* Hashtable helpers. */
55
56 struct stats_counter_hasher
57 {
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 *);
64 };
65
66 /* Hash a statistic counter by its string ID. */
67
68 inline hashval_t
69 stats_counter_hasher::hash (const statistics_counter_t *c)
70 {
71 return htab_hash_string (c->id) + c->val;
72 }
73
74 /* Compare two statistic counters by their string IDs. */
75
76 inline bool
77 stats_counter_hasher::equal (const statistics_counter_t *c1,
78 const statistics_counter_t *c2)
79 {
80 return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
81 }
82
83 /* Free a statistics entry. */
84
85 inline void
86 stats_counter_hasher::remove (statistics_counter_t *v)
87 {
88 free (CONST_CAST (char *, v->id));
89 free (v);
90 }
91
92 typedef hash_table<stats_counter_hasher> stats_counter_table_type;
93
94 /* Array of statistic hashes, indexed by pass id. */
95 static stats_counter_table_type **statistics_hashes;
96 static unsigned nr_statistics_hashes;
97
98 /* Return the current hashtable to be used for recording or printing
99 statistics. */
100
101 static stats_counter_table_type *
102 curr_statistics_hash (void)
103 {
104 unsigned idx;
105
106 gcc_assert (current_pass->static_pass_number >= 0);
107 idx = current_pass->static_pass_number;
108
109 if (idx < nr_statistics_hashes
110 && statistics_hashes[idx])
111 return statistics_hashes[idx];
112
113 if (idx >= nr_statistics_hashes)
114 {
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;
121 }
122
123 statistics_hashes[idx] = new stats_counter_table_type (15);
124
125 return statistics_hashes[idx];
126 }
127
128 /* Helper for statistics_fini_pass. Print the counter difference
129 since the last dump for the pass dump files. */
130
131 int
132 statistics_fini_pass_1 (statistics_counter_t **slot,
133 void *data ATTRIBUTE_UNUSED)
134 {
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;
147 }
148
149 /* Helper for statistics_fini_pass. Print the counter difference
150 since the last dump for the statistics dump. */
151
152 int
153 statistics_fini_pass_2 (statistics_counter_t **slot,
154 void *data ATTRIBUTE_UNUSED)
155 {
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;
179 }
180
181 /* Helper for statistics_fini_pass, reset the counters. */
182
183 int
184 statistics_fini_pass_3 (statistics_counter_t **slot,
185 void *data ATTRIBUTE_UNUSED)
186 {
187 statistics_counter_t *counter = *slot;
188 counter->prev_dumped_count = counter->count;
189 return 1;
190 }
191
192 /* Dump the current statistics incrementally. */
193
194 void
195 statistics_fini_pass (void)
196 {
197 if (current_pass->static_pass_number == -1)
198 return;
199
200 if (dump_file
201 && dump_flags & TDF_STATS)
202 {
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");
209 }
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);
217 }
218
219 /* Helper for printing summary information. */
220
221 int
222 statistics_fini_1 (statistics_counter_t **slot, opt_pass *pass)
223 {
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;
242 }
243
244 /* Finish the statistics and dump summary information. */
245
246 void
247 statistics_fini (void)
248 {
249 gcc::pass_manager *passes = g->get_passes ();
250 if (!statistics_dump_file)
251 return;
252
253 if (statistics_dump_flags & TDF_STATS)
254 {
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));
262 }
263
264 dump_end (statistics_dump_nr, statistics_dump_file);
265 }
266
267 /* Register the statistics dump file. */
268
269 void
270 statistics_early_init (void)
271 {
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);
277 }
278
279 /* Init the statistics. */
280
281 void
282 statistics_init (void)
283 {
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;
287 }
288
289 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
290 and HISTOGRAM_P. */
291
292 static statistics_counter_t *
293 lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
294 bool histogram_p)
295 {
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)
302 {
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;
309 }
310 return *counter;
311 }
312
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. */
316
317 void
318 statistics_counter_event (struct function *fn, const char *id, int incr)
319 {
320 statistics_counter_t *counter;
321
322 if ((!(dump_flags & TDF_STATS)
323 && !statistics_dump_file)
324 || incr == 0)
325 return;
326
327 if (current_pass->static_pass_number != -1)
328 {
329 counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
330 gcc_assert (!counter->histogram_p);
331 counter->count += incr;
332 }
333
334 if (!statistics_dump_file
335 || !(statistics_dump_flags & TDF_DETAILS))
336 return;
337
338 fprintf (statistics_dump_file,
339 "%d %s \"%s\" \"%s\" %d\n",
340 current_pass->static_pass_number,
341 current_pass->name,
342 id,
343 function_name (fn),
344 incr);
345 }
346
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. */
350
351 void
352 statistics_histogram_event (struct function *fn, const char *id, int val)
353 {
354 statistics_counter_t *counter;
355
356 if (!(dump_flags & TDF_STATS)
357 && !statistics_dump_file)
358 return;
359
360 counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
361 gcc_assert (counter->histogram_p);
362 counter->count += 1;
363
364 if (!statistics_dump_file
365 || !(statistics_dump_flags & TDF_DETAILS))
366 return;
367
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));
374 }