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