xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/timevar.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Timing variables for measuring compiler performance.
2*8feb0f0bSmrg    Copyright (C) 2000-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Alex Samuel <samuel@codesourcery.com>
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg #include "config.h"
221debfc3dSmrg #include "system.h"
231debfc3dSmrg #include "coretypes.h"
241debfc3dSmrg #include "timevar.h"
251debfc3dSmrg #include "options.h"
261debfc3dSmrg 
271debfc3dSmrg #ifndef HAVE_CLOCK_T
281debfc3dSmrg typedef int clock_t;
291debfc3dSmrg #endif
301debfc3dSmrg 
311debfc3dSmrg #ifndef HAVE_STRUCT_TMS
321debfc3dSmrg struct tms
331debfc3dSmrg {
341debfc3dSmrg   clock_t tms_utime;
351debfc3dSmrg   clock_t tms_stime;
361debfc3dSmrg   clock_t tms_cutime;
371debfc3dSmrg   clock_t tms_cstime;
381debfc3dSmrg };
391debfc3dSmrg #endif
401debfc3dSmrg 
411debfc3dSmrg #ifndef RUSAGE_SELF
421debfc3dSmrg # define RUSAGE_SELF 0
431debfc3dSmrg #endif
441debfc3dSmrg 
451debfc3dSmrg /* Calculation of scale factor to convert ticks to microseconds.
461debfc3dSmrg    We mustn't use CLOCKS_PER_SEC except with clock().  */
471debfc3dSmrg #if HAVE_SYSCONF && defined _SC_CLK_TCK
481debfc3dSmrg # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
491debfc3dSmrg #else
501debfc3dSmrg # ifdef CLK_TCK
511debfc3dSmrg #  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
521debfc3dSmrg # else
531debfc3dSmrg #  ifdef HZ
541debfc3dSmrg #   define TICKS_PER_SECOND HZ  /* traditional UNIX */
551debfc3dSmrg #  else
561debfc3dSmrg #   define TICKS_PER_SECOND 100 /* often the correct value */
571debfc3dSmrg #  endif
581debfc3dSmrg # endif
591debfc3dSmrg #endif
601debfc3dSmrg 
611debfc3dSmrg /* Prefer times to getrusage to clock (each gives successively less
621debfc3dSmrg    information).  */
631debfc3dSmrg #ifdef HAVE_TIMES
641debfc3dSmrg # if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
651debfc3dSmrg   extern clock_t times (struct tms *);
661debfc3dSmrg # endif
671debfc3dSmrg # define USE_TIMES
681debfc3dSmrg # define HAVE_USER_TIME
691debfc3dSmrg # define HAVE_SYS_TIME
701debfc3dSmrg # define HAVE_WALL_TIME
711debfc3dSmrg #else
721debfc3dSmrg #ifdef HAVE_GETRUSAGE
731debfc3dSmrg # if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
741debfc3dSmrg   extern int getrusage (int, struct rusage *);
751debfc3dSmrg # endif
761debfc3dSmrg # define USE_GETRUSAGE
771debfc3dSmrg # define HAVE_USER_TIME
781debfc3dSmrg # define HAVE_SYS_TIME
791debfc3dSmrg #else
801debfc3dSmrg #ifdef HAVE_CLOCK
811debfc3dSmrg # if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
821debfc3dSmrg   extern clock_t clock (void);
831debfc3dSmrg # endif
841debfc3dSmrg # define USE_CLOCK
851debfc3dSmrg # define HAVE_USER_TIME
861debfc3dSmrg #endif
871debfc3dSmrg #endif
881debfc3dSmrg #endif
891debfc3dSmrg 
901debfc3dSmrg /* libc is very likely to have snuck a call to sysconf() into one of
911debfc3dSmrg    the underlying constants, and that can be very slow, so we have to
921debfc3dSmrg    precompute them.  Whose wonderful idea was it to make all those
931debfc3dSmrg    _constants_ variable at run time, anyway?  */
941debfc3dSmrg #ifdef USE_TIMES
951debfc3dSmrg static double ticks_to_msec;
961debfc3dSmrg #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
971debfc3dSmrg #endif
981debfc3dSmrg 
991debfc3dSmrg #ifdef USE_CLOCK
1001debfc3dSmrg static double clocks_to_msec;
1011debfc3dSmrg #define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
1021debfc3dSmrg #endif
1031debfc3dSmrg 
1041debfc3dSmrg /* Non-NULL if timevars should be used.  In GCC, this happens with
1051debfc3dSmrg    the -ftime-report flag.  */
1061debfc3dSmrg 
1071debfc3dSmrg timer *g_timer;
1081debfc3dSmrg 
1091debfc3dSmrg /* Total amount of memory allocated by garbage collector.  */
1101debfc3dSmrg 
1111debfc3dSmrg size_t timevar_ggc_mem_total;
1121debfc3dSmrg 
1131debfc3dSmrg /* The amount of memory that will cause us to report the timevar even
1141debfc3dSmrg    if the time spent is not significant.  */
1151debfc3dSmrg 
1161debfc3dSmrg #define GGC_MEM_BOUND (1 << 20)
1171debfc3dSmrg 
1181debfc3dSmrg /* See timevar.h for an explanation of timing variables.  */
1191debfc3dSmrg 
1201debfc3dSmrg static void get_time (struct timevar_time_def *);
1211debfc3dSmrg static void timevar_accumulate (struct timevar_time_def *,
1221debfc3dSmrg 				struct timevar_time_def *,
1231debfc3dSmrg 				struct timevar_time_def *);
1241debfc3dSmrg 
1251debfc3dSmrg /* The implementation of timing events for jit client code, allowing
1261debfc3dSmrg    arbitrary named items to appear on the timing stack.  */
1271debfc3dSmrg 
1281debfc3dSmrg class timer::named_items
1291debfc3dSmrg {
1301debfc3dSmrg  public:
1311debfc3dSmrg   named_items (timer *t);
1321debfc3dSmrg   ~named_items ();
1331debfc3dSmrg 
1341debfc3dSmrg   void push (const char *item_name);
1351debfc3dSmrg   void pop ();
1361debfc3dSmrg   void print (FILE *fp, const timevar_time_def *total);
1371debfc3dSmrg 
1381debfc3dSmrg  private:
1391debfc3dSmrg   /* Which timer instance does this relate to?  */
1401debfc3dSmrg   timer *m_timer;
1411debfc3dSmrg 
1421debfc3dSmrg   /* Dictionary, mapping from item names to timevar_def.
1431debfc3dSmrg      Note that currently we merely store/compare the raw string
1441debfc3dSmrg      pointers provided by client code; we don't take a copy,
1451debfc3dSmrg      or use strcmp.  */
1461debfc3dSmrg   hash_map <const char *, timer::timevar_def> m_hash_map;
1471debfc3dSmrg 
1481debfc3dSmrg   /* The order in which items were originally inserted.  */
1491debfc3dSmrg   auto_vec <const char *> m_names;
1501debfc3dSmrg };
1511debfc3dSmrg 
1521debfc3dSmrg /* The constructor for class timer::named_items.  */
1531debfc3dSmrg 
named_items(timer * t)1541debfc3dSmrg timer::named_items::named_items (timer *t)
1551debfc3dSmrg : m_timer (t),
1561debfc3dSmrg   m_hash_map (),
1571debfc3dSmrg   m_names ()
1581debfc3dSmrg {
1591debfc3dSmrg }
1601debfc3dSmrg 
1611debfc3dSmrg /* The destructor for class timer::named_items.  */
1621debfc3dSmrg 
~named_items()1631debfc3dSmrg timer::named_items::~named_items ()
1641debfc3dSmrg {
1651debfc3dSmrg }
1661debfc3dSmrg 
1671debfc3dSmrg /* Push the named item onto the timer stack.  */
1681debfc3dSmrg 
1691debfc3dSmrg void
push(const char * item_name)1701debfc3dSmrg timer::named_items::push (const char *item_name)
1711debfc3dSmrg {
1721debfc3dSmrg   gcc_assert (item_name);
1731debfc3dSmrg 
1741debfc3dSmrg   bool existed;
1751debfc3dSmrg   timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
1761debfc3dSmrg   if (!existed)
1771debfc3dSmrg     {
1781debfc3dSmrg       def->elapsed.user = 0;
1791debfc3dSmrg       def->elapsed.sys = 0;
1801debfc3dSmrg       def->elapsed.wall = 0;
1811debfc3dSmrg       def->name = item_name;
1821debfc3dSmrg       def->standalone = 0;
1831debfc3dSmrg       m_names.safe_push (item_name);
1841debfc3dSmrg     }
1851debfc3dSmrg   m_timer->push_internal (def);
1861debfc3dSmrg }
1871debfc3dSmrg 
1881debfc3dSmrg /* Pop the top item from the timer stack.  */
1891debfc3dSmrg 
1901debfc3dSmrg void
pop()1911debfc3dSmrg timer::named_items::pop ()
1921debfc3dSmrg {
1931debfc3dSmrg   m_timer->pop_internal ();
1941debfc3dSmrg }
1951debfc3dSmrg 
1961debfc3dSmrg /* Print the given client item.  Helper function for timer::print.  */
1971debfc3dSmrg 
1981debfc3dSmrg void
print(FILE * fp,const timevar_time_def * total)1991debfc3dSmrg timer::named_items::print (FILE *fp, const timevar_time_def *total)
2001debfc3dSmrg {
2011debfc3dSmrg   unsigned int i;
2021debfc3dSmrg   const char *item_name;
2031debfc3dSmrg   fprintf (fp, "Client items:\n");
2041debfc3dSmrg   FOR_EACH_VEC_ELT (m_names, i, item_name)
2051debfc3dSmrg     {
2061debfc3dSmrg       timer::timevar_def *def = m_hash_map.get (item_name);
2071debfc3dSmrg       gcc_assert (def);
2081debfc3dSmrg       m_timer->print_row (fp, total, def->name, def->elapsed);
2091debfc3dSmrg     }
2101debfc3dSmrg }
2111debfc3dSmrg 
2121debfc3dSmrg /* Fill the current times into TIME.  The definition of this function
2131debfc3dSmrg    also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
2141debfc3dSmrg    HAVE_WALL_TIME macros.  */
2151debfc3dSmrg 
2161debfc3dSmrg static void
get_time(struct timevar_time_def * now)2171debfc3dSmrg get_time (struct timevar_time_def *now)
2181debfc3dSmrg {
2191debfc3dSmrg   now->user = 0;
2201debfc3dSmrg   now->sys  = 0;
2211debfc3dSmrg   now->wall = 0;
2221debfc3dSmrg   now->ggc_mem = timevar_ggc_mem_total;
2231debfc3dSmrg 
2241debfc3dSmrg   {
2251debfc3dSmrg #ifdef USE_TIMES
2261debfc3dSmrg     struct tms tms;
2271debfc3dSmrg     now->wall = times (&tms)  * ticks_to_msec;
2281debfc3dSmrg     now->user = tms.tms_utime * ticks_to_msec;
2291debfc3dSmrg     now->sys  = tms.tms_stime * ticks_to_msec;
2301debfc3dSmrg #endif
2311debfc3dSmrg #ifdef USE_GETRUSAGE
2321debfc3dSmrg     struct rusage rusage;
2331debfc3dSmrg     getrusage (RUSAGE_SELF, &rusage);
2341debfc3dSmrg     now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
2351debfc3dSmrg     now->sys  = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
2361debfc3dSmrg #endif
2371debfc3dSmrg #ifdef USE_CLOCK
2381debfc3dSmrg     now->user = clock () * clocks_to_msec;
2391debfc3dSmrg #endif
2401debfc3dSmrg   }
2411debfc3dSmrg }
2421debfc3dSmrg 
2431debfc3dSmrg /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
2441debfc3dSmrg 
2451debfc3dSmrg static void
timevar_accumulate(struct timevar_time_def * timer,struct timevar_time_def * start_time,struct timevar_time_def * stop_time)2461debfc3dSmrg timevar_accumulate (struct timevar_time_def *timer,
2471debfc3dSmrg 		    struct timevar_time_def *start_time,
2481debfc3dSmrg 		    struct timevar_time_def *stop_time)
2491debfc3dSmrg {
2501debfc3dSmrg   timer->user += stop_time->user - start_time->user;
2511debfc3dSmrg   timer->sys += stop_time->sys - start_time->sys;
2521debfc3dSmrg   timer->wall += stop_time->wall - start_time->wall;
2531debfc3dSmrg   timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
2541debfc3dSmrg }
2551debfc3dSmrg 
2561debfc3dSmrg /* Class timer's constructor.  */
2571debfc3dSmrg 
timer()2581debfc3dSmrg timer::timer () :
2591debfc3dSmrg   m_stack (NULL),
2601debfc3dSmrg   m_unused_stack_instances (NULL),
2611debfc3dSmrg   m_start_time (),
2621debfc3dSmrg   m_jit_client_items (NULL)
2631debfc3dSmrg {
2641debfc3dSmrg   /* Zero all elapsed times.  */
2651debfc3dSmrg   memset (m_timevars, 0, sizeof (m_timevars));
2661debfc3dSmrg 
2671debfc3dSmrg   /* Initialize the names of timing variables.  */
2681debfc3dSmrg #define DEFTIMEVAR(identifier__, name__) \
2691debfc3dSmrg   m_timevars[identifier__].name = name__;
2701debfc3dSmrg #include "timevar.def"
2711debfc3dSmrg #undef DEFTIMEVAR
2721debfc3dSmrg 
2731debfc3dSmrg   /* Initialize configuration-specific state.
2741debfc3dSmrg      Ideally this would be one-time initialization.  */
2751debfc3dSmrg #ifdef USE_TIMES
2761debfc3dSmrg   ticks_to_msec = TICKS_TO_MSEC;
2771debfc3dSmrg #endif
2781debfc3dSmrg #ifdef USE_CLOCK
2791debfc3dSmrg   clocks_to_msec = CLOCKS_TO_MSEC;
2801debfc3dSmrg #endif
2811debfc3dSmrg }
2821debfc3dSmrg 
2831debfc3dSmrg /* Class timer's destructor.  */
2841debfc3dSmrg 
~timer()2851debfc3dSmrg timer::~timer ()
2861debfc3dSmrg {
2871debfc3dSmrg   timevar_stack_def *iter, *next;
2881debfc3dSmrg 
2891debfc3dSmrg   for (iter = m_stack; iter; iter = next)
2901debfc3dSmrg     {
2911debfc3dSmrg       next = iter->next;
2921debfc3dSmrg       free (iter);
2931debfc3dSmrg     }
2941debfc3dSmrg   for (iter = m_unused_stack_instances; iter; iter = next)
2951debfc3dSmrg     {
2961debfc3dSmrg       next = iter->next;
2971debfc3dSmrg       free (iter);
2981debfc3dSmrg     }
2991debfc3dSmrg   for (unsigned i = 0; i < TIMEVAR_LAST; ++i)
3001debfc3dSmrg     delete m_timevars[i].children;
3011debfc3dSmrg 
3021debfc3dSmrg   delete m_jit_client_items;
3031debfc3dSmrg }
3041debfc3dSmrg 
3051debfc3dSmrg /* Initialize timing variables.  */
3061debfc3dSmrg 
3071debfc3dSmrg void
timevar_init(void)3081debfc3dSmrg timevar_init (void)
3091debfc3dSmrg {
3101debfc3dSmrg   if (g_timer)
3111debfc3dSmrg     return;
3121debfc3dSmrg 
3131debfc3dSmrg   g_timer = new timer ();
3141debfc3dSmrg }
3151debfc3dSmrg 
3161debfc3dSmrg /* Push TIMEVAR onto the timing stack.  No further elapsed time is
3171debfc3dSmrg    attributed to the previous topmost timing variable on the stack;
3181debfc3dSmrg    subsequent elapsed time is attributed to TIMEVAR, until it is
3191debfc3dSmrg    popped or another element is pushed on top.
3201debfc3dSmrg 
3211debfc3dSmrg    TIMEVAR cannot be running as a standalone timer.  */
3221debfc3dSmrg 
3231debfc3dSmrg void
push(timevar_id_t timevar)3241debfc3dSmrg timer::push (timevar_id_t timevar)
3251debfc3dSmrg {
3261debfc3dSmrg   struct timevar_def *tv = &m_timevars[timevar];
3271debfc3dSmrg   push_internal (tv);
3281debfc3dSmrg }
3291debfc3dSmrg 
3301debfc3dSmrg /* Push TV onto the timing stack, either one of the builtin ones
3311debfc3dSmrg    for a timevar_id_t, or one provided by client code to libgccjit.  */
3321debfc3dSmrg 
3331debfc3dSmrg void
push_internal(struct timevar_def * tv)3341debfc3dSmrg timer::push_internal (struct timevar_def *tv)
3351debfc3dSmrg {
3361debfc3dSmrg   struct timevar_stack_def *context;
3371debfc3dSmrg   struct timevar_time_def now;
3381debfc3dSmrg 
3391debfc3dSmrg   gcc_assert (tv);
3401debfc3dSmrg 
3411debfc3dSmrg   /* Mark this timing variable as used.  */
3421debfc3dSmrg   tv->used = 1;
3431debfc3dSmrg 
3441debfc3dSmrg   /* Can't push a standalone timer.  */
3451debfc3dSmrg   gcc_assert (!tv->standalone);
3461debfc3dSmrg 
3471debfc3dSmrg   /* What time is it?  */
3481debfc3dSmrg   get_time (&now);
3491debfc3dSmrg 
3501debfc3dSmrg   /* If the stack isn't empty, attribute the current elapsed time to
3511debfc3dSmrg      the old topmost element.  */
3521debfc3dSmrg   if (m_stack)
3531debfc3dSmrg     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
3541debfc3dSmrg 
3551debfc3dSmrg   /* Reset the start time; from now on, time is attributed to
3561debfc3dSmrg      TIMEVAR.  */
3571debfc3dSmrg   m_start_time = now;
3581debfc3dSmrg 
3591debfc3dSmrg   /* See if we have a previously-allocated stack instance.  If so,
3601debfc3dSmrg      take it off the list.  If not, malloc a new one.  */
3611debfc3dSmrg   if (m_unused_stack_instances != NULL)
3621debfc3dSmrg     {
3631debfc3dSmrg       context = m_unused_stack_instances;
3641debfc3dSmrg       m_unused_stack_instances = m_unused_stack_instances->next;
3651debfc3dSmrg     }
3661debfc3dSmrg   else
3671debfc3dSmrg     context = XNEW (struct timevar_stack_def);
3681debfc3dSmrg 
3691debfc3dSmrg   /* Fill it in and put it on the stack.  */
3701debfc3dSmrg   context->timevar = tv;
3711debfc3dSmrg   context->next = m_stack;
3721debfc3dSmrg   m_stack = context;
3731debfc3dSmrg }
3741debfc3dSmrg 
3751debfc3dSmrg /* Pop the topmost timing variable element off the timing stack.  The
3761debfc3dSmrg    popped variable must be TIMEVAR.  Elapsed time since the that
3771debfc3dSmrg    element was pushed on, or since it was last exposed on top of the
3781debfc3dSmrg    stack when the element above it was popped off, is credited to that
3791debfc3dSmrg    timing variable.  */
3801debfc3dSmrg 
3811debfc3dSmrg void
pop(timevar_id_t timevar)3821debfc3dSmrg timer::pop (timevar_id_t timevar)
3831debfc3dSmrg {
3841debfc3dSmrg   gcc_assert (&m_timevars[timevar] == m_stack->timevar);
3851debfc3dSmrg 
3861debfc3dSmrg   pop_internal ();
3871debfc3dSmrg }
3881debfc3dSmrg 
3891debfc3dSmrg /* Pop the topmost item from the stack, either one of the builtin ones
3901debfc3dSmrg    for a timevar_id_t, or one provided by client code to libgccjit.  */
3911debfc3dSmrg 
3921debfc3dSmrg void
pop_internal()3931debfc3dSmrg timer::pop_internal ()
3941debfc3dSmrg {
3951debfc3dSmrg   struct timevar_time_def now;
3961debfc3dSmrg   struct timevar_stack_def *popped = m_stack;
3971debfc3dSmrg 
3981debfc3dSmrg   /* What time is it?  */
3991debfc3dSmrg   get_time (&now);
4001debfc3dSmrg 
4011debfc3dSmrg   /* Attribute the elapsed time to the element we're popping.  */
4021debfc3dSmrg   timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now);
4031debfc3dSmrg 
4041debfc3dSmrg   /* Take the item off the stack.  */
4051debfc3dSmrg   m_stack = m_stack->next;
4061debfc3dSmrg 
4071debfc3dSmrg   /* Record the elapsed sub-time to the parent as well.  */
4081debfc3dSmrg   if (m_stack && time_report_details)
4091debfc3dSmrg     {
4101debfc3dSmrg       if (! m_stack->timevar->children)
4111debfc3dSmrg 	m_stack->timevar->children = new child_map_t (5);
4121debfc3dSmrg       bool existed_p;
4131debfc3dSmrg       timevar_time_def &time
4141debfc3dSmrg 	= m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p);
4151debfc3dSmrg       if (! existed_p)
4161debfc3dSmrg 	memset (&time, 0, sizeof (timevar_time_def));
4171debfc3dSmrg       timevar_accumulate (&time, &m_start_time, &now);
4181debfc3dSmrg     }
4191debfc3dSmrg 
4201debfc3dSmrg   /* Reset the start time; from now on, time is attributed to the
4211debfc3dSmrg      element just exposed on the stack.  */
4221debfc3dSmrg   m_start_time = now;
4231debfc3dSmrg 
4241debfc3dSmrg   /* Don't delete the stack element; instead, add it to the list of
4251debfc3dSmrg      unused elements for later use.  */
4261debfc3dSmrg   popped->next = m_unused_stack_instances;
4271debfc3dSmrg   m_unused_stack_instances = popped;
4281debfc3dSmrg }
4291debfc3dSmrg 
4301debfc3dSmrg /* Start timing TIMEVAR independently of the timing stack.  Elapsed
4311debfc3dSmrg    time until timevar_stop is called for the same timing variable is
4321debfc3dSmrg    attributed to TIMEVAR.  */
4331debfc3dSmrg 
4341debfc3dSmrg void
timevar_start(timevar_id_t timevar)4351debfc3dSmrg timevar_start (timevar_id_t timevar)
4361debfc3dSmrg {
4371debfc3dSmrg   if (!g_timer)
4381debfc3dSmrg     return;
4391debfc3dSmrg 
4401debfc3dSmrg   g_timer->start (timevar);
4411debfc3dSmrg }
4421debfc3dSmrg 
4431debfc3dSmrg /* See timevar_start above.  */
4441debfc3dSmrg 
4451debfc3dSmrg void
start(timevar_id_t timevar)4461debfc3dSmrg timer::start (timevar_id_t timevar)
4471debfc3dSmrg {
4481debfc3dSmrg   struct timevar_def *tv = &m_timevars[timevar];
4491debfc3dSmrg 
4501debfc3dSmrg   /* Mark this timing variable as used.  */
4511debfc3dSmrg   tv->used = 1;
4521debfc3dSmrg 
4531debfc3dSmrg   /* Don't allow the same timing variable to be started more than
4541debfc3dSmrg      once.  */
4551debfc3dSmrg   gcc_assert (!tv->standalone);
4561debfc3dSmrg   tv->standalone = 1;
4571debfc3dSmrg 
4581debfc3dSmrg   get_time (&tv->start_time);
4591debfc3dSmrg }
4601debfc3dSmrg 
4611debfc3dSmrg /* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
4621debfc3dSmrg    is attributed to it.  */
4631debfc3dSmrg 
4641debfc3dSmrg void
timevar_stop(timevar_id_t timevar)4651debfc3dSmrg timevar_stop (timevar_id_t timevar)
4661debfc3dSmrg {
4671debfc3dSmrg   if (!g_timer)
4681debfc3dSmrg     return;
4691debfc3dSmrg 
4701debfc3dSmrg   g_timer->stop (timevar);
4711debfc3dSmrg }
4721debfc3dSmrg 
4731debfc3dSmrg /* See timevar_stop above.  */
4741debfc3dSmrg 
4751debfc3dSmrg void
stop(timevar_id_t timevar)4761debfc3dSmrg timer::stop (timevar_id_t timevar)
4771debfc3dSmrg {
4781debfc3dSmrg   struct timevar_def *tv = &m_timevars[timevar];
4791debfc3dSmrg   struct timevar_time_def now;
4801debfc3dSmrg 
4811debfc3dSmrg   /* TIMEVAR must have been started via timevar_start.  */
4821debfc3dSmrg   gcc_assert (tv->standalone);
4831debfc3dSmrg   tv->standalone = 0; /* Enable a restart.  */
4841debfc3dSmrg 
4851debfc3dSmrg   get_time (&now);
4861debfc3dSmrg   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
4871debfc3dSmrg }
4881debfc3dSmrg 
4891debfc3dSmrg 
4901debfc3dSmrg /* Conditionally start timing TIMEVAR independently of the timing stack.
4911debfc3dSmrg    If the timer is already running, leave it running and return true.
4921debfc3dSmrg    Otherwise, start the timer and return false.
4931debfc3dSmrg    Elapsed time until the corresponding timevar_cond_stop
4941debfc3dSmrg    is called for the same timing variable is attributed to TIMEVAR.  */
4951debfc3dSmrg 
4961debfc3dSmrg bool
timevar_cond_start(timevar_id_t timevar)4971debfc3dSmrg timevar_cond_start (timevar_id_t timevar)
4981debfc3dSmrg {
4991debfc3dSmrg   if (!g_timer)
5001debfc3dSmrg     return false;
5011debfc3dSmrg 
5021debfc3dSmrg   return g_timer->cond_start (timevar);
5031debfc3dSmrg }
5041debfc3dSmrg 
5051debfc3dSmrg /* See timevar_cond_start above.  */
5061debfc3dSmrg 
5071debfc3dSmrg bool
cond_start(timevar_id_t timevar)5081debfc3dSmrg timer::cond_start (timevar_id_t timevar)
5091debfc3dSmrg {
5101debfc3dSmrg   struct timevar_def *tv = &m_timevars[timevar];
5111debfc3dSmrg 
5121debfc3dSmrg   /* Mark this timing variable as used.  */
5131debfc3dSmrg   tv->used = 1;
5141debfc3dSmrg 
5151debfc3dSmrg   if (tv->standalone)
5161debfc3dSmrg     return true;  /* The timevar is already running.  */
5171debfc3dSmrg 
5181debfc3dSmrg   /* Don't allow the same timing variable
5191debfc3dSmrg      to be unconditionally started more than once.  */
5201debfc3dSmrg   tv->standalone = 1;
5211debfc3dSmrg 
5221debfc3dSmrg   get_time (&tv->start_time);
5231debfc3dSmrg   return false;  /* The timevar was not already running.  */
5241debfc3dSmrg }
5251debfc3dSmrg 
5261debfc3dSmrg /* Conditionally stop timing TIMEVAR.  The RUNNING parameter must come
5271debfc3dSmrg    from the return value of a dynamically matching timevar_cond_start.
5281debfc3dSmrg    If the timer had already been RUNNING, do nothing.  Otherwise, time
5291debfc3dSmrg    elapsed since timevar_cond_start was called is attributed to it.  */
5301debfc3dSmrg 
5311debfc3dSmrg void
timevar_cond_stop(timevar_id_t timevar,bool running)5321debfc3dSmrg timevar_cond_stop (timevar_id_t timevar, bool running)
5331debfc3dSmrg {
5341debfc3dSmrg   if (!g_timer || running)
5351debfc3dSmrg     return;
5361debfc3dSmrg 
5371debfc3dSmrg   g_timer->cond_stop (timevar);
5381debfc3dSmrg }
5391debfc3dSmrg 
5401debfc3dSmrg /* See timevar_cond_stop above.  */
5411debfc3dSmrg 
5421debfc3dSmrg void
cond_stop(timevar_id_t timevar)5431debfc3dSmrg timer::cond_stop (timevar_id_t timevar)
5441debfc3dSmrg {
5451debfc3dSmrg   struct timevar_def *tv;
5461debfc3dSmrg   struct timevar_time_def now;
5471debfc3dSmrg 
5481debfc3dSmrg   tv = &m_timevars[timevar];
5491debfc3dSmrg 
5501debfc3dSmrg   /* TIMEVAR must have been started via timevar_cond_start.  */
5511debfc3dSmrg   gcc_assert (tv->standalone);
5521debfc3dSmrg   tv->standalone = 0; /* Enable a restart.  */
5531debfc3dSmrg 
5541debfc3dSmrg   get_time (&now);
5551debfc3dSmrg   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
5561debfc3dSmrg }
5571debfc3dSmrg 
5581debfc3dSmrg /* Push the named item onto the timing stack.  */
5591debfc3dSmrg 
5601debfc3dSmrg void
push_client_item(const char * item_name)5611debfc3dSmrg timer::push_client_item (const char *item_name)
5621debfc3dSmrg {
5631debfc3dSmrg   gcc_assert (item_name);
5641debfc3dSmrg 
5651debfc3dSmrg   /* Lazily create the named_items instance.  */
5661debfc3dSmrg   if (!m_jit_client_items)
5671debfc3dSmrg     m_jit_client_items = new named_items (this);
5681debfc3dSmrg 
5691debfc3dSmrg   m_jit_client_items->push (item_name);
5701debfc3dSmrg }
5711debfc3dSmrg 
5721debfc3dSmrg /* Pop the top-most client item from the timing stack.  */
5731debfc3dSmrg 
5741debfc3dSmrg void
pop_client_item()5751debfc3dSmrg timer::pop_client_item ()
5761debfc3dSmrg {
5771debfc3dSmrg   gcc_assert (m_jit_client_items);
5781debfc3dSmrg   m_jit_client_items->pop ();
5791debfc3dSmrg }
5801debfc3dSmrg 
5811debfc3dSmrg /* Validate that phase times are consistent.  */
5821debfc3dSmrg 
5831debfc3dSmrg void
validate_phases(FILE * fp)5841debfc3dSmrg timer::validate_phases (FILE *fp) const
5851debfc3dSmrg {
5861debfc3dSmrg   unsigned int /* timevar_id_t */ id;
5871debfc3dSmrg   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
5881debfc3dSmrg   double phase_user = 0.0;
5891debfc3dSmrg   double phase_sys = 0.0;
5901debfc3dSmrg   double phase_wall = 0.0;
5911debfc3dSmrg   size_t phase_ggc_mem = 0;
5921debfc3dSmrg   static char phase_prefix[] = "phase ";
5931debfc3dSmrg   const double tolerance = 1.000001;  /* One part in a million.  */
5941debfc3dSmrg 
5951debfc3dSmrg   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
5961debfc3dSmrg     {
5971debfc3dSmrg       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
5981debfc3dSmrg 
5991debfc3dSmrg       /* Don't evaluate timing variables that were never used.  */
6001debfc3dSmrg       if (!tv->used)
6011debfc3dSmrg 	continue;
6021debfc3dSmrg 
6031debfc3dSmrg       if (strncmp (tv->name, phase_prefix, sizeof phase_prefix - 1) == 0)
6041debfc3dSmrg 	{
6051debfc3dSmrg 	  phase_user += tv->elapsed.user;
6061debfc3dSmrg 	  phase_sys += tv->elapsed.sys;
6071debfc3dSmrg 	  phase_wall += tv->elapsed.wall;
6081debfc3dSmrg 	  phase_ggc_mem += tv->elapsed.ggc_mem;
6091debfc3dSmrg 	}
6101debfc3dSmrg     }
6111debfc3dSmrg 
6121debfc3dSmrg   if (phase_user > total->user * tolerance
6131debfc3dSmrg       || phase_sys > total->sys * tolerance
6141debfc3dSmrg       || phase_wall > total->wall * tolerance
6151debfc3dSmrg       || phase_ggc_mem > total->ggc_mem * tolerance)
6161debfc3dSmrg     {
6171debfc3dSmrg 
6181debfc3dSmrg       fprintf (fp, "Timing error: total of phase timers exceeds total time.\n");
6191debfc3dSmrg       if (phase_user > total->user)
6201debfc3dSmrg 	fprintf (fp, "user    %24.18e > %24.18e\n", phase_user, total->user);
6211debfc3dSmrg       if (phase_sys > total->sys)
6221debfc3dSmrg 	fprintf (fp, "sys     %24.18e > %24.18e\n", phase_sys, total->sys);
6231debfc3dSmrg       if (phase_wall > total->wall)
6241debfc3dSmrg 	fprintf (fp, "wall    %24.18e > %24.18e\n", phase_wall, total->wall);
6251debfc3dSmrg       if (phase_ggc_mem > total->ggc_mem)
6261debfc3dSmrg 	fprintf (fp, "ggc_mem %24lu > %24lu\n", (unsigned long)phase_ggc_mem,
6271debfc3dSmrg 		 (unsigned long)total->ggc_mem);
6281debfc3dSmrg       gcc_unreachable ();
6291debfc3dSmrg     }
6301debfc3dSmrg }
6311debfc3dSmrg 
6321debfc3dSmrg /* Helper function for timer::print.  */
6331debfc3dSmrg 
6341debfc3dSmrg void
print_row(FILE * fp,const timevar_time_def * total,const char * name,const timevar_time_def & elapsed)6351debfc3dSmrg timer::print_row (FILE *fp,
6361debfc3dSmrg 		  const timevar_time_def *total,
6371debfc3dSmrg 		  const char *name, const timevar_time_def &elapsed)
6381debfc3dSmrg {
6391debfc3dSmrg   /* The timing variable name.  */
640a2dc1f3fSmrg   fprintf (fp, " %-35s:", name);
6411debfc3dSmrg 
6421debfc3dSmrg #ifdef HAVE_USER_TIME
6431debfc3dSmrg   /* Print user-mode time for this process.  */
644a2dc1f3fSmrg   fprintf (fp, "%7.2f (%3.0f%%)",
6451debfc3dSmrg 	   elapsed.user,
6461debfc3dSmrg 	   (total->user == 0 ? 0 : elapsed.user / total->user) * 100);
6471debfc3dSmrg #endif /* HAVE_USER_TIME */
6481debfc3dSmrg 
6491debfc3dSmrg #ifdef HAVE_SYS_TIME
6501debfc3dSmrg   /* Print system-mode time for this process.  */
651a2dc1f3fSmrg   fprintf (fp, "%7.2f (%3.0f%%)",
6521debfc3dSmrg 	   elapsed.sys,
6531debfc3dSmrg 	   (total->sys == 0 ? 0 : elapsed.sys / total->sys) * 100);
6541debfc3dSmrg #endif /* HAVE_SYS_TIME */
6551debfc3dSmrg 
6561debfc3dSmrg #ifdef HAVE_WALL_TIME
6571debfc3dSmrg   /* Print wall clock time elapsed.  */
658a2dc1f3fSmrg   fprintf (fp, "%7.2f (%3.0f%%)",
6591debfc3dSmrg 	   elapsed.wall,
6601debfc3dSmrg 	   (total->wall == 0 ? 0 : elapsed.wall / total->wall) * 100);
6611debfc3dSmrg #endif /* HAVE_WALL_TIME */
6621debfc3dSmrg 
6631debfc3dSmrg   /* Print the amount of ggc memory allocated.  */
664a2dc1f3fSmrg   fprintf (fp, "%8u kB (%3.0f%%)",
6651debfc3dSmrg 	   (unsigned) (elapsed.ggc_mem >> 10),
6661debfc3dSmrg 	   (total->ggc_mem == 0
6671debfc3dSmrg 	    ? 0
6681debfc3dSmrg 	    : (float) elapsed.ggc_mem / total->ggc_mem) * 100);
6691debfc3dSmrg 
6701debfc3dSmrg   putc ('\n', fp);
6711debfc3dSmrg }
6721debfc3dSmrg 
6731debfc3dSmrg /* Return whether ELAPSED is all zero.  */
6741debfc3dSmrg 
6751debfc3dSmrg bool
all_zero(const timevar_time_def & elapsed)6761debfc3dSmrg timer::all_zero (const timevar_time_def &elapsed)
6771debfc3dSmrg {
6781debfc3dSmrg   const double tiny = 5e-3;
6791debfc3dSmrg   return (elapsed.user < tiny
6801debfc3dSmrg 	  && elapsed.sys < tiny
6811debfc3dSmrg 	  && elapsed.wall < tiny
6821debfc3dSmrg 	  && elapsed.ggc_mem < GGC_MEM_BOUND);
6831debfc3dSmrg }
6841debfc3dSmrg 
6851debfc3dSmrg /* Summarize timing variables to FP.  The timing variable TV_TOTAL has
6861debfc3dSmrg    a special meaning -- it's considered to be the total elapsed time,
6871debfc3dSmrg    for normalizing the others, and is displayed last.  */
6881debfc3dSmrg 
6891debfc3dSmrg void
print(FILE * fp)6901debfc3dSmrg timer::print (FILE *fp)
6911debfc3dSmrg {
6921debfc3dSmrg   /* Only print stuff if we have some sort of time information.  */
6931debfc3dSmrg #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
6941debfc3dSmrg   unsigned int /* timevar_id_t */ id;
6951debfc3dSmrg   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
6961debfc3dSmrg   struct timevar_time_def now;
6971debfc3dSmrg 
6981debfc3dSmrg   /* Update timing information in case we're calling this from GDB.  */
6991debfc3dSmrg 
7001debfc3dSmrg   if (fp == 0)
7011debfc3dSmrg     fp = stderr;
7021debfc3dSmrg 
7031debfc3dSmrg   /* What time is it?  */
7041debfc3dSmrg   get_time (&now);
7051debfc3dSmrg 
7061debfc3dSmrg   /* If the stack isn't empty, attribute the current elapsed time to
7071debfc3dSmrg      the old topmost element.  */
7081debfc3dSmrg   if (m_stack)
7091debfc3dSmrg     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
7101debfc3dSmrg 
7111debfc3dSmrg   /* Reset the start time; from now on, time is attributed to
7121debfc3dSmrg      TIMEVAR.  */
7131debfc3dSmrg   m_start_time = now;
7141debfc3dSmrg 
715a2dc1f3fSmrg   fprintf (fp, "\n%-35s%16s%14s%14s%18s\n", "Time variable", "usr", "sys",
716a2dc1f3fSmrg 	   "wall", "GGC");
7171debfc3dSmrg   if (m_jit_client_items)
7181debfc3dSmrg     fputs ("GCC items:\n", fp);
7191debfc3dSmrg   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
7201debfc3dSmrg     {
7211debfc3dSmrg       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
7221debfc3dSmrg 
7231debfc3dSmrg       /* Don't print the total execution time here; that goes at the
7241debfc3dSmrg 	 end.  */
7251debfc3dSmrg       if ((timevar_id_t) id == TV_TOTAL)
7261debfc3dSmrg 	continue;
7271debfc3dSmrg 
7281debfc3dSmrg       /* Don't print timing variables that were never used.  */
7291debfc3dSmrg       if (!tv->used)
7301debfc3dSmrg 	continue;
7311debfc3dSmrg 
7321debfc3dSmrg       bool any_children_with_time = false;
7331debfc3dSmrg       if (tv->children)
7341debfc3dSmrg 	for (child_map_t::iterator i = tv->children->begin ();
7351debfc3dSmrg 	     i != tv->children->end (); ++i)
7361debfc3dSmrg 	  if (! all_zero ((*i).second))
7371debfc3dSmrg 	    {
7381debfc3dSmrg 	      any_children_with_time = true;
7391debfc3dSmrg 	      break;
7401debfc3dSmrg 	    }
7411debfc3dSmrg 
7421debfc3dSmrg       /* Don't print timing variables if we're going to get a row of
7431debfc3dSmrg          zeroes.  Unless there are children with non-zero time.  */
7441debfc3dSmrg       if (! any_children_with_time
7451debfc3dSmrg 	  && all_zero (tv->elapsed))
7461debfc3dSmrg 	continue;
7471debfc3dSmrg 
7481debfc3dSmrg       print_row (fp, total, tv->name, tv->elapsed);
7491debfc3dSmrg 
7501debfc3dSmrg       if (tv->children)
7511debfc3dSmrg 	for (child_map_t::iterator i = tv->children->begin ();
7521debfc3dSmrg 	     i != tv->children->end (); ++i)
7531debfc3dSmrg 	  {
7541debfc3dSmrg 	    timevar_def *tv2 = (*i).first;
7551debfc3dSmrg 	    /* Don't print timing variables if we're going to get a row of
7561debfc3dSmrg 	       zeroes.  */
7571debfc3dSmrg 	    if (! all_zero ((*i).second))
7581debfc3dSmrg 	      {
7591debfc3dSmrg 		char lname[256];
7601debfc3dSmrg 		snprintf (lname, 256, "`- %s", tv2->name);
7611debfc3dSmrg 		print_row (fp, total, lname, (*i).second);
7621debfc3dSmrg 	      }
7631debfc3dSmrg 	  }
7641debfc3dSmrg     }
7651debfc3dSmrg   if (m_jit_client_items)
7661debfc3dSmrg     m_jit_client_items->print (fp, total);
7671debfc3dSmrg 
7681debfc3dSmrg   /* Print total time.  */
769a2dc1f3fSmrg   fprintf (fp, " %-35s:", "TOTAL");
7701debfc3dSmrg #ifdef HAVE_USER_TIME
7711debfc3dSmrg   fprintf (fp, "%7.2f      ", total->user);
7721debfc3dSmrg #endif
7731debfc3dSmrg #ifdef HAVE_SYS_TIME
774a2dc1f3fSmrg   fprintf (fp, "%8.2f      ", total->sys);
7751debfc3dSmrg #endif
7761debfc3dSmrg #ifdef HAVE_WALL_TIME
777a2dc1f3fSmrg   fprintf (fp, "%8.2f      ", total->wall);
7781debfc3dSmrg #endif
779a2dc1f3fSmrg   fprintf (fp, "%9u kB\n", (unsigned) (total->ggc_mem >> 10));
7801debfc3dSmrg 
7811debfc3dSmrg   if (CHECKING_P || flag_checking)
7821debfc3dSmrg     fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
7831debfc3dSmrg   if (CHECKING_P)
7841debfc3dSmrg     fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
7851debfc3dSmrg #ifndef ENABLE_ASSERT_CHECKING
7861debfc3dSmrg   fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
7871debfc3dSmrg   fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
7881debfc3dSmrg #endif
7891debfc3dSmrg 
7901debfc3dSmrg #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
7911debfc3dSmrg 	  || defined (HAVE_WALL_TIME) */
7921debfc3dSmrg 
7931debfc3dSmrg   validate_phases (fp);
7941debfc3dSmrg }
7951debfc3dSmrg 
7961debfc3dSmrg /* Get the name of the topmost item.  For use by jit for validating
7971debfc3dSmrg    inputs to gcc_jit_timer_pop.  */
7981debfc3dSmrg const char *
get_topmost_item_name()7991debfc3dSmrg timer::get_topmost_item_name () const
8001debfc3dSmrg {
8011debfc3dSmrg   if (m_stack)
8021debfc3dSmrg     return m_stack->timevar->name;
8031debfc3dSmrg   else
8041debfc3dSmrg     return NULL;
8051debfc3dSmrg }
8061debfc3dSmrg 
8071debfc3dSmrg /* Prints a message to stderr stating that time elapsed in STR is
8081debfc3dSmrg    TOTAL (given in microseconds).  */
8091debfc3dSmrg 
8101debfc3dSmrg void
print_time(const char * str,long total)8111debfc3dSmrg print_time (const char *str, long total)
8121debfc3dSmrg {
8131debfc3dSmrg   long all_time = get_run_time ();
8141debfc3dSmrg   fprintf (stderr,
8151debfc3dSmrg 	   "time in %s: %ld.%06ld (%ld%%)\n",
8161debfc3dSmrg 	   str, total / 1000000, total % 1000000,
8171debfc3dSmrg 	   all_time == 0 ? 0
8181debfc3dSmrg 	   : (long) (((100.0 * (double) total) / (double) all_time) + .5));
8191debfc3dSmrg }
820