* flow.c (mark_used_regs): Revert last change.
[official-gcc.git] / gcc / timevar.c
blob44ea96f35aba5fb3de7117cb1d9fd5a401620356
1 /* Timing variables for measuring compiler performance.
2 Copyright (C) 2000 Free Software Foundation, Inc.
3 Contributed by Alex Samuel <samuel@codesourcery.com>
5 This file is part of GNU CC.
7 GNU CC is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
12 GNU CC is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU CC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
25 #ifdef HAVE_SYS_TIMES_H
26 # include <sys/times.h>
27 #endif
29 #include "flags.h"
30 #include "timevar.h"
32 /* See timevar.h for an explanation of timing variables. */
34 /* This macro evaluates to non-zero if timing variables are enabled. */
35 #define TIMEVAR_ENABLE (!quiet_flag)
37 /* A timing variable. */
39 struct timevar_def
41 /* Elapsed time for this variable. */
42 struct timevar_time_def elapsed;
44 /* If this variable is timed independently of the timing stack,
45 using timevar_start, this contains the start time. */
46 struct timevar_time_def start_time;
48 /* The name of this timing variable. */
49 const char *name;
51 /* Non-zero if this timing variable is running as a standalone
52 timer. */
53 unsigned standalone : 1;
55 /* Non-zero if this timing variable was ever started or pushed onto
56 the timing stack. */
57 unsigned used : 1;
60 /* An element on the timing stack. Elapsed time is attributed to the
61 topmost timing variable on the stack. */
63 struct timevar_stack_def
65 /* The timing variable at this stack level. */
66 struct timevar_def *timevar;
68 /* The next lower timing variable context in the stack. */
69 struct timevar_stack_def *next;
72 /* Declared timing variables. Constructed from the contents of
73 timevar.def. */
74 static struct timevar_def timevars[TIMEVAR_LAST];
76 /* The top of the timing stack. */
77 static struct timevar_stack_def *stack;
79 /* A list of unused (i.e. allocated and subsequently popped)
80 timevar_stack_def instances. */
81 static struct timevar_stack_def *unused_stack_instances;
83 /* The time at which the topmost element on the timing stack was
84 pushed. Time elapsed since then is attributed to the topmost
85 element. */
86 static struct timevar_time_def start_time;
88 static void get_time
89 PARAMS ((struct timevar_time_def *));
90 static void timevar_add
91 PARAMS ((struct timevar_time_def *, struct timevar_time_def *));
92 static void timevar_accumulate
93 PARAMS ((struct timevar_time_def *, struct timevar_time_def *,
94 struct timevar_time_def *));
96 /* Fill the current times into TIME. The definition of this function
97 also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
98 HAVA_WALL_TIME macros. */
100 static void
101 get_time (now)
102 struct timevar_time_def *now;
104 now->user = 0;
105 now->sys = 0;
106 now->wall = 0;
108 if (!TIMEVAR_ENABLE)
109 return;
111 #ifdef __BEOS__
112 /* Nothing. */
113 #else /* not BeOS */
114 #if defined (_WIN32) && !defined (__CYGWIN__)
115 if (clock () >= 0)
116 now->user = clock () * 1000;
117 #define HAVE_USER_TIME
119 #else /* not _WIN32 */
120 #ifdef _SC_CLK_TCK
122 static int tick;
123 struct tms tms;
124 if (tick == 0)
125 tick = 1000000 / sysconf (_SC_CLK_TCK);
126 now->wall = times (&tms) * tick;
127 now->user = tms.tms_utime * tick;
128 now->sys = tms.tms_stime * tick;
130 #define HAVE_USER_TIME
131 #define HAVE_SYS_TIME
132 #define HAVE_WALL_TIME
134 #else
135 #ifdef USG
137 struct tms tms;
138 # if HAVE_SYSCONF && defined _SC_CLK_TCK
139 # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
140 # else
141 # ifdef CLK_TCK
142 # define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
143 # else
144 # define TICKS_PER_SECOND HZ /* traditional UNIX */
145 # endif
146 # endif
147 now->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
148 now->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
149 now->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
151 #define HAVE_USER_TIME
152 #define HAVE_SYS_TIME
153 #define HAVE_WALL_TIME
155 #else
156 #ifndef VMS
158 struct rusage rusage;
159 getrusage (0, &rusage);
160 now->user
161 = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
162 now->sys
163 = rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
165 #define HAVE_USER_TIME
166 #define HAVE_SYS_TIME
168 #else /* VMS */
170 struct
172 int proc_user_time;
173 int proc_system_time;
174 int child_user_time;
175 int child_system_time;
176 } vms_times;
177 now->wall = times ((void *) &vms_times) * 10000;
178 now->user = vms_times.proc_user_time * 10000;
179 now->sys = vms_times.proc_system_time * 10000;
181 #define HAVE_USER_TIME
182 #define HAVE_SYS_TIME
183 #define HAVE_WALL_TIME
185 #endif /* VMS */
186 #endif /* USG */
187 #endif /* _SC_CLK_TCK */
188 #endif /* _WIN32 */
189 #endif /* __BEOS__ */
192 /* Add ELAPSED to TIMER. */
194 static void
195 timevar_add (timer, elapsed)
196 struct timevar_time_def *timer;
197 struct timevar_time_def *elapsed;
199 timer->user += elapsed->user;
200 timer->sys += elapsed->sys;
201 timer->wall += elapsed->wall;
204 /* Add the difference between STOP_TIME and START_TIME to TIMER. */
206 static void
207 timevar_accumulate (timer, start_time, stop_time)
208 struct timevar_time_def *timer;
209 struct timevar_time_def *start_time;
210 struct timevar_time_def *stop_time;
212 timer->user += stop_time->user - start_time->user;
213 timer->sys += stop_time->sys - start_time->sys;
214 timer->wall += stop_time->wall - start_time->wall;
217 /* Initialize timing variables. */
219 void
220 init_timevar ()
222 if (!TIMEVAR_ENABLE)
223 return;
225 /* Zero all elapsed times. */
226 memset ((void *) timevars, 0, sizeof (timevars));
228 /* Initialize the names of timing variables. */
229 #define DEFTIMEVAR(identifer__, name__) \
230 timevars[identifer__].name = name__;
231 #include "timevar.def"
232 #undef DEFTIMEVAR
235 /* Push TIMEVAR onto the timing stack. No further elapsed time is
236 attributed to the previous topmost timing variable on the stack;
237 subsequent elapsed time is attributed to TIMEVAR, until it is
238 popped or another element is pushed on top.
240 TIMEVAR cannot be running as a standalone timer. */
242 void
243 timevar_push (timevar)
244 timevar_id_t timevar;
246 struct timevar_def *tv = &timevars[timevar];
247 struct timevar_stack_def *context;
248 struct timevar_time_def now;
250 if (!TIMEVAR_ENABLE)
251 return;
253 /* Mark this timing variable as used. */
254 tv->used = 1;
256 /* Can't push a standalone timer. */
257 if (tv->standalone)
258 abort ();
260 /* What time is it? */
261 get_time (&now);
263 /* If the stack isn't empty, attribute the current elapsed time to
264 the old topmost element. */
265 if (stack)
266 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
268 /* Reset the start time; from now on, time is attributed to
269 TIMEVAR. */
270 start_time = now;
272 /* See if we have a previously-allocated stack instance. If so,
273 take it off the list. If not, malloc a new one. */
274 if (unused_stack_instances != NULL)
276 context = unused_stack_instances;
277 unused_stack_instances = unused_stack_instances->next;
279 else
280 context = (struct timevar_stack_def *)
281 xmalloc (sizeof (struct timevar_stack_def));
283 /* Fill it in and put it on the stack. */
284 context->timevar = tv;
285 context->next = stack;
286 stack = context;
289 /* Pop the topmost timing variable element off the timing stack. The
290 popped variable must be TIMEVAR. Elapsed time since the that
291 element was pushed on, or since it was last exposed on top of the
292 stack when the element above it was popped off, is credited to that
293 timing variable. */
295 void
296 timevar_pop (timevar)
297 timevar_id_t timevar;
299 struct timevar_time_def now;
300 struct timevar_stack_def *popped = stack;
302 if (!TIMEVAR_ENABLE)
303 return;
305 if (&timevars[timevar] != stack->timevar)
306 abort ();
308 /* What time is it? */
309 get_time (&now);
311 /* Attribute the elapsed time to the element we're popping. */
312 timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
314 /* Reset the start time; from now on, time is attributed to the
315 element just exposed on the stack. */
316 start_time = now;
318 /* Take the item off the stack. */
319 stack = stack->next;
321 /* Don't delete the stack element; instead, add it to the list of
322 unused elements for later use. */
323 popped->next = unused_stack_instances;
324 unused_stack_instances = popped;
327 /* Start timing TIMEVAR independently of the timing stack. Elapsed
328 time until timevar_stop is called for the same timing variable is
329 attributed to TIMEVAR. */
331 void
332 timevar_start (timevar)
333 timevar_id_t timevar;
335 struct timevar_def *tv = &timevars[timevar];
337 if (!TIMEVAR_ENABLE)
338 return;
340 /* Mark this timing variable as used. */
341 tv->used = 1;
343 /* Don't allow the same timing variable to be started more than
344 once. */
345 if (tv->standalone)
346 abort ();
347 tv->standalone = 1;
349 get_time (&tv->start_time);
352 /* Stop timing TIMEVAR. Time elapsed since timevar_start was called
353 is attributed to it. */
355 void
356 timevar_stop (timevar)
357 timevar_id_t timevar;
359 struct timevar_def *tv = &timevars[timevar];
360 struct timevar_time_def now;
362 if (!TIMEVAR_ENABLE)
363 return;
365 /* TIMEVAR must have been started via timevar_start. */
366 if (!tv->standalone)
367 abort ();
369 get_time (&now);
370 timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
373 /* Fill the elapsed time for TIMEVAR into ELAPSED. Returns
374 update-to-date information even if TIMEVAR is currently running. */
376 void
377 timevar_get (timevar, elapsed)
378 timevar_id_t timevar;
379 struct timevar_time_def *elapsed;
381 struct timevar_def *tv = &timevars[timevar];
383 *elapsed = tv->elapsed;
385 /* Is TIMEVAR currently running as a standalone timer? */
386 if (tv->standalone)
387 /* Add the time elapsed since the it was started. */
388 timevar_add (elapsed, &tv->start_time);
390 /* Is TIMEVAR at the top of the timer stack? */
391 if (stack->timevar == tv)
392 /* Add the elapsed time since it was pushed. */
393 timevar_add (elapsed, &start_time);
396 /* Summarize timing variables to FP. The timing variable TV_TOTAL has
397 a special meaning -- it's considered to be the total elapsed time,
398 for normalizing the others, and is displayed last. */
400 void
401 timevar_print (fp)
402 FILE *fp;
404 /* Only print stuff if we have some sort of time information. */
405 #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
406 timevar_id_t id;
407 struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
408 struct timevar_time_def now;
410 if (!TIMEVAR_ENABLE)
411 return;
413 /* Update timing information in case we're calling this from GDB. */
415 if (fp == 0)
416 fp = stderr;
418 /* What time is it? */
419 get_time (&now);
421 /* If the stack isn't empty, attribute the current elapsed time to
422 the old topmost element. */
423 if (stack)
424 timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
426 /* Reset the start time; from now on, time is attributed to
427 TIMEVAR. */
428 start_time = now;
430 fprintf (fp, "\nExecution times (seconds)\n");
431 for (id = 0; id < TIMEVAR_LAST; ++id)
433 struct timevar_def *tv = &timevars[id];
435 /* Don't print the total execution time here; that goes at the
436 end. */
437 if (id == TV_TOTAL)
438 continue;
440 /* Don't print timing variables that were never used. */
441 if (!tv->used)
442 continue;
444 /* The timing variable name. */
445 fprintf (fp, " %-22s:", tv->name);
447 #ifdef HAVE_USER_TIME
448 /* Print user-mode time for this process. */
449 fprintf (fp, "%4ld.%02ld (%2.0f%%) usr",
450 tv->elapsed.user / 1000000,
451 (tv->elapsed.user % 1000000) / 10000,
452 (total->user == 0) ? 0.0
453 : (100.0 * tv->elapsed.user / (double) total->user));
454 #endif /* HAVE_USER_TIME */
456 #ifdef HAVE_SYS_TIME
457 /* Print system-mode time for this process. */
458 fprintf (fp, "%4ld.%02ld (%2.0f%%) sys",
459 tv->elapsed.sys / 1000000,
460 (tv->elapsed.sys % 1000000) / 10000,
461 (total->sys == 0) ? 0.0
462 : (100.0 * tv->elapsed.sys / (double) total->sys));
463 #endif /* HAVE_SYS_TIME */
465 #ifdef HAVE_WALL_TIME
466 /* Print wall clock time elapsed. */
467 fprintf (fp, "%4ld.%02ld (%2.0f%%) wall",
468 tv->elapsed.wall / 1000000,
469 (tv->elapsed.wall % 1000000) / 10000,
470 (total->wall == 0) ? 0.0
471 : (100.0 * tv->elapsed.wall / (double) total->wall));
472 #endif /* HAVE_WALL_TIME */
474 fprintf (fp, "\n");
477 /* Print total time. */
478 fprintf (fp, " TOTAL :");
479 #ifdef HAVE_USER_TIME
480 fprintf (fp, "%4ld.%02ld ",
481 total->user / 1000000, (total->user % 1000000) / 10000);
482 #endif
483 #ifdef HAVE_SYS_TIME
484 fprintf (fp, "%4ld.%02ld ",
485 total->sys / 1000000, (total->sys % 1000000) / 10000);
486 #endif
487 #ifdef HAVE_WALL_TIME
488 fprintf (fp, "%4ld.%02ld\n",
489 total->wall / 1000000, (total->wall % 1000000) / 10000);
490 #endif
492 #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
493 || defined (HAVE_WALL_TIME) */
496 /* Returns time (user + system) used so far by the compiler process,
497 in microseconds. */
499 long
500 get_run_time ()
502 struct timevar_time_def total_elapsed;
503 timevar_get (TV_TOTAL, &total_elapsed);
504 return total_elapsed.user + total_elapsed.sys;
507 /* Prints a message to stderr stating that time elapsed in STR is
508 TOTAL (given in microseconds). */
510 void
511 print_time (str, total)
512 const char *str;
513 long total;
515 long all_time = get_run_time ();
516 fprintf (stderr,
517 "time in %s: %ld.%06ld (%ld%%)\n",
518 str, total / 1000000, total % 1000000,
519 all_time == 0 ? 0
520 : (long) (((100.0 * (double) total) / (double) all_time) + .5));