set thumb as as default option for armv7l-gcc because thumb becomes default since...
[platform/upstream/gcc48.git] / gcc / statistics.c
1 /* Optimization statistics functions.
2    Copyright (C) 2008-2013 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 "hashtab.h"
28 #include "function.h"
29
30 static int statistics_dump_nr;
31 static int statistics_dump_flags;
32 static FILE *statistics_dump_file;
33
34 /* Statistics entry.  A integer counter associated to a string ID
35    and value.  */
36
37 typedef struct statistics_counter_s {
38   const char *id;
39   int val;
40   bool histogram_p;
41   unsigned HOST_WIDE_INT count;
42   unsigned HOST_WIDE_INT prev_dumped_count;
43 } statistics_counter_t;
44
45 /* Array of statistic hashes, indexed by pass id.  */
46 static htab_t *statistics_hashes;
47 static unsigned nr_statistics_hashes;
48
49 /* Hash a statistic counter by its string ID.  */
50
51 static hashval_t
52 hash_statistics_hash (const void *p)
53 {
54   const statistics_counter_t *const c = (const statistics_counter_t *)p;
55   return htab_hash_string (c->id) + c->val;
56 }
57
58 /* Compare two statistic counters by their string IDs.  */
59
60 static int
61 hash_statistics_eq (const void *p, const void *q)
62 {
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;
66 }
67
68 /* Free a statistics entry.  */
69
70 static void
71 hash_statistics_free (void *p)
72 {
73   free (CONST_CAST(char *, ((statistics_counter_t *)p)->id));
74   free (p);
75 }
76
77 /* Return the current hashtable to be used for recording or printing
78    statistics.  */
79
80 static htab_t
81 curr_statistics_hash (void)
82 {
83   unsigned idx;
84
85   gcc_assert (current_pass->static_pass_number >= 0);
86   idx = current_pass->static_pass_number;
87
88   if (idx < nr_statistics_hashes
89       && statistics_hashes[idx] != NULL)
90     return statistics_hashes[idx];
91
92   if (idx >= nr_statistics_hashes)
93     {
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;
98     }
99
100   statistics_hashes[idx] = htab_create (15, hash_statistics_hash,
101                                         hash_statistics_eq,
102                                         hash_statistics_free);
103
104   return statistics_hashes[idx];
105 }
106
107 /* Helper for statistics_fini_pass.  Print the counter difference
108    since the last dump for the pass dump files.  */
109
110 static int
111 statistics_fini_pass_1 (void **slot, void *data ATTRIBUTE_UNUSED)
112 {
113   statistics_counter_t *counter = (statistics_counter_t *)*slot;
114   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
115   if (count == 0)
116     return 1;
117   if (counter->histogram_p)
118     fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
119              counter->id, counter->val, count);
120   else
121     fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
122              counter->id, count);
123   counter->prev_dumped_count = counter->count;
124   return 1;
125 }
126
127 /* Helper for statistics_fini_pass.  Print the counter difference
128    since the last dump for the statistics dump.  */
129
130 static int
131 statistics_fini_pass_2 (void **slot, void *data ATTRIBUTE_UNUSED)
132 {
133   statistics_counter_t *counter = (statistics_counter_t *)*slot;
134   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
135   if (count == 0)
136     return 1;
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,
142              current_pass->name,
143              counter->id, counter->val,
144              current_function_name (),
145              count);
146   else
147     fprintf (statistics_dump_file,
148              "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
149              current_pass->static_pass_number,
150              current_pass->name,
151              counter->id,
152              current_function_name (),
153              count);
154   counter->prev_dumped_count = counter->count;
155   return 1;
156 }
157
158 /* Helper for statistics_fini_pass, reset the counters.  */
159
160 static int
161 statistics_fini_pass_3 (void **slot, void *data ATTRIBUTE_UNUSED)
162 {
163   statistics_counter_t *counter = (statistics_counter_t *)*slot;
164   counter->prev_dumped_count = counter->count;
165   return 1;
166 }
167
168 /* Dump the current statistics incrementally.  */
169
170 void
171 statistics_fini_pass (void)
172 {
173   if (current_pass->static_pass_number == -1)
174     return;
175
176   if (dump_file
177       && dump_flags & TDF_STATS)
178     {
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");
185     }
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);
193 }
194
195 /* Helper for printing summary information.  */
196
197 static int
198 statistics_fini_1 (void **slot, void *data)
199 {
200   struct opt_pass *pass = (struct opt_pass *)data;
201   statistics_counter_t *counter = (statistics_counter_t *)*slot;
202   if (counter->count == 0)
203     return 1;
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,
208              pass->name,
209              counter->id, counter->val,
210              counter->count);
211   else
212     fprintf (statistics_dump_file,
213              "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
214              pass->static_pass_number,
215              pass->name,
216              counter->id,
217              counter->count);
218   return 1;
219 }
220
221 /* Finish the statistics and dump summary information.  */
222
223 void
224 statistics_fini (void)
225 {
226   if (!statistics_dump_file)
227     return;
228
229   if (statistics_dump_flags & TDF_STATS)
230     {
231       unsigned i;
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));
237     }
238
239   dump_end (statistics_dump_nr, statistics_dump_file);
240 }
241
242 /* Register the statistics dump file.  */
243
244 void
245 statistics_early_init (void)
246 {
247   statistics_dump_nr = dump_register (".statistics", "statistics",
248                                       "statistics", TDF_TREE, OPTGROUP_NONE);
249 }
250
251 /* Init the statistics.  */
252
253 void
254 statistics_init (void)
255 {
256   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
257   statistics_dump_flags = get_dump_file_info (statistics_dump_nr)->pflags;
258 }
259
260 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
261    and HISTOGRAM_P.  */
262
263 static statistics_counter_t *
264 lookup_or_add_counter (htab_t hash, const char *id, int val,
265                        bool histogram_p)
266 {
267   statistics_counter_t **counter;
268   statistics_counter_t c;
269   c.id = id;
270   c.val = val;
271   counter = (statistics_counter_t **) htab_find_slot (hash, &c, INSERT);
272   if (!*counter)
273     {
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;
280     }
281   return *counter;
282 }
283
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.  */
287
288 void
289 statistics_counter_event (struct function *fn, const char *id, int incr)
290 {
291   statistics_counter_t *counter;
292
293   if ((!(dump_flags & TDF_STATS)
294        && !statistics_dump_file)
295       || incr == 0)
296     return;
297
298   if (current_pass->static_pass_number != -1)
299     {
300       counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
301       gcc_assert (!counter->histogram_p);
302       counter->count += incr;
303     }
304
305   if (!statistics_dump_file
306       || !(statistics_dump_flags & TDF_DETAILS))
307     return;
308
309   fprintf (statistics_dump_file,
310            "%d %s \"%s\" \"%s\" %d\n",
311            current_pass->static_pass_number,
312            current_pass->name,
313            id,
314            function_name (fn),
315            incr);
316 }
317
318 /* Add statistics information about event ID in function FN with the
319    histogram value VAL.
320    It will dump the event to the global statistics file if requested.  */
321
322 void
323 statistics_histogram_event (struct function *fn, const char *id, int val)
324 {
325   statistics_counter_t *counter;
326
327   if (!(dump_flags & TDF_STATS)
328       && !statistics_dump_file)
329     return;
330
331   counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
332   gcc_assert (counter->histogram_p);
333   counter->count += 1;
334
335   if (!statistics_dump_file
336       || !(statistics_dump_flags & TDF_DETAILS))
337     return;
338
339   fprintf (statistics_dump_file,
340            "%d %s \"%s == %d\" \"%s\" 1\n",
341            current_pass->static_pass_number,
342            current_pass->name,
343            id, val,
344            function_name (fn));
345 }