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
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
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/>. */
23 #include "coretypes.h"
24 #include "tree-pass.h"
25 #include "tree-dump.h"
26 #include "statistics.h"
27 #include "hash-table.h"
33 #include "hard-reg-set.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
46 typedef struct statistics_counter_s
{
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. */
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. */
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. */
86 stats_counter_hasher::remove (statistics_counter_t
*v
)
88 free (CONST_CAST (char *, v
->id
));
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
101 static stats_counter_table_type
*
102 curr_statistics_hash (void)
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
;
139 if (counter
->histogram_p
)
140 fprintf (dump_file
, "%s == %d: " HOST_WIDE_INT_PRINT_DEC
"\n",
141 counter
->id
, counter
->val
, count
);
143 fprintf (dump_file
, "%s: " HOST_WIDE_INT_PRINT_DEC
"\n",
145 counter
->prev_dumped_count
= counter
->count
;
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
;
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
,
166 counter
->id
, counter
->val
,
167 current_function_name (),
170 fprintf (statistics_dump_file
,
171 "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
172 current_pass
->static_pass_number
,
175 current_function_name (),
177 counter
->prev_dumped_count
= counter
->count
;
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
;
192 /* Dump the current statistics incrementally. */
195 statistics_fini_pass (void)
197 if (current_pass
->static_pass_number
== -1)
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)
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
,
232 counter
->id
, counter
->val
,
235 fprintf (statistics_dump_file
,
236 "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
237 pass
->static_pass_number
,
244 /* Finish the statistics and dump summary information. */
247 statistics_fini (void)
249 gcc::pass_manager
*passes
= g
->get_passes ();
250 if (!statistics_dump_file
)
253 if (statistics_dump_flags
& TDF_STATS
)
256 for (i
= 0; i
< nr_statistics_hashes
; ++i
)
257 if (statistics_hashes
[i
]
258 && passes
->get_pass_for_id (i
) != NULL
)
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. */
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
,
279 /* Init the statistics. */
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
292 static statistics_counter_t
*
293 lookup_or_add_counter (stats_counter_table_type
*hash
, const char *id
, int val
,
296 statistics_counter_t
**counter
;
297 statistics_counter_t c
;
300 counter
= hash
->find_slot (&c
, INSERT
);
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;
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. */
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
)
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
))
338 fprintf (statistics_dump_file
,
339 "%d %s \"%s\" \"%s\" %d\n",
340 current_pass
->static_pass_number
,
347 /* Add statistics information about event ID in function FN with the
349 It will dump the event to the global statistics file if requested. */
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
)
360 counter
= lookup_or_add_counter (curr_statistics_hash (), id
, val
, true);
361 gcc_assert (counter
->histogram_p
);
364 if (!statistics_dump_file
365 || !(statistics_dump_flags
& TDF_DETAILS
))
368 fprintf (statistics_dump_file
,
369 "%d %s \"%s == %d\" \"%s\" 1\n",
370 current_pass
->static_pass_number
,