Home | History | Annotate | Line # | Download | only in gcc
      1  1.1  mrg /* Timing variables for measuring compiler performance.
      2  1.1  mrg    Copyright (C) 2000-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Alex Samuel <samuel (at) codesourcery.com>
      4  1.1  mrg 
      5  1.1  mrg This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg GCC is free software; you can redistribute it and/or modify it under
      8  1.1  mrg the terms of the GNU General Public License as published by the Free
      9  1.1  mrg Software Foundation; either version 3, or (at your option) any later
     10  1.1  mrg version.
     11  1.1  mrg 
     12  1.1  mrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
     13  1.1  mrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
     14  1.1  mrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     15  1.1  mrg for more details.
     16  1.1  mrg 
     17  1.1  mrg You should have received a copy of the GNU General Public License
     18  1.1  mrg along with GCC; see the file COPYING3.  If not see
     19  1.1  mrg <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #include "config.h"
     22  1.1  mrg #include "system.h"
     23  1.1  mrg #include "coretypes.h"
     24  1.1  mrg #include "timevar.h"
     25  1.1  mrg #include "options.h"
     26  1.1  mrg 
     27  1.1  mrg #ifndef HAVE_CLOCK_T
     28  1.1  mrg typedef int clock_t;
     29  1.1  mrg #endif
     30  1.1  mrg 
     31  1.1  mrg #ifndef HAVE_STRUCT_TMS
     32  1.1  mrg struct tms
     33  1.1  mrg {
     34  1.1  mrg   clock_t tms_utime;
     35  1.1  mrg   clock_t tms_stime;
     36  1.1  mrg   clock_t tms_cutime;
     37  1.1  mrg   clock_t tms_cstime;
     38  1.1  mrg };
     39  1.1  mrg #endif
     40  1.1  mrg 
     41  1.1  mrg #ifndef RUSAGE_SELF
     42  1.1  mrg # define RUSAGE_SELF 0
     43  1.1  mrg #endif
     44  1.1  mrg 
     45  1.1  mrg /* Calculation of scale factor to convert ticks to microseconds.
     46  1.1  mrg    We mustn't use CLOCKS_PER_SEC except with clock().  */
     47  1.1  mrg #if HAVE_SYSCONF && defined _SC_CLK_TCK
     48  1.1  mrg # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
     49  1.1  mrg #else
     50  1.1  mrg # ifdef CLK_TCK
     51  1.1  mrg #  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
     52  1.1  mrg # else
     53  1.1  mrg #  ifdef HZ
     54  1.1  mrg #   define TICKS_PER_SECOND HZ  /* traditional UNIX */
     55  1.1  mrg #  else
     56  1.1  mrg #   define TICKS_PER_SECOND 100 /* often the correct value */
     57  1.1  mrg #  endif
     58  1.1  mrg # endif
     59  1.1  mrg #endif
     60  1.1  mrg 
     61  1.1  mrg /* Prefer times to getrusage to clock (each gives successively less
     62  1.1  mrg    information).  */
     63  1.1  mrg #ifdef HAVE_TIMES
     64  1.1  mrg # if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
     65  1.1  mrg   extern clock_t times (struct tms *);
     66  1.1  mrg # endif
     67  1.1  mrg # define USE_TIMES
     68  1.1  mrg # define HAVE_USER_TIME
     69  1.1  mrg # define HAVE_SYS_TIME
     70  1.1  mrg # define HAVE_WALL_TIME
     71  1.1  mrg #else
     72  1.1  mrg #ifdef HAVE_GETRUSAGE
     73  1.1  mrg # if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
     74  1.1  mrg   extern int getrusage (int, struct rusage *);
     75  1.1  mrg # endif
     76  1.1  mrg # define USE_GETRUSAGE
     77  1.1  mrg # define HAVE_USER_TIME
     78  1.1  mrg # define HAVE_SYS_TIME
     79  1.1  mrg #else
     80  1.1  mrg #ifdef HAVE_CLOCK
     81  1.1  mrg # if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
     82  1.1  mrg   extern clock_t clock (void);
     83  1.1  mrg # endif
     84  1.1  mrg # define USE_CLOCK
     85  1.1  mrg # define HAVE_USER_TIME
     86  1.1  mrg #endif
     87  1.1  mrg #endif
     88  1.1  mrg #endif
     89  1.1  mrg 
     90  1.1  mrg /* libc is very likely to have snuck a call to sysconf() into one of
     91  1.1  mrg    the underlying constants, and that can be very slow, so we have to
     92  1.1  mrg    precompute them.  Whose wonderful idea was it to make all those
     93  1.1  mrg    _constants_ variable at run time, anyway?  */
     94  1.1  mrg #ifdef USE_TIMES
     95  1.1  mrg static double ticks_to_msec;
     96  1.1  mrg #define TICKS_TO_MSEC (1 / (double)TICKS_PER_SECOND)
     97  1.1  mrg #endif
     98  1.1  mrg 
     99  1.1  mrg #ifdef USE_CLOCK
    100  1.1  mrg static double clocks_to_msec;
    101  1.1  mrg #define CLOCKS_TO_MSEC (1 / (double)CLOCKS_PER_SEC)
    102  1.1  mrg #endif
    103  1.1  mrg 
    104  1.1  mrg /* Non-NULL if timevars should be used.  In GCC, this happens with
    105  1.1  mrg    the -ftime-report flag.  */
    106  1.1  mrg 
    107  1.1  mrg timer *g_timer;
    108  1.1  mrg 
    109  1.1  mrg /* Total amount of memory allocated by garbage collector.  */
    110  1.1  mrg 
    111  1.1  mrg size_t timevar_ggc_mem_total;
    112  1.1  mrg 
    113  1.1  mrg /* The amount of memory that will cause us to report the timevar even
    114  1.1  mrg    if the time spent is not significant.  */
    115  1.1  mrg 
    116  1.1  mrg #define GGC_MEM_BOUND (1 << 20)
    117  1.1  mrg 
    118  1.1  mrg /* See timevar.h for an explanation of timing variables.  */
    119  1.1  mrg 
    120  1.1  mrg static void get_time (struct timevar_time_def *);
    121  1.1  mrg static void timevar_accumulate (struct timevar_time_def *,
    122  1.1  mrg 				struct timevar_time_def *,
    123  1.1  mrg 				struct timevar_time_def *);
    124  1.1  mrg 
    125  1.1  mrg /* The implementation of timing events for jit client code, allowing
    126  1.1  mrg    arbitrary named items to appear on the timing stack.  */
    127  1.1  mrg 
    128  1.1  mrg class timer::named_items
    129  1.1  mrg {
    130  1.1  mrg  public:
    131  1.1  mrg   named_items (timer *t);
    132  1.1  mrg   ~named_items ();
    133  1.1  mrg 
    134  1.1  mrg   void push (const char *item_name);
    135  1.1  mrg   void pop ();
    136  1.1  mrg   void print (FILE *fp, const timevar_time_def *total);
    137  1.1  mrg 
    138  1.1  mrg  private:
    139  1.1  mrg   /* Which timer instance does this relate to?  */
    140  1.1  mrg   timer *m_timer;
    141  1.1  mrg 
    142  1.1  mrg   /* Dictionary, mapping from item names to timevar_def.
    143  1.1  mrg      Note that currently we merely store/compare the raw string
    144  1.1  mrg      pointers provided by client code; we don't take a copy,
    145  1.1  mrg      or use strcmp.  */
    146  1.1  mrg   hash_map <const char *, timer::timevar_def> m_hash_map;
    147  1.1  mrg 
    148  1.1  mrg   /* The order in which items were originally inserted.  */
    149  1.1  mrg   auto_vec <const char *> m_names;
    150  1.1  mrg };
    151  1.1  mrg 
    152  1.1  mrg /* The constructor for class timer::named_items.  */
    153  1.1  mrg 
    154  1.1  mrg timer::named_items::named_items (timer *t)
    155  1.1  mrg : m_timer (t),
    156  1.1  mrg   m_hash_map (),
    157  1.1  mrg   m_names ()
    158  1.1  mrg {
    159  1.1  mrg }
    160  1.1  mrg 
    161  1.1  mrg /* The destructor for class timer::named_items.  */
    162  1.1  mrg 
    163  1.1  mrg timer::named_items::~named_items ()
    164  1.1  mrg {
    165  1.1  mrg }
    166  1.1  mrg 
    167  1.1  mrg /* Push the named item onto the timer stack.  */
    168  1.1  mrg 
    169  1.1  mrg void
    170  1.1  mrg timer::named_items::push (const char *item_name)
    171  1.1  mrg {
    172  1.1  mrg   gcc_assert (item_name);
    173  1.1  mrg 
    174  1.1  mrg   bool existed;
    175  1.1  mrg   timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
    176  1.1  mrg   if (!existed)
    177  1.1  mrg     {
    178  1.1  mrg       def->elapsed.user = 0;
    179  1.1  mrg       def->elapsed.sys = 0;
    180  1.1  mrg       def->elapsed.wall = 0;
    181  1.1  mrg       def->name = item_name;
    182  1.1  mrg       def->standalone = 0;
    183  1.1  mrg       m_names.safe_push (item_name);
    184  1.1  mrg     }
    185  1.1  mrg   m_timer->push_internal (def);
    186  1.1  mrg }
    187  1.1  mrg 
    188  1.1  mrg /* Pop the top item from the timer stack.  */
    189  1.1  mrg 
    190  1.1  mrg void
    191  1.1  mrg timer::named_items::pop ()
    192  1.1  mrg {
    193  1.1  mrg   m_timer->pop_internal ();
    194  1.1  mrg }
    195  1.1  mrg 
    196  1.1  mrg /* Print the given client item.  Helper function for timer::print.  */
    197  1.1  mrg 
    198  1.1  mrg void
    199  1.1  mrg timer::named_items::print (FILE *fp, const timevar_time_def *total)
    200  1.1  mrg {
    201  1.1  mrg   fprintf (fp, "Client items:\n");
    202  1.1  mrg   for (const char *item_name : m_names)
    203  1.1  mrg     {
    204  1.1  mrg       timer::timevar_def *def = m_hash_map.get (item_name);
    205  1.1  mrg       gcc_assert (def);
    206  1.1  mrg       m_timer->print_row (fp, total, def->name, def->elapsed);
    207  1.1  mrg     }
    208  1.1  mrg }
    209  1.1  mrg 
    210  1.1  mrg /* Fill the current times into TIME.  The definition of this function
    211  1.1  mrg    also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
    212  1.1  mrg    HAVE_WALL_TIME macros.  */
    213  1.1  mrg 
    214  1.1  mrg static void
    215  1.1  mrg get_time (struct timevar_time_def *now)
    216  1.1  mrg {
    217  1.1  mrg   now->user = 0;
    218  1.1  mrg   now->sys  = 0;
    219  1.1  mrg   now->wall = 0;
    220  1.1  mrg   now->ggc_mem = timevar_ggc_mem_total;
    221  1.1  mrg 
    222  1.1  mrg   {
    223  1.1  mrg #ifdef USE_TIMES
    224  1.1  mrg     struct tms tms;
    225  1.1  mrg     now->wall = times (&tms)  * ticks_to_msec;
    226  1.1  mrg     now->user = tms.tms_utime * ticks_to_msec;
    227  1.1  mrg     now->sys  = tms.tms_stime * ticks_to_msec;
    228  1.1  mrg #endif
    229  1.1  mrg #ifdef USE_GETRUSAGE
    230  1.1  mrg     struct rusage rusage;
    231  1.1  mrg     getrusage (RUSAGE_SELF, &rusage);
    232  1.1  mrg     now->user = rusage.ru_utime.tv_sec + rusage.ru_utime.tv_usec * 1e-6;
    233  1.1  mrg     now->sys  = rusage.ru_stime.tv_sec + rusage.ru_stime.tv_usec * 1e-6;
    234  1.1  mrg #endif
    235  1.1  mrg #ifdef USE_CLOCK
    236  1.1  mrg     now->user = clock () * clocks_to_msec;
    237  1.1  mrg #endif
    238  1.1  mrg   }
    239  1.1  mrg }
    240  1.1  mrg 
    241  1.1  mrg /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
    242  1.1  mrg 
    243  1.1  mrg static void
    244  1.1  mrg timevar_accumulate (struct timevar_time_def *timer,
    245  1.1  mrg 		    struct timevar_time_def *start_time,
    246  1.1  mrg 		    struct timevar_time_def *stop_time)
    247  1.1  mrg {
    248  1.1  mrg   timer->user += stop_time->user - start_time->user;
    249  1.1  mrg   timer->sys += stop_time->sys - start_time->sys;
    250  1.1  mrg   timer->wall += stop_time->wall - start_time->wall;
    251  1.1  mrg   timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
    252  1.1  mrg }
    253  1.1  mrg 
    254  1.1  mrg /* Class timer's constructor.  */
    255  1.1  mrg 
    256  1.1  mrg timer::timer () :
    257  1.1  mrg   m_stack (NULL),
    258  1.1  mrg   m_unused_stack_instances (NULL),
    259  1.1  mrg   m_start_time (),
    260  1.1  mrg   m_jit_client_items (NULL)
    261  1.1  mrg {
    262  1.1  mrg   /* Zero all elapsed times.  */
    263  1.1  mrg   memset (m_timevars, 0, sizeof (m_timevars));
    264  1.1  mrg 
    265  1.1  mrg   /* Initialize the names of timing variables.  */
    266  1.1  mrg #define DEFTIMEVAR(identifier__, name__) \
    267  1.1  mrg   m_timevars[identifier__].name = name__;
    268  1.1  mrg #include "timevar.def"
    269  1.1  mrg #undef DEFTIMEVAR
    270  1.1  mrg 
    271  1.1  mrg   /* Initialize configuration-specific state.
    272  1.1  mrg      Ideally this would be one-time initialization.  */
    273  1.1  mrg #ifdef USE_TIMES
    274  1.1  mrg   ticks_to_msec = TICKS_TO_MSEC;
    275  1.1  mrg #endif
    276  1.1  mrg #ifdef USE_CLOCK
    277  1.1  mrg   clocks_to_msec = CLOCKS_TO_MSEC;
    278  1.1  mrg #endif
    279  1.1  mrg }
    280  1.1  mrg 
    281  1.1  mrg /* Class timer's destructor.  */
    282  1.1  mrg 
    283  1.1  mrg timer::~timer ()
    284  1.1  mrg {
    285  1.1  mrg   timevar_stack_def *iter, *next;
    286  1.1  mrg 
    287  1.1  mrg   for (iter = m_stack; iter; iter = next)
    288  1.1  mrg     {
    289  1.1  mrg       next = iter->next;
    290  1.1  mrg       free (iter);
    291  1.1  mrg     }
    292  1.1  mrg   for (iter = m_unused_stack_instances; iter; iter = next)
    293  1.1  mrg     {
    294  1.1  mrg       next = iter->next;
    295  1.1  mrg       free (iter);
    296  1.1  mrg     }
    297  1.1  mrg   for (unsigned i = 0; i < TIMEVAR_LAST; ++i)
    298  1.1  mrg     delete m_timevars[i].children;
    299  1.1  mrg 
    300  1.1  mrg   delete m_jit_client_items;
    301  1.1  mrg }
    302  1.1  mrg 
    303  1.1  mrg /* Initialize timing variables.  */
    304  1.1  mrg 
    305  1.1  mrg void
    306  1.1  mrg timevar_init (void)
    307  1.1  mrg {
    308  1.1  mrg   if (g_timer)
    309  1.1  mrg     return;
    310  1.1  mrg 
    311  1.1  mrg   g_timer = new timer ();
    312  1.1  mrg }
    313  1.1  mrg 
    314  1.1  mrg /* Push TIMEVAR onto the timing stack.  No further elapsed time is
    315  1.1  mrg    attributed to the previous topmost timing variable on the stack;
    316  1.1  mrg    subsequent elapsed time is attributed to TIMEVAR, until it is
    317  1.1  mrg    popped or another element is pushed on top.
    318  1.1  mrg 
    319  1.1  mrg    TIMEVAR cannot be running as a standalone timer.  */
    320  1.1  mrg 
    321  1.1  mrg void
    322  1.1  mrg timer::push (timevar_id_t timevar)
    323  1.1  mrg {
    324  1.1  mrg   struct timevar_def *tv = &m_timevars[timevar];
    325  1.1  mrg   push_internal (tv);
    326  1.1  mrg }
    327  1.1  mrg 
    328  1.1  mrg /* Push TV onto the timing stack, either one of the builtin ones
    329  1.1  mrg    for a timevar_id_t, or one provided by client code to libgccjit.  */
    330  1.1  mrg 
    331  1.1  mrg void
    332  1.1  mrg timer::push_internal (struct timevar_def *tv)
    333  1.1  mrg {
    334  1.1  mrg   struct timevar_stack_def *context;
    335  1.1  mrg   struct timevar_time_def now;
    336  1.1  mrg 
    337  1.1  mrg   gcc_assert (tv);
    338  1.1  mrg 
    339  1.1  mrg   /* Mark this timing variable as used.  */
    340  1.1  mrg   tv->used = 1;
    341  1.1  mrg 
    342  1.1  mrg   /* Can't push a standalone timer.  */
    343  1.1  mrg   gcc_assert (!tv->standalone);
    344  1.1  mrg 
    345  1.1  mrg   /* What time is it?  */
    346  1.1  mrg   get_time (&now);
    347  1.1  mrg 
    348  1.1  mrg   /* If the stack isn't empty, attribute the current elapsed time to
    349  1.1  mrg      the old topmost element.  */
    350  1.1  mrg   if (m_stack)
    351  1.1  mrg     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
    352  1.1  mrg 
    353  1.1  mrg   /* Reset the start time; from now on, time is attributed to
    354  1.1  mrg      TIMEVAR.  */
    355  1.1  mrg   m_start_time = now;
    356  1.1  mrg 
    357  1.1  mrg   /* See if we have a previously-allocated stack instance.  If so,
    358  1.1  mrg      take it off the list.  If not, malloc a new one.  */
    359  1.1  mrg   if (m_unused_stack_instances != NULL)
    360  1.1  mrg     {
    361  1.1  mrg       context = m_unused_stack_instances;
    362  1.1  mrg       m_unused_stack_instances = m_unused_stack_instances->next;
    363  1.1  mrg     }
    364  1.1  mrg   else
    365  1.1  mrg     context = XNEW (struct timevar_stack_def);
    366  1.1  mrg 
    367  1.1  mrg   /* Fill it in and put it on the stack.  */
    368  1.1  mrg   context->timevar = tv;
    369  1.1  mrg   context->next = m_stack;
    370  1.1  mrg   m_stack = context;
    371  1.1  mrg }
    372  1.1  mrg 
    373  1.1  mrg /* Pop the topmost timing variable element off the timing stack.  The
    374  1.1  mrg    popped variable must be TIMEVAR.  Elapsed time since the that
    375  1.1  mrg    element was pushed on, or since it was last exposed on top of the
    376  1.1  mrg    stack when the element above it was popped off, is credited to that
    377  1.1  mrg    timing variable.  */
    378  1.1  mrg 
    379  1.1  mrg void
    380  1.1  mrg timer::pop (timevar_id_t timevar)
    381  1.1  mrg {
    382  1.1  mrg   gcc_assert (&m_timevars[timevar] == m_stack->timevar);
    383  1.1  mrg 
    384  1.1  mrg   pop_internal ();
    385  1.1  mrg }
    386  1.1  mrg 
    387  1.1  mrg /* Pop the topmost item from the stack, either one of the builtin ones
    388  1.1  mrg    for a timevar_id_t, or one provided by client code to libgccjit.  */
    389  1.1  mrg 
    390  1.1  mrg void
    391  1.1  mrg timer::pop_internal ()
    392  1.1  mrg {
    393  1.1  mrg   struct timevar_time_def now;
    394  1.1  mrg   struct timevar_stack_def *popped = m_stack;
    395  1.1  mrg 
    396  1.1  mrg   /* What time is it?  */
    397  1.1  mrg   get_time (&now);
    398  1.1  mrg 
    399  1.1  mrg   /* Attribute the elapsed time to the element we're popping.  */
    400  1.1  mrg   timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now);
    401  1.1  mrg 
    402  1.1  mrg   /* Take the item off the stack.  */
    403  1.1  mrg   m_stack = m_stack->next;
    404  1.1  mrg 
    405  1.1  mrg   /* Record the elapsed sub-time to the parent as well.  */
    406  1.1  mrg   if (m_stack && time_report_details)
    407  1.1  mrg     {
    408  1.1  mrg       if (! m_stack->timevar->children)
    409  1.1  mrg 	m_stack->timevar->children = new child_map_t (5);
    410  1.1  mrg       bool existed_p;
    411  1.1  mrg       timevar_time_def &time
    412  1.1  mrg 	= m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p);
    413  1.1  mrg       if (! existed_p)
    414  1.1  mrg 	memset (&time, 0, sizeof (timevar_time_def));
    415  1.1  mrg       timevar_accumulate (&time, &m_start_time, &now);
    416  1.1  mrg     }
    417  1.1  mrg 
    418  1.1  mrg   /* Reset the start time; from now on, time is attributed to the
    419  1.1  mrg      element just exposed on the stack.  */
    420  1.1  mrg   m_start_time = now;
    421  1.1  mrg 
    422  1.1  mrg   /* Don't delete the stack element; instead, add it to the list of
    423  1.1  mrg      unused elements for later use.  */
    424  1.1  mrg   popped->next = m_unused_stack_instances;
    425  1.1  mrg   m_unused_stack_instances = popped;
    426  1.1  mrg }
    427  1.1  mrg 
    428  1.1  mrg /* Start timing TIMEVAR independently of the timing stack.  Elapsed
    429  1.1  mrg    time until timevar_stop is called for the same timing variable is
    430  1.1  mrg    attributed to TIMEVAR.  */
    431  1.1  mrg 
    432  1.1  mrg void
    433  1.1  mrg timevar_start (timevar_id_t timevar)
    434  1.1  mrg {
    435  1.1  mrg   if (!g_timer)
    436  1.1  mrg     return;
    437  1.1  mrg 
    438  1.1  mrg   g_timer->start (timevar);
    439  1.1  mrg }
    440  1.1  mrg 
    441  1.1  mrg /* See timevar_start above.  */
    442  1.1  mrg 
    443  1.1  mrg void
    444  1.1  mrg timer::start (timevar_id_t timevar)
    445  1.1  mrg {
    446  1.1  mrg   struct timevar_def *tv = &m_timevars[timevar];
    447  1.1  mrg 
    448  1.1  mrg   /* Mark this timing variable as used.  */
    449  1.1  mrg   tv->used = 1;
    450  1.1  mrg 
    451  1.1  mrg   /* Don't allow the same timing variable to be started more than
    452  1.1  mrg      once.  */
    453  1.1  mrg   gcc_assert (!tv->standalone);
    454  1.1  mrg   tv->standalone = 1;
    455  1.1  mrg 
    456  1.1  mrg   get_time (&tv->start_time);
    457  1.1  mrg }
    458  1.1  mrg 
    459  1.1  mrg /* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
    460  1.1  mrg    is attributed to it.  */
    461  1.1  mrg 
    462  1.1  mrg void
    463  1.1  mrg timevar_stop (timevar_id_t timevar)
    464  1.1  mrg {
    465  1.1  mrg   if (!g_timer)
    466  1.1  mrg     return;
    467  1.1  mrg 
    468  1.1  mrg   g_timer->stop (timevar);
    469  1.1  mrg }
    470  1.1  mrg 
    471  1.1  mrg /* See timevar_stop above.  */
    472  1.1  mrg 
    473  1.1  mrg void
    474  1.1  mrg timer::stop (timevar_id_t timevar)
    475  1.1  mrg {
    476  1.1  mrg   struct timevar_def *tv = &m_timevars[timevar];
    477  1.1  mrg   struct timevar_time_def now;
    478  1.1  mrg 
    479  1.1  mrg   /* TIMEVAR must have been started via timevar_start.  */
    480  1.1  mrg   gcc_assert (tv->standalone);
    481  1.1  mrg   tv->standalone = 0; /* Enable a restart.  */
    482  1.1  mrg 
    483  1.1  mrg   get_time (&now);
    484  1.1  mrg   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
    485  1.1  mrg }
    486  1.1  mrg 
    487  1.1  mrg 
    488  1.1  mrg /* Conditionally start timing TIMEVAR independently of the timing stack.
    489  1.1  mrg    If the timer is already running, leave it running and return true.
    490  1.1  mrg    Otherwise, start the timer and return false.
    491  1.1  mrg    Elapsed time until the corresponding timevar_cond_stop
    492  1.1  mrg    is called for the same timing variable is attributed to TIMEVAR.  */
    493  1.1  mrg 
    494  1.1  mrg bool
    495  1.1  mrg timevar_cond_start (timevar_id_t timevar)
    496  1.1  mrg {
    497  1.1  mrg   if (!g_timer)
    498  1.1  mrg     return false;
    499  1.1  mrg 
    500  1.1  mrg   return g_timer->cond_start (timevar);
    501  1.1  mrg }
    502  1.1  mrg 
    503  1.1  mrg /* See timevar_cond_start above.  */
    504  1.1  mrg 
    505  1.1  mrg bool
    506  1.1  mrg timer::cond_start (timevar_id_t timevar)
    507  1.1  mrg {
    508  1.1  mrg   struct timevar_def *tv = &m_timevars[timevar];
    509  1.1  mrg 
    510  1.1  mrg   /* Mark this timing variable as used.  */
    511  1.1  mrg   tv->used = 1;
    512  1.1  mrg 
    513  1.1  mrg   if (tv->standalone)
    514  1.1  mrg     return true;  /* The timevar is already running.  */
    515  1.1  mrg 
    516  1.1  mrg   /* Don't allow the same timing variable
    517  1.1  mrg      to be unconditionally started more than once.  */
    518  1.1  mrg   tv->standalone = 1;
    519  1.1  mrg 
    520  1.1  mrg   get_time (&tv->start_time);
    521  1.1  mrg   return false;  /* The timevar was not already running.  */
    522  1.1  mrg }
    523  1.1  mrg 
    524  1.1  mrg /* Conditionally stop timing TIMEVAR.  The RUNNING parameter must come
    525  1.1  mrg    from the return value of a dynamically matching timevar_cond_start.
    526  1.1  mrg    If the timer had already been RUNNING, do nothing.  Otherwise, time
    527  1.1  mrg    elapsed since timevar_cond_start was called is attributed to it.  */
    528  1.1  mrg 
    529  1.1  mrg void
    530  1.1  mrg timevar_cond_stop (timevar_id_t timevar, bool running)
    531  1.1  mrg {
    532  1.1  mrg   if (!g_timer || running)
    533  1.1  mrg     return;
    534  1.1  mrg 
    535  1.1  mrg   g_timer->cond_stop (timevar);
    536  1.1  mrg }
    537  1.1  mrg 
    538  1.1  mrg /* See timevar_cond_stop above.  */
    539  1.1  mrg 
    540  1.1  mrg void
    541  1.1  mrg timer::cond_stop (timevar_id_t timevar)
    542  1.1  mrg {
    543  1.1  mrg   struct timevar_def *tv;
    544  1.1  mrg   struct timevar_time_def now;
    545  1.1  mrg 
    546  1.1  mrg   tv = &m_timevars[timevar];
    547  1.1  mrg 
    548  1.1  mrg   /* TIMEVAR must have been started via timevar_cond_start.  */
    549  1.1  mrg   gcc_assert (tv->standalone);
    550  1.1  mrg   tv->standalone = 0; /* Enable a restart.  */
    551  1.1  mrg 
    552  1.1  mrg   get_time (&now);
    553  1.1  mrg   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
    554  1.1  mrg }
    555  1.1  mrg 
    556  1.1  mrg /* Push the named item onto the timing stack.  */
    557  1.1  mrg 
    558  1.1  mrg void
    559  1.1  mrg timer::push_client_item (const char *item_name)
    560  1.1  mrg {
    561  1.1  mrg   gcc_assert (item_name);
    562  1.1  mrg 
    563  1.1  mrg   /* Lazily create the named_items instance.  */
    564  1.1  mrg   if (!m_jit_client_items)
    565  1.1  mrg     m_jit_client_items = new named_items (this);
    566  1.1  mrg 
    567  1.1  mrg   m_jit_client_items->push (item_name);
    568  1.1  mrg }
    569  1.1  mrg 
    570  1.1  mrg /* Pop the top-most client item from the timing stack.  */
    571  1.1  mrg 
    572  1.1  mrg void
    573  1.1  mrg timer::pop_client_item ()
    574  1.1  mrg {
    575  1.1  mrg   gcc_assert (m_jit_client_items);
    576  1.1  mrg   m_jit_client_items->pop ();
    577  1.1  mrg }
    578  1.1  mrg 
    579  1.1  mrg /* Validate that phase times are consistent.  */
    580  1.1  mrg 
    581  1.1  mrg void
    582  1.1  mrg timer::validate_phases (FILE *fp) const
    583  1.1  mrg {
    584  1.1  mrg   unsigned int /* timevar_id_t */ id;
    585  1.1  mrg   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
    586  1.1  mrg   double phase_user = 0.0;
    587  1.1  mrg   double phase_sys = 0.0;
    588  1.1  mrg   double phase_wall = 0.0;
    589  1.1  mrg   size_t phase_ggc_mem = 0;
    590  1.1  mrg   static char phase_prefix[] = "phase ";
    591  1.1  mrg   const double tolerance = 1.000001;  /* One part in a million.  */
    592  1.1  mrg 
    593  1.1  mrg   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
    594  1.1  mrg     {
    595  1.1  mrg       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
    596  1.1  mrg 
    597  1.1  mrg       /* Don't evaluate timing variables that were never used.  */
    598  1.1  mrg       if (!tv->used)
    599  1.1  mrg 	continue;
    600  1.1  mrg 
    601  1.1  mrg       if (startswith (tv->name, phase_prefix))
    602  1.1  mrg 	{
    603  1.1  mrg 	  phase_user += tv->elapsed.user;
    604  1.1  mrg 	  phase_sys += tv->elapsed.sys;
    605  1.1  mrg 	  phase_wall += tv->elapsed.wall;
    606  1.1  mrg 	  phase_ggc_mem += tv->elapsed.ggc_mem;
    607  1.1  mrg 	}
    608  1.1  mrg     }
    609  1.1  mrg 
    610  1.1  mrg   if (phase_user > total->user * tolerance
    611  1.1  mrg       || phase_sys > total->sys * tolerance
    612  1.1  mrg       || phase_wall > total->wall * tolerance
    613  1.1  mrg       || phase_ggc_mem > total->ggc_mem * tolerance)
    614  1.1  mrg     {
    615  1.1  mrg 
    616  1.1  mrg       fprintf (fp, "Timing error: total of phase timers exceeds total time.\n");
    617  1.1  mrg       if (phase_user > total->user)
    618  1.1  mrg 	fprintf (fp, "user    %24.18e > %24.18e\n", phase_user, total->user);
    619  1.1  mrg       if (phase_sys > total->sys)
    620  1.1  mrg 	fprintf (fp, "sys     %24.18e > %24.18e\n", phase_sys, total->sys);
    621  1.1  mrg       if (phase_wall > total->wall)
    622  1.1  mrg 	fprintf (fp, "wall    %24.18e > %24.18e\n", phase_wall, total->wall);
    623  1.1  mrg       if (phase_ggc_mem > total->ggc_mem)
    624  1.1  mrg 	fprintf (fp, "ggc_mem %24lu > %24lu\n", (unsigned long)phase_ggc_mem,
    625  1.1  mrg 		 (unsigned long)total->ggc_mem);
    626  1.1  mrg       gcc_unreachable ();
    627  1.1  mrg     }
    628  1.1  mrg }
    629  1.1  mrg 
    630  1.1  mrg /* Helper function for timer::print.  */
    631  1.1  mrg 
    632  1.1  mrg void
    633  1.1  mrg timer::print_row (FILE *fp,
    634  1.1  mrg 		  const timevar_time_def *total,
    635  1.1  mrg 		  const char *name, const timevar_time_def &elapsed)
    636  1.1  mrg {
    637  1.1  mrg   /* The timing variable name.  */
    638  1.1  mrg   fprintf (fp, " %-35s:", name);
    639  1.1  mrg 
    640  1.1  mrg #ifdef HAVE_USER_TIME
    641  1.1  mrg   /* Print user-mode time for this process.  */
    642  1.1  mrg   fprintf (fp, "%7.2f (%3.0f%%)",
    643  1.1  mrg 	   elapsed.user,
    644  1.1  mrg 	   (total->user == 0 ? 0 : elapsed.user / total->user) * 100);
    645  1.1  mrg #endif /* HAVE_USER_TIME */
    646  1.1  mrg 
    647  1.1  mrg #ifdef HAVE_SYS_TIME
    648  1.1  mrg   /* Print system-mode time for this process.  */
    649  1.1  mrg   fprintf (fp, "%7.2f (%3.0f%%)",
    650  1.1  mrg 	   elapsed.sys,
    651  1.1  mrg 	   (total->sys == 0 ? 0 : elapsed.sys / total->sys) * 100);
    652  1.1  mrg #endif /* HAVE_SYS_TIME */
    653  1.1  mrg 
    654  1.1  mrg #ifdef HAVE_WALL_TIME
    655  1.1  mrg   /* Print wall clock time elapsed.  */
    656  1.1  mrg   fprintf (fp, "%7.2f (%3.0f%%)",
    657  1.1  mrg 	   elapsed.wall,
    658  1.1  mrg 	   (total->wall == 0 ? 0 : elapsed.wall / total->wall) * 100);
    659  1.1  mrg #endif /* HAVE_WALL_TIME */
    660  1.1  mrg 
    661  1.1  mrg   /* Print the amount of ggc memory allocated.  */
    662  1.1  mrg   fprintf (fp, PRsa (6) " (%3.0f%%)",
    663  1.1  mrg 	   SIZE_AMOUNT (elapsed.ggc_mem),
    664  1.1  mrg 	   (total->ggc_mem == 0
    665  1.1  mrg 	    ? 0
    666  1.1  mrg 	    : (float) elapsed.ggc_mem / total->ggc_mem) * 100);
    667  1.1  mrg 
    668  1.1  mrg   putc ('\n', fp);
    669  1.1  mrg }
    670  1.1  mrg 
    671  1.1  mrg /* Return whether ELAPSED is all zero.  */
    672  1.1  mrg 
    673  1.1  mrg bool
    674  1.1  mrg timer::all_zero (const timevar_time_def &elapsed)
    675  1.1  mrg {
    676  1.1  mrg   const double tiny = 5e-3;
    677  1.1  mrg   return (elapsed.user < tiny
    678  1.1  mrg 	  && elapsed.sys < tiny
    679  1.1  mrg 	  && elapsed.wall < tiny
    680  1.1  mrg 	  && elapsed.ggc_mem < GGC_MEM_BOUND);
    681  1.1  mrg }
    682  1.1  mrg 
    683  1.1  mrg /* Summarize timing variables to FP.  The timing variable TV_TOTAL has
    684  1.1  mrg    a special meaning -- it's considered to be the total elapsed time,
    685  1.1  mrg    for normalizing the others, and is displayed last.  */
    686  1.1  mrg 
    687  1.1  mrg void
    688  1.1  mrg timer::print (FILE *fp)
    689  1.1  mrg {
    690  1.1  mrg   /* Only print stuff if we have some sort of time information.  */
    691  1.1  mrg #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
    692  1.1  mrg   unsigned int /* timevar_id_t */ id;
    693  1.1  mrg   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
    694  1.1  mrg   struct timevar_time_def now;
    695  1.1  mrg 
    696  1.1  mrg   /* Update timing information in case we're calling this from GDB.  */
    697  1.1  mrg 
    698  1.1  mrg   if (fp == 0)
    699  1.1  mrg     fp = stderr;
    700  1.1  mrg 
    701  1.1  mrg   /* What time is it?  */
    702  1.1  mrg   get_time (&now);
    703  1.1  mrg 
    704  1.1  mrg   /* If the stack isn't empty, attribute the current elapsed time to
    705  1.1  mrg      the old topmost element.  */
    706  1.1  mrg   if (m_stack)
    707  1.1  mrg     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
    708  1.1  mrg 
    709  1.1  mrg   /* Reset the start time; from now on, time is attributed to
    710  1.1  mrg      TIMEVAR.  */
    711  1.1  mrg   m_start_time = now;
    712  1.1  mrg 
    713  1.1  mrg   fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys",
    714  1.1  mrg 	   "wall", "GGC");
    715  1.1  mrg   if (m_jit_client_items)
    716  1.1  mrg     fputs ("GCC items:\n", fp);
    717  1.1  mrg   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
    718  1.1  mrg     {
    719  1.1  mrg       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
    720  1.1  mrg 
    721  1.1  mrg       /* Don't print the total execution time here; that goes at the
    722  1.1  mrg 	 end.  */
    723  1.1  mrg       if ((timevar_id_t) id == TV_TOTAL)
    724  1.1  mrg 	continue;
    725  1.1  mrg 
    726  1.1  mrg       /* Don't print timing variables that were never used.  */
    727  1.1  mrg       if (!tv->used)
    728  1.1  mrg 	continue;
    729  1.1  mrg 
    730  1.1  mrg       bool any_children_with_time = false;
    731  1.1  mrg       if (tv->children)
    732  1.1  mrg 	for (child_map_t::iterator i = tv->children->begin ();
    733  1.1  mrg 	     i != tv->children->end (); ++i)
    734  1.1  mrg 	  if (! all_zero ((*i).second))
    735  1.1  mrg 	    {
    736  1.1  mrg 	      any_children_with_time = true;
    737  1.1  mrg 	      break;
    738  1.1  mrg 	    }
    739  1.1  mrg 
    740  1.1  mrg       /* Don't print timing variables if we're going to get a row of
    741  1.1  mrg          zeroes.  Unless there are children with non-zero time.  */
    742  1.1  mrg       if (! any_children_with_time
    743  1.1  mrg 	  && all_zero (tv->elapsed))
    744  1.1  mrg 	continue;
    745  1.1  mrg 
    746  1.1  mrg       print_row (fp, total, tv->name, tv->elapsed);
    747  1.1  mrg 
    748  1.1  mrg       if (tv->children)
    749  1.1  mrg 	for (child_map_t::iterator i = tv->children->begin ();
    750  1.1  mrg 	     i != tv->children->end (); ++i)
    751  1.1  mrg 	  {
    752  1.1  mrg 	    timevar_def *tv2 = (*i).first;
    753  1.1  mrg 	    /* Don't print timing variables if we're going to get a row of
    754  1.1  mrg 	       zeroes.  */
    755  1.1  mrg 	    if (! all_zero ((*i).second))
    756  1.1  mrg 	      {
    757  1.1  mrg 		char lname[256];
    758  1.1  mrg 		snprintf (lname, 256, "`- %s", tv2->name);
    759  1.1  mrg 		print_row (fp, total, lname, (*i).second);
    760  1.1  mrg 	      }
    761  1.1  mrg 	  }
    762  1.1  mrg     }
    763  1.1  mrg   if (m_jit_client_items)
    764  1.1  mrg     m_jit_client_items->print (fp, total);
    765  1.1  mrg 
    766  1.1  mrg   /* Print total time.  */
    767  1.1  mrg   fprintf (fp, " %-35s:", "TOTAL");
    768  1.1  mrg #ifdef HAVE_USER_TIME
    769  1.1  mrg   fprintf (fp, "%7.2f      ", total->user);
    770  1.1  mrg #endif
    771  1.1  mrg #ifdef HAVE_SYS_TIME
    772  1.1  mrg   fprintf (fp, "%8.2f      ", total->sys);
    773  1.1  mrg #endif
    774  1.1  mrg #ifdef HAVE_WALL_TIME
    775  1.1  mrg   fprintf (fp, "%8.2f      ", total->wall);
    776  1.1  mrg #endif
    777  1.1  mrg   fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem));
    778  1.1  mrg 
    779  1.1  mrg   if (CHECKING_P || flag_checking)
    780  1.1  mrg     fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
    781  1.1  mrg   if (CHECKING_P)
    782  1.1  mrg     fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
    783  1.1  mrg #ifndef ENABLE_ASSERT_CHECKING
    784  1.1  mrg   fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
    785  1.1  mrg   fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
    786  1.1  mrg #endif
    787  1.1  mrg 
    788  1.1  mrg #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
    789  1.1  mrg 	  || defined (HAVE_WALL_TIME) */
    790  1.1  mrg 
    791  1.1  mrg   validate_phases (fp);
    792  1.1  mrg }
    793  1.1  mrg 
    794  1.1  mrg /* Get the name of the topmost item.  For use by jit for validating
    795  1.1  mrg    inputs to gcc_jit_timer_pop.  */
    796  1.1  mrg const char *
    797  1.1  mrg timer::get_topmost_item_name () const
    798  1.1  mrg {
    799  1.1  mrg   if (m_stack)
    800  1.1  mrg     return m_stack->timevar->name;
    801  1.1  mrg   else
    802  1.1  mrg     return NULL;
    803  1.1  mrg }
    804  1.1  mrg 
    805  1.1  mrg /* Prints a message to stderr stating that time elapsed in STR is
    806  1.1  mrg    TOTAL (given in microseconds).  */
    807  1.1  mrg 
    808  1.1  mrg void
    809  1.1  mrg print_time (const char *str, long total)
    810  1.1  mrg {
    811  1.1  mrg   long all_time = get_run_time ();
    812  1.1  mrg   fprintf (stderr,
    813  1.1  mrg 	   "time in %s: %ld.%06ld (%ld%%)\n",
    814  1.1  mrg 	   str, total / 1000000, total % 1000000,
    815  1.1  mrg 	   all_time == 0 ? 0
    816  1.1  mrg 	   : (long) (((100.0 * (double) total) / (double) all_time) + .5));
    817  1.1  mrg }
    818