1 /* Optimization statistics functions.
2 Copyright (C) 2008-2013 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"
30 static int statistics_dump_nr
;
31 static int statistics_dump_flags
;
32 static FILE *statistics_dump_file
;
34 /* Statistics entry. A integer counter associated to a string ID
37 typedef struct statistics_counter_s
{
41 unsigned HOST_WIDE_INT count
;
42 unsigned HOST_WIDE_INT prev_dumped_count
;
43 } statistics_counter_t
;
45 /* Array of statistic hashes, indexed by pass id. */
46 static htab_t
*statistics_hashes
;
47 static unsigned nr_statistics_hashes
;
49 /* Hash a statistic counter by its string ID. */
52 hash_statistics_hash (const void *p
)
54 const statistics_counter_t
*const c
= (const statistics_counter_t
*)p
;
55 return htab_hash_string (c
->id
) + c
->val
;
58 /* Compare two statistic counters by their string IDs. */
61 hash_statistics_eq (const void *p
, const void *q
)
63 const statistics_counter_t
*const c1
= (const statistics_counter_t
*)p
;
64 const statistics_counter_t
*const c2
= (const statistics_counter_t
*)q
;
65 return c1
->val
== c2
->val
&& strcmp (c1
->id
, c2
->id
) == 0;
68 /* Free a statistics entry. */
71 hash_statistics_free (void *p
)
73 free (CONST_CAST(char *, ((statistics_counter_t
*)p
)->id
));
77 /* Return the current hashtable to be used for recording or printing
81 curr_statistics_hash (void)
85 gcc_assert (current_pass
->static_pass_number
>= 0);
86 idx
= current_pass
->static_pass_number
;
88 if (idx
< nr_statistics_hashes
89 && statistics_hashes
[idx
] != NULL
)
90 return statistics_hashes
[idx
];
92 if (idx
>= nr_statistics_hashes
)
94 statistics_hashes
= XRESIZEVEC (struct htab
*, statistics_hashes
, idx
+1);
95 memset (statistics_hashes
+ nr_statistics_hashes
, 0,
96 (idx
+ 1 - nr_statistics_hashes
) * sizeof (htab_t
));
97 nr_statistics_hashes
= idx
+ 1;
100 statistics_hashes
[idx
] = htab_create (15, hash_statistics_hash
,
102 hash_statistics_free
);
104 return statistics_hashes
[idx
];
107 /* Helper for statistics_fini_pass. Print the counter difference
108 since the last dump for the pass dump files. */
111 statistics_fini_pass_1 (void **slot
, void *data ATTRIBUTE_UNUSED
)
113 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
114 unsigned HOST_WIDE_INT count
= counter
->count
- counter
->prev_dumped_count
;
117 if (counter
->histogram_p
)
118 fprintf (dump_file
, "%s == %d: " HOST_WIDE_INT_PRINT_DEC
"\n",
119 counter
->id
, counter
->val
, count
);
121 fprintf (dump_file
, "%s: " HOST_WIDE_INT_PRINT_DEC
"\n",
123 counter
->prev_dumped_count
= counter
->count
;
127 /* Helper for statistics_fini_pass. Print the counter difference
128 since the last dump for the statistics dump. */
131 statistics_fini_pass_2 (void **slot
, void *data ATTRIBUTE_UNUSED
)
133 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
134 unsigned HOST_WIDE_INT count
= counter
->count
- counter
->prev_dumped_count
;
137 counter
->prev_dumped_count
= counter
->count
;
138 if (counter
->histogram_p
)
139 fprintf (statistics_dump_file
,
140 "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
141 current_pass
->static_pass_number
,
143 counter
->id
, counter
->val
,
144 current_function_name (),
147 fprintf (statistics_dump_file
,
148 "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
149 current_pass
->static_pass_number
,
152 current_function_name (),
154 counter
->prev_dumped_count
= counter
->count
;
158 /* Helper for statistics_fini_pass, reset the counters. */
161 statistics_fini_pass_3 (void **slot
, void *data ATTRIBUTE_UNUSED
)
163 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
164 counter
->prev_dumped_count
= counter
->count
;
168 /* Dump the current statistics incrementally. */
171 statistics_fini_pass (void)
173 if (current_pass
->static_pass_number
== -1)
177 && dump_flags
& TDF_STATS
)
179 fprintf (dump_file
, "\n");
180 fprintf (dump_file
, "Pass statistics:\n");
181 fprintf (dump_file
, "----------------\n");
182 htab_traverse_noresize (curr_statistics_hash (),
183 statistics_fini_pass_1
, NULL
);
184 fprintf (dump_file
, "\n");
186 if (statistics_dump_file
187 && !(statistics_dump_flags
& TDF_STATS
188 || statistics_dump_flags
& TDF_DETAILS
))
189 htab_traverse_noresize (curr_statistics_hash (),
190 statistics_fini_pass_2
, NULL
);
191 htab_traverse_noresize (curr_statistics_hash (),
192 statistics_fini_pass_3
, NULL
);
195 /* Helper for printing summary information. */
198 statistics_fini_1 (void **slot
, void *data
)
200 struct opt_pass
*pass
= (struct opt_pass
*)data
;
201 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
202 if (counter
->count
== 0)
204 if (counter
->histogram_p
)
205 fprintf (statistics_dump_file
,
206 "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC
"\n",
207 pass
->static_pass_number
,
209 counter
->id
, counter
->val
,
212 fprintf (statistics_dump_file
,
213 "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
214 pass
->static_pass_number
,
221 /* Finish the statistics and dump summary information. */
224 statistics_fini (void)
226 if (!statistics_dump_file
)
229 if (statistics_dump_flags
& TDF_STATS
)
232 for (i
= 0; i
< nr_statistics_hashes
; ++i
)
233 if (statistics_hashes
[i
] != NULL
234 && get_pass_for_id (i
) != NULL
)
235 htab_traverse_noresize (statistics_hashes
[i
],
236 statistics_fini_1
, get_pass_for_id (i
));
239 dump_end (statistics_dump_nr
, statistics_dump_file
);
242 /* Register the statistics dump file. */
245 statistics_early_init (void)
247 statistics_dump_nr
= dump_register (".statistics", "statistics",
248 "statistics", TDF_TREE
, OPTGROUP_NONE
);
251 /* Init the statistics. */
254 statistics_init (void)
256 statistics_dump_file
= dump_begin (statistics_dump_nr
, NULL
);
257 statistics_dump_flags
= get_dump_file_info (statistics_dump_nr
)->pflags
;
260 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
263 static statistics_counter_t
*
264 lookup_or_add_counter (htab_t hash
, const char *id
, int val
,
267 statistics_counter_t
**counter
;
268 statistics_counter_t c
;
271 counter
= (statistics_counter_t
**) htab_find_slot (hash
, &c
, INSERT
);
274 *counter
= XNEW (struct statistics_counter_s
);
275 (*counter
)->id
= xstrdup (id
);
276 (*counter
)->val
= val
;
277 (*counter
)->histogram_p
= histogram_p
;
278 (*counter
)->prev_dumped_count
= 0;
279 (*counter
)->count
= 0;
284 /* Add statistics information about event ID in function FN.
285 This will increment the counter associated with ID by INCR.
286 It will also dump the event to the global statistics file if requested. */
289 statistics_counter_event (struct function
*fn
, const char *id
, int incr
)
291 statistics_counter_t
*counter
;
293 if ((!(dump_flags
& TDF_STATS
)
294 && !statistics_dump_file
)
298 if (current_pass
->static_pass_number
!= -1)
300 counter
= lookup_or_add_counter (curr_statistics_hash (), id
, 0, false);
301 gcc_assert (!counter
->histogram_p
);
302 counter
->count
+= incr
;
305 if (!statistics_dump_file
306 || !(statistics_dump_flags
& TDF_DETAILS
))
309 fprintf (statistics_dump_file
,
310 "%d %s \"%s\" \"%s\" %d\n",
311 current_pass
->static_pass_number
,
318 /* Add statistics information about event ID in function FN with the
320 It will dump the event to the global statistics file if requested. */
323 statistics_histogram_event (struct function
*fn
, const char *id
, int val
)
325 statistics_counter_t
*counter
;
327 if (!(dump_flags
& TDF_STATS
)
328 && !statistics_dump_file
)
331 counter
= lookup_or_add_counter (curr_statistics_hash (), id
, val
, true);
332 gcc_assert (counter
->histogram_p
);
335 if (!statistics_dump_file
336 || !(statistics_dump_flags
& TDF_DETAILS
))
339 fprintf (statistics_dump_file
,
340 "%d %s \"%s == %d\" \"%s\" 1\n",
341 current_pass
->static_pass_number
,