OSDN Git Service

* Makefile.in (local-distclean): Remove leftover built files.
[pf3gnuchains/gcc-fork.git] / gcc / timevar.c
1 /* Timing variables for measuring compiler performance.
2    Copyright (C) 2000 Free Software Foundation, Inc.
3    Contributed by Alex Samuel <samuel@codesourcery.com>
4
5    This file is part of GNU CC.
6
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.
11
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.
16
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.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "intl.h"
25
26 #ifdef HAVE_SYS_TIMES_H
27 # include <sys/times.h>
28 #endif
29
30 #ifdef HAVE_SYS_RESOURCE_H
31 #include <sys/resource.h>
32 #endif
33 #ifdef NEED_DECLARATION_GETRUSAGE
34 extern int getrusage PARAMS ((int, struct rusage *));
35 #endif
36
37 #include "flags.h"
38 #include "timevar.h"
39
40 /* See timevar.h for an explanation of timing variables.  */
41
42 /* This macro evaluates to non-zero if timing variables are enabled. */
43 #define TIMEVAR_ENABLE (time_report)
44
45 /* A timing variable.  */
46
47 struct timevar_def
48 {
49   /* Elapsed time for this variable.  */
50   struct timevar_time_def elapsed;
51
52   /* If this variable is timed independently of the timing stack,
53      using timevar_start, this contains the start time.  */
54   struct timevar_time_def start_time;
55
56   /* The name of this timing variable.  */
57   const char *name;
58
59   /* Non-zero if this timing variable is running as a standalone
60      timer.  */
61   unsigned standalone : 1;
62
63   /* Non-zero if this timing variable was ever started or pushed onto
64      the timing stack.  */
65   unsigned used : 1;
66 };
67
68 /* An element on the timing stack.  Elapsed time is attributed to the
69    topmost timing variable on the stack.  */
70
71 struct timevar_stack_def
72 {
73   /* The timing variable at this stack level.  */
74   struct timevar_def *timevar;
75
76   /* The next lower timing variable context in the stack.  */
77   struct timevar_stack_def *next;
78 };
79
80 /* Declared timing variables.  Constructed from the contents of
81    timevar.def.  */
82 static struct timevar_def timevars[TIMEVAR_LAST];
83
84 /* The top of the timing stack.  */
85 static struct timevar_stack_def *stack;
86
87 /* A list of unused (i.e. allocated and subsequently popped)
88    timevar_stack_def instances.  */
89 static struct timevar_stack_def *unused_stack_instances;
90
91 /* The time at which the topmost element on the timing stack was
92    pushed.  Time elapsed since then is attributed to the topmost
93    element.  */
94 static struct timevar_time_def start_time;
95
96 static void get_time
97   PARAMS ((struct timevar_time_def *));
98 static void timevar_accumulate
99   PARAMS ((struct timevar_time_def *, struct timevar_time_def *, 
100            struct timevar_time_def *));
101
102 /* Fill the current times into TIME.  The definition of this function
103    also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
104    HAVA_WALL_TIME macros.  */
105
106 static void
107 get_time (now)
108      struct timevar_time_def *now;
109 {
110   now->user = 0;
111   now->sys  = 0;
112   now->wall = 0;
113
114   if (!TIMEVAR_ENABLE)
115     return;
116
117 #ifdef __BEOS__
118   /* Nothing.  */
119 #else /* not BeOS */
120 #if defined (_WIN32) && !defined (__CYGWIN__)
121   if (clock () >= 0)
122     now->user = clock () * 1000;
123 #define HAVE_USER_TIME
124
125 #else /* not _WIN32 */
126 #ifdef _SC_CLK_TCK
127   {
128     static int tick;
129     struct tms tms;
130     if (tick == 0)
131       tick = 1000000 / sysconf (_SC_CLK_TCK);
132     now->wall = times (&tms) * tick;
133     now->user = tms.tms_utime * tick;
134     now->sys = tms.tms_stime * tick;
135   }
136 #define HAVE_USER_TIME
137 #define HAVE_SYS_TIME
138 #define HAVE_WALL_TIME
139
140 #else
141 #ifdef USG
142   {
143     struct tms tms;
144 #   if HAVE_SYSCONF && defined _SC_CLK_TCK
145 #    define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
146 #   else
147 #    ifdef CLK_TCK
148 #     define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
149 #    else
150 #     define TICKS_PER_SECOND HZ /* traditional UNIX */
151 #    endif
152 #   endif
153     now->wall = times (&tms) * (1000000 / TICKS_PER_SECOND);
154     now->user = tms.tms_utime * (1000000 / TICKS_PER_SECOND);
155     now->sys = tms.tms_stime * (1000000 / TICKS_PER_SECOND);
156   }
157 #define HAVE_USER_TIME
158 #define HAVE_SYS_TIME
159 #define HAVE_WALL_TIME
160
161 #else
162 #ifndef VMS
163   {
164     struct rusage rusage;
165     getrusage (0, &rusage);
166     now->user 
167       = rusage.ru_utime.tv_sec * 1000000 + rusage.ru_utime.tv_usec;
168     now->sys 
169       = rusage.ru_stime.tv_sec * 1000000 + rusage.ru_stime.tv_usec;
170   }
171 #define HAVE_USER_TIME
172 #define HAVE_SYS_TIME
173
174 #else /* VMS */
175   {
176     struct
177       {
178         int proc_user_time;
179         int proc_system_time;
180         int child_user_time;
181         int child_system_time;
182       } vms_times;
183     now->wall = times ((void *) &vms_times) * 10000;
184     now->user = vms_times.proc_user_time * 10000;
185     now->sys = vms_times.proc_system_time * 10000;
186   }
187 #define HAVE_USER_TIME
188 #define HAVE_SYS_TIME
189 #define HAVE_WALL_TIME
190
191 #endif  /* VMS */
192 #endif  /* USG */
193 #endif  /* _SC_CLK_TCK */
194 #endif  /* _WIN32 */
195 #endif  /* __BEOS__ */
196 }  
197
198 /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
199
200 static void 
201 timevar_accumulate (timer, start_time, stop_time)
202   struct timevar_time_def *timer;
203   struct timevar_time_def *start_time;
204   struct timevar_time_def *stop_time;
205 {
206   timer->user += stop_time->user - start_time->user;
207   timer->sys += stop_time->sys - start_time->sys;
208   timer->wall += stop_time->wall - start_time->wall;
209 }
210
211 /* Initialize timing variables.  */
212
213 void
214 init_timevar ()
215 {
216   if (!TIMEVAR_ENABLE)
217     return;
218
219   /* Zero all elapsed times.  */
220   memset ((void *) timevars, 0, sizeof (timevars));
221
222   /* Initialize the names of timing variables.  */
223 #define DEFTIMEVAR(identifer__, name__) \
224   timevars[identifer__].name = name__;
225 #include "timevar.def"
226 #undef DEFTIMEVAR
227 }
228
229 /* Push TIMEVAR onto the timing stack.  No further elapsed time is
230    attributed to the previous topmost timing variable on the stack;
231    subsequent elapsed time is attributed to TIMEVAR, until it is
232    popped or another element is pushed on top. 
233
234    TIMEVAR cannot be running as a standalone timer.  */
235
236 void
237 timevar_push (timevar)
238      timevar_id_t timevar;
239 {
240   struct timevar_def *tv = &timevars[timevar];
241   struct timevar_stack_def *context;
242   struct timevar_time_def now;
243
244   if (!TIMEVAR_ENABLE)
245     return;
246
247   /* Mark this timing variable as used.  */
248   tv->used = 1;
249
250   /* Can't push a standalone timer.  */
251   if (tv->standalone)
252     abort ();
253
254   /* What time is it?  */
255   get_time (&now);
256
257   /* If the stack isn't empty, attribute the current elapsed time to
258      the old topmost element.  */
259   if (stack)
260     timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
261
262   /* Reset the start time; from now on, time is attributed to
263      TIMEVAR. */
264   start_time = now;
265
266   /* See if we have a previously-allocated stack instance.  If so,
267      take it off the list.  If not, malloc a new one.  */
268   if (unused_stack_instances != NULL) 
269     {
270       context = unused_stack_instances;
271       unused_stack_instances = unused_stack_instances->next;
272     }
273   else
274     context = (struct timevar_stack_def *) 
275       xmalloc (sizeof (struct timevar_stack_def));
276
277   /* Fill it in and put it on the stack.  */
278   context->timevar = tv;
279   context->next = stack;
280   stack = context;
281 }
282
283 /* Pop the topmost timing variable element off the timing stack.  The
284    popped variable must be TIMEVAR.  Elapsed time since the that
285    element was pushed on, or since it was last exposed on top of the
286    stack when the element above it was popped off, is credited to that
287    timing variable.  */
288
289 void
290 timevar_pop (timevar)
291      timevar_id_t timevar;
292 {
293   struct timevar_time_def now;
294   struct timevar_stack_def *popped = stack;
295
296   if (!TIMEVAR_ENABLE)
297     return;
298
299   if (&timevars[timevar] != stack->timevar)
300     abort ();
301
302   /* What time is it?  */
303   get_time (&now);
304
305   /* Attribute the elapsed time to the element we're popping.  */
306   timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
307
308   /* Reset the start time; from now on, time is attributed to the
309      element just exposed on the stack.  */
310   start_time = now;
311
312   /* Take the item off the stack.  */
313   stack = stack->next;
314
315   /* Don't delete the stack element; instead, add it to the list of
316      unused elements for later use.  */
317   popped->next = unused_stack_instances;
318   unused_stack_instances = popped;
319 }
320
321 /* Start timing TIMEVAR independently of the timing stack.  Elapsed
322    time until timevar_stop is called for the same timing variable is
323    attributed to TIMEVAR.  */
324
325 void
326 timevar_start (timevar)
327      timevar_id_t timevar;
328 {
329   struct timevar_def *tv = &timevars[timevar];
330
331   if (!TIMEVAR_ENABLE)
332     return;
333
334   /* Mark this timing variable as used.  */
335   tv->used = 1;
336
337   /* Don't allow the same timing variable to be started more than
338      once.  */
339   if (tv->standalone)
340     abort ();
341   tv->standalone = 1;
342
343   get_time (&tv->start_time);
344 }
345
346 /* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
347    is attributed to it.  */
348
349 void
350 timevar_stop (timevar)
351      timevar_id_t timevar;
352 {
353   struct timevar_def *tv = &timevars[timevar];
354   struct timevar_time_def now;
355
356   if (!TIMEVAR_ENABLE)
357     return;
358
359   /* TIMEVAR must have been started via timevar_start.  */
360   if (!tv->standalone)
361     abort ();
362
363   get_time (&now);
364   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
365 }
366
367 /* Fill the elapsed time for TIMEVAR into ELAPSED.  Returns
368    update-to-date information even if TIMEVAR is currently running.  */
369
370 void
371 timevar_get (timevar, elapsed)
372      timevar_id_t timevar;
373      struct timevar_time_def *elapsed;
374 {
375   struct timevar_def *tv = &timevars[timevar];
376   struct timevar_time_def now;
377
378   *elapsed = tv->elapsed;
379   
380   /* Is TIMEVAR currently running as a standalone timer?  */
381   if (tv->standalone)
382     {
383       get_time (&now);
384       timevar_accumulate (elapsed, &tv->start_time, &now);
385     }
386   /* Or is TIMEVAR at the top of the timer stack?  */
387   else if (stack->timevar == tv)
388     {
389       get_time (&now);
390       timevar_accumulate (elapsed, &start_time, &now);
391     }
392 }
393
394 /* Summarize timing variables to FP.  The timing variable TV_TOTAL has
395    a special meaning -- it's considered to be the total elapsed time,
396    for normalizing the others, and is displayed last.  */
397
398 void
399 timevar_print (fp)
400      FILE *fp;
401 {
402   /* Only print stuff if we have some sort of time information.  */
403 #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
404   timevar_id_t id;
405   struct timevar_time_def *total = &timevars[TV_TOTAL].elapsed;
406   struct timevar_time_def now;
407
408   if (!TIMEVAR_ENABLE)
409     return;
410
411   /* Update timing information in case we're calling this from GDB.  */
412
413   if (fp == 0)
414     fp = stderr;
415
416   /* What time is it?  */
417   get_time (&now);
418
419   /* If the stack isn't empty, attribute the current elapsed time to
420      the old topmost element.  */
421   if (stack)
422     timevar_accumulate (&stack->timevar->elapsed, &start_time, &now);
423
424   /* Reset the start time; from now on, time is attributed to
425      TIMEVAR. */
426   start_time = now;
427
428   fprintf (fp, _("\nExecution times (seconds)\n"));
429   for (id = 0; id < TIMEVAR_LAST; ++id)
430     {
431       struct timevar_def *tv = &timevars[id];
432
433       /* Don't print the total execution time here; that goes at the
434          end.  */
435       if (id == TV_TOTAL)
436         continue;
437
438       /* Don't print timing variables that were never used.  */
439       if (!tv->used)
440         continue;
441
442       /* The timing variable name.  */
443       fprintf (fp, " %-22s:", tv->name);
444
445 #ifdef HAVE_USER_TIME
446       /* Print user-mode time for this process.  */
447       fprintf (fp, "%4ld.%02ld (%2.0f%%) usr", 
448                tv->elapsed.user / 1000000, 
449                (tv->elapsed.user % 1000000) / 10000,
450                (total->user == 0) ? 0.0 
451                : (100.0 * tv->elapsed.user / (double) total->user));
452 #endif /* HAVE_USER_TIME */
453
454 #ifdef HAVE_SYS_TIME
455       /* Print system-mode time for this process.  */
456       fprintf (fp, "%4ld.%02ld (%2.0f%%) sys", 
457                tv->elapsed.sys / 1000000, 
458                (tv->elapsed.sys % 1000000) / 10000,
459                (total->sys == 0) ? 0.0 
460                : (100.0 * tv->elapsed.sys / (double) total->sys));
461 #endif /* HAVE_SYS_TIME */
462
463 #ifdef HAVE_WALL_TIME
464       /* Print wall clock time elapsed.  */
465       fprintf (fp, "%4ld.%02ld (%2.0f%%) wall", 
466                tv->elapsed.wall / 1000000, 
467                (tv->elapsed.wall % 1000000) / 10000,
468                (total->wall == 0) ? 0.0 
469                : (100.0 * tv->elapsed.wall / (double) total->wall));
470 #endif /* HAVE_WALL_TIME */
471
472       fprintf (fp, "\n");
473     }
474
475   /* Print total time.  */
476   fprintf (fp, _(" TOTAL                 :"));
477 #ifdef HAVE_USER_TIME
478   fprintf (fp, "%4ld.%02ld          ", 
479            total->user / 1000000, (total->user % 1000000) / 10000);
480 #endif 
481 #ifdef HAVE_SYS_TIME
482   fprintf (fp, "%4ld.%02ld          ", 
483            total->sys  / 1000000, (total->sys  % 1000000) / 10000);
484 #endif
485 #ifdef HAVE_WALL_TIME
486   fprintf (fp, "%4ld.%02ld\n",
487            total->wall / 1000000, (total->wall % 1000000) / 10000);
488 #endif
489   
490 #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) 
491           || defined (HAVE_WALL_TIME) */
492 }
493
494 /* Returns time (user + system) used so far by the compiler process,
495    in microseconds.  */
496
497 long
498 get_run_time ()
499 {
500   struct timevar_time_def total_elapsed;
501   timevar_get (TV_TOTAL, &total_elapsed);
502   return total_elapsed.user + total_elapsed.sys;
503 }
504
505 /* Prints a message to stderr stating that time elapsed in STR is
506    TOTAL (given in microseconds).  */
507
508 void
509 print_time (str, total)
510      const char *str;
511      long total;
512 {
513   long all_time = get_run_time ();
514   fprintf (stderr,
515            _("time in %s: %ld.%06ld (%ld%%)\n"),
516            str, total / 1000000, total % 1000000,
517            all_time == 0 ? 0
518            : (long) (((100.0 * (double) total) / (double) all_time) + .5));
519 }