1 /* Optimization statistics functions.
3 Free Software Foundation, Inc.
4 Contributed by Richard Guenther <rguenther@suse.de>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
24 #include "coretypes.h"
25 #include "tree-pass.h"
26 #include "tree-dump.h"
27 #include "statistics.h"
32 static int statistics_dump_nr
;
33 static int statistics_dump_flags
;
34 static FILE *statistics_dump_file
;
36 /* Statistics entry. A integer counter associated to a string ID
39 typedef struct statistics_counter_s
{
43 unsigned HOST_WIDE_INT count
;
44 unsigned HOST_WIDE_INT prev_dumped_count
;
45 } statistics_counter_t
;
47 /* Array of statistic hashes, indexed by pass id. */
48 static htab_t
*statistics_hashes
;
49 static unsigned nr_statistics_hashes
;
51 /* Hash a statistic counter by its string ID. */
54 hash_statistics_hash (const void *p
)
56 const statistics_counter_t
*const c
= (const statistics_counter_t
*)p
;
57 return htab_hash_string (c
->id
) + c
->val
;
60 /* Compare two statistic counters by their string IDs. */
63 hash_statistics_eq (const void *p
, const void *q
)
65 const statistics_counter_t
*const c1
= (const statistics_counter_t
*)p
;
66 const statistics_counter_t
*const c2
= (const statistics_counter_t
*)q
;
67 return c1
->val
== c2
->val
&& strcmp (c1
->id
, c2
->id
) == 0;
70 /* Free a statistics entry. */
73 hash_statistics_free (void *p
)
75 free (CONST_CAST(char *, ((statistics_counter_t
*)p
)->id
));
79 /* Return the current hashtable to be used for recording or printing
83 curr_statistics_hash (void)
87 gcc_assert (current_pass
->static_pass_number
>= 0);
88 idx
= current_pass
->static_pass_number
;
90 if (idx
< nr_statistics_hashes
91 && statistics_hashes
[idx
] != NULL
)
92 return statistics_hashes
[idx
];
94 if (idx
>= nr_statistics_hashes
)
96 statistics_hashes
= XRESIZEVEC (struct htab
*, statistics_hashes
, idx
+1);
97 memset (statistics_hashes
+ nr_statistics_hashes
, 0,
98 (idx
+ 1 - nr_statistics_hashes
) * sizeof (htab_t
));
99 nr_statistics_hashes
= idx
+ 1;
102 statistics_hashes
[idx
] = htab_create (15, hash_statistics_hash
,
104 hash_statistics_free
);
106 return statistics_hashes
[idx
];
109 /* Helper for statistics_fini_pass. Print the counter difference
110 since the last dump for the pass dump files. */
113 statistics_fini_pass_1 (void **slot
, void *data ATTRIBUTE_UNUSED
)
115 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
116 unsigned HOST_WIDE_INT count
= counter
->count
- counter
->prev_dumped_count
;
119 if (counter
->histogram_p
)
120 fprintf (dump_file
, "%s == %d: " HOST_WIDE_INT_PRINT_DEC
"\n",
121 counter
->id
, counter
->val
, count
);
123 fprintf (dump_file
, "%s: " HOST_WIDE_INT_PRINT_DEC
"\n",
125 counter
->prev_dumped_count
= counter
->count
;
129 /* Helper for statistics_fini_pass. Print the counter difference
130 since the last dump for the statistics dump. */
133 statistics_fini_pass_2 (void **slot
, void *data ATTRIBUTE_UNUSED
)
135 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
136 unsigned HOST_WIDE_INT count
= counter
->count
- counter
->prev_dumped_count
;
139 counter
->prev_dumped_count
= counter
->count
;
140 if (counter
->histogram_p
)
141 fprintf (statistics_dump_file
,
142 "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
143 current_pass
->static_pass_number
,
145 counter
->id
, counter
->val
,
146 cfun
? IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)) : "(nofn)",
149 fprintf (statistics_dump_file
,
150 "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
151 current_pass
->static_pass_number
,
154 cfun
? IDENTIFIER_POINTER (DECL_NAME (cfun
->decl
)) : "(nofn)",
156 counter
->prev_dumped_count
= counter
->count
;
160 /* Helper for statistics_fini_pass, reset the counters. */
163 statistics_fini_pass_3 (void **slot
, void *data ATTRIBUTE_UNUSED
)
165 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
166 counter
->prev_dumped_count
= counter
->count
;
170 /* Dump the current statistics incrementally. */
173 statistics_fini_pass (void)
175 if (current_pass
->static_pass_number
== -1)
179 && dump_flags
& TDF_STATS
)
181 fprintf (dump_file
, "\n");
182 fprintf (dump_file
, "Pass statistics:\n");
183 fprintf (dump_file
, "----------------\n");
184 htab_traverse_noresize (curr_statistics_hash (),
185 statistics_fini_pass_1
, NULL
);
186 fprintf (dump_file
, "\n");
188 if (statistics_dump_file
189 && !(statistics_dump_flags
& TDF_STATS
190 || statistics_dump_flags
& TDF_DETAILS
))
191 htab_traverse_noresize (curr_statistics_hash (),
192 statistics_fini_pass_2
, NULL
);
193 htab_traverse_noresize (curr_statistics_hash (),
194 statistics_fini_pass_3
, NULL
);
197 /* Helper for printing summary information. */
200 statistics_fini_1 (void **slot
, void *data
)
202 struct opt_pass
*pass
= (struct opt_pass
*)data
;
203 statistics_counter_t
*counter
= (statistics_counter_t
*)*slot
;
204 if (counter
->count
== 0)
206 if (counter
->histogram_p
)
207 fprintf (statistics_dump_file
,
208 "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC
"\n",
209 pass
->static_pass_number
,
211 counter
->id
, counter
->val
,
214 fprintf (statistics_dump_file
,
215 "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC
"\n",
216 pass
->static_pass_number
,
223 /* Finish the statistics and dump summary information. */
226 statistics_fini (void)
228 if (!statistics_dump_file
)
231 if (statistics_dump_flags
& TDF_STATS
)
234 for (i
= 0; i
< nr_statistics_hashes
; ++i
)
235 if (statistics_hashes
[i
] != NULL
236 && get_pass_for_id (i
) != NULL
)
237 htab_traverse_noresize (statistics_hashes
[i
],
238 statistics_fini_1
, get_pass_for_id (i
));
241 dump_end (statistics_dump_nr
, statistics_dump_file
);
244 /* Register the statistics dump file. */
247 statistics_early_init (void)
249 statistics_dump_nr
= dump_register (".statistics", "statistics",
250 "statistics", TDF_TREE
);
253 /* Init the statistics. */
256 statistics_init (void)
258 statistics_dump_file
= dump_begin (statistics_dump_nr
, NULL
);
259 statistics_dump_flags
= get_dump_file_info (statistics_dump_nr
)->flags
;
262 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
265 static statistics_counter_t
*
266 lookup_or_add_counter (htab_t hash
, const char *id
, int val
,
269 statistics_counter_t
**counter
;
270 statistics_counter_t c
;
273 counter
= (statistics_counter_t
**) htab_find_slot (hash
, &c
, INSERT
);
276 *counter
= XNEW (struct statistics_counter_s
);
277 (*counter
)->id
= xstrdup (id
);
278 (*counter
)->val
= val
;
279 (*counter
)->histogram_p
= histogram_p
;
280 (*counter
)->prev_dumped_count
= 0;
281 (*counter
)->count
= 0;
286 /* Add statistics information about event ID in function FN.
287 This will increment the counter associated with ID by INCR.
288 It will also dump the event to the global statistics file if requested. */
291 statistics_counter_event (struct function
*fn
, const char *id
, int incr
)
293 statistics_counter_t
*counter
;
295 if ((!(dump_flags
& TDF_STATS
)
296 && !statistics_dump_file
)
300 if (current_pass
->static_pass_number
!= -1)
302 counter
= lookup_or_add_counter (curr_statistics_hash (), id
, 0, false);
303 gcc_assert (!counter
->histogram_p
);
304 counter
->count
+= incr
;
307 if (!statistics_dump_file
308 || !(statistics_dump_flags
& TDF_DETAILS
))
311 fprintf (statistics_dump_file
,
312 "%d %s \"%s\" \"%s\" %d\n",
313 current_pass
->static_pass_number
,
316 fn
? IDENTIFIER_POINTER (DECL_NAME (fn
->decl
)) : "(nofn)",
320 /* Add statistics information about event ID in function FN with the
322 It will dump the event to the global statistics file if requested. */
325 statistics_histogram_event (struct function
*fn
, const char *id
, int val
)
327 statistics_counter_t
*counter
;
329 if (!(dump_flags
& TDF_STATS
)
330 && !statistics_dump_file
)
333 counter
= lookup_or_add_counter (curr_statistics_hash (), id
, val
, true);
334 gcc_assert (counter
->histogram_p
);
337 if (!statistics_dump_file
338 || !(statistics_dump_flags
& TDF_DETAILS
))
341 fprintf (statistics_dump_file
,
342 "%d %s \"%s == %d\" \"%s\" 1\n",
343 current_pass
->static_pass_number
,
346 fn
? IDENTIFIER_POINTER (DECL_NAME (fn
->decl
)) : "(nofn)");