OSDN Git Service

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