LCOV - code coverage report
Current view: top level - gcc - statistics.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.3 % 128 122
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 14 14
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Optimization statistics functions.
       2              :    Copyright (C) 2008-2026 Free Software Foundation, Inc.
       3              :    Contributed by Richard Guenther  <rguenther@suse.de>
       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 "function.h"
      25              : #include "tree-pass.h"
      26              : #include "context.h"
      27              : #include "pass_manager.h"
      28              : #include "tree.h"
      29              : 
      30              : static int statistics_dump_nr;
      31              : static dump_flags_t statistics_dump_flags;
      32              : static FILE *statistics_dump_file;
      33              : 
      34              : /* Statistics entry.  A integer counter associated to a string ID
      35              :    and value.  */
      36              : 
      37              : struct statistics_counter {
      38              :   const char *id;
      39              :   int val;
      40              :   bool histogram_p;
      41              :   unsigned HOST_WIDE_INT count;
      42              :   unsigned HOST_WIDE_INT prev_dumped_count;
      43              : };
      44              : 
      45              : /* Hashtable helpers.  */
      46              : 
      47              : struct stats_counter_hasher : pointer_hash <statistics_counter>
      48              : {
      49              :   static inline hashval_t hash (const statistics_counter *);
      50              :   static inline bool equal (const statistics_counter *,
      51              :                             const statistics_counter *);
      52              :   static inline void remove (statistics_counter *);
      53              : };
      54              : 
      55              : /* Hash a statistic counter by its string ID.  */
      56              : 
      57              : inline hashval_t
      58       176459 : stats_counter_hasher::hash (const statistics_counter *c)
      59              : {
      60       176459 :   return htab_hash_string (c->id) + c->val;
      61              : }
      62              : 
      63              : /* Compare two statistic counters by their string IDs.  */
      64              : 
      65              : inline bool
      66       175510 : stats_counter_hasher::equal (const statistics_counter *c1,
      67              :                              const statistics_counter *c2)
      68              : {
      69       175510 :   return c1->val == c2->val && strcmp (c1->id, c2->id) == 0;
      70              : }
      71              : 
      72              : /* Free a statistics entry.  */
      73              : 
      74              : inline void
      75              : stats_counter_hasher::remove (statistics_counter *v)
      76              : {
      77              :   free (const_cast<char *> (v->id));
      78              :   free (v);
      79              : }
      80              : 
      81              : typedef hash_table<stats_counter_hasher> stats_counter_table_type;
      82              : 
      83              : /* Array of statistic hashes, indexed by pass id.  */
      84              : static stats_counter_table_type **statistics_hashes;
      85              : static unsigned nr_statistics_hashes;
      86              : 
      87              : /* Return the current hashtable to be used for recording or printing
      88              :    statistics.  */
      89              : 
      90              : static stats_counter_table_type *
      91    581350970 : curr_statistics_hash (bool alloc = true)
      92              : {
      93    581350970 :   unsigned idx;
      94              : 
      95    581350970 :   gcc_assert (current_pass->static_pass_number >= 0);
      96    581350970 :   idx = current_pass->static_pass_number;
      97              : 
      98    581350970 :   if (idx < nr_statistics_hashes
      99       666975 :       && statistics_hashes[idx])
     100              :     return statistics_hashes[idx];
     101              : 
     102    581216652 :   if (!alloc)
     103              :     return nullptr;
     104              : 
     105          694 :   if (idx >= nr_statistics_hashes)
     106              :     {
     107          624 :       statistics_hashes = XRESIZEVEC (stats_counter_table_type *,
     108              :                                       statistics_hashes, idx+1);
     109          624 :       memset (statistics_hashes + nr_statistics_hashes, 0,
     110          624 :               (idx + 1 - nr_statistics_hashes)
     111              :               * sizeof (stats_counter_table_type *));
     112          624 :       nr_statistics_hashes = idx + 1;
     113              :     }
     114              : 
     115          694 :   statistics_hashes[idx] = new stats_counter_table_type (15);
     116              : 
     117          694 :   return statistics_hashes[idx];
     118              : }
     119              : 
     120              : /* Helper function to return asmname or name of FN
     121              :    depending on whether asmname option is set.  */
     122              : 
     123              : static const char *
     124        38833 : get_function_name (struct function *fn)
     125              : {
     126        38833 :   if ((statistics_dump_flags & TDF_ASMNAME)
     127        38833 :       && fn && DECL_ASSEMBLER_NAME_SET_P (fn->decl))
     128              :     {
     129            0 :       tree asmname = decl_assembler_name (fn->decl);
     130            0 :       if (asmname)
     131            0 :         return IDENTIFIER_POINTER (asmname);
     132              :     }
     133        38833 :   return function_name (fn);
     134              : }
     135              : 
     136              : /* Helper for statistics_fini_pass.  Print the counter difference
     137              :    since the last dump for the pass dump files.  */
     138              : 
     139              : int
     140         2252 : statistics_fini_pass_1 (statistics_counter **slot,
     141              :                         void *data ATTRIBUTE_UNUSED)
     142              : {
     143         2252 :   statistics_counter *counter = *slot;
     144         2252 :   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
     145         2252 :   if (count == 0)
     146              :     return 1;
     147         1730 :   if (counter->histogram_p)
     148          686 :     fprintf (dump_file, "%s == %d: " HOST_WIDE_INT_PRINT_DEC "\n",
     149              :              counter->id, counter->val, count);
     150              :   else
     151         1044 :     fprintf (dump_file, "%s: " HOST_WIDE_INT_PRINT_DEC "\n",
     152              :              counter->id, count);
     153         1730 :   counter->prev_dumped_count = counter->count;
     154         1730 :   return 1;
     155              : }
     156              : 
     157              : /* Helper for statistics_fini_pass.  Print the counter difference
     158              :    since the last dump for the statistics dump.  */
     159              : 
     160              : int
     161       518664 : statistics_fini_pass_2 (statistics_counter **slot,
     162              :                         void *data ATTRIBUTE_UNUSED)
     163              : {
     164       518664 :   statistics_counter *counter = *slot;
     165       518664 :   unsigned HOST_WIDE_INT count = counter->count - counter->prev_dumped_count;
     166       518664 :   if (count == 0)
     167              :     return 1;
     168        38833 :   counter->prev_dumped_count = counter->count;
     169        38833 :   if (counter->histogram_p)
     170        19824 :     fprintf (statistics_dump_file,
     171              :              "%d %s \"%s == %d\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
     172              :              current_pass->static_pass_number,
     173              :              current_pass->name,
     174              :              counter->id, counter->val,
     175              :              get_function_name (cfun),
     176              :              count);
     177              :   else
     178        19009 :     fprintf (statistics_dump_file,
     179              :              "%d %s \"%s\" \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
     180              :              current_pass->static_pass_number,
     181              :              current_pass->name,
     182              :              counter->id,
     183              :              get_function_name (cfun),
     184              :              count);
     185        38833 :   counter->prev_dumped_count = counter->count;
     186        38833 :   return 1;
     187              : }
     188              : 
     189              : /* Helper for statistics_fini_pass, reset the counters.  */
     190              : 
     191              : int
     192       643823 : statistics_fini_pass_3 (statistics_counter **slot,
     193              :                         void *data ATTRIBUTE_UNUSED)
     194              : {
     195       643823 :   statistics_counter *counter = *slot;
     196       643823 :   counter->prev_dumped_count = counter->count;
     197       643823 :   return 1;
     198              : }
     199              : 
     200              : /* Dump the current statistics incrementally.  */
     201              : 
     202              : void
     203    640083722 : statistics_fini_pass (void)
     204              : {
     205    640083722 :   if (current_pass->static_pass_number == -1)
     206              :     return;
     207              : 
     208    581305808 :   stats_counter_table_type *stat_hash = curr_statistics_hash (false);
     209              : 
     210    581305808 :   if (dump_file
     211    581305808 :       && dump_flags & TDF_STATS)
     212              :     {
     213         1880 :       fprintf (dump_file, "\n");
     214         1880 :       fprintf (dump_file, "Pass statistics of \"%s\": ", current_pass->name);
     215         1880 :       fprintf (dump_file, "----------------\n");
     216         1880 :       if (stat_hash)
     217         2821 :         stat_hash->traverse_noresize <void *, statistics_fini_pass_1> (NULL);
     218         1880 :       fprintf (dump_file, "\n");
     219              :     }
     220              : 
     221    581305808 :   if (!stat_hash)
     222              :     return;
     223              : 
     224        89850 :   if (statistics_dump_file
     225        89850 :       && !(statistics_dump_flags & TDF_STATS
     226        66758 :            || statistics_dump_flags & TDF_DETAILS))
     227       585422 :     stat_hash->traverse_noresize <void *, statistics_fini_pass_2> (NULL);
     228       733673 :   stat_hash->traverse_noresize <void *, statistics_fini_pass_3> (NULL);
     229              : }
     230              : 
     231              : /* Helper for printing summary information.  */
     232              : 
     233              : int
     234           43 : statistics_fini_1 (statistics_counter **slot, opt_pass *pass)
     235              : {
     236           43 :   statistics_counter *counter = *slot;
     237           43 :   if (counter->count == 0)
     238              :     return 1;
     239           43 :   if (counter->histogram_p)
     240           22 :     fprintf (statistics_dump_file,
     241              :              "%d %s \"%s == %d\" " HOST_WIDE_INT_PRINT_DEC "\n",
     242              :              pass->static_pass_number,
     243              :              pass->name,
     244              :              counter->id, counter->val,
     245              :              counter->count);
     246              :   else
     247           21 :     fprintf (statistics_dump_file,
     248              :              "%d %s \"%s\" " HOST_WIDE_INT_PRINT_DEC "\n",
     249              :              pass->static_pass_number,
     250              :              pass->name,
     251              :              counter->id,
     252              :              counter->count);
     253              :   return 1;
     254              : }
     255              : 
     256              : /* Finish the statistics and dump summary information.  */
     257              : 
     258              : void
     259       276762 : statistics_fini (void)
     260              : {
     261       276762 :   gcc::pass_manager *passes = g->get_passes ();
     262       276762 :   if (!statistics_dump_file)
     263              :     return;
     264              : 
     265           66 :   if (statistics_dump_flags & TDF_STATS)
     266              :     {
     267              :       unsigned i;
     268          317 :       for (i = 0; i < nr_statistics_hashes; ++i)
     269          314 :         if (statistics_hashes[i]
     270          314 :             && passes->get_pass_for_id (i) != NULL)
     271            7 :           statistics_hashes[i]
     272              :             ->traverse_noresize <opt_pass *, statistics_fini_1>
     273           50 :             (passes->get_pass_for_id (i));
     274              :     }
     275              : 
     276           66 :   dump_end (statistics_dump_nr, statistics_dump_file);
     277              : }
     278              : 
     279              : /* Register the statistics dump file.  */
     280              : 
     281              : void
     282       285722 : statistics_early_init (void)
     283              : {
     284       285722 :   gcc::dump_manager *dumps = g->get_dumps ();
     285       285722 :   statistics_dump_nr = dumps->dump_register (".statistics", "statistics",
     286              :                                              "statistics", DK_tree,
     287              :                                              OPTGROUP_NONE,
     288              :                                              false);
     289       285722 : }
     290              : 
     291              : /* Init the statistics.  */
     292              : 
     293              : void
     294       278638 : statistics_init (void)
     295              : {
     296       278638 :   gcc::dump_manager *dumps = g->get_dumps ();
     297       278638 :   statistics_dump_file = dump_begin (statistics_dump_nr, NULL);
     298       278638 :   statistics_dump_flags = dumps->get_dump_file_info (statistics_dump_nr)->pflags;
     299       278638 : }
     300              : 
     301              : /* Lookup or add a statistics counter in the hashtable HASH with ID, VAL
     302              :    and HISTOGRAM_P.  */
     303              : 
     304              : static statistics_counter *
     305        45162 : lookup_or_add_counter (stats_counter_table_type *hash, const char *id, int val,
     306              :                        bool histogram_p)
     307              : {
     308        45162 :   statistics_counter **counter;
     309        45162 :   statistics_counter c;
     310        45162 :   c.id = id;
     311        45162 :   c.val = val;
     312        45162 :   counter = hash->find_slot (&c, INSERT);
     313        45162 :   if (!*counter)
     314              :     {
     315         3396 :       *counter = XNEW (statistics_counter);
     316         3396 :       (*counter)->id = xstrdup (id);
     317         3396 :       (*counter)->val = val;
     318         3396 :       (*counter)->histogram_p = histogram_p;
     319         3396 :       (*counter)->prev_dumped_count = 0;
     320         3396 :       (*counter)->count = 0;
     321              :     }
     322        45162 :   return *counter;
     323              : }
     324              : 
     325              : /* Add statistics information about event ID in function FN.
     326              :    This will increment the counter associated with ID by INCR.
     327              :    It will also dump the event to the global statistics file if requested.  */
     328              : 
     329              : void
     330    229968722 : statistics_counter_event (struct function *fn, const char *id, int incr)
     331              : {
     332    229968722 :   statistics_counter *counter;
     333              : 
     334    229968722 :   if ((!(dump_flags & TDF_STATS)
     335    229966845 :        && !statistics_dump_file)
     336    230110087 :       || incr == 0)
     337              :     return;
     338              : 
     339        21106 :   if (current_pass
     340        21102 :       && current_pass->static_pass_number != -1)
     341              :     {
     342        21102 :       counter = lookup_or_add_counter (curr_statistics_hash (), id, 0, false);
     343        21102 :       gcc_assert (!counter->histogram_p);
     344        21102 :       counter->count += incr;
     345              :     }
     346              : 
     347        21106 :   if (!statistics_dump_file
     348        21106 :       || !(statistics_dump_flags & TDF_DETAILS))
     349              :     return;
     350              : 
     351            0 :   fprintf (statistics_dump_file,
     352              :            "%d %s \"%s\" \"%s\" %d\n",
     353              :            current_pass ? current_pass->static_pass_number : -1,
     354            0 :            current_pass ? current_pass->name : "none",
     355              :            id,
     356              :            get_function_name (fn),
     357              :            incr);
     358              : }
     359              : 
     360              : /* Add statistics information about event ID in function FN with the
     361              :    histogram value VAL.
     362              :    It will dump the event to the global statistics file if requested.  */
     363              : 
     364              : void
     365     76664670 : statistics_histogram_event (struct function *fn, const char *id, int val)
     366              : {
     367     76664670 :   statistics_counter *counter;
     368              : 
     369     76664670 :   if (!(dump_flags & TDF_STATS)
     370     76664670 :       && !statistics_dump_file)
     371              :     return;
     372              : 
     373        24060 :   counter = lookup_or_add_counter (curr_statistics_hash (), id, val, true);
     374        24060 :   gcc_assert (counter->histogram_p);
     375        24060 :   counter->count += 1;
     376              : 
     377        24060 :   if (!statistics_dump_file
     378        24060 :       || !(statistics_dump_flags & TDF_DETAILS))
     379              :     return;
     380              : 
     381            0 :   fprintf (statistics_dump_file,
     382              :            "%d %s \"%s == %d\" \"%s\" 1\n",
     383              :            current_pass->static_pass_number,
     384              :            current_pass->name,
     385              :            id, val,
     386              :            get_function_name (fn));
     387              : }
        

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.