timevar.cc revision 1.1.1.1 1 1.1 mrg /* Timing variables for measuring compiler performance.
2 1.1 mrg Copyright (C) 2000-2022 Free Software Foundation, Inc.
3 1.1 mrg Contributed by Alex Samuel <samuel (at) codesourcery.com>
4 1.1 mrg
5 1.1 mrg This file is part of GCC.
6 1.1 mrg
7 1.1 mrg GCC is free software; you can redistribute it and/or modify it under
8 1.1 mrg the terms of the GNU General Public License as published by the Free
9 1.1 mrg Software Foundation; either version 3, or (at your option) any later
10 1.1 mrg version.
11 1.1 mrg
12 1.1 mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 1.1 mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 1.1 mrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 1.1 mrg for more details.
16 1.1 mrg
17 1.1 mrg You should have received a copy of the GNU General Public License
18 1.1 mrg along with GCC; see the file COPYING3. If not see
19 1.1 mrg <http://www.gnu.org/licenses/>. */
20 1.1 mrg
21 1.1 mrg #include "config.h"
22 1.1 mrg #include "system.h"
23 1.1 mrg #include "coretypes.h"
24 1.1 mrg #include "timevar.h"
25 1.1 mrg #include "options.h"
26 1.1 mrg
27 1.1 mrg #ifndef HAVE_CLOCK_T
28 1.1 mrg typedef int clock_t;
29 1.1 mrg #endif
30 1.1 mrg
31 1.1 mrg #ifndef HAVE_STRUCT_TMS
32 1.1 mrg struct tms
33 1.1 mrg {
34 1.1 mrg clock_t tms_utime;
35 1.1 mrg clock_t tms_stime;
36 1.1 mrg clock_t tms_cutime;
37 1.1 mrg clock_t tms_cstime;
38 1.1 mrg };
39 1.1 mrg #endif
40 1.1 mrg
41 1.1 mrg #ifndef RUSAGE_SELF
42 1.1 mrg # define RUSAGE_SELF 0
43 1.1 mrg #endif
44 1.1 mrg
45 1.1 mrg /* Calculation of scale factor to convert ticks to microseconds.
46 1.1 mrg We mustn't use CLOCKS_PER_SEC except with clock(). */
47 1.1 mrg #if HAVE_SYSCONF && defined _SC_CLK_TCK
48 1.1 mrg # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
49 1.1 mrg #else
50 1.1 mrg # ifdef CLK_TCK
51 1.1 mrg # define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
52 1.1 mrg # else
53 1.1 mrg # ifdef HZ
54 1.1 mrg # define TICKS_PER_SECOND HZ /* traditional UNIX */
55 1.1 mrg # else
56 1.1 mrg # define TICKS_PER_SECOND 100 /* often the correct value */
57 1.1 mrg # endif
58 1.1 mrg # endif
59 1.1 mrg #endif
60 1.1 mrg
61 1.1 mrg /* Prefer times to getrusage to clock (each gives successively less
62 1.1 mrg information). */
63 1.1 mrg #ifdef HAVE_TIMES
64 1.1 mrg # if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
65 1.1 mrg extern clock_t times (struct tms *);
66 1.1 mrg # endif
67 1.1 mrg # define USE_TIMES
68 1.1 mrg # define HAVE_USER_TIME
69 1.1 mrg # define HAVE_SYS_TIME
70 1.1 mrg # define HAVE_WALL_TIME
71 1.1 mrg #else
72 1.1 mrg #ifdef HAVE_GETRUSAGE
73 1.1 mrg # if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
74 1.1 mrg extern int getrusage (int, struct rusage *);
75 1.1 mrg # endif
76 1.1 mrg # define USE_GETRUSAGE
77 1.1 mrg # define HAVE_USER_TIME
78 1.1 mrg # define HAVE_SYS_TIME
79 1.1 mrg #else
80 1.1 mrg #ifdef HAVE_CLOCK
81 1.1 mrg # if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
82 1.1 mrg extern clock_t clock (void);
83 1.1 mrg # endif
84 1.1 mrg # define USE_CLOCK
85 1.1 mrg # define HAVE_USER_TIME
86 1.1 mrg #endif
87 1.1 mrg #endif
88 1.1 mrg #endif
89 1.1 mrg
90 1.1 mrg /* libc is very likely to have snuck a call to sysconf() into one of
91 1.1 mrg the underlying constants, and that can be very slow, so we have to
92 1.1 mrg precompute them. Whose wonderful idea was it to make all those
93 1.1 mrg _constants_ variable at run time, anyway? */
94 1.1 mrg #ifdef USE_TIMES
95 1.1 mrg static double ticks_to_msec;
96 1.1 mrg #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
97 1.1 mrg #endif
98 1.1 mrg
99 1.1 mrg #ifdef USE_CLOCK
100 1.1 mrg static double clocks_to_msec;
101 1.1 mrg #define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
102 1.1 mrg #endif
103 1.1 mrg
104 1.1 mrg /* Non-NULL if timevars should be used. In GCC, this happens with
105 1.1 mrg the -ftime-report flag. */
106 1.1 mrg
107 1.1 mrg timer *g_timer;
108 1.1 mrg
109 1.1 mrg /* Total amount of memory allocated by garbage collector. */
110 1.1 mrg
111 1.1 mrg size_t timevar_ggc_mem_total;
112 1.1 mrg
113 1.1 mrg /* The amount of memory that will cause us to report the timevar even
114 1.1 mrg if the time spent is not significant. */
115 1.1 mrg
116 1.1 mrg #define GGC_MEM_BOUND (1 << 20)
117 1.1 mrg
118 1.1 mrg /* See timevar.h for an explanation of timing variables. */
119 1.1 mrg
120 1.1 mrg static void get_time (struct timevar_time_def *);
121 1.1 mrg static void timevar_accumulate (struct timevar_time_def *,
122 1.1 mrg struct timevar_time_def *,
123 1.1 mrg struct timevar_time_def *);
124 1.1 mrg
125 1.1 mrg /* The implementation of timing events for jit client code, allowing
126 1.1 mrg arbitrary named items to appear on the timing stack. */
127 1.1 mrg
128 1.1 mrg class timer::named_items
129 1.1 mrg {
130 1.1 mrg public:
131 1.1 mrg named_items (timer *t);
132 1.1 mrg ~named_items ();
133 1.1 mrg
134 1.1 mrg void push (const char *item_name);
135 1.1 mrg void pop ();
136 1.1 mrg void print (FILE *fp, const timevar_time_def *total);
137 1.1 mrg
138 1.1 mrg private:
139 1.1 mrg /* Which timer instance does this relate to? */
140 1.1 mrg timer *m_timer;
141 1.1 mrg
142 1.1 mrg /* Dictionary, mapping from item names to timevar_def.
143 1.1 mrg Note that currently we merely store/compare the raw string
144 1.1 mrg pointers provided by client code; we don't take a copy,
145 1.1 mrg or use strcmp. */
146 1.1 mrg hash_map <const char *, timer::timevar_def> m_hash_map;
147 1.1 mrg
148 1.1 mrg /* The order in which items were originally inserted. */
149 1.1 mrg auto_vec <const char *> m_names;
150 1.1 mrg };
151 1.1 mrg
152 1.1 mrg /* The constructor for class timer::named_items. */
153 1.1 mrg
154 1.1 mrg timer::named_items::named_items (timer *t)
155 1.1 mrg : m_timer (t),
156 1.1 mrg m_hash_map (),
157 1.1 mrg m_names ()
158 1.1 mrg {
159 1.1 mrg }
160 1.1 mrg
161 1.1 mrg /* The destructor for class timer::named_items. */
162 1.1 mrg
163 1.1 mrg timer::named_items::~named_items ()
164 1.1 mrg {
165 1.1 mrg }
166 1.1 mrg
167 1.1 mrg /* Push the named item onto the timer stack. */
168 1.1 mrg
169 1.1 mrg void
170 1.1 mrg timer::named_items::push (const char *item_name)
171 1.1 mrg {
172 1.1 mrg gcc_assert (item_name);
173 1.1 mrg
174 1.1 mrg bool existed;
175 1.1 mrg timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
176 1.1 mrg if (!existed)
177 1.1 mrg {
178 1.1 mrg def->elapsed.user = 0;
179 1.1 mrg def->elapsed.sys = 0;
180 1.1 mrg def->elapsed.wall = 0;
181 1.1 mrg def->name = item_name;
182 1.1 mrg def->standalone = 0;
183 1.1 mrg m_names.safe_push (item_name);
184 1.1 mrg }
185 1.1 mrg m_timer->push_internal (def);
186 1.1 mrg }
187 1.1 mrg
188 1.1 mrg /* Pop the top item from the timer stack. */
189 1.1 mrg
190 1.1 mrg void
191 1.1 mrg timer::named_items::pop ()
192 1.1 mrg {
193 1.1 mrg m_timer->pop_internal ();
194 1.1 mrg }
195 1.1 mrg
196 1.1 mrg /* Print the given client item. Helper function for timer::print. */
197 1.1 mrg
198 1.1 mrg void
199 1.1 mrg timer::named_items::print (FILE *fp, const timevar_time_def *total)
200 1.1 mrg {
201 1.1 mrg fprintf (fp, "Client items:\n");
202 1.1 mrg for (const char *item_name : m_names)
203 1.1 mrg {
204 1.1 mrg timer::timevar_def *def = m_hash_map.get (item_name);
205 1.1 mrg gcc_assert (def);
206 1.1 mrg m_timer->print_row (fp, total, def->name, def->elapsed);
207 1.1 mrg }
208 1.1 mrg }
209 1.1 mrg
210 1.1 mrg /* Fill the current times into TIME. The definition of this function
211 1.1 mrg also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
212 1.1 mrg HAVE_WALL_TIME macros. */
213 1.1 mrg
214 1.1 mrg static void
215 1.1 mrg get_time (struct timevar_time_def *now)
216 1.1 mrg {
217 1.1 mrg now->user = 0;
218 1.1 mrg now->sys = 0;
219 1.1 mrg now->wall = 0;
220 1.1 mrg now->ggc_mem = timevar_ggc_mem_total;
221 1.1 mrg
222 1.1 mrg {
223 1.1 mrg #ifdef USE_TIMES
224 1.1 mrg struct tms tms;
225 1.1 mrg now->wall = times (&tms) * ticks_to_msec;
226 1.1 mrg now->user = tms.tms_utime * ticks_to_msec;
227 1.1 mrg now->sys = tms.tms_stime * ticks_to_msec;
228 1.1 mrg #endif
229 1.1 mrg #ifdef USE_GETRUSAGE
230 1.1 mrg struct rusage rusage;
231 1.1 mrg getrusage (RUSAGE_SELF, &rusage);
232 1.1 mrg now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
233 1.1 mrg now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
234 1.1 mrg #endif
235 1.1 mrg #ifdef USE_CLOCK
236 1.1 mrg now->user = clock () * clocks_to_msec;
237 1.1 mrg #endif
238 1.1 mrg }
239 1.1 mrg }
240 1.1 mrg
241 1.1 mrg /* Add the difference between STOP_TIME and START_TIME to TIMER. */
242 1.1 mrg
243 1.1 mrg static void
244 1.1 mrg timevar_accumulate (struct timevar_time_def *timer,
245 1.1 mrg struct timevar_time_def *start_time,
246 1.1 mrg struct timevar_time_def *stop_time)
247 1.1 mrg {
248 1.1 mrg timer->user += stop_time->user - start_time->user;
249 1.1 mrg timer->sys += stop_time->sys - start_time->sys;
250 1.1 mrg timer->wall += stop_time->wall - start_time->wall;
251 1.1 mrg timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
252 1.1 mrg }
253 1.1 mrg
254 1.1 mrg /* Class timer's constructor. */
255 1.1 mrg
256 1.1 mrg timer::timer () :
257 1.1 mrg m_stack (NULL),
258 1.1 mrg m_unused_stack_instances (NULL),
259 1.1 mrg m_start_time (),
260 1.1 mrg m_jit_client_items (NULL)
261 1.1 mrg {
262 1.1 mrg /* Zero all elapsed times. */
263 1.1 mrg memset (m_timevars, 0, sizeof (m_timevars));
264 1.1 mrg
265 1.1 mrg /* Initialize the names of timing variables. */
266 1.1 mrg #define DEFTIMEVAR(identifier__, name__) \
267 1.1 mrg m_timevars[identifier__].name = name__;
268 1.1 mrg #include "timevar.def"
269 1.1 mrg #undef DEFTIMEVAR
270 1.1 mrg
271 1.1 mrg /* Initialize configuration-specific state.
272 1.1 mrg Ideally this would be one-time initialization. */
273 1.1 mrg #ifdef USE_TIMES
274 1.1 mrg ticks_to_msec = TICKS_TO_MSEC;
275 1.1 mrg #endif
276 1.1 mrg #ifdef USE_CLOCK
277 1.1 mrg clocks_to_msec = CLOCKS_TO_MSEC;
278 1.1 mrg #endif
279 1.1 mrg }
280 1.1 mrg
281 1.1 mrg /* Class timer's destructor. */
282 1.1 mrg
283 1.1 mrg timer::~timer ()
284 1.1 mrg {
285 1.1 mrg timevar_stack_def *iter, *next;
286 1.1 mrg
287 1.1 mrg for (iter = m_stack; iter; iter = next)
288 1.1 mrg {
289 1.1 mrg next = iter->next;
290 1.1 mrg free (iter);
291 1.1 mrg }
292 1.1 mrg for (iter = m_unused_stack_instances; iter; iter = next)
293 1.1 mrg {
294 1.1 mrg next = iter->next;
295 1.1 mrg free (iter);
296 1.1 mrg }
297 1.1 mrg for (unsigned i = 0; i < TIMEVAR_LAST; ++i)
298 1.1 mrg delete m_timevars[i].children;
299 1.1 mrg
300 1.1 mrg delete m_jit_client_items;
301 1.1 mrg }
302 1.1 mrg
303 1.1 mrg /* Initialize timing variables. */
304 1.1 mrg
305 1.1 mrg void
306 1.1 mrg timevar_init (void)
307 1.1 mrg {
308 1.1 mrg if (g_timer)
309 1.1 mrg return;
310 1.1 mrg
311 1.1 mrg g_timer = new timer ();
312 1.1 mrg }
313 1.1 mrg
314 1.1 mrg /* Push TIMEVAR onto the timing stack. No further elapsed time is
315 1.1 mrg attributed to the previous topmost timing variable on the stack;
316 1.1 mrg subsequent elapsed time is attributed to TIMEVAR, until it is
317 1.1 mrg popped or another element is pushed on top.
318 1.1 mrg
319 1.1 mrg TIMEVAR cannot be running as a standalone timer. */
320 1.1 mrg
321 1.1 mrg void
322 1.1 mrg timer::push (timevar_id_t timevar)
323 1.1 mrg {
324 1.1 mrg struct timevar_def *tv = &m_timevars[timevar];
325 1.1 mrg push_internal (tv);
326 1.1 mrg }
327 1.1 mrg
328 1.1 mrg /* Push TV onto the timing stack, either one of the builtin ones
329 1.1 mrg for a timevar_id_t, or one provided by client code to libgccjit. */
330 1.1 mrg
331 1.1 mrg void
332 1.1 mrg timer::push_internal (struct timevar_def *tv)
333 1.1 mrg {
334 1.1 mrg struct timevar_stack_def *context;
335 1.1 mrg struct timevar_time_def now;
336 1.1 mrg
337 1.1 mrg gcc_assert (tv);
338 1.1 mrg
339 1.1 mrg /* Mark this timing variable as used. */
340 1.1 mrg tv->used = 1;
341 1.1 mrg
342 1.1 mrg /* Can't push a standalone timer. */
343 1.1 mrg gcc_assert (!tv->standalone);
344 1.1 mrg
345 1.1 mrg /* What time is it? */
346 1.1 mrg get_time (&now);
347 1.1 mrg
348 1.1 mrg /* If the stack isn't empty, attribute the current elapsed time to
349 1.1 mrg the old topmost element. */
350 1.1 mrg if (m_stack)
351 1.1 mrg timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
352 1.1 mrg
353 1.1 mrg /* Reset the start time; from now on, time is attributed to
354 1.1 mrg TIMEVAR. */
355 1.1 mrg m_start_time = now;
356 1.1 mrg
357 1.1 mrg /* See if we have a previously-allocated stack instance. If so,
358 1.1 mrg take it off the list. If not, malloc a new one. */
359 1.1 mrg if (m_unused_stack_instances != NULL)
360 1.1 mrg {
361 1.1 mrg context = m_unused_stack_instances;
362 1.1 mrg m_unused_stack_instances = m_unused_stack_instances->next;
363 1.1 mrg }
364 1.1 mrg else
365 1.1 mrg context = XNEW (struct timevar_stack_def);
366 1.1 mrg
367 1.1 mrg /* Fill it in and put it on the stack. */
368 1.1 mrg context->timevar = tv;
369 1.1 mrg context->next = m_stack;
370 1.1 mrg m_stack = context;
371 1.1 mrg }
372 1.1 mrg
373 1.1 mrg /* Pop the topmost timing variable element off the timing stack. The
374 1.1 mrg popped variable must be TIMEVAR. Elapsed time since the that
375 1.1 mrg element was pushed on, or since it was last exposed on top of the
376 1.1 mrg stack when the element above it was popped off, is credited to that
377 1.1 mrg timing variable. */
378 1.1 mrg
379 1.1 mrg void
380 1.1 mrg timer::pop (timevar_id_t timevar)
381 1.1 mrg {
382 1.1 mrg gcc_assert (&m_timevars[timevar] == m_stack->timevar);
383 1.1 mrg
384 1.1 mrg pop_internal ();
385 1.1 mrg }
386 1.1 mrg
387 1.1 mrg /* Pop the topmost item from the stack, either one of the builtin ones
388 1.1 mrg for a timevar_id_t, or one provided by client code to libgccjit. */
389 1.1 mrg
390 1.1 mrg void
391 1.1 mrg timer::pop_internal ()
392 1.1 mrg {
393 1.1 mrg struct timevar_time_def now;
394 1.1 mrg struct timevar_stack_def *popped = m_stack;
395 1.1 mrg
396 1.1 mrg /* What time is it? */
397 1.1 mrg get_time (&now);
398 1.1 mrg
399 1.1 mrg /* Attribute the elapsed time to the element we're popping. */
400 1.1 mrg timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now);
401 1.1 mrg
402 1.1 mrg /* Take the item off the stack. */
403 1.1 mrg m_stack = m_stack->next;
404 1.1 mrg
405 1.1 mrg /* Record the elapsed sub-time to the parent as well. */
406 1.1 mrg if (m_stack && time_report_details)
407 1.1 mrg {
408 1.1 mrg if (! m_stack->timevar->children)
409 1.1 mrg m_stack->timevar->children = new child_map_t (5);
410 1.1 mrg bool existed_p;
411 1.1 mrg timevar_time_def &time
412 1.1 mrg = m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p);
413 1.1 mrg if (! existed_p)
414 1.1 mrg memset (&time, 0, sizeof (timevar_time_def));
415 1.1 mrg timevar_accumulate (&time, &m_start_time, &now);
416 1.1 mrg }
417 1.1 mrg
418 1.1 mrg /* Reset the start time; from now on, time is attributed to the
419 1.1 mrg element just exposed on the stack. */
420 1.1 mrg m_start_time = now;
421 1.1 mrg
422 1.1 mrg /* Don't delete the stack element; instead, add it to the list of
423 1.1 mrg unused elements for later use. */
424 1.1 mrg popped->next = m_unused_stack_instances;
425 1.1 mrg m_unused_stack_instances = popped;
426 1.1 mrg }
427 1.1 mrg
428 1.1 mrg /* Start timing TIMEVAR independently of the timing stack. Elapsed
429 1.1 mrg time until timevar_stop is called for the same timing variable is
430 1.1 mrg attributed to TIMEVAR. */
431 1.1 mrg
432 1.1 mrg void
433 1.1 mrg timevar_start (timevar_id_t timevar)
434 1.1 mrg {
435 1.1 mrg if (!g_timer)
436 1.1 mrg return;
437 1.1 mrg
438 1.1 mrg g_timer->start (timevar);
439 1.1 mrg }
440 1.1 mrg
441 1.1 mrg /* See timevar_start above. */
442 1.1 mrg
443 1.1 mrg void
444 1.1 mrg timer::start (timevar_id_t timevar)
445 1.1 mrg {
446 1.1 mrg struct timevar_def *tv = &m_timevars[timevar];
447 1.1 mrg
448 1.1 mrg /* Mark this timing variable as used. */
449 1.1 mrg tv->used = 1;
450 1.1 mrg
451 1.1 mrg /* Don't allow the same timing variable to be started more than
452 1.1 mrg once. */
453 1.1 mrg gcc_assert (!tv->standalone);
454 1.1 mrg tv->standalone = 1;
455 1.1 mrg
456 1.1 mrg get_time (&tv->start_time);
457 1.1 mrg }
458 1.1 mrg
459 1.1 mrg /* Stop timing TIMEVAR. Time elapsed since timevar_start was called
460 1.1 mrg is attributed to it. */
461 1.1 mrg
462 1.1 mrg void
463 1.1 mrg timevar_stop (timevar_id_t timevar)
464 1.1 mrg {
465 1.1 mrg if (!g_timer)
466 1.1 mrg return;
467 1.1 mrg
468 1.1 mrg g_timer->stop (timevar);
469 1.1 mrg }
470 1.1 mrg
471 1.1 mrg /* See timevar_stop above. */
472 1.1 mrg
473 1.1 mrg void
474 1.1 mrg timer::stop (timevar_id_t timevar)
475 1.1 mrg {
476 1.1 mrg struct timevar_def *tv = &m_timevars[timevar];
477 1.1 mrg struct timevar_time_def now;
478 1.1 mrg
479 1.1 mrg /* TIMEVAR must have been started via timevar_start. */
480 1.1 mrg gcc_assert (tv->standalone);
481 1.1 mrg tv->standalone = 0; /* Enable a restart. */
482 1.1 mrg
483 1.1 mrg get_time (&now);
484 1.1 mrg timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
485 1.1 mrg }
486 1.1 mrg
487 1.1 mrg
488 1.1 mrg /* Conditionally start timing TIMEVAR independently of the timing stack.
489 1.1 mrg If the timer is already running, leave it running and return true.
490 1.1 mrg Otherwise, start the timer and return false.
491 1.1 mrg Elapsed time until the corresponding timevar_cond_stop
492 1.1 mrg is called for the same timing variable is attributed to TIMEVAR. */
493 1.1 mrg
494 1.1 mrg bool
495 1.1 mrg timevar_cond_start (timevar_id_t timevar)
496 1.1 mrg {
497 1.1 mrg if (!g_timer)
498 1.1 mrg return false;
499 1.1 mrg
500 1.1 mrg return g_timer->cond_start (timevar);
501 1.1 mrg }
502 1.1 mrg
503 1.1 mrg /* See timevar_cond_start above. */
504 1.1 mrg
505 1.1 mrg bool
506 1.1 mrg timer::cond_start (timevar_id_t timevar)
507 1.1 mrg {
508 1.1 mrg struct timevar_def *tv = &m_timevars[timevar];
509 1.1 mrg
510 1.1 mrg /* Mark this timing variable as used. */
511 1.1 mrg tv->used = 1;
512 1.1 mrg
513 1.1 mrg if (tv->standalone)
514 1.1 mrg return true; /* The timevar is already running. */
515 1.1 mrg
516 1.1 mrg /* Don't allow the same timing variable
517 1.1 mrg to be unconditionally started more than once. */
518 1.1 mrg tv->standalone = 1;
519 1.1 mrg
520 1.1 mrg get_time (&tv->start_time);
521 1.1 mrg return false; /* The timevar was not already running. */
522 1.1 mrg }
523 1.1 mrg
524 1.1 mrg /* Conditionally stop timing TIMEVAR. The RUNNING parameter must come
525 1.1 mrg from the return value of a dynamically matching timevar_cond_start.
526 1.1 mrg If the timer had already been RUNNING, do nothing. Otherwise, time
527 1.1 mrg elapsed since timevar_cond_start was called is attributed to it. */
528 1.1 mrg
529 1.1 mrg void
530 1.1 mrg timevar_cond_stop (timevar_id_t timevar, bool running)
531 1.1 mrg {
532 1.1 mrg if (!g_timer || running)
533 1.1 mrg return;
534 1.1 mrg
535 1.1 mrg g_timer->cond_stop (timevar);
536 1.1 mrg }
537 1.1 mrg
538 1.1 mrg /* See timevar_cond_stop above. */
539 1.1 mrg
540 1.1 mrg void
541 1.1 mrg timer::cond_stop (timevar_id_t timevar)
542 1.1 mrg {
543 1.1 mrg struct timevar_def *tv;
544 1.1 mrg struct timevar_time_def now;
545 1.1 mrg
546 1.1 mrg tv = &m_timevars[timevar];
547 1.1 mrg
548 1.1 mrg /* TIMEVAR must have been started via timevar_cond_start. */
549 1.1 mrg gcc_assert (tv->standalone);
550 1.1 mrg tv->standalone = 0; /* Enable a restart. */
551 1.1 mrg
552 1.1 mrg get_time (&now);
553 1.1 mrg timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
554 1.1 mrg }
555 1.1 mrg
556 1.1 mrg /* Push the named item onto the timing stack. */
557 1.1 mrg
558 1.1 mrg void
559 1.1 mrg timer::push_client_item (const char *item_name)
560 1.1 mrg {
561 1.1 mrg gcc_assert (item_name);
562 1.1 mrg
563 1.1 mrg /* Lazily create the named_items instance. */
564 1.1 mrg if (!m_jit_client_items)
565 1.1 mrg m_jit_client_items = new named_items (this);
566 1.1 mrg
567 1.1 mrg m_jit_client_items->push (item_name);
568 1.1 mrg }
569 1.1 mrg
570 1.1 mrg /* Pop the top-most client item from the timing stack. */
571 1.1 mrg
572 1.1 mrg void
573 1.1 mrg timer::pop_client_item ()
574 1.1 mrg {
575 1.1 mrg gcc_assert (m_jit_client_items);
576 1.1 mrg m_jit_client_items->pop ();
577 1.1 mrg }
578 1.1 mrg
579 1.1 mrg /* Validate that phase times are consistent. */
580 1.1 mrg
581 1.1 mrg void
582 1.1 mrg timer::validate_phases (FILE *fp) const
583 1.1 mrg {
584 1.1 mrg unsigned int /* timevar_id_t */ id;
585 1.1 mrg const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
586 1.1 mrg double phase_user = 0.0;
587 1.1 mrg double phase_sys = 0.0;
588 1.1 mrg double phase_wall = 0.0;
589 1.1 mrg size_t phase_ggc_mem = 0;
590 1.1 mrg static char phase_prefix[] = "phase ";
591 1.1 mrg const double tolerance = 1.000001; /* One part in a million. */
592 1.1 mrg
593 1.1 mrg for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
594 1.1 mrg {
595 1.1 mrg const timevar_def *tv = &m_timevars[(timevar_id_t) id];
596 1.1 mrg
597 1.1 mrg /* Don't evaluate timing variables that were never used. */
598 1.1 mrg if (!tv->used)
599 1.1 mrg continue;
600 1.1 mrg
601 1.1 mrg if (startswith (tv->name, phase_prefix))
602 1.1 mrg {
603 1.1 mrg phase_user += tv->elapsed.user;
604 1.1 mrg phase_sys += tv->elapsed.sys;
605 1.1 mrg phase_wall += tv->elapsed.wall;
606 1.1 mrg phase_ggc_mem += tv->elapsed.ggc_mem;
607 1.1 mrg }
608 1.1 mrg }
609 1.1 mrg
610 1.1 mrg if (phase_user > total->user * tolerance
611 1.1 mrg || phase_sys > total->sys * tolerance
612 1.1 mrg || phase_wall > total->wall * tolerance
613 1.1 mrg || phase_ggc_mem > total->ggc_mem * tolerance)
614 1.1 mrg {
615 1.1 mrg
616 1.1 mrg fprintf (fp, "Timing error: total of phase timers exceeds total time.\n");
617 1.1 mrg if (phase_user > total->user)
618 1.1 mrg fprintf (fp, "user %24.18e > %24.18e\n", phase_user, total->user);
619 1.1 mrg if (phase_sys > total->sys)
620 1.1 mrg fprintf (fp, "sys %24.18e > %24.18e\n", phase_sys, total->sys);
621 1.1 mrg if (phase_wall > total->wall)
622 1.1 mrg fprintf (fp, "wall %24.18e > %24.18e\n", phase_wall, total->wall);
623 1.1 mrg if (phase_ggc_mem > total->ggc_mem)
624 1.1 mrg fprintf (fp, "ggc_mem %24lu > %24lu\n", (unsigned long)phase_ggc_mem,
625 1.1 mrg (unsigned long)total->ggc_mem);
626 1.1 mrg gcc_unreachable ();
627 1.1 mrg }
628 1.1 mrg }
629 1.1 mrg
630 1.1 mrg /* Helper function for timer::print. */
631 1.1 mrg
632 1.1 mrg void
633 1.1 mrg timer::print_row (FILE *fp,
634 1.1 mrg const timevar_time_def *total,
635 1.1 mrg const char *name, const timevar_time_def &elapsed)
636 1.1 mrg {
637 1.1 mrg /* The timing variable name. */
638 1.1 mrg fprintf (fp, " %-35s:", name);
639 1.1 mrg
640 1.1 mrg #ifdef HAVE_USER_TIME
641 1.1 mrg /* Print user-mode time for this process. */
642 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)",
643 1.1 mrg elapsed.user,
644 1.1 mrg (total->user == 0 ? 0 : elapsed.user / total->user) * 100);
645 1.1 mrg #endif /* HAVE_USER_TIME */
646 1.1 mrg
647 1.1 mrg #ifdef HAVE_SYS_TIME
648 1.1 mrg /* Print system-mode time for this process. */
649 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)",
650 1.1 mrg elapsed.sys,
651 1.1 mrg (total->sys == 0 ? 0 : elapsed.sys / total->sys) * 100);
652 1.1 mrg #endif /* HAVE_SYS_TIME */
653 1.1 mrg
654 1.1 mrg #ifdef HAVE_WALL_TIME
655 1.1 mrg /* Print wall clock time elapsed. */
656 1.1 mrg fprintf (fp, "%7.2f (%3.0f%%)",
657 1.1 mrg elapsed.wall,
658 1.1 mrg (total->wall == 0 ? 0 : elapsed.wall / total->wall) * 100);
659 1.1 mrg #endif /* HAVE_WALL_TIME */
660 1.1 mrg
661 1.1 mrg /* Print the amount of ggc memory allocated. */
662 1.1 mrg fprintf (fp, PRsa (6) " (%3.0f%%)",
663 1.1 mrg SIZE_AMOUNT (elapsed.ggc_mem),
664 1.1 mrg (total->ggc_mem == 0
665 1.1 mrg ? 0
666 1.1 mrg : (float) elapsed.ggc_mem / total->ggc_mem) * 100);
667 1.1 mrg
668 1.1 mrg putc ('\n', fp);
669 1.1 mrg }
670 1.1 mrg
671 1.1 mrg /* Return whether ELAPSED is all zero. */
672 1.1 mrg
673 1.1 mrg bool
674 1.1 mrg timer::all_zero (const timevar_time_def &elapsed)
675 1.1 mrg {
676 1.1 mrg const double tiny = 5e-3;
677 1.1 mrg return (elapsed.user < tiny
678 1.1 mrg && elapsed.sys < tiny
679 1.1 mrg && elapsed.wall < tiny
680 1.1 mrg && elapsed.ggc_mem < GGC_MEM_BOUND);
681 1.1 mrg }
682 1.1 mrg
683 1.1 mrg /* Summarize timing variables to FP. The timing variable TV_TOTAL has
684 1.1 mrg a special meaning -- it's considered to be the total elapsed time,
685 1.1 mrg for normalizing the others, and is displayed last. */
686 1.1 mrg
687 1.1 mrg void
688 1.1 mrg timer::print (FILE *fp)
689 1.1 mrg {
690 1.1 mrg /* Only print stuff if we have some sort of time information. */
691 1.1 mrg #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
692 1.1 mrg unsigned int /* timevar_id_t */ id;
693 1.1 mrg const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
694 1.1 mrg struct timevar_time_def now;
695 1.1 mrg
696 1.1 mrg /* Update timing information in case we're calling this from GDB. */
697 1.1 mrg
698 1.1 mrg if (fp == 0)
699 1.1 mrg fp = stderr;
700 1.1 mrg
701 1.1 mrg /* What time is it? */
702 1.1 mrg get_time (&now);
703 1.1 mrg
704 1.1 mrg /* If the stack isn't empty, attribute the current elapsed time to
705 1.1 mrg the old topmost element. */
706 1.1 mrg if (m_stack)
707 1.1 mrg timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
708 1.1 mrg
709 1.1 mrg /* Reset the start time; from now on, time is attributed to
710 1.1 mrg TIMEVAR. */
711 1.1 mrg m_start_time = now;
712 1.1 mrg
713 1.1 mrg fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys",
714 1.1 mrg "wall", "GGC");
715 1.1 mrg if (m_jit_client_items)
716 1.1 mrg fputs ("GCC items:\n", fp);
717 1.1 mrg for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
718 1.1 mrg {
719 1.1 mrg const timevar_def *tv = &m_timevars[(timevar_id_t) id];
720 1.1 mrg
721 1.1 mrg /* Don't print the total execution time here; that goes at the
722 1.1 mrg end. */
723 1.1 mrg if ((timevar_id_t) id == TV_TOTAL)
724 1.1 mrg continue;
725 1.1 mrg
726 1.1 mrg /* Don't print timing variables that were never used. */
727 1.1 mrg if (!tv->used)
728 1.1 mrg continue;
729 1.1 mrg
730 1.1 mrg bool any_children_with_time = false;
731 1.1 mrg if (tv->children)
732 1.1 mrg for (child_map_t::iterator i = tv->children->begin ();
733 1.1 mrg i != tv->children->end (); ++i)
734 1.1 mrg if (! all_zero ((*i).second))
735 1.1 mrg {
736 1.1 mrg any_children_with_time = true;
737 1.1 mrg break;
738 1.1 mrg }
739 1.1 mrg
740 1.1 mrg /* Don't print timing variables if we're going to get a row of
741 1.1 mrg zeroes. Unless there are children with non-zero time. */
742 1.1 mrg if (! any_children_with_time
743 1.1 mrg && all_zero (tv->elapsed))
744 1.1 mrg continue;
745 1.1 mrg
746 1.1 mrg print_row (fp, total, tv->name, tv->elapsed);
747 1.1 mrg
748 1.1 mrg if (tv->children)
749 1.1 mrg for (child_map_t::iterator i = tv->children->begin ();
750 1.1 mrg i != tv->children->end (); ++i)
751 1.1 mrg {
752 1.1 mrg timevar_def *tv2 = (*i).first;
753 1.1 mrg /* Don't print timing variables if we're going to get a row of
754 1.1 mrg zeroes. */
755 1.1 mrg if (! all_zero ((*i).second))
756 1.1 mrg {
757 1.1 mrg char lname[256];
758 1.1 mrg snprintf (lname, 256, "`- %s", tv2->name);
759 1.1 mrg print_row (fp, total, lname, (*i).second);
760 1.1 mrg }
761 1.1 mrg }
762 1.1 mrg }
763 1.1 mrg if (m_jit_client_items)
764 1.1 mrg m_jit_client_items->print (fp, total);
765 1.1 mrg
766 1.1 mrg /* Print total time. */
767 1.1 mrg fprintf (fp, " %-35s:", "TOTAL");
768 1.1 mrg #ifdef HAVE_USER_TIME
769 1.1 mrg fprintf (fp, "%7.2f ", total->user);
770 1.1 mrg #endif
771 1.1 mrg #ifdef HAVE_SYS_TIME
772 1.1 mrg fprintf (fp, "%8.2f ", total->sys);
773 1.1 mrg #endif
774 1.1 mrg #ifdef HAVE_WALL_TIME
775 1.1 mrg fprintf (fp, "%8.2f ", total->wall);
776 1.1 mrg #endif
777 1.1 mrg fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem));
778 1.1 mrg
779 1.1 mrg if (CHECKING_P || flag_checking)
780 1.1 mrg fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
781 1.1 mrg if (CHECKING_P)
782 1.1 mrg fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
783 1.1 mrg #ifndef ENABLE_ASSERT_CHECKING
784 1.1 mrg fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
785 1.1 mrg fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
786 1.1 mrg #endif
787 1.1 mrg
788 1.1 mrg #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
789 1.1 mrg || defined (HAVE_WALL_TIME) */
790 1.1 mrg
791 1.1 mrg validate_phases (fp);
792 1.1 mrg }
793 1.1 mrg
794 1.1 mrg /* Get the name of the topmost item. For use by jit for validating
795 1.1 mrg inputs to gcc_jit_timer_pop. */
796 1.1 mrg const char *
797 1.1 mrg timer::get_topmost_item_name () const
798 1.1 mrg {
799 1.1 mrg if (m_stack)
800 1.1 mrg return m_stack->timevar->name;
801 1.1 mrg else
802 1.1 mrg return NULL;
803 1.1 mrg }
804 1.1 mrg
805 1.1 mrg /* Prints a message to stderr stating that time elapsed in STR is
806 1.1 mrg TOTAL (given in microseconds). */
807 1.1 mrg
808 1.1 mrg void
809 1.1 mrg print_time (const char *str, long total)
810 1.1 mrg {
811 1.1 mrg long all_time = get_run_time ();
812 1.1 mrg fprintf (stderr,
813 1.1 mrg "time in %s: %ld.%06ld (%ld%%)\n",
814 1.1 mrg str, total / 1000000, total % 1000000,
815 1.1 mrg all_time == 0 ? 0
816 1.1 mrg : (long) (((100.0 * (double) total) / (double) all_time) + .5));
817 1.1 mrg }
818