LCOV - code coverage report
Current view: top level - gcc - tree-streamer.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.9 % 169 162
Test Date: 2024-11-30 13:30:02 Functions: 100.0 % 12 12
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Miscellaneous utilities for tree streaming.  Things that are used
       2                 :             :    in both input and output are here.
       3                 :             : 
       4                 :             :    Copyright (C) 2011-2024 Free Software Foundation, Inc.
       5                 :             :    Contributed by Diego Novillo <dnovillo@google.com>
       6                 :             : 
       7                 :             : This file is part of GCC.
       8                 :             : 
       9                 :             : GCC is free software; you can redistribute it and/or modify it under
      10                 :             : the terms of the GNU General Public License as published by the Free
      11                 :             : Software Foundation; either version 3, or (at your option) any later
      12                 :             : version.
      13                 :             : 
      14                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      15                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      16                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      17                 :             : for more details.
      18                 :             : 
      19                 :             : You should have received a copy of the GNU General Public License
      20                 :             : along with GCC; see the file COPYING3.  If not see
      21                 :             : <http://www.gnu.org/licenses/>.  */
      22                 :             : 
      23                 :             : #include "config.h"
      24                 :             : #include "system.h"
      25                 :             : #include "coretypes.h"
      26                 :             : #include "backend.h"
      27                 :             : #include "tree.h"
      28                 :             : #include "gimple.h"
      29                 :             : #include "tree-streamer.h"
      30                 :             : #include "cgraph.h"
      31                 :             : 
      32                 :             : /* Table indexed by machine_mode, used for 2 different purposes.
      33                 :             :    During streaming out we record there non-zero value for all modes
      34                 :             :    that were streamed out.
      35                 :             :    During streaming in, we translate the on the disk mode using this
      36                 :             :    table.  For normal LTO it is set to identity, for ACCEL_COMPILER
      37                 :             :    depending on the mode_table content.  */
      38                 :             : unsigned char streamer_mode_table[MAX_MACHINE_MODE];
      39                 :             : 
      40                 :             : /* Check that all the TS_* structures handled by the streamer_write_* and
      41                 :             :    streamer_read_* routines are exactly ALL the structures defined in
      42                 :             :    treestruct.def.  */
      43                 :             : 
      44                 :             : void
      45                 :       56452 : streamer_check_handled_ts_structures (void)
      46                 :             : {
      47                 :       56452 :   bool handled_p[LAST_TS_ENUM];
      48                 :       56452 :   unsigned i;
      49                 :             : 
      50                 :       56452 :   memset (&handled_p, 0, sizeof (handled_p));
      51                 :             : 
      52                 :             :   /* These are the TS_* structures that are either handled or
      53                 :             :      explicitly ignored by the streamer routines.  */
      54                 :       56452 :   handled_p[TS_BASE] = true;
      55                 :       56452 :   handled_p[TS_TYPED] = true;
      56                 :       56452 :   handled_p[TS_COMMON] = true;
      57                 :       56452 :   handled_p[TS_INT_CST] = true;
      58                 :       56452 :   handled_p[TS_POLY_INT_CST] = true;
      59                 :       56452 :   handled_p[TS_REAL_CST] = true;
      60                 :       56452 :   handled_p[TS_FIXED_CST] = true;
      61                 :       56452 :   handled_p[TS_VECTOR] = true;
      62                 :       56452 :   handled_p[TS_STRING] = true;
      63                 :       56452 :   handled_p[TS_RAW_DATA_CST] = true;
      64                 :       56452 :   handled_p[TS_COMPLEX] = true;
      65                 :       56452 :   handled_p[TS_IDENTIFIER] = true;
      66                 :       56452 :   handled_p[TS_DECL_MINIMAL] = true;
      67                 :       56452 :   handled_p[TS_DECL_COMMON] = true;
      68                 :       56452 :   handled_p[TS_DECL_WRTL] = true;
      69                 :       56452 :   handled_p[TS_DECL_NON_COMMON] = true;
      70                 :       56452 :   handled_p[TS_DECL_WITH_VIS] = true;
      71                 :       56452 :   handled_p[TS_FIELD_DECL] = true;
      72                 :       56452 :   handled_p[TS_VAR_DECL] = true;
      73                 :       56452 :   handled_p[TS_PARM_DECL] = true;
      74                 :       56452 :   handled_p[TS_LABEL_DECL] = true;
      75                 :       56452 :   handled_p[TS_RESULT_DECL] = true;
      76                 :       56452 :   handled_p[TS_CONST_DECL] = true;
      77                 :       56452 :   handled_p[TS_TYPE_DECL] = true;
      78                 :       56452 :   handled_p[TS_FUNCTION_DECL] = true;
      79                 :       56452 :   handled_p[TS_TYPE_COMMON] = true;
      80                 :       56452 :   handled_p[TS_TYPE_WITH_LANG_SPECIFIC] = true;
      81                 :       56452 :   handled_p[TS_TYPE_NON_COMMON] = true;
      82                 :       56452 :   handled_p[TS_LIST] = true;
      83                 :       56452 :   handled_p[TS_VEC] = true;
      84                 :       56452 :   handled_p[TS_EXP] = true;
      85                 :       56452 :   handled_p[TS_SSA_NAME] = true;
      86                 :       56452 :   handled_p[TS_BLOCK] = true;
      87                 :       56452 :   handled_p[TS_BINFO] = true;
      88                 :       56452 :   handled_p[TS_STATEMENT_LIST] = true;
      89                 :       56452 :   handled_p[TS_CONSTRUCTOR] = true;
      90                 :       56452 :   handled_p[TS_OMP_CLAUSE] = true;
      91                 :       56452 :   handled_p[TS_OPTIMIZATION] = true;
      92                 :       56452 :   handled_p[TS_TARGET_OPTION] = true;
      93                 :       56452 :   handled_p[TS_TRANSLATION_UNIT_DECL] = true;
      94                 :             : 
      95                 :             :   /* Anything not marked above will trigger the following assertion.
      96                 :             :      If this assertion triggers, it means that there is a new TS_*
      97                 :             :      structure that should be handled by the streamer.  */
      98                 :     2314532 :   for (i = 0; i < LAST_TS_ENUM; i++)
      99                 :     2258080 :     gcc_assert (handled_p[i]);
     100                 :       56452 : }
     101                 :             : 
     102                 :             : 
     103                 :             : /* Helper for streamer_tree_cache_insert_1.  Add T to CACHE->NODES at
     104                 :             :    slot IX.  */
     105                 :             : 
     106                 :             : static void
     107                 :   129471203 : streamer_tree_cache_add_to_node_array (struct streamer_tree_cache_d *cache,
     108                 :             :                                        unsigned ix, tree t, hashval_t hash)
     109                 :             : {
     110                 :             :   /* We're either replacing an old element or appending consecutively.  */
     111                 :   129471203 :   if (cache->nodes.exists ())
     112                 :             :     {
     113                 :    52284312 :       if (cache->nodes.length () == ix)
     114                 :    52115525 :         cache->nodes.safe_push (t);
     115                 :             :       else
     116                 :      168787 :         cache->nodes[ix] = t;
     117                 :             :     }
     118                 :   129471203 :   if (cache->hashes.exists ())
     119                 :             :     {
     120                 :    66392196 :       if (cache->hashes.length () == ix)
     121                 :    66392196 :         cache->hashes.safe_push (hash);
     122                 :             :       else
     123                 :           0 :         cache->hashes[ix] = hash;
     124                 :             :     }
     125                 :   129471203 : }
     126                 :             : 
     127                 :             : 
     128                 :             : /* Helper for streamer_tree_cache_insert and streamer_tree_cache_insert_at.
     129                 :             :    CACHE, T, and IX_P are as in streamer_tree_cache_insert.
     130                 :             : 
     131                 :             :    If INSERT_AT_NEXT_SLOT_P is true, T is inserted at the next available
     132                 :             :    slot in the cache.  Otherwise, T is inserted at the position indicated
     133                 :             :    in *IX_P.
     134                 :             : 
     135                 :             :    If T already existed in CACHE, return true.  Otherwise,
     136                 :             :    return false.  */
     137                 :             : 
     138                 :             : static bool
     139                 :    77186891 : streamer_tree_cache_insert_1 (struct streamer_tree_cache_d *cache,
     140                 :             :                               tree t, hashval_t hash, unsigned *ix_p,
     141                 :             :                               bool insert_at_next_slot_p)
     142                 :             : {
     143                 :    77186891 :   bool existed_p;
     144                 :             : 
     145                 :    77186891 :   gcc_assert (t);
     146                 :             : 
     147                 :    77186891 :   unsigned int &ix = cache->node_map->get_or_insert (t, &existed_p);
     148                 :    77186891 :   if (!existed_p)
     149                 :             :     {
     150                 :             :       /* Determine the next slot to use in the cache.  */
     151                 :    49826170 :       if (insert_at_next_slot_p)
     152                 :    10249303 :         ix = cache->next_idx++;
     153                 :             :       else
     154                 :    39576867 :         ix = *ix_p;
     155                 :             : 
     156                 :    49826170 :       streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
     157                 :             :     }
     158                 :             :   else
     159                 :             :     {
     160                 :    27360721 :       if (!insert_at_next_slot_p && ix != *ix_p)
     161                 :             :         {
     162                 :             :           /* If the caller wants to insert T at a specific slot
     163                 :             :              location, and ENTRY->TO does not match *IX_P, add T to
     164                 :             :              the requested location slot.  */
     165                 :    27360721 :           ix = *ix_p;
     166                 :    27360721 :           streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
     167                 :             :         }
     168                 :             :     }
     169                 :             : 
     170                 :    77186891 :   if (ix_p)
     171                 :    76928784 :     *ix_p = ix;
     172                 :             : 
     173                 :    77186891 :   return existed_p;
     174                 :             : }
     175                 :             : 
     176                 :             : 
     177                 :             : /* Insert tree node T in CACHE.  If T already existed in the cache
     178                 :             :    return true.  Otherwise, return false.
     179                 :             : 
     180                 :             :    If IX_P is non-null, update it with the index into the cache where
     181                 :             :    T has been stored.  */
     182                 :             : 
     183                 :             : bool
     184                 :    10249303 : streamer_tree_cache_insert (struct streamer_tree_cache_d *cache, tree t,
     185                 :             :                             hashval_t hash, unsigned *ix_p)
     186                 :             : {
     187                 :    10249303 :   return streamer_tree_cache_insert_1 (cache, t, hash, ix_p, true);
     188                 :             : }
     189                 :             : 
     190                 :             : 
     191                 :             : /* Replace the tree node with T in CACHE at slot IX.  */
     192                 :             : 
     193                 :             : void
     194                 :      168787 : streamer_tree_cache_replace_tree (struct streamer_tree_cache_d *cache,
     195                 :             :                                   tree t, unsigned ix)
     196                 :             : {
     197                 :      168787 :   hashval_t hash = 0;
     198                 :      168787 :   if (cache->hashes.exists ())
     199                 :           0 :     hash = streamer_tree_cache_get_hash (cache, ix);
     200                 :      168787 :   if (!cache->node_map)
     201                 :      168787 :     streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
     202                 :             :   else
     203                 :           0 :     streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
     204                 :      168787 : }
     205                 :             : 
     206                 :             : 
     207                 :             : /* Appends tree node T to CACHE, even if T already existed in it.  */
     208                 :             : 
     209                 :             : void
     210                 :   119053113 : streamer_tree_cache_append (struct streamer_tree_cache_d *cache,
     211                 :             :                             tree t, hashval_t hash)
     212                 :             : {
     213                 :   119053113 :   unsigned ix = cache->next_idx++;
     214                 :   119053113 :   if (!cache->node_map)
     215                 :    52115525 :     streamer_tree_cache_add_to_node_array (cache, ix, t, hash);
     216                 :             :   else
     217                 :    66937588 :     streamer_tree_cache_insert_1 (cache, t, hash, &ix, false);
     218                 :   119053113 : }
     219                 :             : 
     220                 :             : /* Return true if tree node T exists in CACHE, otherwise false.  If IX_P is
     221                 :             :    not NULL, write to *IX_P the index into the cache where T is stored
     222                 :             :    ((unsigned)-1 if T is not found).  */
     223                 :             : 
     224                 :             : bool
     225                 :    72169111 : streamer_tree_cache_lookup (struct streamer_tree_cache_d *cache, tree t,
     226                 :             :                             unsigned *ix_p)
     227                 :             : {
     228                 :    72169111 :   unsigned *slot;
     229                 :    72169111 :   bool retval;
     230                 :    72169111 :   unsigned ix;
     231                 :             : 
     232                 :    72169111 :   gcc_assert (t);
     233                 :             : 
     234                 :    72169111 :   slot = cache->node_map->get (t);
     235                 :    72169111 :   if (slot == NULL)
     236                 :             :     {
     237                 :             :       retval = false;
     238                 :             :       ix = -1;
     239                 :             :     }
     240                 :             :   else
     241                 :             :     {
     242                 :    46377676 :       retval = true;
     243                 :    46377676 :       ix = *slot;
     244                 :             :     }
     245                 :             : 
     246                 :    72169111 :   if (ix_p)
     247                 :    44765420 :     *ix_p = ix;
     248                 :             : 
     249                 :    72169111 :   return retval;
     250                 :             : }
     251                 :             : 
     252                 :             : 
     253                 :             : /* Verify that NODE is in CACHE.  */
     254                 :             : 
     255                 :             : static void
     256                 :     5949910 : verify_common_node_recorded (struct streamer_tree_cache_d *cache, tree node)
     257                 :             : {
     258                 :             :   /* Restrict this to flag_checking only because in general violating it is
     259                 :             :      harmless plus we never know what happens on all targets/frontend/flag(!)
     260                 :             :      combinations.  */
     261                 :     5949910 :   if (!flag_checking)
     262                 :             :     return;
     263                 :             : 
     264                 :     5949550 :   if (cache->node_map)
     265                 :     3560150 :     gcc_assert (streamer_tree_cache_lookup (cache, node, NULL));
     266                 :             :   else
     267                 :             :     {
     268                 :     2389400 :       bool found = false;
     269                 :     2389400 :       gcc_assert (cache->nodes.exists ());
     270                 :             :       /* Linear search...  */
     271                 :   134045340 :       for (unsigned i = 0; !found && i < cache->nodes.length (); ++i)
     272                 :   131655940 :         if (cache->nodes[i] == node)
     273                 :     2389400 :           found = true;
     274                 :     2389400 :       gcc_assert (found);
     275                 :             :     }
     276                 :             : }
     277                 :             : 
     278                 :             : 
     279                 :             : /* Record NODE in CACHE.  */
     280                 :             : 
     281                 :             : static void
     282                 :   104123425 : record_common_node (struct streamer_tree_cache_d *cache, tree node)
     283                 :             : {
     284                 :             :   /* If we recursively end up at nodes we do not want to preload simply don't.
     285                 :             :      ???  We'd want to verify that this doesn't happen, or alternatively
     286                 :             :      do not recurse at all.  */
     287                 :   111858308 :   if (node == char_type_node)
     288                 :             :     return;
     289                 :             : 
     290                 :   111858308 :   gcc_checking_assert (node != boolean_type_node
     291                 :             :                        && node != boolean_true_node
     292                 :             :                        && node != boolean_false_node);
     293                 :             : 
     294                 :             :   /* We have to make sure to fill exactly the same number of
     295                 :             :      elements for all frontends.  That can include NULL trees.
     296                 :             :      As our hash table can't deal with zero entries we'll simply stream
     297                 :             :      a random other tree.  A NULL tree never will be looked up so it
     298                 :             :      doesn't matter which tree we replace it with, just to be sure
     299                 :             :      use error_mark_node.  */
     300                 :   111858308 :   if (!node)
     301                 :     5354919 :     node = error_mark_node;
     302                 :             : 
     303                 :             :   /* This hash needs to be equal for all frontend and lto1 invocations.  So
     304                 :             :      just use the position in the cache as hash value.
     305                 :             :      Small integers are used by hash_tree to record positions within scc
     306                 :             :      hash. Values are not in same range.  */
     307                 :   111858308 :   streamer_tree_cache_append (cache, node, cache->next_idx + 0xc001);
     308                 :             : 
     309                 :   111858308 :   switch (TREE_CODE (node))
     310                 :             :     {
     311                 :             :     case ERROR_MARK:
     312                 :             :     case FIELD_DECL:
     313                 :             :     case FIXED_POINT_TYPE:
     314                 :             :     case IDENTIFIER_NODE:
     315                 :             :     case INTEGER_CST:
     316                 :             :     case INTEGER_TYPE:
     317                 :             :     case REAL_TYPE:
     318                 :             :     case TREE_LIST:
     319                 :             :     case VOID_CST:
     320                 :             :     case VOID_TYPE:
     321                 :             :     case OPAQUE_TYPE:
     322                 :             :       /* No recursive trees.  */
     323                 :             :       break;
     324                 :     7734883 :     case ARRAY_TYPE:
     325                 :     7734883 :     case POINTER_TYPE:
     326                 :     7734883 :     case REFERENCE_TYPE:
     327                 :     7734883 :       record_common_node (cache, TREE_TYPE (node));
     328                 :     7734883 :       break;
     329                 :     5949910 :     case COMPLEX_TYPE:
     330                 :             :       /* Verify that a complex type's component type (node_type) has been
     331                 :             :          handled already (and we thus don't need to recurse here).  */
     332                 :     5949910 :       verify_common_node_recorded (cache, TREE_TYPE (node));
     333                 :     5949910 :       break;
     334                 :      594991 :     case RECORD_TYPE:
     335                 :             :       /* The FIELD_DECLs of structures should be shared, so that every
     336                 :             :          COMPONENT_REF uses the same tree node when referencing a field.
     337                 :             :          Pointer equality between FIELD_DECLs is used by the alias
     338                 :             :          machinery to compute overlapping component references (see
     339                 :             :          nonoverlapping_component_refs_p and
     340                 :             :          nonoverlapping_component_refs_of_decl_p).  */
     341                 :     2974955 :       for (tree f = TYPE_FIELDS (node); f; f = TREE_CHAIN (f))
     342                 :     2379964 :         record_common_node (cache, f);
     343                 :             :       break;
     344                 :           0 :     default:
     345                 :             :       /* Unexpected tree code.  */
     346                 :           0 :       gcc_unreachable ();
     347                 :             :     }
     348                 :             : }
     349                 :             : 
     350                 :             : 
     351                 :             : /* Preload common nodes into CACHE and make sure they are merged
     352                 :             :    properly according to the gimple type table.  */
     353                 :             : 
     354                 :             : static void
     355                 :      594991 : preload_common_nodes (struct streamer_tree_cache_d *cache)
     356                 :             : {
     357                 :      594991 :   unsigned i;
     358                 :             : 
     359                 :    11899820 :   for (i = 0; i < itk_none; i++)
     360                 :             :     /* Skip itk_char.  char_type_node is dependent on -f[un]signed-char.  */
     361                 :    11304829 :     if (i != itk_char)
     362                 :    10709838 :       record_common_node (cache, integer_types[i]);
     363                 :             : 
     364                 :     2974955 :   for (i = 0; i < stk_type_kind_last; i++)
     365                 :     2379964 :     record_common_node (cache, sizetype_tab[i]);
     366                 :             : 
     367                 :    96983533 :   for (i = 0; i < TI_MAX; i++)
     368                 :             :     /* Skip boolean type and constants, they are frontend dependent.  */
     369                 :    96388542 :     if (i != TI_BOOLEAN_TYPE
     370                 :    96388542 :         && i != TI_BOOLEAN_FALSE
     371                 :    95198560 :         && i != TI_BOOLEAN_TRUE
     372                 :             :         /* MAIN_IDENTIFIER is not always initialized by Fortran FE.  */
     373                 :    95198560 :         && i != TI_MAIN_IDENTIFIER
     374                 :             :         /* PID_TYPE is initialized only by C family front-ends.  */
     375                 :    94008578 :         && i != TI_PID_TYPE
     376                 :             :         /* Skip optimization and target option nodes; they depend on flags.  */
     377                 :    94008578 :         && i != TI_OPTIMIZATION_DEFAULT
     378                 :             :         && i != TI_OPTIMIZATION_CURRENT
     379                 :    92818596 :         && i != TI_TARGET_OPTION_DEFAULT
     380                 :             :         && i != TI_TARGET_OPTION_CURRENT
     381                 :             :         && i != TI_CURRENT_TARGET_PRAGMA
     382                 :             :         && i != TI_CURRENT_OPTIMIZE_PRAGMA
     383                 :             :         /* SCEV state shouldn't reach the IL.  */
     384                 :             :         && i != TI_CHREC_DONT_KNOW
     385                 :             :         && i != TI_CHREC_KNOWN
     386                 :             :         /* Skip va_list* related nodes if offloading.  For native LTO
     387                 :             :            we want them to be merged for the stdarg pass, for offloading
     388                 :             :            they might not be identical between host and offloading target.  */
     389                 :    88653659 :         && (!lto_stream_offload_p
     390                 :           0 :             || (i != TI_VA_LIST_TYPE
     391                 :             :                 && i != TI_VA_LIST_GPR_COUNTER_FIELD
     392                 :           0 :                 && i != TI_VA_LIST_FPR_COUNTER_FIELD)))
     393                 :    88653659 :       record_common_node (cache, global_trees[i]);
     394                 :      594991 : }
     395                 :             : 
     396                 :             : 
     397                 :             : /* Create a cache of pickled nodes.  */
     398                 :             : 
     399                 :             : struct streamer_tree_cache_d *
     400                 :      594991 : streamer_tree_cache_create (bool with_hashes, bool with_map, bool with_vec)
     401                 :             : {
     402                 :      594991 :   struct streamer_tree_cache_d *cache;
     403                 :             : 
     404                 :      594991 :   cache = XCNEW (struct streamer_tree_cache_d);
     405                 :             : 
     406                 :      594991 :   if (with_map)
     407                 :      356051 :     cache->node_map = new hash_map<tree, unsigned> (251);
     408                 :      594991 :   cache->next_idx = 0;
     409                 :      594991 :   if (with_vec)
     410                 :      238940 :     cache->nodes.create (165);
     411                 :      594991 :   if (with_hashes)
     412                 :      303177 :     cache->hashes.create (165);
     413                 :             : 
     414                 :             :   /* Load all the well-known tree nodes that are always created by
     415                 :             :      the compiler on startup.  This prevents writing them out
     416                 :             :      unnecessarily.  */
     417                 :      594991 :   preload_common_nodes (cache);
     418                 :             : 
     419                 :      594991 :   return cache;
     420                 :             : }
     421                 :             : 
     422                 :             : 
     423                 :             : /* Delete the streamer cache C.  */
     424                 :             : 
     425                 :             : void
     426                 :      594991 : streamer_tree_cache_delete (struct streamer_tree_cache_d *c)
     427                 :             : {
     428                 :      594991 :   if (c == NULL)
     429                 :             :     return;
     430                 :             : 
     431                 :      951042 :   delete c->node_map;
     432                 :      594991 :   c->node_map = NULL;
     433                 :      594991 :   c->nodes.release ();
     434                 :      594991 :   c->hashes.release ();
     435                 :      594991 :   free (c);
     436                 :             : }
        

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.