]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/timevar.c
sbitmap.c: Convert prototypes to ISO C90.
[thirdparty/gcc.git] / gcc / timevar.c
CommitLineData
2a9a326b 1/* Timing variables for measuring compiler performance.
33b0d00f 2 Copyright (C) 2000, 2003 Free Software Foundation, Inc.
2a9a326b
AS
3 Contributed by Alex Samuel <samuel@codesourcery.com>
4
5237fc07 5This file is part of GCC.
2a9a326b 6
5237fc07
RK
7GCC is free software; you can redistribute it and/or modify it under
8the terms of the GNU General Public License as published by the Free
9Software Foundation; either version 2, or (at your option) any later
10version.
2a9a326b 11
5237fc07
RK
12GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13WARRANTY; without even the implied warranty of MERCHANTABILITY or
14FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15for more details.
2a9a326b 16
5237fc07
RK
17You should have received a copy of the GNU General Public License
18along with GCC; see the file COPYING. If not, write to the Free
19Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2002111-1307, USA. */
2a9a326b
AS
21
22#include "config.h"
23#include "system.h"
2a9a326b
AS
24#ifdef HAVE_SYS_TIMES_H
25# include <sys/times.h>
26#endif
f9721d41
HPN
27#ifdef HAVE_SYS_RESOURCE_H
28#include <sys/resource.h>
29#endif
dd1b7476
KG
30#include "coretypes.h"
31#include "tm.h"
32#include "intl.h"
33#include "rtl.h"
34#include "toplev.h"
35
c1800ec8
ZW
36#ifndef HAVE_CLOCK_T
37typedef int clock_t;
38#endif
39
40#ifndef HAVE_STRUCT_TMS
41struct tms
42{
43 clock_t tms_utime;
44 clock_t tms_stime;
45 clock_t tms_cutime;
46 clock_t tms_cstime;
47};
48#endif
49
c1800ec8
ZW
50#ifndef RUSAGE_SELF
51# define RUSAGE_SELF 0
52#endif
53
54/* Calculation of scale factor to convert ticks to microseconds.
55 We mustn't use CLOCKS_PER_SEC except with clock(). */
56#if HAVE_SYSCONF && defined _SC_CLK_TCK
57# define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
58#else
59# ifdef CLK_TCK
60# define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
61# else
62# ifdef HZ
63# define TICKS_PER_SECOND HZ /* traditional UNIX */
64# else
65# define TICKS_PER_SECOND 100 /* often the correct value */
66# endif
67# endif
68#endif
69
c1800ec8
ZW
70/* Prefer times to getrusage to clock (each gives successively less
71 information). */
72#ifdef HAVE_TIMES
8f9a402c 73# if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
46c5ad27 74 extern clock_t times (struct tms *);
8f9a402c 75# endif
c1800ec8
ZW
76# define USE_TIMES
77# define HAVE_USER_TIME
78# define HAVE_SYS_TIME
79# define HAVE_WALL_TIME
80#else
81#ifdef HAVE_GETRUSAGE
8f9a402c
DS
82# if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
83 extern int getrusage PARAMS ((int, struct rusage *));
84# endif
c1800ec8
ZW
85# define USE_GETRUSAGE
86# define HAVE_USER_TIME
87# define HAVE_SYS_TIME
88#else
89#ifdef HAVE_CLOCK
8f9a402c
DS
90# if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
91 extern clock_t clock PARAMS ((void));
92# endif
c1800ec8
ZW
93# define USE_CLOCK
94# define HAVE_USER_TIME
95#endif
96#endif
97#endif
f9721d41 98
d9b6874b
ZW
99/* libc is very likely to have snuck a call to sysconf() into one of
100 the underlying constants, and that can be very slow, so we have to
101 precompute them. Whose wonderful idea was it to make all those
102 _constants_ variable at run time, anyway? */
103#ifdef USE_TIMES
4977bab6
ZW
104static double ticks_to_msec;
105#define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
d9b6874b
ZW
106#endif
107
108#ifdef USE_CLOCK
4977bab6
ZW
109static double clocks_to_msec;
110#define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
d9b6874b
ZW
111#endif
112
26026d38 113#include "flags.h"
2a9a326b
AS
114#include "timevar.h"
115
09b04f2d 116static bool timevar_enable;
2a9a326b 117
09b04f2d 118/* See timevar.h for an explanation of timing variables. */
26026d38 119
2a9a326b
AS
120/* A timing variable. */
121
122struct timevar_def
123{
124 /* Elapsed time for this variable. */
125 struct timevar_time_def elapsed;
126
127 /* If this variable is timed independently of the timing stack,
128 using timevar_start, this contains the start time. */
129 struct timevar_time_def start_time;
130
26026d38
AS
131 /* The name of this timing variable. */
132 const char *name;
133
272d0bee 134 /* Nonzero if this timing variable is running as a standalone
2a9a326b 135 timer. */
26026d38 136 unsigned standalone : 1;
2a9a326b 137
272d0bee 138 /* Nonzero if this timing variable was ever started or pushed onto
26026d38
AS
139 the timing stack. */
140 unsigned used : 1;
2a9a326b
AS
141};
142
143/* An element on the timing stack. Elapsed time is attributed to the
144 topmost timing variable on the stack. */
145
146struct timevar_stack_def
147{
148 /* The timing variable at this stack level. */
149 struct timevar_def *timevar;
150
151 /* The next lower timing variable context in the stack. */
152 struct timevar_stack_def *next;
153};
154
155/* Declared timing variables. Constructed from the contents of
156 timevar.def. */
157static struct timevar_def timevars[TIMEVAR_LAST];
158
159/* The top of the timing stack. */
160static struct timevar_stack_def *stack;
161
26026d38
AS
162/* A list of unused (i.e. allocated and subsequently popped)
163 timevar_stack_def instances. */
164static struct timevar_stack_def *unused_stack_instances;
165
2a9a326b
AS
166/* The time at which the topmost element on the timing stack was
167 pushed. Time elapsed since then is attributed to the topmost
168 element. */
169static struct timevar_time_def start_time;
170
46c5ad27
AJ
171static void get_time (struct timevar_time_def *);
172static void timevar_accumulate (struct timevar_time_def *,
173 struct timevar_time_def *,
174 struct timevar_time_def *);
2a9a326b
AS
175
176/* Fill the current times into TIME. The definition of this function
177 also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
83a3aefb 178 HAVE_WALL_TIME macros. */
2a9a326b
AS
179
180static void
46c5ad27 181get_time (struct timevar_time_def *now)
2a9a326b 182{
26026d38
AS
183 now->user = 0;
184 now->sys = 0;
185 now->wall = 0;
186
09b04f2d 187 if (!timevar_enable)
26026d38 188 return;
2a9a326b 189
2a9a326b 190 {
c1800ec8 191#ifdef USE_TIMES
2a9a326b 192 struct tms tms;
d9b6874b
ZW
193 now->wall = times (&tms) * ticks_to_msec;
194 now->user = tms.tms_utime * ticks_to_msec;
195 now->sys = tms.tms_stime * ticks_to_msec;
c1800ec8
ZW
196#endif
197#ifdef USE_GETRUSAGE
2a9a326b 198 struct rusage rusage;
c1800ec8 199 getrusage (RUSAGE_SELF, &rusage);
20cc76d5
RH
200 now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
201 now->sys = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
c1800ec8
ZW
202#endif
203#ifdef USE_CLOCK
d9b6874b 204 now->user = clock () * clocks_to_msec;
c1800ec8 205#endif
2a9a326b 206 }
c1800ec8 207}
2a9a326b 208
2a9a326b
AS
209/* Add the difference between STOP_TIME and START_TIME to TIMER. */
210
d92b4486 211static void
46c5ad27
AJ
212timevar_accumulate (struct timevar_time_def *timer,
213 struct timevar_time_def *start_time,
214 struct timevar_time_def *stop_time)
2a9a326b
AS
215{
216 timer->user += stop_time->user - start_time->user;
217 timer->sys += stop_time->sys - start_time->sys;
218 timer->wall += stop_time->wall - start_time->wall;
219}
220
221/* Initialize timing variables. */
222
223void
46c5ad27 224timevar_init (void)
2a9a326b 225{
09b04f2d 226 timevar_enable = true;
26026d38 227
2a9a326b
AS
228 /* Zero all elapsed times. */
229 memset ((void *) timevars, 0, sizeof (timevars));
230
231 /* Initialize the names of timing variables. */
affd4f33
JM
232#define DEFTIMEVAR(identifier__, name__) \
233 timevars[identifier__].name = name__;
2a9a326b
AS
234#include "timevar.def"
235#undef DEFTIMEVAR
d9b6874b
ZW
236
237#ifdef USE_TIMES
238 ticks_to_msec = TICKS_TO_MSEC;
239#endif
240#ifdef USE_CLOCK
241 clocks_to_msec = CLOCKS_TO_MSEC;
242#endif
2a9a326b
AS
243}
244
245/* Push TIMEVAR onto the timing stack. No further elapsed time is
246 attributed to the previous topmost timing variable on the stack;
247 subsequent elapsed time is attributed to TIMEVAR, until it is
d92b4486 248 popped or another element is pushed on top.
2a9a326b
AS
249
250 TIMEVAR cannot be running as a standalone timer. */
251
252void
46c5ad27 253timevar_push (timevar_id_t timevar)
2a9a326b
AS
254{
255 struct timevar_def *tv = &timevars[timevar];
256 struct timevar_stack_def *context;
257 struct timevar_time_def now;
258
09b04f2d 259 if (!timevar_enable)
26026d38
AS
260 return;
261
262 /* Mark this timing variable as used. */
263 tv->used = 1;
264
2a9a326b
AS
265 /* Can't push a standalone timer. */
266 if (tv->standalone)
267 abort ();
268
269 /* What time is it? */
270 get_time (&now);
271
272 /* If the stack isn't empty, attribute the current elapsed time to
273 the old topmost element. */
274 if (stack)
275 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
276
277 /* Reset the start time; from now on, time is attributed to
2d76cb1a 278 TIMEVAR. */
2a9a326b
AS
279 start_time = now;
280
26026d38
AS
281 /* See if we have a previously-allocated stack instance. If so,
282 take it off the list. If not, malloc a new one. */
d92b4486 283 if (unused_stack_instances != NULL)
26026d38
AS
284 {
285 context = unused_stack_instances;
286 unused_stack_instances = unused_stack_instances->next;
287 }
288 else
d92b4486 289 context = (struct timevar_stack_def *)
26026d38
AS
290 xmalloc (sizeof (struct timevar_stack_def));
291
292 /* Fill it in and put it on the stack. */
2a9a326b
AS
293 context->timevar = tv;
294 context->next = stack;
295 stack = context;
296}
297
298/* Pop the topmost timing variable element off the timing stack. The
299 popped variable must be TIMEVAR. Elapsed time since the that
300 element was pushed on, or since it was last exposed on top of the
301 stack when the element above it was popped off, is credited to that
302 timing variable. */
303
304void
46c5ad27 305timevar_pop (timevar_id_t timevar)
2a9a326b
AS
306{
307 struct timevar_time_def now;
26026d38
AS
308 struct timevar_stack_def *popped = stack;
309
09b04f2d 310 if (!timevar_enable)
26026d38 311 return;
2a9a326b
AS
312
313 if (&timevars[timevar] != stack->timevar)
fd371a93
GDR
314 {
315 sorry ("cannot timevar_pop '%s' when top of timevars stack is '%s'",
316 timevars[timevar].name, stack->timevar->name);
317 abort ();
318 }
2a9a326b
AS
319
320 /* What time is it? */
321 get_time (&now);
322
323 /* Attribute the elapsed time to the element we're popping. */
26026d38 324 timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
2a9a326b
AS
325
326 /* Reset the start time; from now on, time is attributed to the
327 element just exposed on the stack. */
328 start_time = now;
329
26026d38
AS
330 /* Take the item off the stack. */
331 stack = stack->next;
332
333 /* Don't delete the stack element; instead, add it to the list of
334 unused elements for later use. */
335 popped->next = unused_stack_instances;
336 unused_stack_instances = popped;
2a9a326b
AS
337}
338
339/* Start timing TIMEVAR independently of the timing stack. Elapsed
340 time until timevar_stop is called for the same timing variable is
341 attributed to TIMEVAR. */
342
343void
46c5ad27 344timevar_start (timevar_id_t timevar)
2a9a326b
AS
345{
346 struct timevar_def *tv = &timevars[timevar];
347
09b04f2d 348 if (!timevar_enable)
26026d38
AS
349 return;
350
351 /* Mark this timing variable as used. */
352 tv->used = 1;
353
2a9a326b
AS
354 /* Don't allow the same timing variable to be started more than
355 once. */
356 if (tv->standalone)
357 abort ();
358 tv->standalone = 1;
359
360 get_time (&tv->start_time);
361}
362
363/* Stop timing TIMEVAR. Time elapsed since timevar_start was called
364 is attributed to it. */
365
366void
46c5ad27 367timevar_stop (timevar_id_t timevar)
2a9a326b
AS
368{
369 struct timevar_def *tv = &timevars[timevar];
370 struct timevar_time_def now;
371
09b04f2d 372 if (!timevar_enable)
26026d38
AS
373 return;
374
2a9a326b
AS
375 /* TIMEVAR must have been started via timevar_start. */
376 if (!tv->standalone)
377 abort ();
378
379 get_time (&now);
380 timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
381}
382
383/* Fill the elapsed time for TIMEVAR into ELAPSED. Returns
384 update-to-date information even if TIMEVAR is currently running. */
385
386void
46c5ad27 387timevar_get (timevar_id_t timevar, struct timevar_time_def *elapsed)
2a9a326b
AS
388{
389 struct timevar_def *tv = &timevars[timevar];
eab828ba 390 struct timevar_time_def now;
2a9a326b
AS
391
392 *elapsed = tv->elapsed;
d92b4486 393
2a9a326b
AS
394 /* Is TIMEVAR currently running as a standalone timer? */
395 if (tv->standalone)
eab828ba
ZW
396 {
397 get_time (&now);
398 timevar_accumulate (elapsed, &tv->start_time, &now);
399 }
400 /* Or is TIMEVAR at the top of the timer stack? */
401 else if (stack->timevar == tv)
402 {
403 get_time (&now);
404 timevar_accumulate (elapsed, &start_time, &now);
405 }
2a9a326b
AS
406}
407
408/* Summarize timing variables to FP. The timing variable TV_TOTAL has
409 a special meaning -- it's considered to be the total elapsed time,
410 for normalizing the others, and is displayed last. */
411
412void
46c5ad27 413timevar_print (FILE *fp)
2a9a326b
AS
414{
415 /* Only print stuff if we have some sort of time information. */
416#if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
dbbbbf3b 417 unsigned int /* timevar_id_t */ id;
2a9a326b 418 struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
ea11ca7e 419 struct timevar_time_def now;
2a9a326b 420
09b04f2d 421 if (!timevar_enable)
26026d38
AS
422 return;
423
ea11ca7e
JM
424 /* Update timing information in case we're calling this from GDB. */
425
426 if (fp == 0)
427 fp = stderr;
428
429 /* What time is it? */
430 get_time (&now);
431
432 /* If the stack isn't empty, attribute the current elapsed time to
433 the old topmost element. */
434 if (stack)
435 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
436
437 /* Reset the start time; from now on, time is attributed to
2d76cb1a 438 TIMEVAR. */
ea11ca7e
JM
439 start_time = now;
440
d9b6874b 441 fputs (_("\nExecution times (seconds)\n"), fp);
dbbbbf3b 442 for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
2a9a326b 443 {
dbbbbf3b 444 struct timevar_def *tv = &timevars[(timevar_id_t) id];
4977bab6 445 const double tiny = 5e-3;
2a9a326b
AS
446
447 /* Don't print the total execution time here; that goes at the
448 end. */
dbbbbf3b 449 if ((timevar_id_t) id == TV_TOTAL)
2a9a326b
AS
450 continue;
451
26026d38
AS
452 /* Don't print timing variables that were never used. */
453 if (!tv->used)
454 continue;
455
d9b6874b
ZW
456 /* Don't print timing variables if we're going to get a row of
457 zeroes. */
20cc76d5
RH
458 if (tv->elapsed.user < tiny
459 && tv->elapsed.sys < tiny
460 && tv->elapsed.wall < tiny)
d9b6874b
ZW
461 continue;
462
2a9a326b
AS
463 /* The timing variable name. */
464 fprintf (fp, " %-22s:", tv->name);
465
466#ifdef HAVE_USER_TIME
467 /* Print user-mode time for this process. */
d92b4486 468 fprintf (fp, "%7.2f (%2.0f%%) usr",
20cc76d5
RH
469 tv->elapsed.user,
470 (total->user == 0 ? 0 : tv->elapsed.user / total->user) * 100);
2a9a326b
AS
471#endif /* HAVE_USER_TIME */
472
473#ifdef HAVE_SYS_TIME
474 /* Print system-mode time for this process. */
d92b4486 475 fprintf (fp, "%7.2f (%2.0f%%) sys",
20cc76d5
RH
476 tv->elapsed.sys,
477 (total->sys == 0 ? 0 : tv->elapsed.sys / total->sys) * 100);
2a9a326b
AS
478#endif /* HAVE_SYS_TIME */
479
480#ifdef HAVE_WALL_TIME
481 /* Print wall clock time elapsed. */
d92b4486 482 fprintf (fp, "%7.2f (%2.0f%%) wall",
20cc76d5
RH
483 tv->elapsed.wall,
484 (total->wall == 0 ? 0 : tv->elapsed.wall / total->wall) * 100);
2a9a326b
AS
485#endif /* HAVE_WALL_TIME */
486
d9b6874b 487 putc ('\n', fp);
2a9a326b
AS
488 }
489
490 /* Print total time. */
d9b6874b 491 fputs (_(" TOTAL :"), fp);
2a9a326b 492#ifdef HAVE_USER_TIME
20cc76d5 493 fprintf (fp, "%7.2f ", total->user);
d92b4486 494#endif
2a9a326b 495#ifdef HAVE_SYS_TIME
20cc76d5 496 fprintf (fp, "%7.2f ", total->sys);
2a9a326b
AS
497#endif
498#ifdef HAVE_WALL_TIME
20cc76d5 499 fprintf (fp, "%7.2f\n", total->wall);
2a9a326b 500#endif
d92b4486
KH
501
502#endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
2a9a326b
AS
503 || defined (HAVE_WALL_TIME) */
504}
505
2a9a326b
AS
506/* Prints a message to stderr stating that time elapsed in STR is
507 TOTAL (given in microseconds). */
508
509void
46c5ad27 510print_time (const char *str, long total)
2a9a326b
AS
511{
512 long all_time = get_run_time ();
513 fprintf (stderr,
5e4adfba 514 _("time in %s: %ld.%06ld (%ld%%)\n"),
2a9a326b 515 str, total / 1000000, total % 1000000,
d92b4486
KH
516 all_time == 0 ? 0
517 : (long) (((100.0 * (double) total) / (double) all_time) + .5));
2a9a326b 518}