gcc80: Handle TZ specific "%+" format in strftime.
[dragonfly.git] / contrib / gcc-8.0 / gcc / statistics.c
1 /* Optimization statistics functions.
2    Copyright (C) 2008-2018 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 "function.h"
25 #include "tree-pass.h"
26 #include "context.h"
27 #include "pass_manager.h"
28
29 static int statistics_dump_nr;
30 static dump_flags_t statistics_dump_flags;
31 static FILE *statistics_dump_file;
32
33 /* Statistics entry.  A integer counter associated to a string ID
34    and value.  */
35
36 struct statistics_counter {
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;
42 };
43
44 /* Hashtable helpers.  */
45
46 struct stats_counter_hasher : pointer_hash <statistics_counter>
47 {
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 *);
52 };
53
54 /* Hash a statistic counter by its string ID.  */
55
56 inline hashval_t
57 stats_counter_hasher::hash (const statistics_counter *c)
58 {
59   return htab_hash_string (c->id) + c->val;
60 }
61
62 /* Compare two statistic counters by their string IDs.  */
63
64 inline bool
65 stats_counter_hasher::equal (const statistics_counter *c1,
66                              const statistics_counter *c2)
67 {
68   return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
69 }
70
71 /* Free a statistics entry.  */
72
73 inline void
74 stats_counter_hasher::remove (statistics_counter *v)
75 {
76   free (CONST_CAST (char *, v->id));
77   free (v);
78 }
79
80 typedef hash_table<stats_counter_hasher> stats_counter_table_type;
81
82 /* Array of statistic hashes, indexed by pass id.  */
83 static stats_counter_table_type **statistics_hashes;
84 static unsigned nr_statistics_hashes;
85
86 /* Return the current hashtable to be used for recording or printing
87    statistics.  */
88
89 static stats_counter_table_type *
90 curr_statistics_hash (void)
91 {
92   unsigned idx;
93
94   gcc_assert (current_pass->static_pass_number >= 0);
95   idx = current_pass->static_pass_number;
96
97   if (idx < nr_statistics_hashes
98       && statistics_hashes[idx])
99     return statistics_hashes[idx];
100
101   if (idx >= nr_statistics_hashes)
102     {
103       statistics_hashes = XRESIZEVEC (stats_counter_table_type *,
104                                       statistics_hashes, idx+1);
105       memset (statistics_hashes + nr_statistics_hashes, 0,
106               (idx + 1 - nr_statistics_hashes)
107               * sizeof (stats_counter_table_type *));
108       nr_statistics_hashes = idx + 1;
109     }
110
111   statistics_hashes[idx] = new stats_counter_table_type (15);
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
119 int
120 statistics_fini_pass_1 (statistics_counter **slot,
121                         void *data ATTRIBUTE_UNUSED)
122 {
123   statistics_counter *counter = *slot;
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
140 int
141 statistics_fini_pass_2 (statistics_counter **slot,
142                         void *data ATTRIBUTE_UNUSED)
143 {
144   statistics_counter *counter = *slot;
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,
155              current_function_name (),
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,
163              current_function_name (),
164              count);
165   counter->prev_dumped_count = counter->count;
166   return 1;
167 }
168
169 /* Helper for statistics_fini_pass, reset the counters.  */
170
171 int
172 statistics_fini_pass_3 (statistics_counter **slot,
173                         void *data ATTRIBUTE_UNUSED)
174 {
175   statistics_counter *counter = *slot;
176   counter->prev_dumped_count = counter->count;
177   return 1;
178 }
179
180 /* Dump the current statistics incrementally.  */
181
182 void
183 statistics_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");
192       fprintf (dump_file, "Pass statistics of \"%s\": ", current_pass->name);
193       fprintf (dump_file, "----------------\n");
194       curr_statistics_hash ()
195         ->traverse_noresize <void *, statistics_fini_pass_1> (NULL);
196       fprintf (dump_file, "\n");
197     }
198   if (statistics_dump_file
199       && !(statistics_dump_flags & TDF_STATS
200            || statistics_dump_flags & TDF_DETAILS))
201     curr_statistics_hash ()
202       ->traverse_noresize <void *, statistics_fini_pass_2> (NULL);
203   curr_statistics_hash ()
204     ->traverse_noresize <void *, statistics_fini_pass_3> (NULL);
205 }
206
207 /* Helper for printing summary information.  */
208
209 int
210 statistics_fini_1 (statistics_counter **slot, opt_pass *pass)
211 {
212   statistics_counter *counter = *slot;
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
234 void
235 statistics_fini (void)
236 {
237   gcc::pass_manager *passes = g->get_passes ();
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)
245         if (statistics_hashes[i]
246             && passes->get_pass_for_id (i) != NULL)
247           statistics_hashes[i]
248             ->traverse_noresize <opt_pass *, statistics_fini_1>
249             (passes->get_pass_for_id (i));
250     }
251
252   dump_end (statistics_dump_nr, statistics_dump_file);
253 }
254
255 /* Register the statistics dump file.  */
256
257 void
258 statistics_early_init (void)
259 {
260   gcc::dump_manager *dumps = g->get_dumps ();
261   statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
262                                              "statistics", DK_tree,
263                                              OPTGROUP_NONE,
264                                              false);
265 }
266
267 /* Init the statistics.  */
268
269 void
270 statistics_init (void)
271 {
272   gcc::dump_manager *dumps = g->get_dumps ();
273   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
274   statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
275 }
276
277 /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
278    and HISTOGRAM_P.  */
279
280 static statistics_counter *
281 lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
282                        bool histogram_p)
283 {
284   statistics_counter **counter;
285   statistics_counter c;
286   c.id = id;
287   c.val = val;
288   counter = hash->find_slot (&c, INSERT);
289   if (!*counter)
290     {
291       *counter = XNEW (statistics_counter);
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
305 void
306 statistics_counter_event (struct function *fn, const char *id, int incr)
307 {
308   statistics_counter *counter;
309
310   if ((!(dump_flags & TDF_STATS)
311        && !statistics_dump_file)
312       || incr == 0)
313     return;
314
315   if (current_pass
316       && current_pass->static_pass_number != -1)
317     {
318       counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
319       gcc_assert (!counter->histogram_p);
320       counter->count += incr;
321     }
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",
329            current_pass ? current_pass->static_pass_number : -1,
330            current_pass ? current_pass->name : "none",
331            id,
332            function_name (fn),
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
340 void
341 statistics_histogram_event (struct function *fn, const char *id, int val)
342 {
343   statistics_counter *counter;
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,
362            function_name (fn));
363 }