LCOV - code coverage report
Current view: top level - gcc - timevar.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.1 % 355 302
Test Date: 2024-04-13 14:00:49 Functions: 85.7 % 35 30
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Timing variables for measuring compiler performance.
       2                 :             :    Copyright (C) 2000-2024 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                 :             : #ifndef HAVE_CLOCK_T
      29                 :             : typedef int clock_t;
      30                 :             : #endif
      31                 :             : 
      32                 :             : #ifndef HAVE_STRUCT_TMS
      33                 :             : struct tms
      34                 :             : {
      35                 :             :   clock_t tms_utime;
      36                 :             :   clock_t tms_stime;
      37                 :             :   clock_t tms_cutime;
      38                 :             :   clock_t tms_cstime;
      39                 :             : };
      40                 :             : #endif
      41                 :             : 
      42                 :             : #ifndef RUSAGE_SELF
      43                 :             : # define RUSAGE_SELF 0
      44                 :             : #endif
      45                 :             : 
      46                 :             : /* Calculation of scale factor to convert ticks to seconds.
      47                 :             :    We mustn't use CLOCKS_PER_SEC except with clock().  */
      48                 :             : #if HAVE_SYSCONF && defined _SC_CLK_TCK
      49                 :             : # define TICKS_PER_SECOND sysconf (_SC_CLK_TCK) /* POSIX 1003.1-1996 */
      50                 :             : #else
      51                 :             : # ifdef CLK_TCK
      52                 :             : #  define TICKS_PER_SECOND CLK_TCK /* POSIX 1003.1-1988; obsolescent */
      53                 :             : # else
      54                 :             : #  ifdef HZ
      55                 :             : #   define TICKS_PER_SECOND HZ  /* traditional UNIX */
      56                 :             : #  else
      57                 :             : #   define TICKS_PER_SECOND 100 /* often the correct value */
      58                 :             : #  endif
      59                 :             : # endif
      60                 :             : #endif
      61                 :             : 
      62                 :             : /* Prefer times to getrusage to clock (each gives successively less
      63                 :             :    information).  */
      64                 :             : #ifdef HAVE_TIMES
      65                 :             : # if defined HAVE_DECL_TIMES && !HAVE_DECL_TIMES
      66                 :             :   extern clock_t times (struct tms *);
      67                 :             : # endif
      68                 :             : # define USE_TIMES
      69                 :             : # define HAVE_USER_TIME
      70                 :             : # define HAVE_SYS_TIME
      71                 :             : # define HAVE_WALL_TIME
      72                 :             : #else
      73                 :             : #ifdef HAVE_GETRUSAGE
      74                 :             : # if defined HAVE_DECL_GETRUSAGE && !HAVE_DECL_GETRUSAGE
      75                 :             :   extern int getrusage (int, struct rusage *);
      76                 :             : # endif
      77                 :             : # define USE_GETRUSAGE
      78                 :             : # define HAVE_USER_TIME
      79                 :             : # define HAVE_SYS_TIME
      80                 :             : #else
      81                 :             : #ifdef HAVE_CLOCK
      82                 :             : # if defined HAVE_DECL_CLOCK && !HAVE_DECL_CLOCK
      83                 :             :   extern clock_t clock (void);
      84                 :             : # endif
      85                 :             : # define USE_CLOCK
      86                 :             : # define HAVE_USER_TIME
      87                 :             : #endif
      88                 :             : #endif
      89                 :             : #endif
      90                 :             : 
      91                 :             : /* libc is very likely to have snuck a call to sysconf() into one of
      92                 :             :    the underlying constants, and that can be very slow, so we have to
      93                 :             :    precompute them.  Whose wonderful idea was it to make all those
      94                 :             :    _constants_ variable at run time, anyway?  */
      95                 :             : #define NANOSEC_PER_SEC 1000000000
      96                 :             : #ifdef USE_TIMES
      97                 :             : static uint64_t ticks_to_nanosec;
      98                 :             : #define TICKS_TO_NANOSEC (NANOSEC_PER_SEC / TICKS_PER_SECOND)
      99                 :             : #endif
     100                 :             : 
     101                 :             : #ifdef USE_CLOCK
     102                 :             : static uint64_t clocks_to_nanosec;
     103                 :             : #define CLOCKS_TO_NANOSEC (NANOSEC_PER_SEC / CLOCKS_PER_SEC)
     104                 :             : #endif
     105                 :             : 
     106                 :             : /* Non-NULL if timevars should be used.  In GCC, this happens with
     107                 :             :    the -ftime-report flag.  */
     108                 :             : 
     109                 :             : timer *g_timer;
     110                 :             : 
     111                 :             : /* Total amount of memory allocated by garbage collector.  */
     112                 :             : 
     113                 :             : size_t timevar_ggc_mem_total;
     114                 :             : 
     115                 :             : /* The amount of memory that will cause us to report the timevar even
     116                 :             :    if the time spent is not significant.  */
     117                 :             : 
     118                 :             : #define GGC_MEM_BOUND (1 << 20)
     119                 :             : 
     120                 :             : /* See timevar.h for an explanation of timing variables.  */
     121                 :             : 
     122                 :             : static void get_time (struct timevar_time_def *);
     123                 :             : static void timevar_accumulate (struct timevar_time_def *,
     124                 :             :                                 struct timevar_time_def *,
     125                 :             :                                 struct timevar_time_def *);
     126                 :             : 
     127                 :             : /* The implementation of timing events for jit client code, allowing
     128                 :             :    arbitrary named items to appear on the timing stack.  */
     129                 :             : 
     130                 :             : class timer::named_items
     131                 :             : {
     132                 :             :  public:
     133                 :             :   named_items (timer *t);
     134                 :             :   ~named_items ();
     135                 :             : 
     136                 :             :   void push (const char *item_name);
     137                 :             :   void pop ();
     138                 :             :   void print (FILE *fp, const timevar_time_def *total);
     139                 :             : 
     140                 :             :   json::value *make_json () const;
     141                 :             : 
     142                 :             :  private:
     143                 :             :   /* Which timer instance does this relate to?  */
     144                 :             :   timer *m_timer;
     145                 :             : 
     146                 :             :   /* Dictionary, mapping from item names to timevar_def.
     147                 :             :      Note that currently we merely store/compare the raw string
     148                 :             :      pointers provided by client code; we don't take a copy,
     149                 :             :      or use strcmp.  */
     150                 :             :   typedef hash_map <const char *, timer::timevar_def> hash_map_t;
     151                 :             :   hash_map_t m_hash_map;
     152                 :             : 
     153                 :             :   /* The order in which items were originally inserted.  */
     154                 :             :   auto_vec <const char *> m_names;
     155                 :             : };
     156                 :             : 
     157                 :             : /* The constructor for class timer::named_items.  */
     158                 :             : 
     159                 :           9 : timer::named_items::named_items (timer *t)
     160                 :           9 : : m_timer (t),
     161                 :           9 :   m_hash_map (),
     162                 :           9 :   m_names ()
     163                 :             : {
     164                 :           9 : }
     165                 :             : 
     166                 :             : /* The destructor for class timer::named_items.  */
     167                 :             : 
     168                 :           9 : timer::named_items::~named_items ()
     169                 :             : {
     170                 :           9 : }
     171                 :             : 
     172                 :             : /* Push the named item onto the timer stack.  */
     173                 :             : 
     174                 :             : void
     175                 :        1605 : timer::named_items::push (const char *item_name)
     176                 :             : {
     177                 :        1605 :   gcc_assert (item_name);
     178                 :             : 
     179                 :        1605 :   bool existed;
     180                 :        1605 :   timer::timevar_def *def = &m_hash_map.get_or_insert (item_name, &existed);
     181                 :        1605 :   if (!existed)
     182                 :             :     {
     183                 :          21 :       def->elapsed.user = 0;
     184                 :          21 :       def->elapsed.sys = 0;
     185                 :          21 :       def->elapsed.wall = 0;
     186                 :          21 :       def->name = item_name;
     187                 :          21 :       def->standalone = 0;
     188                 :          21 :       m_names.safe_push (item_name);
     189                 :             :     }
     190                 :        1605 :   m_timer->push_internal (def);
     191                 :        1605 : }
     192                 :             : 
     193                 :             : /* Pop the top item from the timer stack.  */
     194                 :             : 
     195                 :             : void
     196                 :        1600 : timer::named_items::pop ()
     197                 :             : {
     198                 :        1600 :   m_timer->pop_internal ();
     199                 :        1600 : }
     200                 :             : 
     201                 :             : /* Print the given client item.  Helper function for timer::print.  */
     202                 :             : 
     203                 :             : void
     204                 :           4 : timer::named_items::print (FILE *fp, const timevar_time_def *total)
     205                 :             : {
     206                 :           4 :   fprintf (fp, "Client items:\n");
     207                 :          28 :   for (const char *item_name : m_names)
     208                 :             :     {
     209                 :          16 :       timer::timevar_def *def = m_hash_map.get (item_name);
     210                 :          16 :       gcc_assert (def);
     211                 :          16 :       m_timer->print_row (fp, total, def->name, def->elapsed);
     212                 :             :     }
     213                 :           4 : }
     214                 :             : 
     215                 :             : /* Create a json value representing this object, suitable for use
     216                 :             :    in SARIF output.  */
     217                 :             : 
     218                 :             : json::value *
     219                 :           0 : timer::named_items::make_json () const
     220                 :             : {
     221                 :           0 :   json::array *arr = new json::array ();
     222                 :           0 :   for (const char *item_name : m_names)
     223                 :             :     {
     224                 :           0 :       hash_map_t &mut_map = const_cast <hash_map_t &> (m_hash_map);
     225                 :           0 :       timer::timevar_def *def = mut_map.get (item_name);
     226                 :           0 :       gcc_assert (def);
     227                 :           0 :       arr->append (def->make_json ());
     228                 :             :     }
     229                 :           0 :   return arr;
     230                 :             : }
     231                 :             : 
     232                 :             : /* Fill the current times into TIME.  The definition of this function
     233                 :             :    also defines any or all of the HAVE_USER_TIME, HAVE_SYS_TIME, and
     234                 :             :    HAVE_WALL_TIME macros.  */
     235                 :             : 
     236                 :             : static void
     237                 :     1320979 : get_time (struct timevar_time_def *now)
     238                 :             : {
     239                 :     1320979 :   now->user = 0;
     240                 :     1320979 :   now->sys  = 0;
     241                 :     1320979 :   now->wall = 0;
     242                 :     1320979 :   now->ggc_mem = timevar_ggc_mem_total;
     243                 :             : 
     244                 :     1320979 :   {
     245                 :             : #ifdef USE_TIMES
     246                 :     1320979 :     struct tms tms;
     247                 :     1320979 :     now->wall = times (&tms)  * ticks_to_nanosec;
     248                 :     1320979 :     now->user = tms.tms_utime * ticks_to_nanosec;
     249                 :     1320979 :     now->sys  = tms.tms_stime * ticks_to_nanosec;
     250                 :             : #endif
     251                 :             : #ifdef USE_GETRUSAGE
     252                 :             :     struct rusage rusage;
     253                 :             :     getrusage (RUSAGE_SELF, &rusage);
     254                 :             :     now->user = rusage.ru_utime.tv_sec * NANOSEC_PER_SEC
     255                 :             :                 + rusage.ru_utime.tv_usec * 1000;
     256                 :             :     now->sys  = rusage.ru_stime.tv_sec * NANOSEC_PER_SEC
     257                 :             :                 + rusage.ru_stime.tv_usec * 1000;
     258                 :             : #endif
     259                 :             : #ifdef USE_CLOCK
     260                 :             :     now->user = clock () * clocks_to_nanosec;
     261                 :             : #endif
     262                 :             :   }
     263                 :     1320979 : }
     264                 :             : 
     265                 :             : /* Add the difference between STOP_TIME and START_TIME to TIMER.  */
     266                 :             : 
     267                 :             : static void
     268                 :     1258730 : timevar_accumulate (struct timevar_time_def *timer,
     269                 :             :                     struct timevar_time_def *start_time,
     270                 :             :                     struct timevar_time_def *stop_time)
     271                 :             : {
     272                 :     1258730 :   timer->user += stop_time->user - start_time->user;
     273                 :     1258730 :   timer->sys += stop_time->sys - start_time->sys;
     274                 :     1258730 :   timer->wall += stop_time->wall - start_time->wall;
     275                 :     1258730 :   timer->ggc_mem += stop_time->ggc_mem - start_time->ggc_mem;
     276                 :     1258730 : }
     277                 :             : 
     278                 :             : /* Get the difference between STOP_TIME and START_TIME.  */
     279                 :             : 
     280                 :             : static void
     281                 :          10 : timevar_diff (struct timevar_time_def *out,
     282                 :             :               const timevar_time_def &start_time,
     283                 :             :               const timevar_time_def &stop_time)
     284                 :             : {
     285                 :          10 :   out->user = stop_time.user - start_time.user;
     286                 :          10 :   out->sys = stop_time.sys - start_time.sys;
     287                 :          10 :   out->wall = stop_time.wall - start_time.wall;
     288                 :          10 :   out->ggc_mem = stop_time.ggc_mem - start_time.ggc_mem;
     289                 :           0 : }
     290                 :             : 
     291                 :             : /* Class timer's constructor.  */
     292                 :             : 
     293                 :          32 : timer::timer () :
     294                 :          32 :   m_stack (NULL),
     295                 :          32 :   m_unused_stack_instances (NULL),
     296                 :          32 :   m_start_time (),
     297                 :          32 :   m_jit_client_items (NULL)
     298                 :             : {
     299                 :             :   /* Zero all elapsed times.  */
     300                 :          32 :   memset (m_timevars, 0, sizeof (m_timevars));
     301                 :             : 
     302                 :             :   /* Initialize the names of timing variables.  */
     303                 :             : #define DEFTIMEVAR(identifier__, name__) \
     304                 :             :   m_timevars[identifier__].name = name__;
     305                 :             : #include "timevar.def"
     306                 :             : #undef DEFTIMEVAR
     307                 :             : 
     308                 :             :   /* Initialize configuration-specific state.
     309                 :             :      Ideally this would be one-time initialization.  */
     310                 :             : #ifdef USE_TIMES
     311                 :          32 :   ticks_to_nanosec = TICKS_TO_NANOSEC;
     312                 :             : #endif
     313                 :             : #ifdef USE_CLOCK
     314                 :             :   clocks_to_nanosec = CLOCKS_TO_NANOSEC;
     315                 :             : #endif
     316                 :          32 : }
     317                 :             : 
     318                 :             : /* Class timer's destructor.  */
     319                 :             : 
     320                 :          32 : timer::~timer ()
     321                 :             : {
     322                 :          32 :   timevar_stack_def *iter, *next;
     323                 :             : 
     324                 :          51 :   for (iter = m_stack; iter; iter = next)
     325                 :             :     {
     326                 :          19 :       next = iter->next;
     327                 :          19 :       free (iter);
     328                 :             :     }
     329                 :         162 :   for (iter = m_unused_stack_instances; iter; iter = next)
     330                 :             :     {
     331                 :         130 :       next = iter->next;
     332                 :         130 :       free (iter);
     333                 :             :     }
     334                 :        9280 :   for (unsigned i = 0; i < TIMEVAR_LAST; ++i)
     335                 :        9274 :     delete m_timevars[i].children;
     336                 :             : 
     337                 :          32 :   delete m_jit_client_items;
     338                 :          32 : }
     339                 :             : 
     340                 :             : /* Initialize timing variables.  */
     341                 :             : 
     342                 :             : void
     343                 :          18 : timevar_init (void)
     344                 :             : {
     345                 :          18 :   if (g_timer)
     346                 :             :     return;
     347                 :             : 
     348                 :          18 :   g_timer = new timer ();
     349                 :             : }
     350                 :             : 
     351                 :             : /* Push TIMEVAR onto the timing stack.  No further elapsed time is
     352                 :             :    attributed to the previous topmost timing variable on the stack;
     353                 :             :    subsequent elapsed time is attributed to TIMEVAR, until it is
     354                 :             :    popped or another element is pushed on top.
     355                 :             : 
     356                 :             :    TIMEVAR cannot be running as a standalone timer.  */
     357                 :             : 
     358                 :             : void
     359                 :      596481 : timer::push (timevar_id_t timevar)
     360                 :             : {
     361                 :      596481 :   struct timevar_def *tv = &m_timevars[timevar];
     362                 :      596481 :   push_internal (tv);
     363                 :      596481 : }
     364                 :             : 
     365                 :             : /* Push TV onto the timing stack, either one of the builtin ones
     366                 :             :    for a timevar_id_t, or one provided by client code to libgccjit.  */
     367                 :             : 
     368                 :             : void
     369                 :      598086 : timer::push_internal (struct timevar_def *tv)
     370                 :             : {
     371                 :      598086 :   struct timevar_stack_def *context;
     372                 :      598086 :   struct timevar_time_def now;
     373                 :             : 
     374                 :      598086 :   gcc_assert (tv);
     375                 :             : 
     376                 :             :   /* Mark this timing variable as used.  */
     377                 :      598086 :   tv->used = 1;
     378                 :             : 
     379                 :             :   /* Can't push a standalone timer.  */
     380                 :      598086 :   gcc_assert (!tv->standalone);
     381                 :             : 
     382                 :             :   /* What time is it?  */
     383                 :      598086 :   get_time (&now);
     384                 :             : 
     385                 :             :   /* If the stack isn't empty, attribute the current elapsed time to
     386                 :             :      the old topmost element.  */
     387                 :      598086 :   if (m_stack)
     388                 :      597982 :     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
     389                 :             : 
     390                 :             :   /* Reset the start time; from now on, time is attributed to
     391                 :             :      TIMEVAR.  */
     392                 :      598086 :   m_start_time = now;
     393                 :             : 
     394                 :             :   /* See if we have a previously-allocated stack instance.  If so,
     395                 :             :      take it off the list.  If not, malloc a new one.  */
     396                 :      598086 :   if (m_unused_stack_instances != NULL)
     397                 :             :     {
     398                 :      597937 :       context = m_unused_stack_instances;
     399                 :      597937 :       m_unused_stack_instances = m_unused_stack_instances->next;
     400                 :             :     }
     401                 :             :   else
     402                 :         149 :     context = XNEW (struct timevar_stack_def);
     403                 :             : 
     404                 :             :   /* Fill it in and put it on the stack.  */
     405                 :      598086 :   context->timevar = tv;
     406                 :      598086 :   context->next = m_stack;
     407                 :      598086 :   m_stack = context;
     408                 :      598086 : }
     409                 :             : 
     410                 :             : /* Pop the topmost timing variable element off the timing stack.  The
     411                 :             :    popped variable must be TIMEVAR.  Elapsed time since the that
     412                 :             :    element was pushed on, or since it was last exposed on top of the
     413                 :             :    stack when the element above it was popped off, is credited to that
     414                 :             :    timing variable.  */
     415                 :             : 
     416                 :             : void
     417                 :      596467 : timer::pop (timevar_id_t timevar)
     418                 :             : {
     419                 :      596467 :   gcc_assert (&m_timevars[timevar] == m_stack->timevar);
     420                 :             : 
     421                 :      596467 :   pop_internal ();
     422                 :      596467 : }
     423                 :             : 
     424                 :             : /* Pop the topmost item from the stack, either one of the builtin ones
     425                 :             :    for a timevar_id_t, or one provided by client code to libgccjit.  */
     426                 :             : 
     427                 :             : void
     428                 :      598067 : timer::pop_internal ()
     429                 :             : {
     430                 :      598067 :   struct timevar_time_def now;
     431                 :      598067 :   struct timevar_stack_def *popped = m_stack;
     432                 :             : 
     433                 :             :   /* What time is it?  */
     434                 :      598067 :   get_time (&now);
     435                 :             : 
     436                 :             :   /* Attribute the elapsed time to the element we're popping.  */
     437                 :      598067 :   timevar_accumulate (&popped->timevar->elapsed, &m_start_time, &now);
     438                 :             : 
     439                 :             :   /* Take the item off the stack.  */
     440                 :      598067 :   m_stack = m_stack->next;
     441                 :             : 
     442                 :             :   /* Record the elapsed sub-time to the parent as well.  */
     443                 :      598067 :   if (m_stack && time_report_details)
     444                 :             :     {
     445                 :         291 :       if (! m_stack->timevar->children)
     446                 :          26 :         m_stack->timevar->children = new child_map_t (5);
     447                 :         291 :       bool existed_p;
     448                 :         291 :       timevar_time_def &time
     449                 :         291 :         = m_stack->timevar->children->get_or_insert (popped->timevar, &existed_p);
     450                 :         291 :       if (! existed_p)
     451                 :          86 :         memset (&time, 0, sizeof (timevar_time_def));
     452                 :         291 :       timevar_accumulate (&time, &m_start_time, &now);
     453                 :             :     }
     454                 :             : 
     455                 :             :   /* Reset the start time; from now on, time is attributed to the
     456                 :             :      element just exposed on the stack.  */
     457                 :      598067 :   m_start_time = now;
     458                 :             : 
     459                 :             :   /* Don't delete the stack element; instead, add it to the list of
     460                 :             :      unused elements for later use.  */
     461                 :      598067 :   popped->next = m_unused_stack_instances;
     462                 :      598067 :   m_unused_stack_instances = popped;
     463                 :      598067 : }
     464                 :             : 
     465                 :             : /* Start timing TIMEVAR independently of the timing stack.  Elapsed
     466                 :             :    time until timevar_stop is called for the same timing variable is
     467                 :             :    attributed to TIMEVAR.  */
     468                 :             : 
     469                 :             : void
     470                 :   270135489 : timevar_start (timevar_id_t timevar)
     471                 :             : {
     472                 :   270135489 :   if (!g_timer)
     473                 :             :     return;
     474                 :             : 
     475                 :        3000 :   g_timer->start (timevar);
     476                 :             : }
     477                 :             : 
     478                 :             : /* See timevar_start above.  */
     479                 :             : 
     480                 :             : void
     481                 :        3018 : timer::start (timevar_id_t timevar)
     482                 :             : {
     483                 :        3018 :   struct timevar_def *tv = &m_timevars[timevar];
     484                 :             : 
     485                 :             :   /* Mark this timing variable as used.  */
     486                 :        3018 :   tv->used = 1;
     487                 :             : 
     488                 :             :   /* Don't allow the same timing variable to be started more than
     489                 :             :      once.  */
     490                 :        3018 :   gcc_assert (!tv->standalone);
     491                 :        3018 :   tv->standalone = 1;
     492                 :             : 
     493                 :        3018 :   get_time (&tv->start_time);
     494                 :        3018 : }
     495                 :             : 
     496                 :             : /* Stop timing TIMEVAR.  Time elapsed since timevar_start was called
     497                 :             :    is attributed to it.  */
     498                 :             : 
     499                 :             : void
     500                 :   269854183 : timevar_stop (timevar_id_t timevar)
     501                 :             : {
     502                 :   269854183 :   if (!g_timer)
     503                 :             :     return;
     504                 :             : 
     505                 :        2982 :   g_timer->stop (timevar);
     506                 :             : }
     507                 :             : 
     508                 :             : /* See timevar_stop above.  */
     509                 :             : 
     510                 :             : void
     511                 :        2994 : timer::stop (timevar_id_t timevar)
     512                 :             : {
     513                 :        2994 :   struct timevar_def *tv = &m_timevars[timevar];
     514                 :        2994 :   struct timevar_time_def now;
     515                 :             : 
     516                 :             :   /* TIMEVAR must have been started via timevar_start.  */
     517                 :        2994 :   gcc_assert (tv->standalone);
     518                 :        2994 :   tv->standalone = 0; /* Enable a restart.  */
     519                 :             : 
     520                 :        2994 :   get_time (&now);
     521                 :        2994 :   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
     522                 :        2994 : }
     523                 :             : 
     524                 :             : 
     525                 :             : /* Conditionally start timing TIMEVAR independently of the timing stack.
     526                 :             :    If the timer is already running, leave it running and return true.
     527                 :             :    Otherwise, start the timer and return false.
     528                 :             :    Elapsed time until the corresponding timevar_cond_stop
     529                 :             :    is called for the same timing variable is attributed to TIMEVAR.  */
     530                 :             : 
     531                 :             : bool
     532                 :           0 : timevar_cond_start (timevar_id_t timevar)
     533                 :             : {
     534                 :           0 :   if (!g_timer)
     535                 :             :     return false;
     536                 :             : 
     537                 :           0 :   return g_timer->cond_start (timevar);
     538                 :             : }
     539                 :             : 
     540                 :             : /* See timevar_cond_start above.  */
     541                 :             : 
     542                 :             : bool
     543                 :       81216 : timer::cond_start (timevar_id_t timevar)
     544                 :             : {
     545                 :       81216 :   struct timevar_def *tv = &m_timevars[timevar];
     546                 :             : 
     547                 :             :   /* Mark this timing variable as used.  */
     548                 :       81216 :   tv->used = 1;
     549                 :             : 
     550                 :       81216 :   if (tv->standalone)
     551                 :             :     return true;  /* The timevar is already running.  */
     552                 :             : 
     553                 :             :   /* Don't allow the same timing variable
     554                 :             :      to be unconditionally started more than once.  */
     555                 :       59396 :   tv->standalone = 1;
     556                 :             : 
     557                 :       59396 :   get_time (&tv->start_time);
     558                 :       59396 :   return false;  /* The timevar was not already running.  */
     559                 :             : }
     560                 :             : 
     561                 :             : /* Conditionally stop timing TIMEVAR.  The RUNNING parameter must come
     562                 :             :    from the return value of a dynamically matching timevar_cond_start.
     563                 :             :    If the timer had already been RUNNING, do nothing.  Otherwise, time
     564                 :             :    elapsed since timevar_cond_start was called is attributed to it.  */
     565                 :             : 
     566                 :             : void
     567                 :           0 : timevar_cond_stop (timevar_id_t timevar, bool running)
     568                 :             : {
     569                 :           0 :   if (!g_timer || running)
     570                 :             :     return;
     571                 :             : 
     572                 :           0 :   g_timer->cond_stop (timevar);
     573                 :             : }
     574                 :             : 
     575                 :             : /* See timevar_cond_stop above.  */
     576                 :             : 
     577                 :             : void
     578                 :       59396 : timer::cond_stop (timevar_id_t timevar)
     579                 :             : {
     580                 :       59396 :   struct timevar_def *tv;
     581                 :       59396 :   struct timevar_time_def now;
     582                 :             : 
     583                 :       59396 :   tv = &m_timevars[timevar];
     584                 :             : 
     585                 :             :   /* TIMEVAR must have been started via timevar_cond_start.  */
     586                 :       59396 :   gcc_assert (tv->standalone);
     587                 :       59396 :   tv->standalone = 0; /* Enable a restart.  */
     588                 :             : 
     589                 :       59396 :   get_time (&now);
     590                 :       59396 :   timevar_accumulate (&tv->elapsed, &tv->start_time, &now);
     591                 :       59396 : }
     592                 :             : 
     593                 :             : /* Push the named item onto the timing stack.  */
     594                 :             : 
     595                 :             : void
     596                 :        1605 : timer::push_client_item (const char *item_name)
     597                 :             : {
     598                 :        1605 :   gcc_assert (item_name);
     599                 :             : 
     600                 :             :   /* Lazily create the named_items instance.  */
     601                 :        1605 :   if (!m_jit_client_items)
     602                 :           9 :     m_jit_client_items = new named_items (this);
     603                 :             : 
     604                 :        1605 :   m_jit_client_items->push (item_name);
     605                 :        1605 : }
     606                 :             : 
     607                 :             : /* Pop the top-most client item from the timing stack.  */
     608                 :             : 
     609                 :             : void
     610                 :        1600 : timer::pop_client_item ()
     611                 :             : {
     612                 :        1600 :   gcc_assert (m_jit_client_items);
     613                 :        1600 :   m_jit_client_items->pop ();
     614                 :        1600 : }
     615                 :             : 
     616                 :             : /* Validate that phase times are consistent.  */
     617                 :             : 
     618                 :             : void
     619                 :          12 : timer::validate_phases (FILE *fp) const
     620                 :             : {
     621                 :          12 :   unsigned int /* timevar_id_t */ id;
     622                 :          12 :   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
     623                 :          12 :   uint64_t phase_user = 0;
     624                 :          12 :   uint64_t phase_sys = 0;
     625                 :          12 :   uint64_t phase_wall = 0;
     626                 :          12 :   size_t phase_ggc_mem = 0;
     627                 :          12 :   static char phase_prefix[] = "phase ";
     628                 :             : 
     629                 :        3480 :   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
     630                 :             :     {
     631                 :        3468 :       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
     632                 :             : 
     633                 :             :       /* Don't evaluate timing variables that were never used.  */
     634                 :        3468 :       if (!tv->used)
     635                 :        2464 :         continue;
     636                 :             : 
     637                 :        1004 :       if (startswith (tv->name, phase_prefix))
     638                 :             :         {
     639                 :          72 :           phase_user += tv->elapsed.user;
     640                 :          72 :           phase_sys += tv->elapsed.sys;
     641                 :          72 :           phase_wall += tv->elapsed.wall;
     642                 :          72 :           phase_ggc_mem += tv->elapsed.ggc_mem;
     643                 :             :         }
     644                 :             :     }
     645                 :             : 
     646                 :          12 :   if (phase_user > total->user
     647                 :          12 :       || phase_sys > total->sys
     648                 :          12 :       || phase_wall > total->wall
     649                 :          12 :       || phase_ggc_mem > total->ggc_mem)
     650                 :             :     {
     651                 :             : 
     652                 :           0 :       fprintf (fp, "Timing error: total of phase timers exceeds total time.\n");
     653                 :           0 :       if (phase_user > total->user)
     654                 :           0 :         fprintf (fp, "user    %13" PRIu64 " > %13" PRIu64 "\n",
     655                 :             :                  phase_user, total->user);
     656                 :           0 :       if (phase_sys > total->sys)
     657                 :           0 :         fprintf (fp, "sys     %13" PRIu64 " > %13" PRIu64 "\n",
     658                 :             :                  phase_sys, total->sys);
     659                 :           0 :       if (phase_wall > total->wall)
     660                 :           0 :         fprintf (fp, "wall    %13" PRIu64 " > %13" PRIu64 "\n",
     661                 :             :                  phase_wall, total->wall);
     662                 :           0 :       if (phase_ggc_mem > total->ggc_mem)
     663                 :           0 :         fprintf (fp, "ggc_mem %13lu > %13lu\n", (unsigned long)phase_ggc_mem,
     664                 :             :                  (unsigned long)total->ggc_mem);
     665                 :           0 :       gcc_unreachable ();
     666                 :             :     }
     667                 :          12 : }
     668                 :             : 
     669                 :             : #define nanosec_to_floating_sec(NANO) ((double)(NANO) * 1e-9)
     670                 :             : #define percent_of(TOTAL, SUBTOTAL) \
     671                 :             :   ((TOTAL) == 0 ? 0 : ((double)SUBTOTAL / TOTAL) * 100)
     672                 :             : /* Helper function for timer::print.  */
     673                 :             : 
     674                 :             : void
     675                 :         363 : timer::print_row (FILE *fp,
     676                 :             :                   const timevar_time_def *total,
     677                 :             :                   const char *name, const timevar_time_def &elapsed)
     678                 :             : {
     679                 :             :   /* The timing variable name.  */
     680                 :         363 :   fprintf (fp, " %-35s:", name);
     681                 :             : 
     682                 :             : #ifdef HAVE_USER_TIME
     683                 :             :   /* Print user-mode time for this process.  */
     684                 :        1089 :   fprintf (fp, "%7.2f (%3.0f%%)",
     685                 :         363 :            nanosec_to_floating_sec (elapsed.user),
     686                 :         363 :            percent_of (total->user, elapsed.user));
     687                 :             : #endif /* HAVE_USER_TIME */
     688                 :             : 
     689                 :             : #ifdef HAVE_SYS_TIME
     690                 :             :   /* Print system-mode time for this process.  */
     691                 :        1081 :   fprintf (fp, "%7.2f (%3.0f%%)",
     692                 :         363 :            nanosec_to_floating_sec (elapsed.sys),
     693                 :         363 :            percent_of (total->sys, elapsed.sys));
     694                 :             : #endif /* HAVE_SYS_TIME */
     695                 :             : 
     696                 :             : #ifdef HAVE_WALL_TIME
     697                 :             :   /* Print wall clock time elapsed.  */
     698                 :        1089 :   fprintf (fp, "%7.2f (%3.0f%%)",
     699                 :         363 :            nanosec_to_floating_sec (elapsed.wall),
     700                 :         363 :            percent_of (total->wall, elapsed.wall));
     701                 :             : #endif /* HAVE_WALL_TIME */
     702                 :             : 
     703                 :             :   /* Print the amount of ggc memory allocated.  */
     704                 :         568 :   fprintf (fp, PRsa (6) " (%3.0f%%)",
     705                 :         410 :            SIZE_AMOUNT (elapsed.ggc_mem),
     706                 :         363 :            (total->ggc_mem == 0
     707                 :         363 :             ? 0
     708                 :         363 :             : (float) elapsed.ggc_mem / total->ggc_mem) * 100);
     709                 :             : 
     710                 :         363 :   putc ('\n', fp);
     711                 :         363 : }
     712                 :             : 
     713                 :             : /* Return whether ELAPSED is all zero.  */
     714                 :             : 
     715                 :             : bool
     716                 :        1337 : timer::all_zero (const timevar_time_def &elapsed)
     717                 :             : {
     718                 :             :   /* 5000000 nanosec == 5e-3 seconds.  */
     719                 :        1337 :   uint64_t tiny = 5000000;
     720                 :        1337 :   return (elapsed.user < tiny
     721                 :        1089 :           && elapsed.sys < tiny
     722                 :        1062 :           && elapsed.wall < tiny
     723                 :        2309 :           && elapsed.ggc_mem < GGC_MEM_BOUND);
     724                 :             : }
     725                 :             : 
     726                 :             : /* Summarize timing variables to FP.  The timing variable TV_TOTAL has
     727                 :             :    a special meaning -- it's considered to be the total elapsed time,
     728                 :             :    for normalizing the others, and is displayed last.  */
     729                 :             : 
     730                 :             : void
     731                 :          12 : timer::print (FILE *fp)
     732                 :             : {
     733                 :             :   /* Only print stuff if we have some sort of time information.  */
     734                 :             : #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
     735                 :          12 :   unsigned int /* timevar_id_t */ id;
     736                 :          12 :   const timevar_time_def *total = &m_timevars[TV_TOTAL].elapsed;
     737                 :          12 :   struct timevar_time_def now;
     738                 :             : 
     739                 :             :   /* Update timing information in case we're calling this from GDB.  */
     740                 :             : 
     741                 :          12 :   if (fp == 0)
     742                 :           0 :     fp = stderr;
     743                 :             : 
     744                 :             :   /* What time is it?  */
     745                 :          12 :   get_time (&now);
     746                 :             : 
     747                 :             :   /* If the stack isn't empty, attribute the current elapsed time to
     748                 :             :      the old topmost element.  */
     749                 :          12 :   if (m_stack)
     750                 :           0 :     timevar_accumulate (&m_stack->timevar->elapsed, &m_start_time, &now);
     751                 :             : 
     752                 :             :   /* Reset the start time; from now on, time is attributed to
     753                 :             :      TIMEVAR.  */
     754                 :          12 :   m_start_time = now;
     755                 :             : 
     756                 :          12 :   fprintf (fp, "\n%-35s%16s%14s%14s%14s\n", "Time variable", "usr", "sys",
     757                 :             :            "wall", "GGC");
     758                 :          12 :   if (m_jit_client_items)
     759                 :           4 :     fputs ("GCC items:\n", fp);
     760                 :        3480 :   for (id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
     761                 :             :     {
     762                 :        3468 :       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
     763                 :             : 
     764                 :             :       /* Don't print the total execution time here; that goes at the
     765                 :             :          end.  */
     766                 :        3468 :       if ((timevar_id_t) id == TV_TOTAL)
     767                 :          12 :         continue;
     768                 :             : 
     769                 :             :       /* Don't print timing variables that were never used.  */
     770                 :        3456 :       if (!tv->used)
     771                 :        2464 :         continue;
     772                 :             : 
     773                 :         992 :       bool any_children_with_time = false;
     774                 :         992 :       if (tv->children)
     775                 :           0 :         for (child_map_t::iterator i = tv->children->begin ();
     776                 :           0 :              i != tv->children->end (); ++i)
     777                 :           0 :           if (! all_zero ((*i).second))
     778                 :             :             {
     779                 :             :               any_children_with_time = true;
     780                 :             :               break;
     781                 :             :             }
     782                 :             : 
     783                 :             :       /* Don't print timing variables if we're going to get a row of
     784                 :             :          zeroes.  Unless there are children with non-zero time.  */
     785                 :         645 :       if (! any_children_with_time
     786                 :         992 :           && all_zero (tv->elapsed))
     787                 :         645 :         continue;
     788                 :             : 
     789                 :         347 :       print_row (fp, total, tv->name, tv->elapsed);
     790                 :             : 
     791                 :         347 :       if (tv->children)
     792                 :           0 :         for (child_map_t::iterator i = tv->children->begin ();
     793                 :           0 :              i != tv->children->end (); ++i)
     794                 :             :           {
     795                 :           0 :             timevar_def *tv2 = (*i).first;
     796                 :             :             /* Don't print timing variables if we're going to get a row of
     797                 :             :                zeroes.  */
     798                 :           0 :             if (! all_zero ((*i).second))
     799                 :             :               {
     800                 :           0 :                 char lname[256];
     801                 :           0 :                 snprintf (lname, 256, "`- %s", tv2->name);
     802                 :           0 :                 print_row (fp, total, lname, (*i).second);
     803                 :             :               }
     804                 :             :           }
     805                 :             :     }
     806                 :          12 :   if (m_jit_client_items)
     807                 :           4 :     m_jit_client_items->print (fp, total);
     808                 :             : 
     809                 :             :   /* Print total time.  */
     810                 :          12 :   fprintf (fp, " %-35s:", "TOTAL");
     811                 :             : #ifdef HAVE_USER_TIME
     812                 :          12 :   fprintf (fp, "%7.2f      ", nanosec_to_floating_sec (total->user));
     813                 :             : #endif
     814                 :             : #ifdef HAVE_SYS_TIME
     815                 :          12 :   fprintf (fp, "%8.2f      ", nanosec_to_floating_sec (total->sys));
     816                 :             : #endif
     817                 :             : #ifdef HAVE_WALL_TIME
     818                 :          12 :   fprintf (fp, "%8.2f      ", nanosec_to_floating_sec (total->wall));
     819                 :             : #endif
     820                 :          16 :   fprintf (fp, PRsa (7) "\n", SIZE_AMOUNT (total->ggc_mem));
     821                 :             : 
     822                 :          12 :   if (CHECKING_P || flag_checking)
     823                 :          12 :     fprintf (fp, "Extra diagnostic checks enabled; compiler may run slowly.\n");
     824                 :          12 :   if (CHECKING_P)
     825                 :          12 :     fprintf (fp, "Configure with --enable-checking=release to disable checks.\n");
     826                 :             : #ifndef ENABLE_ASSERT_CHECKING
     827                 :             :   fprintf (fp, "Internal checks disabled; compiler is not suited for release.\n");
     828                 :             :   fprintf (fp, "Configure with --enable-checking=release to enable checks.\n");
     829                 :             : #endif
     830                 :             : 
     831                 :             : #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
     832                 :             :           || defined (HAVE_WALL_TIME) */
     833                 :             : 
     834                 :          12 :   validate_phases (fp);
     835                 :          12 : }
     836                 :             : 
     837                 :             : /* Create a json value representing this object, suitable for use
     838                 :             :    in SARIF output.  */
     839                 :             : 
     840                 :             : json::object *
     841                 :          28 : make_json_for_timevar_time_def (const timevar_time_def &ttd)
     842                 :             : {
     843                 :          28 :   json::object *obj = new json::object ();
     844                 :          28 :   obj->set_float ("user", nanosec_to_floating_sec (ttd.user));
     845                 :          28 :   obj->set_float ("sys", nanosec_to_floating_sec (ttd.sys));
     846                 :          28 :   obj->set_float ("wall", nanosec_to_floating_sec (ttd.wall));
     847                 :          28 :   obj->set_integer ("ggc_mem", ttd.ggc_mem);
     848                 :          28 :   return obj;
     849                 :             : }
     850                 :             : #undef nanosec_to_floating_sec
     851                 :             : #undef percent_of
     852                 :             : 
     853                 :             : /* Create a json value representing this object, suitable for use
     854                 :             :    in SARIF output.  */
     855                 :             : 
     856                 :             : json::value *
     857                 :          18 : timer::timevar_def::make_json () const
     858                 :             : {
     859                 :          18 :   json::object *timevar_obj = new json::object ();
     860                 :          18 :   timevar_obj->set_string ("name", name);
     861                 :          18 :   timevar_obj->set ("elapsed", make_json_for_timevar_time_def (elapsed));
     862                 :             : 
     863                 :          18 :   if (children)
     864                 :             :     {
     865                 :           1 :       bool any_children_with_time = false;
     866                 :           3 :       for (auto i : *children)
     867                 :           1 :         if (!all_zero (i.second))
     868                 :             :           {
     869                 :             :             any_children_with_time = true;
     870                 :             :             break;
     871                 :             :           }
     872                 :           1 :       if (any_children_with_time)
     873                 :             :         {
     874                 :           0 :           json::array *children_arr = new json::array ();
     875                 :           0 :           timevar_obj->set ("children", children_arr);
     876                 :           0 :           for (auto i : *children)
     877                 :             :             {
     878                 :             :               /* Don't emit timing variables if we're going to get a row of
     879                 :             :                  zeroes.  */
     880                 :           0 :               if (all_zero (i.second))
     881                 :           0 :                 continue;
     882                 :           0 :               json::object *child_obj = new json::object;
     883                 :           0 :               children_arr->append (child_obj);
     884                 :           0 :               child_obj->set_string ("name", i.first->name);
     885                 :           0 :               child_obj->set ("elapsed",
     886                 :           0 :                               make_json_for_timevar_time_def (i.second));
     887                 :             :             }
     888                 :             :         }
     889                 :             :     }
     890                 :             : 
     891                 :          18 :   return timevar_obj;
     892                 :             : }
     893                 :             : 
     894                 :             : /* Create a json value representing this object, suitable for use
     895                 :             :    in SARIF output.  */
     896                 :             : 
     897                 :             : json::value *
     898                 :          10 : timer::make_json () const
     899                 :             : {
     900                 :             :   /* Only generate stuff if we have some sort of time information.  */
     901                 :             : #if defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME) || defined (HAVE_WALL_TIME)
     902                 :          10 :   json::object *report_obj = new json::object ();
     903                 :          10 :   json::array *json_arr = new json::array ();
     904                 :          10 :   report_obj->set ("timevars", json_arr);
     905                 :             : 
     906                 :        2900 :   for (unsigned id = 0; id < (unsigned int) TIMEVAR_LAST; ++id)
     907                 :             :     {
     908                 :        2890 :       const timevar_def *tv = &m_timevars[(timevar_id_t) id];
     909                 :             : 
     910                 :             :       /* Don't print the total execution time here; this isn't initialized
     911                 :             :          by the time the sarif output runs.  */
     912                 :        2890 :       if ((timevar_id_t) id == TV_TOTAL)
     913                 :          10 :         continue;
     914                 :             : 
     915                 :             :       /* Don't emit timing variables that were never used.  */
     916                 :        2880 :       if (!tv->used)
     917                 :        2622 :         continue;
     918                 :             : 
     919                 :         258 :       bool any_children_with_time = false;
     920                 :         258 :       if (tv->children)
     921                 :         112 :         for (child_map_t::iterator i = tv->children->begin ();
     922                 :         198 :              i != tv->children->end (); ++i)
     923                 :          86 :           if (! all_zero ((*i).second))
     924                 :             :             {
     925                 :             :               any_children_with_time = true;
     926                 :             :               break;
     927                 :             :             }
     928                 :             : 
     929                 :             :       /* Don't emit timing variables if we're going to get a row of
     930                 :             :          zeroes.  Unless there are children with non-zero time.  */
     931                 :         266 :       if (! any_children_with_time
     932                 :         258 :           && all_zero (tv->elapsed))
     933                 :         240 :         continue;
     934                 :             : 
     935                 :          18 :       json_arr->append (tv->make_json ());
     936                 :             :     }
     937                 :             : 
     938                 :             :   /* Special-case for total.  */
     939                 :          10 :   {
     940                 :             :     /* Get our own total up till now, without affecting TV_TOTAL.  */
     941                 :          10 :     struct timevar_time_def total_now;
     942                 :          10 :     struct timevar_time_def total_elapsed;
     943                 :          10 :     get_time (&total_now);
     944                 :          10 :     timevar_diff (&total_elapsed, m_timevars[TV_TOTAL].start_time, total_now);
     945                 :             : 
     946                 :          10 :     json::object *total_obj = new json::object();
     947                 :          10 :     json_arr->append (total_obj);
     948                 :          10 :     total_obj->set_string ("name", "TOTAL");
     949                 :          10 :     total_obj->set ("elapsed", make_json_for_timevar_time_def (total_elapsed));
     950                 :             :   }
     951                 :             : 
     952                 :          10 :   if (m_jit_client_items)
     953                 :           0 :     report_obj->set ("client_items", m_jit_client_items->make_json ());
     954                 :             : 
     955                 :          10 :   report_obj->set_bool ("CHECKING_P", CHECKING_P);
     956                 :          10 :   report_obj->set_bool ("flag_checking", flag_checking);
     957                 :             : 
     958                 :          10 :   return report_obj;
     959                 :             : 
     960                 :             : #else /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
     961                 :             :           || defined (HAVE_WALL_TIME) */
     962                 :             :   return NULL;
     963                 :             : #endif /* defined (HAVE_USER_TIME) || defined (HAVE_SYS_TIME)
     964                 :             :           || defined (HAVE_WALL_TIME) */
     965                 :             : }
     966                 :             : 
     967                 :             : /* Get the name of the topmost item.  For use by jit for validating
     968                 :             :    inputs to gcc_jit_timer_pop.  */
     969                 :             : const char *
     970                 :        1610 : timer::get_topmost_item_name () const
     971                 :             : {
     972                 :        1610 :   if (m_stack)
     973                 :        1610 :     return m_stack->timevar->name;
     974                 :             :   else
     975                 :             :     return NULL;
     976                 :             : }
     977                 :             : 
     978                 :             : /* Prints a message to stderr stating that time elapsed in STR is
     979                 :             :    TOTAL (given in microseconds).  */
     980                 :             : 
     981                 :             : void
     982                 :           0 : print_time (const char *str, long total)
     983                 :             : {
     984                 :           0 :   long all_time = get_run_time ();
     985                 :           0 :   fprintf (stderr,
     986                 :             :            "time in %s: %ld.%06ld (%ld%%)\n",
     987                 :             :            str, total / 1000000, total % 1000000,
     988                 :             :            all_time == 0 ? 0
     989                 :           0 :            : (long) (((100.0 * (double) total) / (double) all_time) + .5));
     990                 :           0 : }
        

Generated by: LCOV version 2.1-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.