LCOV - code coverage report
Current view: top level - gcc - ipa-reference.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.0 % 609 554
Test Date: 2026-02-28 14:20:25 Functions: 90.9 % 33 30
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Callgraph based analysis of static variables.
       2              :    Copyright (C) 2004-2026 Free Software Foundation, Inc.
       3              :    Contributed by Kenneth Zadeck <zadeck@naturalbridge.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              : /* This file gathers information about how variables whose scope is
      22              :    confined to the compilation unit are used.
      23              : 
      24              :    The transitive call site specific clobber effects are computed
      25              :    for the variables whose scope is contained within this compilation
      26              :    unit.
      27              : 
      28              :    First each function and static variable initialization is analyzed
      29              :    to determine which local static variables are either read, written,
      30              :    or have their address taken.  Any local static that has its address
      31              :    taken is removed from consideration.  Once the local read and
      32              :    writes are determined, a transitive closure of this information is
      33              :    performed over the call graph to determine the worst case set of
      34              :    side effects of each call.  In later parts of the compiler, these
      35              :    local and global sets are examined to make the call clobbering less
      36              :    traumatic, promote some statics to registers, and improve aliasing
      37              :    information.  */
      38              : 
      39              : #include "config.h"
      40              : #include "system.h"
      41              : #include "coretypes.h"
      42              : #include "backend.h"
      43              : #include "tree.h"
      44              : #include "gimple.h"
      45              : #include "tree-pass.h"
      46              : #include "cgraph.h"
      47              : #include "data-streamer.h"
      48              : #include "calls.h"
      49              : #include "ipa-utils.h"
      50              : #include "ipa-reference.h"
      51              : #include "alloc-pool.h"
      52              : #include "symbol-summary.h"
      53              : 
      54              : /* The static variables defined within the compilation unit that are
      55              :    loaded or stored directly by function that owns this structure.  */
      56              : 
      57              : struct ipa_reference_local_vars_info_d
      58              : {
      59              :   bitmap statics_read;
      60              :   bitmap statics_written;
      61              : };
      62              : 
      63              : /* Statics that are read and written by some set of functions. The
      64              :    local ones are based on the loads and stores local to the function.
      65              :    The global ones are based on the local info as well as the
      66              :    transitive closure of the functions that are called. */
      67              : 
      68              : struct ipa_reference_global_vars_info_d
      69              : {
      70              :   bitmap statics_read;
      71              :   bitmap statics_written;
      72              : };
      73              : 
      74              : /* Information we save about every function after ipa-reference is completed.  */
      75              : 
      76              : struct ipa_reference_optimization_summary_d
      77              : {
      78              :   bitmap statics_read;
      79              :   bitmap statics_written;
      80              : };
      81              : 
      82              : typedef ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
      83              : typedef ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
      84              : typedef ipa_reference_optimization_summary_d *
      85              :   ipa_reference_optimization_summary_t;
      86              : 
      87              : struct ipa_reference_vars_info_d
      88              : {
      89              :   struct ipa_reference_local_vars_info_d local;
      90              :   struct ipa_reference_global_vars_info_d global;
      91              : };
      92              : 
      93              : typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
      94              : 
      95              : /* This map contains all of the static variables that are
      96              :    being considered by the compilation level alias analysis.  */
      97              : typedef hash_map<tree, int> reference_vars_map_t;
      98              : static reference_vars_map_t *ipa_reference_vars_map;
      99              : static int ipa_reference_vars_uids;
     100              : static vec<tree> *reference_vars_to_consider;
     101              : varpool_node_hook_list *varpool_node_hooks;
     102              : 
     103              : /* Set of all interesting module statics.  A bit is set for every module
     104              :    static we are considering.  This is added to the local info when asm
     105              :    code is found that clobbers all memory.  */
     106              : static bitmap all_module_statics;
     107              : /* Zero bitmap.  */
     108              : static bitmap no_module_statics;
     109              : /* Set of all statics that should be ignored because they are touched by
     110              :    -fno-ipa-reference code.  */
     111              : static bitmap ignore_module_statics;
     112              : 
     113              : /* Obstack holding bitmaps of local analysis (live from analysis to
     114              :    propagation)  */
     115              : static bitmap_obstack local_info_obstack;
     116              : /* Obstack holding global analysis live forever.  */
     117              : static bitmap_obstack optimization_summary_obstack;
     118              : 
     119              : class ipa_ref_var_info_summary_t: public fast_function_summary
     120              :                           <ipa_reference_vars_info_d *, va_heap>
     121              : {
     122              : public:
     123       151640 :   ipa_ref_var_info_summary_t (symbol_table *symtab):
     124       303280 :     fast_function_summary <ipa_reference_vars_info_d *, va_heap> (symtab) {}
     125              : };
     126              : 
     127              : static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL;
     128              : 
     129              : class ipa_ref_opt_summary_t: public fast_function_summary
     130              :                              <ipa_reference_optimization_summary_d *, va_heap>
     131              : {
     132              : public:
     133       159830 :   ipa_ref_opt_summary_t (symbol_table *symtab):
     134       319660 :     fast_function_summary <ipa_reference_optimization_summary_d *, va_heap> (symtab) {}
     135              : 
     136              :   void remove (cgraph_node *src_node,
     137              :                ipa_reference_optimization_summary_d *data) final override;
     138              :   void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
     139              :                   ipa_reference_optimization_summary_d *src_data,
     140              :                   ipa_reference_optimization_summary_d *dst_data) final override;
     141              : };
     142              : 
     143              : static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL;
     144              : 
     145              : /* Return ID used by ipa-reference bitmaps.  -1 if failed.  */
     146              : int
     147     14848018 : ipa_reference_var_uid (tree t)
     148              : {
     149     14848018 :   if (!ipa_reference_vars_map)
     150              :     return -1;
     151     11526693 :   int *id = ipa_reference_vars_map->get
     152     11526693 :     (symtab_node::get (t)->ultimate_alias_target (NULL)->decl);
     153     11526693 :   if (!id)
     154              :     return -1;
     155      4796416 :   return *id;
     156              : }
     157              : 
     158              : /* Return ID used by ipa-reference bitmaps.  Create new entry if
     159              :    T is not in map.  Set EXISTED accordinly  */
     160              : int
     161       401465 : ipa_reference_var_get_or_insert_uid (tree t, bool *existed)
     162              : {
     163       401465 :   int &id = ipa_reference_vars_map->get_or_insert
     164       401465 :     (symtab_node::get (t)->ultimate_alias_target (NULL)->decl, existed);
     165       401465 :   if (!*existed)
     166        56298 :     id = ipa_reference_vars_uids++;
     167       401465 :   return id;
     168              : }
     169              : 
     170              : /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
     171              : static inline ipa_reference_vars_info_t
     172      7363410 : get_reference_vars_info (struct cgraph_node *node)
     173              : {
     174      7363410 :   if (ipa_ref_var_info_summaries == NULL)
     175              :     return NULL;
     176              : 
     177      7363410 :   ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node);
     178      7363410 :   return v == NULL ? NULL : v;
     179              : }
     180              : 
     181              : /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
     182              : static inline ipa_reference_optimization_summary_t
     183      4496660 : get_reference_optimization_summary (struct cgraph_node *node)
     184              : {
     185      4496660 :   if (ipa_ref_opt_sum_summaries == NULL)
     186              :     return NULL;
     187              : 
     188      4496660 :   ipa_reference_optimization_summary_t v
     189      4496660 :     = ipa_ref_opt_sum_summaries->get (node);
     190              : 
     191      4496660 :   return v == NULL ? NULL : v;
     192              : }
     193              : 
     194              : /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
     195              :    that are *not* read during the execution of the function FN.  Returns
     196              :    NULL if no data is available.  */
     197              : 
     198              : bitmap
     199       138023 : ipa_reference_get_read_global (struct cgraph_node *fn)
     200              : {
     201       138023 :   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
     202              :     return NULL;
     203              : 
     204       138023 :   enum availability avail;
     205       138023 :   struct cgraph_node *fn2 = fn->function_symbol (&avail);
     206       138023 :   ipa_reference_optimization_summary_t info =
     207       138023 :     get_reference_optimization_summary (fn2);
     208              : 
     209       138023 :   if (info
     210         8090 :       && (avail >= AVAIL_AVAILABLE
     211            0 :           || (avail == AVAIL_INTERPOSABLE
     212            0 :               && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
     213       146113 :       && opt_for_fn (fn2->decl, flag_ipa_reference))
     214         8090 :     return info->statics_read;
     215       129933 :   else if (avail == AVAIL_NOT_AVAILABLE
     216       129933 :            && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
     217         8245 :     return no_module_statics;
     218              :   else
     219       121688 :     return NULL;
     220              : }
     221              : 
     222              : /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
     223              :    that are *not* written during the execution of the function FN.  Note
     224              :    that variables written may or may not be read during the function
     225              :    call.  Returns NULL if no data is available.  */
     226              : 
     227              : bitmap
     228      4307833 : ipa_reference_get_written_global (struct cgraph_node *fn)
     229              : {
     230      4307833 :   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
     231              :     return NULL;
     232              : 
     233      4307833 :   enum availability avail;
     234      4307833 :   struct cgraph_node *fn2 = fn->function_symbol (&avail);
     235      4307833 :   ipa_reference_optimization_summary_t info =
     236      4307833 :     get_reference_optimization_summary (fn2);
     237              : 
     238      4307833 :   if (info
     239        75780 :       && (avail >= AVAIL_AVAILABLE
     240            0 :           || (avail == AVAIL_INTERPOSABLE
     241            0 :               && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
     242      4383613 :       && opt_for_fn (fn2->decl, flag_ipa_reference))
     243        75780 :     return info->statics_written;
     244      4232053 :   else if (avail == AVAIL_NOT_AVAILABLE
     245      4232053 :            && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
     246        18178 :     return no_module_statics;
     247              :   else
     248      4213875 :     return NULL;
     249              : }
     250              : 
     251              : 
     252              : /* Hepler for is_proper_for_analysis.  */
     253              : static bool
     254      3563993 : is_improper (symtab_node *n, void *v ATTRIBUTE_UNUSED)
     255              : {
     256      3563993 :   tree t = n->decl;
     257              :   /* If the variable has the "used" attribute, treat it as if it had a
     258              :      been touched by the devil.  */
     259      3563993 :   if (DECL_PRESERVE_P (t))
     260              :     return true;
     261              : 
     262              :   /* Do not want to do anything with volatile except mark any
     263              :      function that uses one to be not const or pure.  */
     264      3561420 :   if (TREE_THIS_VOLATILE (t))
     265              :     return true;
     266              : 
     267              :   /* We do not need to analyze readonly vars, we already know they do not
     268              :      alias.  */
     269      3239457 :   if (TREE_READONLY (t))
     270              :     return true;
     271              : 
     272              :   /* We cannot track variables with address taken.  */
     273      2316511 :   if (TREE_ADDRESSABLE (t))
     274              :     return true;
     275              : 
     276              :   /* TODO: We could track public variables that are not addressable, but
     277              :      currently frontends don't give us those.  */
     278       897973 :   if (TREE_PUBLIC (t))
     279       498326 :     return true;
     280              : 
     281              :   return false;
     282              : }
     283              : 
     284              : /* Return true if the variable T is the right kind of static variable to
     285              :    perform compilation unit scope escape analysis.  */
     286              : 
     287              : static inline bool
     288      3563978 : is_proper_for_analysis (tree t)
     289              : {
     290      3563978 :   int id = ipa_reference_var_uid (t);
     291              : 
     292      3563978 :   if (id != -1 && bitmap_bit_p (ignore_module_statics, id))
     293              :     return false;
     294              : 
     295      3563978 :   if (symtab_node::get (t)
     296      3563978 :         ->call_for_symbol_and_aliases (is_improper, NULL, true))
     297              :     return false;
     298              : 
     299              :   return true;
     300              : }
     301              : 
     302              : /* Lookup the tree node for the static variable that has UID and
     303              :    convert the name to a string for debugging.  */
     304              : 
     305              : static const char *
     306            0 : get_static_name (int index)
     307              : {
     308            0 :   return fndecl_name ((*reference_vars_to_consider)[index]);
     309              : }
     310              : 
     311              : /* Dump a set of static vars to FILE.  */
     312              : static void
     313          132 : dump_static_vars_set_to_file (FILE *f, bitmap set)
     314              : {
     315          132 :   unsigned int index;
     316          132 :   bitmap_iterator bi;
     317          132 :   if (set == NULL)
     318            0 :     return;
     319          132 :   else if (set == all_module_statics)
     320           34 :     fprintf (f, "ALL");
     321           98 :   else if (set == no_module_statics)
     322            0 :     fprintf (f, "NO");
     323              :   else
     324           98 :     EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
     325              :       {
     326            0 :         fprintf (f, "%s ", get_static_name (index));
     327              :       }
     328              : }
     329              : 
     330              : /* Compute X |= Y, taking into account the possibility that
     331              :    either X or Y is already the maximum set.
     332              :    Return true if X is the maximum set after taking the union with Y.  */
     333              : 
     334              : static bool
     335      2907167 : union_static_var_sets (bitmap &x, bitmap y)
     336              : {
     337      2907167 :   if (x != all_module_statics)
     338              :     {
     339      2061072 :       if (y == all_module_statics)
     340              :         {
     341       830640 :           BITMAP_FREE (x);
     342       830640 :           x = all_module_statics;
     343              :         }
     344      1230432 :       else if (bitmap_ior_into (x, y))
     345              :         {
     346              :           /* The union may have reduced X to the maximum set.
     347              :              In that case, we want to make that visible explicitly.
     348              :              Even though bitmap_equal_p can be very expensive, it
     349              :              turns out to be an overall win to check this here for
     350              :              an LTO bootstrap of GCC itself.  Liberally extrapoliate
     351              :              that result to be applicable to all cases.  */
     352        13907 :           if (bitmap_equal_p (x, all_module_statics))
     353              :             {
     354        11377 :               BITMAP_FREE (x);
     355        11377 :               x = all_module_statics;
     356              :             }
     357              :         }
     358              :     }
     359      2907167 :   return x == all_module_statics;
     360              : }
     361              : 
     362              : /* Return a copy of SET on the bitmap obstack containing SET.
     363              :    But if SET is NULL or the maximum set, return that instead.  */
     364              : 
     365              : static bitmap
     366      2675308 : copy_static_var_set (bitmap set, bool for_propagation)
     367              : {
     368      2675308 :   if (set == NULL || set == all_module_statics)
     369              :     return set;
     370      2675308 :   if (!for_propagation && set == no_module_statics)
     371              :     return set;
     372      2675308 :   bitmap_obstack *o = set->obstack;
     373      2675308 :   gcc_checking_assert (o);
     374      2675308 :   bitmap copy = BITMAP_ALLOC (o);
     375      2675308 :   bitmap_copy (copy, set);
     376      2675308 :   return copy;
     377              : }
     378              : 
     379              : /* Compute the union all of the statics read and written by every callee of X
     380              :    into X_GLOBAL->statics_read and X_GLOBAL->statics_written.  X_GLOBAL is
     381              :    actually the set representing the cycle containing X.  If the read and
     382              :    written sets of X_GLOBAL has been reduced to the maximum set, we don't
     383              :    have to look at the remaining callees.  */
     384              : 
     385              : static void
     386      1372475 : propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
     387              : {
     388      1372475 :   struct cgraph_edge *e;
     389      1372475 :   bool read_all = x_global->statics_read == all_module_statics;
     390      1372475 :   bool write_all = x_global->statics_written == all_module_statics;
     391      1372475 :   for (e = x->callees;
     392      4215669 :        e && !(read_all && write_all);
     393      2843194 :        e = e->next_callee)
     394              :     {
     395      2843194 :       enum availability avail;
     396      2843194 :       struct cgraph_node *y = e->callee->function_symbol (&avail);
     397      2843194 :       if (!y)
     398       193964 :         continue;
     399              : 
     400              :       /* Only look into nodes we can propagate something.  */
     401      2843194 :       int flags = flags_from_decl_or_type (y->decl);
     402      2843194 :       if (opt_for_fn (y->decl, flag_ipa_reference)
     403      2843194 :           && (avail > AVAIL_INTERPOSABLE
     404      1274290 :               || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
     405              :         {
     406      1568939 :           if (get_reference_vars_info (y))
     407              :             {
     408      1568939 :               ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
     409      1568939 :               ipa_reference_global_vars_info_t y_global = &y_info->global;
     410              : 
     411              :               /* Calls in the current cycle do not have their global set
     412              :                  computed yet (but everything else does because we're
     413              :                  visiting nodes in topological order).  */
     414      1568939 :               if (!y_global->statics_read)
     415         4882 :                 continue;
     416              : 
     417              :               /* If the function is const, it reads no memory even if it
     418              :                  seems so to local analysis.  */
     419      1564057 :               if (flags & ECF_CONST)
     420        38618 :                 continue;
     421              : 
     422      1525439 :               union_static_var_sets (x_global->statics_read,
     423              :                                      y_global->statics_read);
     424              : 
     425              :               /* If the function is pure, it has no stores even if it
     426              :                  seems so to local analysis.  If we cannot return from
     427              :                  the function, we can safely ignore the call.  */
     428      1675903 :               if ((flags & ECF_PURE)
     429      1525439 :                   || e->cannot_lead_to_return_p ())
     430       150464 :                 continue;
     431              : 
     432      1374975 :               union_static_var_sets (x_global->statics_written,
     433              :                                      y_global->statics_written);
     434              :             }
     435              :           else
     436            0 :             gcc_unreachable ();
     437              :         }
     438              :     }
     439      1372475 : }
     440              : 
     441              : /* Delete NODE from map.  */
     442              : 
     443              : static void
     444        55821 : varpool_removal_hook (varpool_node *node, void *)
     445              : {
     446        55821 :   ipa_reference_vars_map->remove (node->decl);
     447        55821 : }
     448              : 
     449              : static bool ipa_init_p = false;
     450              : 
     451              : /* The init routine for analyzing global static variable usage.  See
     452              :    comments at top for description.  */
     453              : static void
     454       151640 : ipa_init (void)
     455              : {
     456       151640 :   if (ipa_init_p)
     457              :     return;
     458              : 
     459       151640 :   ipa_init_p = true;
     460              : 
     461       151640 :   if (dump_file)
     462           19 :     vec_alloc (reference_vars_to_consider, 10);
     463              : 
     464       151640 :   if (ipa_ref_opt_sum_summaries != NULL)
     465              :     {
     466            0 :       delete ipa_ref_opt_sum_summaries;
     467            0 :       ipa_ref_opt_sum_summaries = NULL;
     468            0 :       delete ipa_reference_vars_map;
     469              :     }
     470       151640 :   ipa_reference_vars_map = new reference_vars_map_t(257);
     471       151640 :   varpool_node_hooks
     472       151640 :          = symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
     473       151640 :   ipa_reference_vars_uids = 0;
     474              : 
     475       151640 :   bitmap_obstack_initialize (&local_info_obstack);
     476       151640 :   bitmap_obstack_initialize (&optimization_summary_obstack);
     477       151640 :   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
     478       151640 :   no_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
     479       151640 :   ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
     480              : 
     481       151640 :   if (ipa_ref_var_info_summaries == NULL)
     482       151640 :     ipa_ref_var_info_summaries = new ipa_ref_var_info_summary_t (symtab);
     483              : }
     484              : 
     485              : 
     486              : /* Set up the persistent info for FN.  */
     487              : 
     488              : static ipa_reference_local_vars_info_t
     489      2399406 : init_function_info (struct cgraph_node *fn)
     490              : {
     491      2399406 :   ipa_reference_vars_info_t info
     492      2399406 :     = ipa_ref_var_info_summaries->get_create (fn);
     493              : 
     494      2399406 :   info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
     495      2399406 :   info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
     496      2399406 :   info->global.statics_read = NULL;
     497              : 
     498      2399406 :   return &info->local;
     499              : }
     500              : 
     501              : 
     502              : /* This is the main routine for finding the reference patterns for
     503              :    global variables within a function FN.  */
     504              : 
     505              : static void
     506      2409024 : analyze_function (struct cgraph_node *fn)
     507              : {
     508      2409024 :   ipa_reference_local_vars_info_t local;
     509      2409024 :   struct ipa_ref *ref = NULL;
     510      2409024 :   int i;
     511      2409024 :   tree var;
     512              : 
     513      2409024 :   if (!opt_for_fn (fn->decl, flag_ipa_reference))
     514         9618 :     return;
     515      2399406 :   local = init_function_info (fn);
     516      6263458 :   for (i = 0; fn->iterate_reference (i, ref); i++)
     517              :     {
     518      3864052 :       int id;
     519      3864052 :       bool existed;
     520      3864052 :       if (!is_a <varpool_node *> (ref->referred))
     521      3464541 :         continue;
     522      3562604 :       var = ref->referred->decl;
     523      3562604 :       if (!is_proper_for_analysis (var))
     524      3163093 :         continue;
     525              :       /* This is a variable we care about.  Check if we have seen it
     526              :          before, and if not add it the set of variables we care about.  */
     527       399511 :       id = ipa_reference_var_get_or_insert_uid (var, &existed);
     528       399511 :       if (!existed)
     529              :         {
     530        54344 :           bitmap_set_bit (all_module_statics, id);
     531        54344 :           if (dump_file)
     532            0 :             reference_vars_to_consider->safe_push (var);
     533              :         }
     534       399511 :       switch (ref->use)
     535              :         {
     536       258975 :         case IPA_REF_LOAD:
     537       258975 :           bitmap_set_bit (local->statics_read, id);
     538       258975 :           break;
     539       140536 :         case IPA_REF_STORE:
     540       140536 :           if (ref->cannot_lead_to_return ())
     541              :             break;
     542       139554 :           bitmap_set_bit (local->statics_written, id);
     543       139554 :           break;
     544              :         case IPA_REF_ADDR:
     545              :           break;
     546            0 :         default:
     547            0 :           gcc_unreachable ();
     548              :         }
     549              :     }
     550              : 
     551      2399406 :   if (fn->cannot_return_p ())
     552        26404 :     bitmap_clear (local->statics_written);
     553              : }
     554              : 
     555              : 
     556              : /* Called when new clone is inserted to callgraph late.  */
     557              : 
     558              : void
     559            0 : ipa_ref_opt_summary_t::duplicate (cgraph_node *, cgraph_node *,
     560              :                                   ipa_reference_optimization_summary_d *ginfo,
     561              :                                   ipa_reference_optimization_summary_d
     562              :                                   *dst_ginfo)
     563              : {
     564            0 :   dst_ginfo->statics_read =
     565            0 :     copy_static_var_set (ginfo->statics_read, false);
     566            0 :   dst_ginfo->statics_written =
     567            0 :     copy_static_var_set (ginfo->statics_written, false);
     568            0 : }
     569              : 
     570              : /* Called when node is removed.  */
     571              : 
     572              : void
     573            0 : ipa_ref_opt_summary_t::remove (cgraph_node *,
     574              :                                ipa_reference_optimization_summary_d *ginfo)
     575              : {
     576            0 :   if (ginfo->statics_read
     577            0 :       && ginfo->statics_read != all_module_statics
     578            0 :       && ginfo->statics_read != no_module_statics)
     579            0 :     BITMAP_FREE (ginfo->statics_read);
     580              : 
     581            0 :   if (ginfo->statics_written
     582            0 :       && ginfo->statics_written != all_module_statics
     583            0 :       && ginfo->statics_written != no_module_statics)
     584            0 :     BITMAP_FREE (ginfo->statics_written);
     585            0 : }
     586              : 
     587              : /* Analyze each function in the cgraph to see which global or statics
     588              :    are read or written.  */
     589              : 
     590              : static void
     591       151640 : generate_summary (void)
     592              : {
     593       151640 :   struct cgraph_node *node;
     594       151640 :   unsigned int index;
     595       151640 :   bitmap_iterator bi;
     596              : 
     597       151640 :   ipa_init ();
     598              : 
     599              :   /* Process all of the functions next.  */
     600      2560664 :   FOR_EACH_DEFINED_FUNCTION (node)
     601      2409024 :     if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
     602              :       {
     603        12485 :         struct ipa_ref *ref = NULL;
     604              :         int i;
     605              :         tree var;
     606      2416132 :         for (i = 0; node->iterate_reference (i, ref); i++)
     607              :           {
     608         3929 :             if (!is_a <varpool_node *> (ref->referred))
     609         2555 :               continue;
     610         1374 :             var = ref->referred->decl;
     611         1374 :             if (!is_proper_for_analysis (var))
     612         1253 :               continue;
     613          121 :             bitmap_set_bit (ignore_module_statics, ipa_reference_var_uid (var));
     614              :           }
     615              :       }
     616      2560664 :   FOR_EACH_DEFINED_FUNCTION (node)
     617      2409024 :     analyze_function (node);
     618              : 
     619       151640 :   if (dump_file)
     620           19 :     EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
     621              :       {
     622            0 :         fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
     623              :                  get_static_name (index), index);
     624              :       }
     625              : 
     626       151640 :   if (dump_file)
     627           52 :     FOR_EACH_DEFINED_FUNCTION (node)
     628           33 :       if (node->get_availability () >= AVAIL_INTERPOSABLE
     629           33 :           && opt_for_fn (node->decl, flag_ipa_reference))
     630              :         {
     631           33 :           ipa_reference_local_vars_info_t l;
     632           33 :           unsigned int index;
     633           33 :           bitmap_iterator bi;
     634              : 
     635           33 :           l = &get_reference_vars_info (node)->local;
     636           33 :           fprintf (dump_file,
     637              :                    "\nFunction name:%s:", node->dump_name ());
     638           33 :           fprintf (dump_file, "\n  locals read: ");
     639           33 :           if (l->statics_read)
     640           33 :             EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
     641              :                                       0, index, bi)
     642              :               {
     643            0 :                 fprintf (dump_file, "%s ",
     644              :                          get_static_name (index));
     645              :               }
     646           33 :           fprintf (dump_file, "\n  locals written: ");
     647           33 :           if (l->statics_written)
     648           33 :             EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
     649              :                                       0, index, bi)
     650              :               {
     651            0 :                 fprintf (dump_file, "%s ", get_static_name (index));
     652              :               }
     653              :         }
     654       151640 : }
     655              : 
     656              : /* Set READ_ALL/WRITE_ALL based on decl flags of NODE.  */
     657              : 
     658              : static void
     659      2556360 : read_write_all_from_decl (struct cgraph_node *node,
     660              :                           bool &read_all, bool &write_all)
     661              : {
     662      2556360 :   tree decl = node->decl;
     663      2556360 :   int flags = flags_from_decl_or_type (decl);
     664      2556360 :   if ((flags & ECF_LEAF)
     665      2556360 :       && node->get_availability () < AVAIL_INTERPOSABLE)
     666              :     ;
     667      1107458 :   else if (flags & ECF_CONST)
     668              :     ;
     669      1091395 :   else if ((flags & ECF_PURE) || node->cannot_return_p ())
     670              :     {
     671       183138 :       read_all = true;
     672       183138 :       if (dump_file && (dump_flags & TDF_DETAILS))
     673            0 :         fprintf (dump_file, "   %s -> read all\n", node->dump_name ());
     674              :     }
     675              :   else
     676              :     {
     677              :        /* TODO: To be able to produce sane results, we should also handle
     678              :           common builtins, in particular throw.  */
     679       908257 :       read_all = true;
     680       908257 :       write_all = true;
     681       908257 :       if (dump_file && (dump_flags & TDF_DETAILS))
     682            0 :         fprintf (dump_file, "   %s -> read all, write all\n",
     683              :                   node->dump_name ());
     684              :     }
     685      2556360 : }
     686              : 
     687              : /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
     688              :    in the cycle of NODE.  */
     689              : 
     690              : static void
     691      2350078 : get_read_write_all_from_node (struct cgraph_node *node,
     692              :                               bool &read_all, bool &write_all)
     693              : {
     694      2350078 :   struct cgraph_edge *e, *ie;
     695              : 
     696              :   /* When function is overwritable, we cannot assume anything.  */
     697      2350078 :   if (node->get_availability () <= AVAIL_INTERPOSABLE
     698      2350078 :       || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
     699        86177 :     read_write_all_from_decl (node, read_all, write_all);
     700              : 
     701      2350078 :   for (e = node->callees;
     702      6752087 :        e && !(read_all && write_all);
     703      4402009 :        e = e->next_callee)
     704              :     {
     705      4402009 :       enum availability avail;
     706      4402009 :       struct cgraph_node *callee = e->callee->function_symbol (&avail);
     707      4402009 :       gcc_checking_assert (callee);
     708      4402009 :       if (avail <= AVAIL_INTERPOSABLE
     709      4402009 :           || (callee->analyzed && !opt_for_fn (callee->decl,
     710              :                                                flag_ipa_reference)))
     711      2470183 :         read_write_all_from_decl (callee, read_all, write_all);
     712              :     }
     713              : 
     714      2350078 :   for (ie = node->indirect_calls;
     715      2416585 :        ie && !(read_all && write_all);
     716        66507 :        ie = ie->next_callee)
     717        66507 :     if (!(ie->indirect_info->ecf_flags & ECF_CONST))
     718              :       {
     719        66488 :         read_all = true;
     720        66488 :         if (dump_file && (dump_flags & TDF_DETAILS))
     721            0 :           fprintf (dump_file, "   indirect call -> read all\n");
     722        66488 :         if (!ie->cannot_lead_to_return_p ()
     723        66488 :             && !(ie->indirect_info->ecf_flags & ECF_PURE))
     724              :           {
     725        66380 :             if (dump_file && (dump_flags & TDF_DETAILS))
     726            0 :               fprintf (dump_file, "   indirect call -> write all\n");
     727        66380 :             write_all = true;
     728              :           }
     729              :       }
     730      2350078 : }
     731              : 
     732              : /* Skip edges from and to nodes without ipa_reference enabled.
     733              :    Ignore not available symbols.  This leave
     734              :    them out of strongly connected components and makes them easy to skip in the
     735              :    propagation loop below.  */
     736              : 
     737              : static bool
     738      7344596 : ignore_edge_p (cgraph_edge *e)
     739              : {
     740      7344596 :   enum availability avail;
     741      7344596 :   cgraph_node *ultimate_target
     742      7344596 :     = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
     743              : 
     744      7344596 :   return (avail < AVAIL_INTERPOSABLE
     745      2650700 :           || (avail == AVAIL_INTERPOSABLE
     746        77779 :               && !(flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))
     747      2572969 :           || !opt_for_fn (e->caller->decl, flag_ipa_reference)
     748      9908854 :           || !opt_for_fn (ultimate_target->decl, flag_ipa_reference));
     749              : }
     750              : 
     751              : /* Produce the global information by preforming a transitive closure
     752              :    on the local information that was produced by ipa_analyze_function.  */
     753              : 
     754              : static unsigned int
     755       151640 : propagate (void)
     756              : {
     757       151640 :   struct cgraph_node *node;
     758       151640 :   struct cgraph_node **order =
     759       151640 :     XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
     760       151640 :   int order_pos;
     761       151640 :   int i;
     762       151640 :   bool remove_p;
     763              : 
     764       151640 :   if (dump_file)
     765           19 :     cgraph_node::dump_cgraph (dump_file);
     766              : 
     767       151640 :   remove_p = ipa_discover_variable_flags ();
     768       151640 :   generate_summary ();
     769              : 
     770              :   /* Propagate the local information through the call graph to produce
     771              :      the global information.  All the nodes within a cycle will have
     772              :      the same info so we collapse cycles first.  Then we can do the
     773              :      propagation in one pass from the leaves to the roots.  */
     774       151640 :   order_pos = ipa_reduced_postorder (order, true, ignore_edge_p);
     775       151640 :   if (dump_file)
     776           19 :     ipa_print_order (dump_file, "reduced", order, order_pos);
     777              : 
     778      2540297 :   for (i = 0; i < order_pos; i++ )
     779              :     {
     780      2388657 :       unsigned x;
     781      2388657 :       struct cgraph_node *w;
     782      2388657 :       ipa_reference_vars_info_t node_info;
     783      2388657 :       ipa_reference_global_vars_info_t node_g;
     784      2388657 :       ipa_reference_local_vars_info_t node_l;
     785      2388657 :       bool read_all = false;
     786      2388657 :       bool write_all = false;
     787              : 
     788      2388657 :       node = order[i];
     789      2388657 :       if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
     790        46026 :         continue;
     791              : 
     792      2342631 :       node_info = get_reference_vars_info (node);
     793      2342631 :       gcc_assert (node_info);
     794      2342631 :       node_l = &node_info->local;
     795      2342631 :       node_g = &node_info->global;
     796              : 
     797      2342631 :       if (dump_file && (dump_flags & TDF_DETAILS))
     798            0 :         fprintf (dump_file, "Starting cycle with %s\n", node->dump_name ());
     799              : 
     800      2342631 :       vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
     801              : 
     802              :       /* If any node in a cycle is read_all or write_all, they all are.  */
     803      6060703 :       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
     804              :         {
     805      2350078 :           if (dump_file && (dump_flags & TDF_DETAILS))
     806            0 :             fprintf (dump_file, "  Visiting %s\n", w->dump_asm_name ());
     807      2350078 :           get_read_write_all_from_node (w, read_all, write_all);
     808      2350078 :           if (read_all && write_all)
     809              :             break;
     810              :         }
     811              : 
     812              :       /* Initialized the bitmaps global sets for the reduced node.  */
     813      2342631 :       if (read_all)
     814      1035317 :         node_g->statics_read = all_module_statics;
     815              :       else
     816      1307314 :         node_g->statics_read = copy_static_var_set (node_l->statics_read, true);
     817      2342631 :       if (write_all)
     818       974637 :         node_g->statics_written = all_module_statics;
     819              :       else
     820      1367994 :         node_g->statics_written
     821      1367994 :           = copy_static_var_set (node_l->statics_written, true);
     822              : 
     823              :       /* Merge the sets of this cycle with all sets of callees reached
     824              :          from this cycle.  */
     825      3715106 :       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
     826              :         {
     827      2347498 :           if (read_all && write_all)
     828              :             break;
     829              : 
     830      1372475 :           if (w != node)
     831              :             {
     832         4481 :               ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
     833         4481 :               ipa_reference_local_vars_info_t w_l = &w_ri->local;
     834         4481 :               int flags = flags_from_decl_or_type (w->decl);
     835              : 
     836         4481 :               if (!(flags & ECF_CONST))
     837         3258 :                 read_all = union_static_var_sets (node_g->statics_read,
     838              :                                                   w_l->statics_read);
     839         4481 :               if (!(flags & ECF_PURE)
     840         4481 :                   && !w->cannot_return_p ())
     841         3495 :                 write_all = union_static_var_sets (node_g->statics_written,
     842              :                                                    w_l->statics_written);
     843              :             }
     844              : 
     845      1372475 :           propagate_bits (node_g, w);
     846              :         }
     847              : 
     848              :       /* All nodes within a cycle have the same global info bitmaps.  */
     849      4705625 :       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
     850              :         {
     851      2362994 :           ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
     852      2362994 :           w_ri->global = *node_g;
     853              :         }
     854              : 
     855      2342631 :       cycle_nodes.release ();
     856              :     }
     857              : 
     858       151640 :   if (dump_file)
     859              :     {
     860           52 :       for (i = 0; i < order_pos; i++)
     861              :         {
     862           33 :           unsigned x;
     863           33 :           struct cgraph_node *w;
     864              : 
     865           33 :           node = order[i];
     866           33 :           if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
     867            0 :             continue;
     868              : 
     869           33 :           fprintf (dump_file, "\nFunction name:%s:", node->dump_asm_name ());
     870              : 
     871           33 :           ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
     872           33 :           ipa_reference_global_vars_info_t node_g = &node_info->global;
     873              : 
     874           33 :           vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
     875           66 :           FOR_EACH_VEC_ELT (cycle_nodes, x, w)
     876              :             {
     877           33 :               ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
     878           33 :               ipa_reference_local_vars_info_t w_l = &w_ri->local;
     879           33 :               if (w != node)
     880            0 :                 fprintf (dump_file, "\n  next cycle: %s ", w->dump_asm_name ());
     881           33 :               fprintf (dump_file, "\n    locals read: ");
     882           33 :               dump_static_vars_set_to_file (dump_file, w_l->statics_read);
     883           33 :               fprintf (dump_file, "\n    locals written: ");
     884           33 :               dump_static_vars_set_to_file (dump_file, w_l->statics_written);
     885              :             }
     886           33 :           cycle_nodes.release ();
     887              : 
     888           33 :           fprintf (dump_file, "\n  globals read: ");
     889           33 :           dump_static_vars_set_to_file (dump_file, node_g->statics_read);
     890           33 :           fprintf (dump_file, "\n  globals written: ");
     891           33 :           dump_static_vars_set_to_file (dump_file, node_g->statics_written);
     892           33 :           fprintf (dump_file, "\n");
     893              :         }
     894              :     }
     895              : 
     896       151640 :   if (ipa_ref_opt_sum_summaries == NULL)
     897              :     {
     898       151640 :       ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
     899       151640 :       ipa_ref_opt_sum_summaries->disable_insertion_hook ();
     900              :     }
     901              : 
     902              :   /* Cleanup. */
     903      2560664 :   FOR_EACH_DEFINED_FUNCTION (node)
     904              :     {
     905      2409024 :       ipa_reference_vars_info_t node_info;
     906      2409024 :       ipa_reference_global_vars_info_t node_g;
     907              : 
     908              :       /* No need to produce summaries for inline clones.  */
     909      2409024 :       if (node->inlined_to)
     910      1324758 :         continue;
     911              : 
     912      1084266 :       node_info = get_reference_vars_info (node);
     913      1084266 :       if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference))
     914              :         {
     915      1038236 :           node_g = &node_info->global;
     916      1038236 :           bool read_all =
     917      1038236 :                 (node_g->statics_read == all_module_statics
     918      1038236 :                  || bitmap_equal_p (node_g->statics_read, all_module_statics));
     919      1038236 :           bool written_all =
     920      1038236 :                 (node_g->statics_written == all_module_statics
     921      1038236 :                  || bitmap_equal_p (node_g->statics_written,
     922      1041868 :                                     all_module_statics));
     923              : 
     924              :           /* There is no need to produce summary if we collected nothing
     925              :              useful.  */
     926       994688 :           if (read_all && written_all)
     927       991056 :             continue;
     928              : 
     929        47180 :           ipa_reference_optimization_summary_d *opt
     930        47180 :             = ipa_ref_opt_sum_summaries->get_create (node);
     931              : 
     932              :           /* Create the complimentary sets.  */
     933              : 
     934        47180 :           if (bitmap_empty_p (node_g->statics_read))
     935        37598 :             opt->statics_read = no_module_statics;
     936         9582 :           else if (read_all)
     937         7451 :             opt->statics_read = all_module_statics;
     938              :           else
     939              :             {
     940         2131 :               opt->statics_read
     941         2131 :                  = BITMAP_ALLOC (&optimization_summary_obstack);
     942         2131 :               bitmap_copy (opt->statics_read, node_g->statics_read);
     943              :             }
     944              : 
     945        47180 :           if (bitmap_empty_p (node_g->statics_written))
     946        41458 :             opt->statics_written = no_module_statics;
     947         5722 :           else if (written_all)
     948         3632 :             opt->statics_written = all_module_statics;
     949              :           else
     950              :             {
     951         2090 :               opt->statics_written
     952         2090 :                 = BITMAP_ALLOC (&optimization_summary_obstack);
     953         2090 :               bitmap_copy (opt->statics_written, node_g->statics_written);
     954              :             }
     955              :         }
     956              :    }
     957              : 
     958       151640 :   ipa_free_postorder_info ();
     959       151640 :   free (order);
     960              : 
     961       151640 :   bitmap_obstack_release (&local_info_obstack);
     962              : 
     963       151640 :   if (ipa_ref_var_info_summaries != NULL)
     964              :     {
     965       151640 :       delete ipa_ref_var_info_summaries;
     966       151640 :       ipa_ref_var_info_summaries = NULL;
     967              :     }
     968              : 
     969       151640 :   if (dump_file)
     970              :     {
     971           19 :       vec_free (reference_vars_to_consider);
     972           19 :       reference_vars_to_consider = NULL;
     973              :     }
     974              :   else
     975       151621 :     gcc_checking_assert (!reference_vars_to_consider);
     976       151640 :   return remove_p ? TODO_remove_functions : 0;
     977              : }
     978              : 
     979              : /* Return true if we need to write summary of NODE. */
     980              : 
     981              : static bool
     982        98442 : write_node_summary_p (struct cgraph_node *node,
     983              :                       lto_symtab_encoder_t encoder,
     984              :                       bitmap ltrans_statics)
     985              : {
     986        98442 :   ipa_reference_optimization_summary_t info;
     987              : 
     988              :   /* See if we have (non-empty) info.  */
     989        98442 :   if (!node->definition || node->inlined_to)
     990              :     return false;
     991        46932 :   info = get_reference_optimization_summary (node);
     992        46932 :   if (!info)
     993              :     return false;
     994              : 
     995              :   /* See if we want to encode it.
     996              :      Encode also referenced functions since constant folding might turn it into
     997              :      a direct call.
     998              : 
     999              :      In future we might also want to include summaries of functions references
    1000              :      by initializers of constant variables references in current unit.  */
    1001         9242 :   if (!reachable_from_this_partition_p (node, encoder)
    1002         9242 :       && !referenced_from_this_partition_p (node, encoder))
    1003              :     return false;
    1004              : 
    1005              :   /* See if the info has non-empty intersections with vars we want to
    1006              :      encode.  */
    1007         7744 :   bitmap_iterator bi;
    1008         7744 :   unsigned int i;
    1009         7744 :   EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics, info->statics_read, 0,
    1010              :                                   i, bi)
    1011              :     return true;
    1012         2364 :   EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics, info->statics_written, 0,
    1013              :                                   i, bi)
    1014              :     return true;
    1015              :   return false;
    1016              : }
    1017              : 
    1018              : /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
    1019              :    LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
    1020              :    or -1.  When it is positive, just output -1 when
    1021              :    BITS&LTRANS_STATICS == BITS&LTRANS_STATICS.  */
    1022              : 
    1023              : static void
    1024         8651 : stream_out_bitmap (struct lto_simple_output_block *ob,
    1025              :                    bitmap bits, bitmap ltrans_statics,
    1026              :                    int ltrans_statics_bitcount)
    1027              : {
    1028         8651 :   int count = 0;
    1029         8651 :   unsigned int index;
    1030         8651 :   bitmap_iterator bi;
    1031         8651 :   if (bits == all_module_statics)
    1032              :     {
    1033         1492 :       streamer_write_hwi_stream (ob->main_stream, -1);
    1034         8134 :       return;
    1035              :     }
    1036        10701 :   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
    1037         3542 :     count ++;
    1038         7159 :   if (count == ltrans_statics_bitcount)
    1039              :     {
    1040            0 :       streamer_write_hwi_stream (ob->main_stream, -1);
    1041            0 :       return;
    1042              :     }
    1043         7159 :   streamer_write_hwi_stream (ob->main_stream, count);
    1044         7159 :   if (!count)
    1045              :     return;
    1046         5551 :   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
    1047              :     {
    1048         3542 :       tree decl = (*reference_vars_to_consider) [index];
    1049         3542 :       lto_output_var_decl_ref (ob->decl_state, ob->main_stream, decl);
    1050              :     }
    1051              : }
    1052              : 
    1053              : /* Serialize the ipa info for lto.  */
    1054              : 
    1055              : static void
    1056         8190 : ipa_reference_write_optimization_summary (void)
    1057              : {
    1058         8190 :   struct lto_simple_output_block *ob
    1059         8190 :     = lto_create_simple_output_block (LTO_section_ipa_reference);
    1060         8190 :   unsigned int count = 0;
    1061         8190 :   int ltrans_statics_bitcount = 0;
    1062         8190 :   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
    1063         8190 :   auto_bitmap ltrans_statics;
    1064         8190 :   int i;
    1065              : 
    1066         8190 :   gcc_checking_assert (!reference_vars_to_consider);
    1067         8190 :   vec_alloc (reference_vars_to_consider, ipa_reference_vars_uids);
    1068         8190 :   reference_vars_to_consider->safe_grow (ipa_reference_vars_uids, true);
    1069              : 
    1070              :   /* See what variables we are interested in.  */
    1071       231448 :   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
    1072              :     {
    1073       107538 :       toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
    1074       215076 :       varpool_node *vnode = dyn_cast <varpool_node *> (tnode);
    1075        24739 :       int id;
    1076              : 
    1077        24739 :       if (vnode
    1078        24739 :           && (id = ipa_reference_var_uid (vnode->decl)) != -1
    1079         3805 :           && referenced_from_this_partition_p (vnode, encoder))
    1080              :         {
    1081         3799 :           tree decl = vnode->decl;
    1082         3799 :           bitmap_set_bit (ltrans_statics, id);
    1083         3799 :           (*reference_vars_to_consider)[id] = decl;
    1084         3799 :           ltrans_statics_bitcount ++;
    1085              :         }
    1086              :     }
    1087              : 
    1088              : 
    1089         8190 :   if (ltrans_statics_bitcount)
    1090       118088 :     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
    1091              :       {
    1092        57227 :         toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
    1093       114454 :         cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
    1094        49221 :         if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
    1095         3872 :           count++;
    1096              :       }
    1097              : 
    1098         8190 :   streamer_write_uhwi_stream (ob->main_stream, count);
    1099         8190 :   if (count)
    1100          907 :     stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
    1101              :                        -1);
    1102              : 
    1103              :   /* Process all of the functions.  */
    1104         8190 :   if (ltrans_statics_bitcount)
    1105       118088 :     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
    1106              :       {
    1107        57227 :         toplevel_node *tnode = lto_symtab_encoder_deref (encoder, i);
    1108       114454 :         cgraph_node *cnode = dyn_cast <cgraph_node *> (tnode);
    1109        49221 :         if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
    1110              :           {
    1111         3872 :             ipa_reference_optimization_summary_t info;
    1112         3872 :             int node_ref;
    1113              : 
    1114         3872 :             info = get_reference_optimization_summary (cnode);
    1115         3872 :             node_ref = lto_symtab_encoder_encode (encoder, tnode);
    1116         3872 :             streamer_write_uhwi_stream (ob->main_stream, node_ref);
    1117              : 
    1118         3872 :             stream_out_bitmap (ob, info->statics_read, ltrans_statics,
    1119              :                                ltrans_statics_bitcount);
    1120         3872 :             stream_out_bitmap (ob, info->statics_written, ltrans_statics,
    1121              :                                ltrans_statics_bitcount);
    1122              :           }
    1123              :       }
    1124         8190 :   lto_destroy_simple_output_block (ob);
    1125         8190 :   vec_free (reference_vars_to_consider);
    1126         8190 :   reference_vars_to_consider = NULL;
    1127         8190 : }
    1128              : 
    1129              : /* Deserialize the ipa info for lto.  */
    1130              : 
    1131              : static void
    1132         8190 : ipa_reference_read_optimization_summary (void)
    1133              : {
    1134         8190 :   struct lto_file_decl_data ** file_data_vec
    1135         8190 :     = lto_get_file_decl_data ();
    1136         8190 :   struct lto_file_decl_data * file_data;
    1137         8190 :   unsigned int j = 0;
    1138         8190 :   bitmap_obstack_initialize (&optimization_summary_obstack);
    1139              : 
    1140         8190 :   gcc_checking_assert (ipa_ref_opt_sum_summaries == NULL);
    1141         8190 :   ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
    1142         8190 :   ipa_ref_opt_sum_summaries->disable_insertion_hook ();
    1143         8190 :   ipa_reference_vars_map = new reference_vars_map_t(257);
    1144         8190 :   varpool_node_hooks
    1145         8190 :          = symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
    1146         8190 :   ipa_reference_vars_uids = 0;
    1147              : 
    1148         8190 :   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
    1149         8190 :   no_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
    1150              : 
    1151        16380 :   while ((file_data = file_data_vec[j++]))
    1152              :     {
    1153         8190 :       const char *data;
    1154         8190 :       size_t len;
    1155         8190 :       class lto_input_block *ib
    1156         8190 :         = lto_create_simple_input_block (file_data,
    1157              :                                          LTO_section_ipa_reference,
    1158              :                                          &data, &len);
    1159         8190 :       if (ib)
    1160              :         {
    1161         8190 :           unsigned int i;
    1162         8190 :           unsigned int f_count = streamer_read_uhwi (ib);
    1163         8190 :           int b_count;
    1164         8190 :           if (!f_count)
    1165         7283 :             continue;
    1166          907 :           b_count = streamer_read_hwi (ib);
    1167          907 :           if (dump_file)
    1168            0 :             fprintf (dump_file, "all module statics:");
    1169         2861 :           for (i = 0; i < (unsigned int)b_count; i++)
    1170              :             {
    1171         1954 :               tree v_decl = lto_input_var_decl_ref (ib, file_data);
    1172         1954 :               bool existed;
    1173         1954 :               bitmap_set_bit (all_module_statics,
    1174              :                               ipa_reference_var_get_or_insert_uid
    1175              :                                  (v_decl, &existed));
    1176         1954 :               gcc_checking_assert (!existed);
    1177         1954 :               if (dump_file)
    1178            0 :                 fprintf (dump_file, " %s", fndecl_name (v_decl));
    1179              :             }
    1180              : 
    1181         4779 :           for (i = 0; i < f_count; i++)
    1182              :             {
    1183         3872 :               unsigned int j, index;
    1184         3872 :               struct cgraph_node *node;
    1185         3872 :               int v_count;
    1186         3872 :               lto_symtab_encoder_t encoder;
    1187              : 
    1188         3872 :               index = streamer_read_uhwi (ib);
    1189         3872 :               encoder = file_data->symtab_node_encoder;
    1190         3872 :               node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
    1191              :                 (encoder, index));
    1192              : 
    1193         3872 :               ipa_reference_optimization_summary_d *info
    1194         3872 :                 = ipa_ref_opt_sum_summaries->get_create (node);
    1195              : 
    1196         3872 :               if (dump_file)
    1197            0 :                 fprintf (dump_file,
    1198              :                          "\nFunction name:%s:\n  static read:",
    1199              :                          node->dump_asm_name ());
    1200              : 
    1201              :               /* Set the statics read.  */
    1202         3872 :               v_count = streamer_read_hwi (ib);
    1203         3872 :               if (v_count == -1)
    1204              :                 {
    1205         1182 :                   info->statics_read = all_module_statics;
    1206         1182 :                   if (dump_file)
    1207            0 :                     fprintf (dump_file, " all module statics");
    1208              :                 }
    1209         2690 :               else if (v_count == 0)
    1210         2097 :                 info->statics_read = no_module_statics;
    1211              :               else
    1212              :                 {
    1213         1186 :                   info->statics_read = BITMAP_ALLOC
    1214          593 :                     (&optimization_summary_obstack);
    1215         1505 :                   for (j = 0; j < (unsigned int)v_count; j++)
    1216              :                     {
    1217          912 :                       tree v_decl = lto_input_var_decl_ref (ib, file_data);
    1218          912 :                       bitmap_set_bit (info->statics_read,
    1219              :                                       ipa_reference_var_uid (v_decl));
    1220          912 :                       if (dump_file)
    1221            0 :                         fprintf (dump_file, " %s", fndecl_name (v_decl));
    1222              :                     }
    1223              :                 }
    1224              : 
    1225         3872 :               if (dump_file)
    1226            0 :                 fprintf (dump_file,
    1227              :                          "\n  static written:");
    1228              :               /* Set the statics written.  */
    1229         3872 :               v_count = streamer_read_hwi (ib);
    1230         3872 :               if (v_count == -1)
    1231              :                 {
    1232          310 :                   info->statics_written = all_module_statics;
    1233          310 :                   if (dump_file)
    1234            0 :                     fprintf (dump_file, " all module statics");
    1235              :                 }
    1236         3562 :               else if (v_count == 0)
    1237         3053 :                 info->statics_written = no_module_statics;
    1238              :               else
    1239              :                 {
    1240         1018 :                   info->statics_written = BITMAP_ALLOC
    1241          509 :                     (&optimization_summary_obstack);
    1242         1185 :                   for (j = 0; j < (unsigned int)v_count; j++)
    1243              :                     {
    1244          676 :                       tree v_decl = lto_input_var_decl_ref (ib, file_data);
    1245          676 :                       bitmap_set_bit (info->statics_written,
    1246              :                                       ipa_reference_var_uid (v_decl));
    1247          676 :                       if (dump_file)
    1248            0 :                         fprintf (dump_file, " %s", fndecl_name (v_decl));
    1249              :                     }
    1250              :                 }
    1251         3872 :               if (dump_file)
    1252            0 :                 fprintf (dump_file, "\n");
    1253              :             }
    1254              : 
    1255          907 :           lto_destroy_simple_input_block (file_data,
    1256              :                                           LTO_section_ipa_reference,
    1257              :                                           ib, data, len);
    1258              :         }
    1259              :       else
    1260              :         /* Fatal error here.  We do not want to support compiling ltrans units
    1261              :            with different version of compiler or different flags than
    1262              :            the WPA unit, so this should never happen.  */
    1263            0 :         fatal_error (input_location,
    1264              :                      "ipa reference summary is missing in ltrans unit");
    1265              :     }
    1266         8190 : }
    1267              : 
    1268              : namespace {
    1269              : 
    1270              : const pass_data pass_data_ipa_reference =
    1271              : {
    1272              :   IPA_PASS, /* type */
    1273              :   "static-var", /* name */
    1274              :   OPTGROUP_NONE, /* optinfo_flags */
    1275              :   TV_IPA_REFERENCE, /* tv_id */
    1276              :   0, /* properties_required */
    1277              :   0, /* properties_provided */
    1278              :   0, /* properties_destroyed */
    1279              :   0, /* todo_flags_start */
    1280              :   0, /* todo_flags_finish */
    1281              : };
    1282              : 
    1283              : class pass_ipa_reference : public ipa_opt_pass_d
    1284              : {
    1285              : public:
    1286       285722 :   pass_ipa_reference (gcc::context *ctxt)
    1287              :     : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
    1288              :                       NULL, /* generate_summary */
    1289              :                       NULL, /* write_summary */
    1290              :                       NULL, /* read_summary */
    1291              :                       ipa_reference_write_optimization_summary, /*
    1292              :                       write_optimization_summary */
    1293              :                       ipa_reference_read_optimization_summary, /*
    1294              :                       read_optimization_summary */
    1295              :                       NULL, /* stmt_fixup */
    1296              :                       0, /* function_transform_todo_flags_start */
    1297              :                       NULL, /* function_transform */
    1298       285722 :                       NULL) /* variable_transform */
    1299       285722 :     {}
    1300              : 
    1301              :   /* opt_pass methods: */
    1302       571909 :   bool gate (function *) final override
    1303              :     {
    1304       447705 :       return ((in_lto_p || flag_ipa_reference)
    1305              :               /* Don't bother doing anything if the program has errors.  */
    1306       860008 :               && !seen_error ());
    1307              :     }
    1308              : 
    1309       151640 :   unsigned int execute (function *) final override { return propagate (); }
    1310              : 
    1311              : }; // class pass_ipa_reference
    1312              : 
    1313              : } // anon namespace
    1314              : 
    1315              : ipa_opt_pass_d *
    1316       285722 : make_pass_ipa_reference (gcc::context *ctxt)
    1317              : {
    1318       285722 :   return new pass_ipa_reference (ctxt);
    1319              : }
    1320              : 
    1321              : /* Reset all state within ipa-reference.cc so that we can rerun the compiler
    1322              :    within the same process.  For use by toplev::finalize.  */
    1323              : 
    1324              : void
    1325       256621 : ipa_reference_cc_finalize (void)
    1326              : {
    1327       256621 :   if (ipa_ref_opt_sum_summaries != NULL)
    1328              :     {
    1329       159613 :       delete ipa_ref_opt_sum_summaries;
    1330       159613 :       ipa_ref_opt_sum_summaries = NULL;
    1331       319226 :       delete ipa_reference_vars_map;
    1332       159613 :       ipa_reference_vars_map = NULL;
    1333       159613 :       symtab->remove_varpool_removal_hook (varpool_node_hooks);
    1334              :     }
    1335              : 
    1336       256621 :   if (ipa_init_p)
    1337              :     {
    1338       151423 :       bitmap_obstack_release (&optimization_summary_obstack);
    1339       151423 :       ipa_init_p = false;
    1340              :     }
    1341       256621 : }
        

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.