OSDN Git Service

* config/rs6000/rs6000.md (movsi): Constify 'name'.
[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
25 #ifdef HAVE_SYS_TIMES_H
26 # include <sys/times.h>
27 #endif
28
29 #include "flags.h"
30 #include "timevar.h"
31
32 /* See timevar.h for an explanation of timing variables.  */
33
34 /* This macro evaluates to non-zero if timing variables are enabled. */
35 #define TIMEVAR_ENABLE (!quiet_flag)
36
37 /* A timing variable.  */
38
39 struct timevar_def
40 {
41   /* Elapsed time for this variable.  */
42   struct timevar_time_def elapsed;
43
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;
47
48   /* The name of this timing variable.  */
49   const char *name;
50
51   /* Non-zero if this timing variable is running as a standalone
52      timer.  */
53   unsigned standalone : 1;
54
55   /* Non-zero if this timing variable was ever started or pushed onto
56      the timing stack.  */
57   unsigned used : 1;
58 };
59
60 /* An element on the timing stack.  Elapsed time is attributed to the
61    topmost timing variable on the stack.  */
62
63 struct timevar_stack_def
64 {
65   /* The timing variable at this stack level.  */
66   struct timevar_def *timevar;
67
68   /* The next lower timing variable context in the stack.  */
69   struct timevar_stack_def *next;
70 };
71
72 /* Declared timing variables.  Constructed from the contents of
73    timevar.def.  */
74 static struct timevar_def timevars[TIMEVAR_LAST];
75
76 /* The top of the timing stack.  */
77 static struct timevar_stack_def *stack;
78
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;
82
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;
87
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 *));
95
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.  */
99
100 static void
101 get_time (now)
102      struct timevar_time_def *now;
103 {
104   now->user = 0;
105   now->sys  = 0;
106   now->wall = 0;
107
108   if (!TIMEVAR_ENABLE)
109     return;
110
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
118
119 #else /* not _WIN32 */
120 #ifdef _SC_CLK_TCK
121   {
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;
129   }
130 #define HAVE_USER_TIME
131 #define HAVE_SYS_TIME
132 #define HAVE_WALL_TIME
133
134 #else
135 #ifdef USG
136   {
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);
150   }
151 #define HAVE_USER_TIME
152 #define HAVE_SYS_TIME
153 #define HAVE_WALL_TIME
154
155 #else
156 #ifndef VMS
157   {
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;
164   }
165 #define HAVE_USER_TIME
166 #define HAVE_SYS_TIME
167
168 #else /* VMS */
169   {
170     struct
171       {
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;
180   }
181 #define HAVE_USER_TIME
182 #define HAVE_SYS_TIME
183 #define HAVE_WALL_TIME
184
185 #endif  /* VMS */
186 #endif  /* USG */
187 #endif  /* _SC_CLK_TCK */
188 #endif  /* _WIN32 */
189 #endif  /* __BEOS__ */
190 }  
191
192 /* Add ELAPSED to TIMER.  */
193
194 static void
195 timevar_add (timer, elapsed)
196      struct timevar_time_def *timer;
197      struct timevar_time_def *elapsed;
198 {
199   timer->user += elapsed->user;
200   timer->sys += elapsed->sys;
201   timer->wall += elapsed->wall;
202 }
203
204 /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
205
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;
211 {
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;
215 }
216
217 /* Initialize timing variables.  */
218
219 void
220 init_timevar ()
221 {
222   if (!TIMEVAR_ENABLE)
223     return;
224
225   /* Zero all elapsed times.  */
226   memset ((void *) timevars, 0, sizeof (timevars));
227
228   /* Initialize the names of timing variables.  */
229 #define DEFTIMEVAR(identifer__, name__) \
230   timevars[identifer__].name = name__;
231 #include "timevar.def"
232 #undef DEFTIMEVAR
233 }
234
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. 
239
240    TIMEVAR cannot be running as a standalone timer.  */
241
242 void
243 timevar_push (timevar)
244      timevar_id_t timevar;
245 {
246   struct timevar_def *tv = &timevars[timevar];
247   struct timevar_stack_def *context;
248   struct timevar_time_def now;
249
250   if (!TIMEVAR_ENABLE)
251     return;
252
253   /* Mark this timing variable as used.  */
254   tv->used = 1;
255
256   /* Can't push a standalone timer.  */
257   if (tv->standalone)
258     abort ();
259
260   /* What time is it?  */
261   get_time (&now);
262
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);
267
268   /* Reset the start time; from now on, time is attributed to
269      TIMEVAR. */
270   start_time = now;
271
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) 
275     {
276       context = unused_stack_instances;
277       unused_stack_instances = unused_stack_instances->next;
278     }
279   else
280     context = (struct timevar_stack_def *) 
281       xmalloc (sizeof (struct timevar_stack_def));
282
283   /* Fill it in and put it on the stack.  */
284   context->timevar = tv;
285   context->next = stack;
286   stack = context;
287 }
288
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.  */
294
295 void
296 timevar_pop (timevar)
297      timevar_id_t timevar;
298 {
299   struct timevar_time_def now;
300   struct timevar_stack_def *popped = stack;
301
302   if (!TIMEVAR_ENABLE)
303     return;
304
305   if (&timevars[timevar] != stack->timevar)
306     abort ();
307
308   /* What time is it?  */
309   get_time (&now);
310
311   /* Attribute the elapsed time to the element we're popping.  */
312   timevar_accumulate (&popped->timevar->elapsed, &start_time, &now);
313
314   /* Reset the start time; from now on, time is attributed to the
315      element just exposed on the stack.  */
316   start_time = now;
317
318   /* Take the item off the stack.  */
319   stack = stack->next;
320
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;
325 }
326
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.  */
330
331 void
332 timevar_start (timevar)
333      timevar_id_t timevar;
334 {
335   struct timevar_def *tv = &timevars[timevar];
336
337   if (!TIMEVAR_ENABLE)
338     return;
339
340   /* Mark this timing variable as used.  */
341   tv->used = 1;
342
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;
348
349   get_time (&tv->start_time);
350 }
351
352 /* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
353    is attributed to it.  */
354
355 void
356 timevar_stop (timevar)
357      timevar_id_t timevar;
358 {
359   struct timevar_def *tv = &timevars[timevar];
360   struct timevar_time_def now;
361
362   if (!TIMEVAR_ENABLE)
363     return;
364
365   /* TIMEVAR must have been started via timevar_start.  */
366   if (!tv->standalone)
367     abort ();
368
369   get_time (&now);
370   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
371 }
372
373 /* Fill the elapsed time for TIMEVAR into ELAPSED.  Returns
374    update-to-date information even if TIMEVAR is currently running.  */
375
376 void
377 timevar_get (timevar, elapsed)
378      timevar_id_t timevar;
379      struct timevar_time_def *elapsed;
380 {
381   struct timevar_def *tv = &timevars[timevar];
382
383   *elapsed = tv->elapsed;
384
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);
389
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);
394 }
395
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.  */
399
400 void
401 timevar_print (fp)
402      FILE *fp;
403 {
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
409   if (!TIMEVAR_ENABLE)
410     return;
411
412   fprintf (fp, "\nExecution times (seconds)\n");
413   for (id = 0; id < TIMEVAR_LAST; ++id)
414     {
415       struct timevar_def *tv = &timevars[id];
416
417       /* Don't print the total execution time here; that goes at the
418          end.  */
419       if (id == TV_TOTAL)
420         continue;
421
422       /* Don't print timing variables that were never used.  */
423       if (!tv->used)
424         continue;
425
426       /* The timing variable name.  */
427       fprintf (fp, " %-22s:", tv->name);
428
429 #ifdef HAVE_USER_TIME
430       /* Print user-mode time for this process.  */
431       fprintf (fp, "%4ld.%02ld (%2.0f%%) usr", 
432                tv->elapsed.user / 1000000, 
433                (tv->elapsed.user % 1000000) / 10000,
434                (total->user == 0) ? 0.0 
435                : (100.0 * tv->elapsed.user / (double) total->user));
436 #endif /* HAVE_USER_TIME */
437
438 #ifdef HAVE_SYS_TIME
439       /* Print system-mode time for this process.  */
440       fprintf (fp, "%4ld.%02ld (%2.0f%%) sys", 
441                tv->elapsed.sys / 1000000, 
442                (tv->elapsed.sys % 1000000) / 10000,
443                (total->sys == 0) ? 0.0 
444                : (100.0 * tv->elapsed.sys / (double) total->sys));
445 #endif /* HAVE_SYS_TIME */
446
447 #ifdef HAVE_WALL_TIME
448       /* Print wall clock time elapsed.  */
449       fprintf (fp, "%4ld.%02ld (%2.0f%%) wall", 
450                tv->elapsed.wall / 1000000, 
451                (tv->elapsed.wall % 1000000) / 10000,
452                (total->wall == 0) ? 0.0 
453                : (100.0 * tv->elapsed.wall / (double) total->wall));
454 #endif /* HAVE_WALL_TIME */
455
456       fprintf (fp, "\n");
457     }
458
459   /* Print total time.  */
460   fprintf (fp, " TOTAL                 :");
461 #ifdef HAVE_USER_TIME
462   fprintf (fp, "%4ld.%02ld          ", 
463            total->user / 1000000, (total->user % 1000000) / 10000);
464 #endif 
465 #ifdef HAVE_SYS_TIME
466   fprintf (fp, "%4ld.%02ld          ", 
467            total->sys  / 1000000, (total->sys  % 1000000) / 10000);
468 #endif
469 #ifdef HAVE_WALL_TIME
470   fprintf (fp, "%4ld.%02ld\n",
471            total->wall / 1000000, (total->wall % 1000000) / 10000);
472 #endif
473   
474 #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) 
475           || defined (HAVE_WALL_TIME) */
476 }
477
478 /* Returns time (user + system) used so far by the compiler process,
479    in microseconds.  */
480
481 long
482 get_run_time ()
483 {
484   struct timevar_time_def total_elapsed;
485   timevar_get (TV_TOTAL, &total_elapsed);
486   return total_elapsed.user + total_elapsed.sys;
487 }
488
489 /* Prints a message to stderr stating that time elapsed in STR is
490    TOTAL (given in microseconds).  */
491
492 void
493 print_time (str, total)
494      const char *str;
495      long total;
496 {
497   long all_time = get_run_time ();
498   fprintf (stderr,
499            "time in %s: %ld.%06ld (%ld%%)\n",
500            str, total / 1000000, total % 1000000,
501            all_time == 0 ? 0
502            : (long) (((100.0 * (double) total) / (double) all_time) + .5));
503 }