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