LCOV - code coverage report
Current view: top level - gcc - timevar.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 84.7 % 327 277
Test Date: 2026-02-28 14:20:25 Functions: 94.3 % 35 33
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.