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