xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/ipa-reference.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
11debfc3dSmrg /* Callgraph based analysis of static variables.
2*8feb0f0bSmrg    Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg    Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
41debfc3dSmrg 
51debfc3dSmrg This file is part of GCC.
61debfc3dSmrg 
71debfc3dSmrg GCC is free software; you can redistribute it and/or modify it under
81debfc3dSmrg the terms of the GNU General Public License as published by the Free
91debfc3dSmrg Software Foundation; either version 3, or (at your option) any later
101debfc3dSmrg version.
111debfc3dSmrg 
121debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT ANY
131debfc3dSmrg WARRANTY; without even the implied warranty of MERCHANTABILITY or
141debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
151debfc3dSmrg for more details.
161debfc3dSmrg 
171debfc3dSmrg You should have received a copy of the GNU General Public License
181debfc3dSmrg along with GCC; see the file COPYING3.  If not see
191debfc3dSmrg <http://www.gnu.org/licenses/>.  */
201debfc3dSmrg 
211debfc3dSmrg /* This file gathers information about how variables whose scope is
221debfc3dSmrg    confined to the compilation unit are used.
231debfc3dSmrg 
241debfc3dSmrg    The transitive call site specific clobber effects are computed
251debfc3dSmrg    for the variables whose scope is contained within this compilation
261debfc3dSmrg    unit.
271debfc3dSmrg 
281debfc3dSmrg    First each function and static variable initialization is analyzed
291debfc3dSmrg    to determine which local static variables are either read, written,
301debfc3dSmrg    or have their address taken.  Any local static that has its address
311debfc3dSmrg    taken is removed from consideration.  Once the local read and
321debfc3dSmrg    writes are determined, a transitive closure of this information is
331debfc3dSmrg    performed over the call graph to determine the worst case set of
341debfc3dSmrg    side effects of each call.  In later parts of the compiler, these
351debfc3dSmrg    local and global sets are examined to make the call clobbering less
361debfc3dSmrg    traumatic, promote some statics to registers, and improve aliasing
371debfc3dSmrg    information.  */
381debfc3dSmrg 
391debfc3dSmrg #include "config.h"
401debfc3dSmrg #include "system.h"
411debfc3dSmrg #include "coretypes.h"
421debfc3dSmrg #include "backend.h"
431debfc3dSmrg #include "tree.h"
441debfc3dSmrg #include "gimple.h"
451debfc3dSmrg #include "tree-pass.h"
461debfc3dSmrg #include "cgraph.h"
471debfc3dSmrg #include "data-streamer.h"
481debfc3dSmrg #include "calls.h"
491debfc3dSmrg #include "ipa-utils.h"
501debfc3dSmrg #include "ipa-reference.h"
51*8feb0f0bSmrg #include "alloc-pool.h"
52c0a68be4Smrg #include "symbol-summary.h"
531debfc3dSmrg 
541debfc3dSmrg /* The static variables defined within the compilation unit that are
551debfc3dSmrg    loaded or stored directly by function that owns this structure.  */
561debfc3dSmrg 
571debfc3dSmrg struct ipa_reference_local_vars_info_d
581debfc3dSmrg {
591debfc3dSmrg   bitmap statics_read;
601debfc3dSmrg   bitmap statics_written;
611debfc3dSmrg };
621debfc3dSmrg 
631debfc3dSmrg /* Statics that are read and written by some set of functions. The
641debfc3dSmrg    local ones are based on the loads and stores local to the function.
651debfc3dSmrg    The global ones are based on the local info as well as the
661debfc3dSmrg    transitive closure of the functions that are called. */
671debfc3dSmrg 
681debfc3dSmrg struct ipa_reference_global_vars_info_d
691debfc3dSmrg {
701debfc3dSmrg   bitmap statics_read;
711debfc3dSmrg   bitmap statics_written;
721debfc3dSmrg };
731debfc3dSmrg 
741debfc3dSmrg /* Information we save about every function after ipa-reference is completed.  */
751debfc3dSmrg 
761debfc3dSmrg struct ipa_reference_optimization_summary_d
771debfc3dSmrg {
78*8feb0f0bSmrg   bitmap statics_read;
79*8feb0f0bSmrg   bitmap statics_written;
801debfc3dSmrg };
811debfc3dSmrg 
82c0a68be4Smrg typedef ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
83c0a68be4Smrg typedef ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
84c0a68be4Smrg typedef ipa_reference_optimization_summary_d *
85c0a68be4Smrg   ipa_reference_optimization_summary_t;
861debfc3dSmrg 
871debfc3dSmrg struct ipa_reference_vars_info_d
881debfc3dSmrg {
891debfc3dSmrg   struct ipa_reference_local_vars_info_d local;
901debfc3dSmrg   struct ipa_reference_global_vars_info_d global;
911debfc3dSmrg };
921debfc3dSmrg 
931debfc3dSmrg typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
941debfc3dSmrg 
95*8feb0f0bSmrg /* This map contains all of the static variables that are
961debfc3dSmrg    being considered by the compilation level alias analysis.  */
97*8feb0f0bSmrg typedef hash_map<tree, int> reference_vars_map_t;
98*8feb0f0bSmrg static reference_vars_map_t *ipa_reference_vars_map;
99*8feb0f0bSmrg static int ipa_reference_vars_uids;
100*8feb0f0bSmrg static vec<tree> *reference_vars_to_consider;
101*8feb0f0bSmrg varpool_node_hook_list *varpool_node_hooks;
1021debfc3dSmrg 
1031debfc3dSmrg /* Set of all interesting module statics.  A bit is set for every module
1041debfc3dSmrg    static we are considering.  This is added to the local info when asm
1051debfc3dSmrg    code is found that clobbers all memory.  */
1061debfc3dSmrg static bitmap all_module_statics;
107*8feb0f0bSmrg /* Zero bitmap.  */
108*8feb0f0bSmrg static bitmap no_module_statics;
1091debfc3dSmrg /* Set of all statics that should be ignored because they are touched by
1101debfc3dSmrg    -fno-ipa-reference code.  */
1111debfc3dSmrg static bitmap ignore_module_statics;
1121debfc3dSmrg 
1131debfc3dSmrg /* Obstack holding bitmaps of local analysis (live from analysis to
1141debfc3dSmrg    propagation)  */
1151debfc3dSmrg static bitmap_obstack local_info_obstack;
1161debfc3dSmrg /* Obstack holding global analysis live forever.  */
1171debfc3dSmrg static bitmap_obstack optimization_summary_obstack;
1181debfc3dSmrg 
119c0a68be4Smrg class ipa_ref_var_info_summary_t: public fast_function_summary
120c0a68be4Smrg 			  <ipa_reference_vars_info_d *, va_heap>
121c0a68be4Smrg {
122c0a68be4Smrg public:
ipa_ref_var_info_summary_t(symbol_table * symtab)123c0a68be4Smrg   ipa_ref_var_info_summary_t (symbol_table *symtab):
124c0a68be4Smrg     fast_function_summary <ipa_reference_vars_info_d *, va_heap> (symtab) {}
125c0a68be4Smrg };
1261debfc3dSmrg 
127c0a68be4Smrg static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL;
1281debfc3dSmrg 
129c0a68be4Smrg class ipa_ref_opt_summary_t: public fast_function_summary
130c0a68be4Smrg 			     <ipa_reference_optimization_summary_d *, va_heap>
131c0a68be4Smrg {
132c0a68be4Smrg public:
ipa_ref_opt_summary_t(symbol_table * symtab)133c0a68be4Smrg   ipa_ref_opt_summary_t (symbol_table *symtab):
134c0a68be4Smrg     fast_function_summary <ipa_reference_optimization_summary_d *, va_heap> (symtab) {}
135c0a68be4Smrg 
136c0a68be4Smrg   virtual void remove (cgraph_node *src_node,
137c0a68be4Smrg 		       ipa_reference_optimization_summary_d *data);
138c0a68be4Smrg   virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
139c0a68be4Smrg 			  ipa_reference_optimization_summary_d *src_data,
140c0a68be4Smrg 			  ipa_reference_optimization_summary_d *dst_data);
141c0a68be4Smrg };
142c0a68be4Smrg 
143c0a68be4Smrg static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL;
1441debfc3dSmrg 
145*8feb0f0bSmrg /* Return ID used by ipa-reference bitmaps.  -1 if failed.  */
146*8feb0f0bSmrg int
ipa_reference_var_uid(tree t)147*8feb0f0bSmrg ipa_reference_var_uid (tree t)
148*8feb0f0bSmrg {
149*8feb0f0bSmrg   if (!ipa_reference_vars_map)
150*8feb0f0bSmrg     return -1;
151*8feb0f0bSmrg   int *id = ipa_reference_vars_map->get
152*8feb0f0bSmrg     (symtab_node::get (t)->ultimate_alias_target (NULL)->decl);
153*8feb0f0bSmrg   if (!id)
154*8feb0f0bSmrg     return -1;
155*8feb0f0bSmrg   return *id;
156*8feb0f0bSmrg }
157*8feb0f0bSmrg 
158*8feb0f0bSmrg /* Return ID used by ipa-reference bitmaps.  Create new entry if
159*8feb0f0bSmrg    T is not in map.  Set EXISTED accordinly  */
160*8feb0f0bSmrg int
ipa_reference_var_get_or_insert_uid(tree t,bool * existed)161*8feb0f0bSmrg ipa_reference_var_get_or_insert_uid (tree t, bool *existed)
162*8feb0f0bSmrg {
163*8feb0f0bSmrg   int &id = ipa_reference_vars_map->get_or_insert
164*8feb0f0bSmrg     (symtab_node::get (t)->ultimate_alias_target (NULL)->decl, existed);
165*8feb0f0bSmrg   if (!*existed)
166*8feb0f0bSmrg     id = ipa_reference_vars_uids++;
167*8feb0f0bSmrg   return id;
168*8feb0f0bSmrg }
169*8feb0f0bSmrg 
1701debfc3dSmrg /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
1711debfc3dSmrg static inline ipa_reference_vars_info_t
get_reference_vars_info(struct cgraph_node * node)1721debfc3dSmrg get_reference_vars_info (struct cgraph_node *node)
1731debfc3dSmrg {
174c0a68be4Smrg   if (ipa_ref_var_info_summaries == NULL)
1751debfc3dSmrg     return NULL;
176c0a68be4Smrg 
177c0a68be4Smrg   ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node);
178c0a68be4Smrg   return v == NULL ? NULL : v;
1791debfc3dSmrg }
1801debfc3dSmrg 
1811debfc3dSmrg /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
1821debfc3dSmrg static inline ipa_reference_optimization_summary_t
get_reference_optimization_summary(struct cgraph_node * node)1831debfc3dSmrg get_reference_optimization_summary (struct cgraph_node *node)
1841debfc3dSmrg {
185c0a68be4Smrg   if (ipa_ref_opt_sum_summaries == NULL)
1861debfc3dSmrg     return NULL;
1871debfc3dSmrg 
188c0a68be4Smrg   ipa_reference_optimization_summary_t v
189c0a68be4Smrg     = ipa_ref_opt_sum_summaries->get (node);
1901debfc3dSmrg 
191c0a68be4Smrg   return v == NULL ? NULL : v;
1921debfc3dSmrg }
1931debfc3dSmrg 
1941debfc3dSmrg /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
1951debfc3dSmrg    that are *not* read during the execution of the function FN.  Returns
1961debfc3dSmrg    NULL if no data is available.  */
1971debfc3dSmrg 
1981debfc3dSmrg bitmap
ipa_reference_get_read_global(struct cgraph_node * fn)199*8feb0f0bSmrg ipa_reference_get_read_global (struct cgraph_node *fn)
2001debfc3dSmrg {
2011debfc3dSmrg   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
2021debfc3dSmrg     return NULL;
2031debfc3dSmrg 
2041debfc3dSmrg   enum availability avail;
2051debfc3dSmrg   struct cgraph_node *fn2 = fn->function_symbol (&avail);
2061debfc3dSmrg   ipa_reference_optimization_summary_t info =
2071debfc3dSmrg     get_reference_optimization_summary (fn2);
2081debfc3dSmrg 
2091debfc3dSmrg   if (info
2101debfc3dSmrg       && (avail >= AVAIL_AVAILABLE
2111debfc3dSmrg 	  || (avail == AVAIL_INTERPOSABLE
2121debfc3dSmrg 	      && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
2131debfc3dSmrg       && opt_for_fn (fn2->decl, flag_ipa_reference))
214*8feb0f0bSmrg     return info->statics_read;
2151debfc3dSmrg   else if (avail == AVAIL_NOT_AVAILABLE
2161debfc3dSmrg 	   && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
217*8feb0f0bSmrg     return no_module_statics;
2181debfc3dSmrg   else
2191debfc3dSmrg     return NULL;
2201debfc3dSmrg }
2211debfc3dSmrg 
2221debfc3dSmrg /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
2231debfc3dSmrg    that are *not* written during the execution of the function FN.  Note
2241debfc3dSmrg    that variables written may or may not be read during the function
2251debfc3dSmrg    call.  Returns NULL if no data is available.  */
2261debfc3dSmrg 
2271debfc3dSmrg bitmap
ipa_reference_get_written_global(struct cgraph_node * fn)228*8feb0f0bSmrg ipa_reference_get_written_global (struct cgraph_node *fn)
2291debfc3dSmrg {
2301debfc3dSmrg   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
2311debfc3dSmrg     return NULL;
2321debfc3dSmrg 
2331debfc3dSmrg   enum availability avail;
2341debfc3dSmrg   struct cgraph_node *fn2 = fn->function_symbol (&avail);
2351debfc3dSmrg   ipa_reference_optimization_summary_t info =
2361debfc3dSmrg     get_reference_optimization_summary (fn2);
2371debfc3dSmrg 
2381debfc3dSmrg   if (info
2391debfc3dSmrg       && (avail >= AVAIL_AVAILABLE
2401debfc3dSmrg 	  || (avail == AVAIL_INTERPOSABLE
2411debfc3dSmrg 	      && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
2421debfc3dSmrg       && opt_for_fn (fn2->decl, flag_ipa_reference))
243*8feb0f0bSmrg     return info->statics_written;
2441debfc3dSmrg   else if (avail == AVAIL_NOT_AVAILABLE
2451debfc3dSmrg 	   && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
246*8feb0f0bSmrg     return no_module_statics;
2471debfc3dSmrg   else
2481debfc3dSmrg     return NULL;
2491debfc3dSmrg }
2501debfc3dSmrg 
2511debfc3dSmrg 
2521debfc3dSmrg /* Hepler for is_proper_for_analysis.  */
2531debfc3dSmrg static bool
is_improper(symtab_node * n,void * v ATTRIBUTE_UNUSED)2541debfc3dSmrg is_improper (symtab_node *n, void *v ATTRIBUTE_UNUSED)
2551debfc3dSmrg {
2561debfc3dSmrg   tree t = n->decl;
2571debfc3dSmrg   /* If the variable has the "used" attribute, treat it as if it had a
2581debfc3dSmrg      been touched by the devil.  */
2591debfc3dSmrg   if (DECL_PRESERVE_P (t))
2601debfc3dSmrg     return true;
2611debfc3dSmrg 
2621debfc3dSmrg   /* Do not want to do anything with volatile except mark any
2631debfc3dSmrg      function that uses one to be not const or pure.  */
2641debfc3dSmrg   if (TREE_THIS_VOLATILE (t))
2651debfc3dSmrg     return true;
2661debfc3dSmrg 
2671debfc3dSmrg   /* We do not need to analyze readonly vars, we already know they do not
2681debfc3dSmrg      alias.  */
2691debfc3dSmrg   if (TREE_READONLY (t))
2701debfc3dSmrg     return true;
2711debfc3dSmrg 
2721debfc3dSmrg   /* We cannot track variables with address taken.  */
2731debfc3dSmrg   if (TREE_ADDRESSABLE (t))
2741debfc3dSmrg     return true;
2751debfc3dSmrg 
2761debfc3dSmrg   /* TODO: We could track public variables that are not addressable, but
2771debfc3dSmrg      currently frontends don't give us those.  */
2781debfc3dSmrg   if (TREE_PUBLIC (t))
2791debfc3dSmrg     return true;
2801debfc3dSmrg 
2811debfc3dSmrg   return false;
2821debfc3dSmrg }
2831debfc3dSmrg 
2841debfc3dSmrg /* Return true if the variable T is the right kind of static variable to
2851debfc3dSmrg    perform compilation unit scope escape analysis.  */
2861debfc3dSmrg 
2871debfc3dSmrg static inline bool
is_proper_for_analysis(tree t)2881debfc3dSmrg is_proper_for_analysis (tree t)
2891debfc3dSmrg {
290*8feb0f0bSmrg   int id = ipa_reference_var_uid (t);
291*8feb0f0bSmrg 
292*8feb0f0bSmrg   if (id != -1 && bitmap_bit_p (ignore_module_statics, id))
2931debfc3dSmrg     return false;
2941debfc3dSmrg 
2951debfc3dSmrg   if (symtab_node::get (t)
2961debfc3dSmrg 	->call_for_symbol_and_aliases (is_improper, NULL, true))
2971debfc3dSmrg     return false;
2981debfc3dSmrg 
2991debfc3dSmrg   return true;
3001debfc3dSmrg }
3011debfc3dSmrg 
3021debfc3dSmrg /* Lookup the tree node for the static variable that has UID and
3031debfc3dSmrg    convert the name to a string for debugging.  */
3041debfc3dSmrg 
3051debfc3dSmrg static const char *
get_static_name(int index)3061debfc3dSmrg get_static_name (int index)
3071debfc3dSmrg {
308*8feb0f0bSmrg   return fndecl_name ((*reference_vars_to_consider)[index]);
3091debfc3dSmrg }
3101debfc3dSmrg 
3111debfc3dSmrg /* Dump a set of static vars to FILE.  */
3121debfc3dSmrg static void
dump_static_vars_set_to_file(FILE * f,bitmap set)3131debfc3dSmrg dump_static_vars_set_to_file (FILE *f, bitmap set)
3141debfc3dSmrg {
3151debfc3dSmrg   unsigned int index;
3161debfc3dSmrg   bitmap_iterator bi;
3171debfc3dSmrg   if (set == NULL)
3181debfc3dSmrg     return;
3191debfc3dSmrg   else if (set == all_module_statics)
3201debfc3dSmrg     fprintf (f, "ALL");
321*8feb0f0bSmrg   else if (set == no_module_statics)
322*8feb0f0bSmrg     fprintf (f, "NO");
3231debfc3dSmrg   else
3241debfc3dSmrg     EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
3251debfc3dSmrg       {
3261debfc3dSmrg         fprintf (f, "%s ", get_static_name (index));
3271debfc3dSmrg       }
3281debfc3dSmrg }
3291debfc3dSmrg 
3301debfc3dSmrg /* Compute X |= Y, taking into account the possibility that
3311debfc3dSmrg    either X or Y is already the maximum set.
3321debfc3dSmrg    Return true if X is the maximum set after taking the union with Y.  */
3331debfc3dSmrg 
3341debfc3dSmrg static bool
union_static_var_sets(bitmap & x,bitmap y)3351debfc3dSmrg union_static_var_sets (bitmap &x, bitmap y)
3361debfc3dSmrg {
3371debfc3dSmrg   if (x != all_module_statics)
3381debfc3dSmrg     {
3391debfc3dSmrg       if (y == all_module_statics)
3401debfc3dSmrg 	{
3411debfc3dSmrg 	  BITMAP_FREE (x);
3421debfc3dSmrg 	  x = all_module_statics;
3431debfc3dSmrg 	}
3441debfc3dSmrg       else if (bitmap_ior_into (x, y))
3451debfc3dSmrg 	{
3461debfc3dSmrg 	  /* The union may have reduced X to the maximum set.
3471debfc3dSmrg 	     In that case, we want to make that visible explicitly.
3481debfc3dSmrg 	     Even though bitmap_equal_p can be very expensive, it
3491debfc3dSmrg 	     turns out to be an overall win to check this here for
3501debfc3dSmrg 	     an LTO bootstrap of GCC itself.  Liberally extrapoliate
3511debfc3dSmrg 	     that result to be applicable to all cases.  */
3521debfc3dSmrg 	  if (bitmap_equal_p (x, all_module_statics))
3531debfc3dSmrg 	    {
3541debfc3dSmrg 	      BITMAP_FREE (x);
3551debfc3dSmrg 	      x = all_module_statics;
3561debfc3dSmrg 	    }
3571debfc3dSmrg 	}
3581debfc3dSmrg     }
3591debfc3dSmrg   return x == all_module_statics;
3601debfc3dSmrg }
3611debfc3dSmrg 
3621debfc3dSmrg /* Return a copy of SET on the bitmap obstack containing SET.
3631debfc3dSmrg    But if SET is NULL or the maximum set, return that instead.  */
3641debfc3dSmrg 
3651debfc3dSmrg static bitmap
copy_static_var_set(bitmap set,bool for_propagation)366*8feb0f0bSmrg copy_static_var_set (bitmap set, bool for_propagation)
3671debfc3dSmrg {
3681debfc3dSmrg   if (set == NULL || set == all_module_statics)
3691debfc3dSmrg     return set;
370*8feb0f0bSmrg   if (!for_propagation && set == no_module_statics)
371*8feb0f0bSmrg     return set;
3721debfc3dSmrg   bitmap_obstack *o = set->obstack;
3731debfc3dSmrg   gcc_checking_assert (o);
3741debfc3dSmrg   bitmap copy = BITMAP_ALLOC (o);
3751debfc3dSmrg   bitmap_copy (copy, set);
3761debfc3dSmrg   return copy;
3771debfc3dSmrg }
3781debfc3dSmrg 
3791debfc3dSmrg /* Compute the union all of the statics read and written by every callee of X
3801debfc3dSmrg    into X_GLOBAL->statics_read and X_GLOBAL->statics_written.  X_GLOBAL is
3811debfc3dSmrg    actually the set representing the cycle containing X.  If the read and
3821debfc3dSmrg    written sets of X_GLOBAL has been reduced to the maximum set, we don't
3831debfc3dSmrg    have to look at the remaining callees.  */
3841debfc3dSmrg 
3851debfc3dSmrg static void
propagate_bits(ipa_reference_global_vars_info_t x_global,struct cgraph_node * x)3861debfc3dSmrg propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
3871debfc3dSmrg {
3881debfc3dSmrg   struct cgraph_edge *e;
3891debfc3dSmrg   bool read_all = x_global->statics_read == all_module_statics;
3901debfc3dSmrg   bool write_all = x_global->statics_written == all_module_statics;
3911debfc3dSmrg   for (e = x->callees;
3921debfc3dSmrg        e && !(read_all && write_all);
3931debfc3dSmrg        e = e->next_callee)
3941debfc3dSmrg     {
3951debfc3dSmrg       enum availability avail;
3961debfc3dSmrg       struct cgraph_node *y = e->callee->function_symbol (&avail);
3971debfc3dSmrg       if (!y)
3981debfc3dSmrg 	continue;
3991debfc3dSmrg 
4001debfc3dSmrg       /* Only look into nodes we can propagate something.  */
4011debfc3dSmrg       int flags = flags_from_decl_or_type (y->decl);
4021debfc3dSmrg       if (opt_for_fn (y->decl, flag_ipa_reference)
4031debfc3dSmrg 	  && (avail > AVAIL_INTERPOSABLE
4041debfc3dSmrg 	      || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
4051debfc3dSmrg 	{
4061debfc3dSmrg 	  if (get_reference_vars_info (y))
4071debfc3dSmrg 	    {
4081debfc3dSmrg 	      ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
4091debfc3dSmrg 	      ipa_reference_global_vars_info_t y_global = &y_info->global;
4101debfc3dSmrg 
4111debfc3dSmrg 	      /* Calls in the current cycle do not have their global set
4121debfc3dSmrg 		 computed yet (but everything else does because we're
4131debfc3dSmrg 		 visiting nodes in topological order).  */
4141debfc3dSmrg 	      if (!y_global->statics_read)
4151debfc3dSmrg 		continue;
4161debfc3dSmrg 
4171debfc3dSmrg 	      /* If the function is const, it reads no memory even if it
4181debfc3dSmrg 		 seems so to local analysis.  */
4191debfc3dSmrg 	      if (flags & ECF_CONST)
4201debfc3dSmrg 		continue;
4211debfc3dSmrg 
4221debfc3dSmrg 	      union_static_var_sets (x_global->statics_read,
4231debfc3dSmrg 				     y_global->statics_read);
4241debfc3dSmrg 
4251debfc3dSmrg 	      /* If the function is pure, it has no stores even if it
4261debfc3dSmrg 		 seems so to local analysis.  If we cannot return from
4271debfc3dSmrg 		 the function, we can safely ignore the call.  */
4281debfc3dSmrg 	      if ((flags & ECF_PURE)
4291debfc3dSmrg 		  || e->cannot_lead_to_return_p ())
4301debfc3dSmrg 		continue;
4311debfc3dSmrg 
4321debfc3dSmrg 	      union_static_var_sets (x_global->statics_written,
4331debfc3dSmrg 				     y_global->statics_written);
4341debfc3dSmrg 	    }
4351debfc3dSmrg 	  else
4361debfc3dSmrg 	    gcc_unreachable ();
4371debfc3dSmrg 	}
4381debfc3dSmrg     }
4391debfc3dSmrg }
4401debfc3dSmrg 
441*8feb0f0bSmrg /* Delete NODE from map.  */
442*8feb0f0bSmrg 
443*8feb0f0bSmrg static void
varpool_removal_hook(varpool_node * node,void *)444*8feb0f0bSmrg varpool_removal_hook (varpool_node *node, void *)
445*8feb0f0bSmrg {
446*8feb0f0bSmrg   ipa_reference_vars_map->remove (node->decl);
447*8feb0f0bSmrg }
448*8feb0f0bSmrg 
4491debfc3dSmrg static bool ipa_init_p = false;
4501debfc3dSmrg 
4511debfc3dSmrg /* The init routine for analyzing global static variable usage.  See
4521debfc3dSmrg    comments at top for description.  */
4531debfc3dSmrg static void
ipa_init(void)4541debfc3dSmrg ipa_init (void)
4551debfc3dSmrg {
4561debfc3dSmrg   if (ipa_init_p)
4571debfc3dSmrg     return;
4581debfc3dSmrg 
4591debfc3dSmrg   ipa_init_p = true;
4601debfc3dSmrg 
461*8feb0f0bSmrg   vec_alloc (reference_vars_to_consider, 10);
4621debfc3dSmrg 
463c0a68be4Smrg 
464c0a68be4Smrg   if (ipa_ref_opt_sum_summaries != NULL)
465c0a68be4Smrg     {
466c0a68be4Smrg       delete ipa_ref_opt_sum_summaries;
467c0a68be4Smrg       ipa_ref_opt_sum_summaries = NULL;
468*8feb0f0bSmrg       delete ipa_reference_vars_map;
469c0a68be4Smrg     }
470*8feb0f0bSmrg   ipa_reference_vars_map = new reference_vars_map_t(257);
471*8feb0f0bSmrg   varpool_node_hooks
472*8feb0f0bSmrg 	 = symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
473*8feb0f0bSmrg   ipa_reference_vars_uids = 0;
474*8feb0f0bSmrg 
475*8feb0f0bSmrg   bitmap_obstack_initialize (&local_info_obstack);
476*8feb0f0bSmrg   bitmap_obstack_initialize (&optimization_summary_obstack);
477*8feb0f0bSmrg   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
478*8feb0f0bSmrg   no_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
479*8feb0f0bSmrg   ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
480*8feb0f0bSmrg 
481*8feb0f0bSmrg   if (ipa_ref_var_info_summaries == NULL)
482*8feb0f0bSmrg     ipa_ref_var_info_summaries = new ipa_ref_var_info_summary_t (symtab);
4831debfc3dSmrg }
4841debfc3dSmrg 
4851debfc3dSmrg 
4861debfc3dSmrg /* Set up the persistent info for FN.  */
4871debfc3dSmrg 
4881debfc3dSmrg static ipa_reference_local_vars_info_t
init_function_info(struct cgraph_node * fn)4891debfc3dSmrg init_function_info (struct cgraph_node *fn)
4901debfc3dSmrg {
4911debfc3dSmrg   ipa_reference_vars_info_t info
492c0a68be4Smrg     = ipa_ref_var_info_summaries->get_create (fn);
4931debfc3dSmrg 
4941debfc3dSmrg   info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
4951debfc3dSmrg   info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
496*8feb0f0bSmrg   info->global.statics_read = NULL;
4971debfc3dSmrg 
4981debfc3dSmrg   return &info->local;
4991debfc3dSmrg }
5001debfc3dSmrg 
5011debfc3dSmrg 
5021debfc3dSmrg /* This is the main routine for finding the reference patterns for
5031debfc3dSmrg    global variables within a function FN.  */
5041debfc3dSmrg 
5051debfc3dSmrg static void
analyze_function(struct cgraph_node * fn)5061debfc3dSmrg analyze_function (struct cgraph_node *fn)
5071debfc3dSmrg {
5081debfc3dSmrg   ipa_reference_local_vars_info_t local;
5091debfc3dSmrg   struct ipa_ref *ref = NULL;
5101debfc3dSmrg   int i;
5111debfc3dSmrg   tree var;
5121debfc3dSmrg 
5131debfc3dSmrg   if (!opt_for_fn (fn->decl, flag_ipa_reference))
5141debfc3dSmrg     return;
5151debfc3dSmrg   local = init_function_info (fn);
5161debfc3dSmrg   for (i = 0; fn->iterate_reference (i, ref); i++)
5171debfc3dSmrg     {
518*8feb0f0bSmrg       int id;
519*8feb0f0bSmrg       bool existed;
5201debfc3dSmrg       if (!is_a <varpool_node *> (ref->referred))
5211debfc3dSmrg 	continue;
5221debfc3dSmrg       var = ref->referred->decl;
5231debfc3dSmrg       if (!is_proper_for_analysis (var))
5241debfc3dSmrg 	continue;
5251debfc3dSmrg       /* This is a variable we care about.  Check if we have seen it
5261debfc3dSmrg 	 before, and if not add it the set of variables we care about.  */
527*8feb0f0bSmrg       id = ipa_reference_var_get_or_insert_uid (var, &existed);
528*8feb0f0bSmrg       if (!existed)
5291debfc3dSmrg 	{
530*8feb0f0bSmrg 	  bitmap_set_bit (all_module_statics, id);
5311debfc3dSmrg 	  if (dump_file)
532*8feb0f0bSmrg 	    reference_vars_to_consider->safe_push (var);
5331debfc3dSmrg 	}
5341debfc3dSmrg       switch (ref->use)
5351debfc3dSmrg 	{
5361debfc3dSmrg 	case IPA_REF_LOAD:
537*8feb0f0bSmrg           bitmap_set_bit (local->statics_read, id);
5381debfc3dSmrg 	  break;
5391debfc3dSmrg 	case IPA_REF_STORE:
5401debfc3dSmrg 	  if (ref->cannot_lead_to_return ())
5411debfc3dSmrg 	    break;
542*8feb0f0bSmrg           bitmap_set_bit (local->statics_written, id);
5431debfc3dSmrg 	  break;
5441debfc3dSmrg 	case IPA_REF_ADDR:
5451debfc3dSmrg 	  break;
5461debfc3dSmrg 	default:
5471debfc3dSmrg 	  gcc_unreachable ();
5481debfc3dSmrg 	}
5491debfc3dSmrg     }
5501debfc3dSmrg 
5511debfc3dSmrg   if (fn->cannot_return_p ())
5521debfc3dSmrg     bitmap_clear (local->statics_written);
5531debfc3dSmrg }
5541debfc3dSmrg 
5551debfc3dSmrg 
5561debfc3dSmrg /* Called when new clone is inserted to callgraph late.  */
5571debfc3dSmrg 
558c0a68be4Smrg void
duplicate(cgraph_node *,cgraph_node *,ipa_reference_optimization_summary_d * ginfo,ipa_reference_optimization_summary_d * dst_ginfo)559c0a68be4Smrg ipa_ref_opt_summary_t::duplicate (cgraph_node *, cgraph_node *,
560c0a68be4Smrg 				  ipa_reference_optimization_summary_d *ginfo,
561c0a68be4Smrg 				  ipa_reference_optimization_summary_d
562c0a68be4Smrg 				  *dst_ginfo)
5631debfc3dSmrg {
564*8feb0f0bSmrg   dst_ginfo->statics_read =
565*8feb0f0bSmrg     copy_static_var_set (ginfo->statics_read, false);
566*8feb0f0bSmrg   dst_ginfo->statics_written =
567*8feb0f0bSmrg     copy_static_var_set (ginfo->statics_written, false);
5681debfc3dSmrg }
5691debfc3dSmrg 
5701debfc3dSmrg /* Called when node is removed.  */
5711debfc3dSmrg 
572c0a68be4Smrg void
remove(cgraph_node *,ipa_reference_optimization_summary_d * ginfo)573c0a68be4Smrg ipa_ref_opt_summary_t::remove (cgraph_node *,
574c0a68be4Smrg 			       ipa_reference_optimization_summary_d *ginfo)
5751debfc3dSmrg {
576*8feb0f0bSmrg   if (ginfo->statics_read
577*8feb0f0bSmrg       && ginfo->statics_read != all_module_statics
578*8feb0f0bSmrg       && ginfo->statics_read != no_module_statics)
579*8feb0f0bSmrg     BITMAP_FREE (ginfo->statics_read);
5801debfc3dSmrg 
581*8feb0f0bSmrg   if (ginfo->statics_written
582*8feb0f0bSmrg       && ginfo->statics_written != all_module_statics
583*8feb0f0bSmrg       && ginfo->statics_written != no_module_statics)
584*8feb0f0bSmrg     BITMAP_FREE (ginfo->statics_written);
5851debfc3dSmrg }
5861debfc3dSmrg 
5871debfc3dSmrg /* Analyze each function in the cgraph to see which global or statics
5881debfc3dSmrg    are read or written.  */
5891debfc3dSmrg 
5901debfc3dSmrg static void
generate_summary(void)5911debfc3dSmrg generate_summary (void)
5921debfc3dSmrg {
5931debfc3dSmrg   struct cgraph_node *node;
5941debfc3dSmrg   unsigned int index;
5951debfc3dSmrg   bitmap_iterator bi;
5961debfc3dSmrg 
5971debfc3dSmrg   ipa_init ();
5981debfc3dSmrg 
5991debfc3dSmrg   /* Process all of the functions next.  */
6001debfc3dSmrg   FOR_EACH_DEFINED_FUNCTION (node)
6011debfc3dSmrg     if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
6021debfc3dSmrg       {
6031debfc3dSmrg         struct ipa_ref *ref = NULL;
6041debfc3dSmrg         int i;
6051debfc3dSmrg         tree var;
6061debfc3dSmrg 	for (i = 0; node->iterate_reference (i, ref); i++)
6071debfc3dSmrg 	  {
6081debfc3dSmrg 	    if (!is_a <varpool_node *> (ref->referred))
6091debfc3dSmrg 	      continue;
6101debfc3dSmrg 	    var = ref->referred->decl;
6111debfc3dSmrg 	    if (!is_proper_for_analysis (var))
6121debfc3dSmrg 	      continue;
6131debfc3dSmrg 	    bitmap_set_bit (ignore_module_statics, ipa_reference_var_uid (var));
6141debfc3dSmrg 	  }
6151debfc3dSmrg       }
6161debfc3dSmrg   FOR_EACH_DEFINED_FUNCTION (node)
6171debfc3dSmrg     analyze_function (node);
6181debfc3dSmrg 
6191debfc3dSmrg   if (dump_file)
6201debfc3dSmrg     EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
6211debfc3dSmrg       {
6221debfc3dSmrg 	fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
6231debfc3dSmrg 		 get_static_name (index), index);
6241debfc3dSmrg       }
6251debfc3dSmrg 
6261debfc3dSmrg   if (dump_file)
6271debfc3dSmrg     FOR_EACH_DEFINED_FUNCTION (node)
6281debfc3dSmrg       if (node->get_availability () >= AVAIL_INTERPOSABLE
6291debfc3dSmrg 	  && opt_for_fn (node->decl, flag_ipa_reference))
6301debfc3dSmrg 	{
6311debfc3dSmrg 	  ipa_reference_local_vars_info_t l;
6321debfc3dSmrg 	  unsigned int index;
6331debfc3dSmrg 	  bitmap_iterator bi;
6341debfc3dSmrg 
6351debfc3dSmrg 	  l = &get_reference_vars_info (node)->local;
6361debfc3dSmrg 	  fprintf (dump_file,
637a2dc1f3fSmrg 		   "\nFunction name:%s:", node->dump_name ());
6381debfc3dSmrg 	  fprintf (dump_file, "\n  locals read: ");
6391debfc3dSmrg 	  if (l->statics_read)
6401debfc3dSmrg 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
6411debfc3dSmrg 				      0, index, bi)
6421debfc3dSmrg 	      {
6431debfc3dSmrg 	        fprintf (dump_file, "%s ",
6441debfc3dSmrg 		         get_static_name (index));
6451debfc3dSmrg 	      }
6461debfc3dSmrg 	  fprintf (dump_file, "\n  locals written: ");
6471debfc3dSmrg 	  if (l->statics_written)
6481debfc3dSmrg 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
6491debfc3dSmrg 				      0, index, bi)
6501debfc3dSmrg 	      {
6511debfc3dSmrg 	        fprintf (dump_file, "%s ", get_static_name (index));
6521debfc3dSmrg 	      }
6531debfc3dSmrg 	}
6541debfc3dSmrg }
6551debfc3dSmrg 
6561debfc3dSmrg /* Set READ_ALL/WRITE_ALL based on decl flags of NODE.  */
6571debfc3dSmrg 
6581debfc3dSmrg static void
read_write_all_from_decl(struct cgraph_node * node,bool & read_all,bool & write_all)6591debfc3dSmrg read_write_all_from_decl (struct cgraph_node *node,
6601debfc3dSmrg 			  bool &read_all, bool &write_all)
6611debfc3dSmrg {
6621debfc3dSmrg   tree decl = node->decl;
6631debfc3dSmrg   int flags = flags_from_decl_or_type (decl);
6641debfc3dSmrg   if ((flags & ECF_LEAF)
6651debfc3dSmrg       && node->get_availability () < AVAIL_INTERPOSABLE)
6661debfc3dSmrg     ;
6671debfc3dSmrg   else if (flags & ECF_CONST)
6681debfc3dSmrg     ;
6691debfc3dSmrg   else if ((flags & ECF_PURE) || node->cannot_return_p ())
6701debfc3dSmrg     {
6711debfc3dSmrg       read_all = true;
6721debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
673a2dc1f3fSmrg 	fprintf (dump_file, "   %s -> read all\n", node->dump_name ());
6741debfc3dSmrg     }
6751debfc3dSmrg   else
6761debfc3dSmrg     {
6771debfc3dSmrg        /* TODO: To be able to produce sane results, we should also handle
6781debfc3dSmrg 	  common builtins, in particular throw.  */
6791debfc3dSmrg       read_all = true;
6801debfc3dSmrg       write_all = true;
6811debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
682a2dc1f3fSmrg 	fprintf (dump_file, "   %s -> read all, write all\n",
683a2dc1f3fSmrg 		  node->dump_name ());
6841debfc3dSmrg     }
6851debfc3dSmrg }
6861debfc3dSmrg 
6871debfc3dSmrg /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
6881debfc3dSmrg    in the cycle of NODE.  */
6891debfc3dSmrg 
6901debfc3dSmrg static void
get_read_write_all_from_node(struct cgraph_node * node,bool & read_all,bool & write_all)6911debfc3dSmrg get_read_write_all_from_node (struct cgraph_node *node,
6921debfc3dSmrg 			      bool &read_all, bool &write_all)
6931debfc3dSmrg {
6941debfc3dSmrg   struct cgraph_edge *e, *ie;
6951debfc3dSmrg 
6961debfc3dSmrg   /* When function is overwritable, we cannot assume anything.  */
6971debfc3dSmrg   if (node->get_availability () <= AVAIL_INTERPOSABLE
6981debfc3dSmrg       || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
6991debfc3dSmrg     read_write_all_from_decl (node, read_all, write_all);
7001debfc3dSmrg 
7011debfc3dSmrg   for (e = node->callees;
7021debfc3dSmrg        e && !(read_all && write_all);
7031debfc3dSmrg        e = e->next_callee)
7041debfc3dSmrg     {
7051debfc3dSmrg       enum availability avail;
7061debfc3dSmrg       struct cgraph_node *callee = e->callee->function_symbol (&avail);
7071debfc3dSmrg       gcc_checking_assert (callee);
7081debfc3dSmrg       if (avail <= AVAIL_INTERPOSABLE
709c0a68be4Smrg 	  || (callee->analyzed && !opt_for_fn (callee->decl,
710c0a68be4Smrg 					       flag_ipa_reference)))
7111debfc3dSmrg 	read_write_all_from_decl (callee, read_all, write_all);
7121debfc3dSmrg     }
7131debfc3dSmrg 
7141debfc3dSmrg   for (ie = node->indirect_calls;
7151debfc3dSmrg        ie && !(read_all && write_all);
7161debfc3dSmrg        ie = ie->next_callee)
7171debfc3dSmrg     if (!(ie->indirect_info->ecf_flags & ECF_CONST))
7181debfc3dSmrg       {
7191debfc3dSmrg 	read_all = true;
7201debfc3dSmrg 	if (dump_file && (dump_flags & TDF_DETAILS))
7211debfc3dSmrg 	  fprintf (dump_file, "   indirect call -> read all\n");
7221debfc3dSmrg 	if (!ie->cannot_lead_to_return_p ()
7231debfc3dSmrg 	    && !(ie->indirect_info->ecf_flags & ECF_PURE))
7241debfc3dSmrg 	  {
7251debfc3dSmrg 	    if (dump_file && (dump_flags & TDF_DETAILS))
7261debfc3dSmrg 	      fprintf (dump_file, "   indirect call -> write all\n");
7271debfc3dSmrg 	    write_all = true;
7281debfc3dSmrg 	  }
7291debfc3dSmrg       }
7301debfc3dSmrg }
7311debfc3dSmrg 
732*8feb0f0bSmrg /* Skip edges from and to nodes without ipa_reference enabled.
733*8feb0f0bSmrg    Ignore not available symbols.  This leave
734*8feb0f0bSmrg    them out of strongly connected components and makes them easy to skip in the
7351debfc3dSmrg    propagation loop bellow.  */
7361debfc3dSmrg 
7371debfc3dSmrg static bool
ignore_edge_p(cgraph_edge * e)7381debfc3dSmrg ignore_edge_p (cgraph_edge *e)
7391debfc3dSmrg {
740*8feb0f0bSmrg   enum availability avail;
741*8feb0f0bSmrg   cgraph_node *ultimate_target
742*8feb0f0bSmrg     = e->callee->function_or_virtual_thunk_symbol (&avail, e->caller);
743*8feb0f0bSmrg 
744*8feb0f0bSmrg   return (avail < AVAIL_INTERPOSABLE
745*8feb0f0bSmrg 	  || (avail == AVAIL_INTERPOSABLE
746*8feb0f0bSmrg 	      && !(flags_from_decl_or_type (e->callee->decl) & ECF_LEAF))
747*8feb0f0bSmrg 	  || !opt_for_fn (e->caller->decl, flag_ipa_reference)
748*8feb0f0bSmrg           || !opt_for_fn (ultimate_target->decl, flag_ipa_reference));
7491debfc3dSmrg }
7501debfc3dSmrg 
7511debfc3dSmrg /* Produce the global information by preforming a transitive closure
7521debfc3dSmrg    on the local information that was produced by ipa_analyze_function.  */
7531debfc3dSmrg 
7541debfc3dSmrg static unsigned int
propagate(void)7551debfc3dSmrg propagate (void)
7561debfc3dSmrg {
7571debfc3dSmrg   struct cgraph_node *node;
7581debfc3dSmrg   struct cgraph_node **order =
7591debfc3dSmrg     XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
7601debfc3dSmrg   int order_pos;
7611debfc3dSmrg   int i;
7621debfc3dSmrg   bool remove_p;
7631debfc3dSmrg 
7641debfc3dSmrg   if (dump_file)
7651debfc3dSmrg     cgraph_node::dump_cgraph (dump_file);
7661debfc3dSmrg 
767c0a68be4Smrg   remove_p = ipa_discover_variable_flags ();
7681debfc3dSmrg   generate_summary ();
7691debfc3dSmrg 
7701debfc3dSmrg   /* Propagate the local information through the call graph to produce
7711debfc3dSmrg      the global information.  All the nodes within a cycle will have
7721debfc3dSmrg      the same info so we collapse cycles first.  Then we can do the
7731debfc3dSmrg      propagation in one pass from the leaves to the roots.  */
774a05ac97eSmrg   order_pos = ipa_reduced_postorder (order, true, ignore_edge_p);
7751debfc3dSmrg   if (dump_file)
7761debfc3dSmrg     ipa_print_order (dump_file, "reduced", order, order_pos);
7771debfc3dSmrg 
7781debfc3dSmrg   for (i = 0; i < order_pos; i++ )
7791debfc3dSmrg     {
7801debfc3dSmrg       unsigned x;
7811debfc3dSmrg       struct cgraph_node *w;
7821debfc3dSmrg       ipa_reference_vars_info_t node_info;
7831debfc3dSmrg       ipa_reference_global_vars_info_t node_g;
7841debfc3dSmrg       ipa_reference_local_vars_info_t node_l;
7851debfc3dSmrg       bool read_all = false;
7861debfc3dSmrg       bool write_all = false;
7871debfc3dSmrg 
7881debfc3dSmrg       node = order[i];
7891debfc3dSmrg       if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
7901debfc3dSmrg 	continue;
7911debfc3dSmrg 
7921debfc3dSmrg       node_info = get_reference_vars_info (node);
7931debfc3dSmrg       gcc_assert (node_info);
7941debfc3dSmrg       node_l = &node_info->local;
7951debfc3dSmrg       node_g = &node_info->global;
7961debfc3dSmrg 
7971debfc3dSmrg       if (dump_file && (dump_flags & TDF_DETAILS))
798a2dc1f3fSmrg 	fprintf (dump_file, "Starting cycle with %s\n", node->dump_name ());
7991debfc3dSmrg 
8001debfc3dSmrg       vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
8011debfc3dSmrg 
8021debfc3dSmrg       /* If any node in a cycle is read_all or write_all, they all are.  */
8031debfc3dSmrg       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
8041debfc3dSmrg 	{
8051debfc3dSmrg 	  if (dump_file && (dump_flags & TDF_DETAILS))
806a2dc1f3fSmrg 	    fprintf (dump_file, "  Visiting %s\n", w->dump_asm_name ());
8071debfc3dSmrg 	  get_read_write_all_from_node (w, read_all, write_all);
8081debfc3dSmrg 	  if (read_all && write_all)
8091debfc3dSmrg 	    break;
8101debfc3dSmrg 	}
8111debfc3dSmrg 
8121debfc3dSmrg       /* Initialized the bitmaps global sets for the reduced node.  */
8131debfc3dSmrg       if (read_all)
8141debfc3dSmrg 	node_g->statics_read = all_module_statics;
8151debfc3dSmrg       else
816*8feb0f0bSmrg 	node_g->statics_read = copy_static_var_set (node_l->statics_read, true);
8171debfc3dSmrg       if (write_all)
8181debfc3dSmrg 	node_g->statics_written = all_module_statics;
8191debfc3dSmrg       else
820*8feb0f0bSmrg 	node_g->statics_written
821*8feb0f0bSmrg 	  = copy_static_var_set (node_l->statics_written, true);
8221debfc3dSmrg 
8231debfc3dSmrg       /* Merge the sets of this cycle with all sets of callees reached
8241debfc3dSmrg          from this cycle.  */
8251debfc3dSmrg       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
8261debfc3dSmrg 	{
8271debfc3dSmrg 	  if (read_all && write_all)
8281debfc3dSmrg 	    break;
8291debfc3dSmrg 
8301debfc3dSmrg 	  if (w != node)
8311debfc3dSmrg 	    {
8321debfc3dSmrg 	      ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
8331debfc3dSmrg 	      ipa_reference_local_vars_info_t w_l = &w_ri->local;
8341debfc3dSmrg 	      int flags = flags_from_decl_or_type (w->decl);
8351debfc3dSmrg 
8361debfc3dSmrg 	      if (!(flags & ECF_CONST))
8371debfc3dSmrg 		read_all = union_static_var_sets (node_g->statics_read,
8381debfc3dSmrg 						  w_l->statics_read);
8391debfc3dSmrg 	      if (!(flags & ECF_PURE)
8401debfc3dSmrg 		  && !w->cannot_return_p ())
8411debfc3dSmrg 		write_all = union_static_var_sets (node_g->statics_written,
8421debfc3dSmrg 						   w_l->statics_written);
8431debfc3dSmrg 	    }
8441debfc3dSmrg 
8451debfc3dSmrg 	  propagate_bits (node_g, w);
8461debfc3dSmrg 	}
8471debfc3dSmrg 
8481debfc3dSmrg       /* All nodes within a cycle have the same global info bitmaps.  */
8491debfc3dSmrg       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
8501debfc3dSmrg 	{
8511debfc3dSmrg 	  ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
8521debfc3dSmrg           w_ri->global = *node_g;
8531debfc3dSmrg 	}
8541debfc3dSmrg 
8551debfc3dSmrg       cycle_nodes.release ();
8561debfc3dSmrg     }
8571debfc3dSmrg 
8581debfc3dSmrg   if (dump_file)
8591debfc3dSmrg     {
8601debfc3dSmrg       for (i = 0; i < order_pos; i++)
8611debfc3dSmrg 	{
8621debfc3dSmrg 	  unsigned x;
8631debfc3dSmrg 	  struct cgraph_node *w;
8641debfc3dSmrg 
8651debfc3dSmrg 	  node = order[i];
8661debfc3dSmrg           if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
8671debfc3dSmrg 	    continue;
8681debfc3dSmrg 
869a2dc1f3fSmrg 	  fprintf (dump_file, "\nFunction name:%s:", node->dump_asm_name ());
8701debfc3dSmrg 
8711debfc3dSmrg 	  ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
8721debfc3dSmrg 	  ipa_reference_global_vars_info_t node_g = &node_info->global;
8731debfc3dSmrg 
8741debfc3dSmrg 	  vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
8751debfc3dSmrg 	  FOR_EACH_VEC_ELT (cycle_nodes, x, w)
8761debfc3dSmrg 	    {
8771debfc3dSmrg 	      ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
8781debfc3dSmrg 	      ipa_reference_local_vars_info_t w_l = &w_ri->local;
8791debfc3dSmrg 	      if (w != node)
880a2dc1f3fSmrg 		fprintf (dump_file, "\n  next cycle: %s ", w->dump_asm_name ());
8811debfc3dSmrg 	      fprintf (dump_file, "\n    locals read: ");
8821debfc3dSmrg 	      dump_static_vars_set_to_file (dump_file, w_l->statics_read);
8831debfc3dSmrg 	      fprintf (dump_file, "\n    locals written: ");
8841debfc3dSmrg 	      dump_static_vars_set_to_file (dump_file, w_l->statics_written);
8851debfc3dSmrg 	    }
8861debfc3dSmrg 	  cycle_nodes.release ();
8871debfc3dSmrg 
8881debfc3dSmrg 	  fprintf (dump_file, "\n  globals read: ");
8891debfc3dSmrg 	  dump_static_vars_set_to_file (dump_file, node_g->statics_read);
8901debfc3dSmrg 	  fprintf (dump_file, "\n  globals written: ");
8911debfc3dSmrg 	  dump_static_vars_set_to_file (dump_file, node_g->statics_written);
8921debfc3dSmrg 	  fprintf (dump_file, "\n");
8931debfc3dSmrg 	}
8941debfc3dSmrg     }
8951debfc3dSmrg 
896c0a68be4Smrg   if (ipa_ref_opt_sum_summaries == NULL)
897c0a68be4Smrg     ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
898c0a68be4Smrg 
8991debfc3dSmrg   /* Cleanup. */
9001debfc3dSmrg   FOR_EACH_DEFINED_FUNCTION (node)
9011debfc3dSmrg     {
9021debfc3dSmrg       ipa_reference_vars_info_t node_info;
9031debfc3dSmrg       ipa_reference_global_vars_info_t node_g;
9041debfc3dSmrg 
905*8feb0f0bSmrg       /* No need to produce summaries for inline clones.  */
906*8feb0f0bSmrg       if (node->inlined_to)
907*8feb0f0bSmrg 	continue;
908*8feb0f0bSmrg 
9091debfc3dSmrg       node_info = get_reference_vars_info (node);
910*8feb0f0bSmrg       if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference))
9111debfc3dSmrg 	{
9121debfc3dSmrg 	  node_g = &node_info->global;
913*8feb0f0bSmrg 	  bool read_all =
914*8feb0f0bSmrg 		(node_g->statics_read == all_module_statics
915*8feb0f0bSmrg 		 || bitmap_equal_p (node_g->statics_read, all_module_statics));
916*8feb0f0bSmrg 	  bool written_all =
917*8feb0f0bSmrg 		(node_g->statics_written == all_module_statics
918*8feb0f0bSmrg 		 || bitmap_equal_p (node_g->statics_written,
919*8feb0f0bSmrg 				    all_module_statics));
920*8feb0f0bSmrg 
921*8feb0f0bSmrg 	  /* There is no need to produce summary if we collected nothing
922*8feb0f0bSmrg 	     useful.  */
923*8feb0f0bSmrg 	  if (read_all && written_all)
924*8feb0f0bSmrg 	    continue;
9251debfc3dSmrg 
926c0a68be4Smrg 	  ipa_reference_optimization_summary_d *opt
927c0a68be4Smrg 	    = ipa_ref_opt_sum_summaries->get_create (node);
9281debfc3dSmrg 
9291debfc3dSmrg 	  /* Create the complimentary sets.  */
9301debfc3dSmrg 
9311debfc3dSmrg 	  if (bitmap_empty_p (node_g->statics_read))
932*8feb0f0bSmrg 	    opt->statics_read = no_module_statics;
933*8feb0f0bSmrg 	  else if (read_all)
934*8feb0f0bSmrg 	    opt->statics_read = all_module_statics;
9351debfc3dSmrg 	  else
9361debfc3dSmrg 	    {
937*8feb0f0bSmrg 	      opt->statics_read
9381debfc3dSmrg 		 = BITMAP_ALLOC (&optimization_summary_obstack);
939*8feb0f0bSmrg 	      bitmap_copy (opt->statics_read, node_g->statics_read);
9401debfc3dSmrg 	    }
9411debfc3dSmrg 
9421debfc3dSmrg 	  if (bitmap_empty_p (node_g->statics_written))
943*8feb0f0bSmrg 	    opt->statics_written = no_module_statics;
944*8feb0f0bSmrg 	  else if (written_all)
945*8feb0f0bSmrg 	    opt->statics_written = all_module_statics;
9461debfc3dSmrg 	  else
9471debfc3dSmrg 	    {
948*8feb0f0bSmrg 	      opt->statics_written
9491debfc3dSmrg 	        = BITMAP_ALLOC (&optimization_summary_obstack);
950*8feb0f0bSmrg 	      bitmap_copy (opt->statics_written, node_g->statics_written);
9511debfc3dSmrg 	    }
9521debfc3dSmrg 	}
9531debfc3dSmrg    }
9541debfc3dSmrg 
9551debfc3dSmrg   ipa_free_postorder_info ();
9561debfc3dSmrg   free (order);
9571debfc3dSmrg 
9581debfc3dSmrg   bitmap_obstack_release (&local_info_obstack);
959c0a68be4Smrg 
960*8feb0f0bSmrg   if (ipa_ref_var_info_summaries != NULL)
961c0a68be4Smrg     {
962c0a68be4Smrg       delete ipa_ref_var_info_summaries;
963c0a68be4Smrg       ipa_ref_var_info_summaries = NULL;
964c0a68be4Smrg     }
965c0a68be4Smrg 
9661debfc3dSmrg   if (dump_file)
967*8feb0f0bSmrg     vec_free (reference_vars_to_consider);
9681debfc3dSmrg   reference_vars_to_consider = NULL;
9691debfc3dSmrg   return remove_p ? TODO_remove_functions : 0;
9701debfc3dSmrg }
9711debfc3dSmrg 
9721debfc3dSmrg /* Return true if we need to write summary of NODE. */
9731debfc3dSmrg 
9741debfc3dSmrg static bool
write_node_summary_p(struct cgraph_node * node,lto_symtab_encoder_t encoder,bitmap ltrans_statics)9751debfc3dSmrg write_node_summary_p (struct cgraph_node *node,
9761debfc3dSmrg 		      lto_symtab_encoder_t encoder,
9771debfc3dSmrg 		      bitmap ltrans_statics)
9781debfc3dSmrg {
9791debfc3dSmrg   ipa_reference_optimization_summary_t info;
9801debfc3dSmrg 
9811debfc3dSmrg   /* See if we have (non-empty) info.  */
982*8feb0f0bSmrg   if (!node->definition || node->inlined_to)
9831debfc3dSmrg     return false;
9841debfc3dSmrg   info = get_reference_optimization_summary (node);
985*8feb0f0bSmrg   if (!info)
9861debfc3dSmrg     return false;
9871debfc3dSmrg 
9881debfc3dSmrg   /* See if we want to encode it.
9891debfc3dSmrg      Encode also referenced functions since constant folding might turn it into
9901debfc3dSmrg      a direct call.
9911debfc3dSmrg 
9921debfc3dSmrg      In future we might also want to include summaries of functions references
9931debfc3dSmrg      by initializers of constant variables references in current unit.  */
9941debfc3dSmrg   if (!reachable_from_this_partition_p (node, encoder)
9951debfc3dSmrg       && !referenced_from_this_partition_p (node, encoder))
9961debfc3dSmrg     return false;
9971debfc3dSmrg 
998*8feb0f0bSmrg   /* See if the info has non-empty intersections with vars we want to
999*8feb0f0bSmrg      encode.  */
1000*8feb0f0bSmrg   bitmap_iterator bi;
1001*8feb0f0bSmrg   unsigned int i;
1002*8feb0f0bSmrg   EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics, info->statics_read, 0,
1003*8feb0f0bSmrg 				  i, bi)
10041debfc3dSmrg     return true;
1005*8feb0f0bSmrg   EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics, info->statics_written, 0,
1006*8feb0f0bSmrg 				  i, bi)
1007*8feb0f0bSmrg     return true;
1008*8feb0f0bSmrg   return false;
10091debfc3dSmrg }
10101debfc3dSmrg 
10111debfc3dSmrg /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
10121debfc3dSmrg    LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
10131debfc3dSmrg    or -1.  When it is positive, just output -1 when
10141debfc3dSmrg    BITS&LTRANS_STATICS == BITS&LTRANS_STATICS.  */
10151debfc3dSmrg 
10161debfc3dSmrg static void
stream_out_bitmap(struct lto_simple_output_block * ob,bitmap bits,bitmap ltrans_statics,int ltrans_statics_bitcount)10171debfc3dSmrg stream_out_bitmap (struct lto_simple_output_block *ob,
10181debfc3dSmrg 		   bitmap bits, bitmap ltrans_statics,
10191debfc3dSmrg 		   int ltrans_statics_bitcount)
10201debfc3dSmrg {
10211debfc3dSmrg   int count = 0;
10221debfc3dSmrg   unsigned int index;
10231debfc3dSmrg   bitmap_iterator bi;
10241debfc3dSmrg   if (bits == all_module_statics)
10251debfc3dSmrg     {
10261debfc3dSmrg       streamer_write_hwi_stream (ob->main_stream, -1);
10271debfc3dSmrg       return;
10281debfc3dSmrg     }
10291debfc3dSmrg   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
10301debfc3dSmrg     count ++;
10311debfc3dSmrg   if (count == ltrans_statics_bitcount)
10321debfc3dSmrg     {
10331debfc3dSmrg       streamer_write_hwi_stream (ob->main_stream, -1);
10341debfc3dSmrg       return;
10351debfc3dSmrg     }
10361debfc3dSmrg   streamer_write_hwi_stream (ob->main_stream, count);
10371debfc3dSmrg   if (!count)
10381debfc3dSmrg     return;
10391debfc3dSmrg   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
10401debfc3dSmrg     {
1041*8feb0f0bSmrg       tree decl = (*reference_vars_to_consider) [index];
10421debfc3dSmrg       lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
10431debfc3dSmrg     }
10441debfc3dSmrg }
10451debfc3dSmrg 
10461debfc3dSmrg /* Serialize the ipa info for lto.  */
10471debfc3dSmrg 
10481debfc3dSmrg static void
ipa_reference_write_optimization_summary(void)10491debfc3dSmrg ipa_reference_write_optimization_summary (void)
10501debfc3dSmrg {
10511debfc3dSmrg   struct lto_simple_output_block *ob
10521debfc3dSmrg     = lto_create_simple_output_block (LTO_section_ipa_reference);
10531debfc3dSmrg   unsigned int count = 0;
10541debfc3dSmrg   int ltrans_statics_bitcount = 0;
10551debfc3dSmrg   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
1056a2dc1f3fSmrg   auto_bitmap ltrans_statics;
10571debfc3dSmrg   int i;
10581debfc3dSmrg 
1059*8feb0f0bSmrg   vec_alloc (reference_vars_to_consider, ipa_reference_vars_uids);
1060*8feb0f0bSmrg   reference_vars_to_consider->safe_grow (ipa_reference_vars_uids);
10611debfc3dSmrg 
10621debfc3dSmrg   /* See what variables we are interested in.  */
10631debfc3dSmrg   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
10641debfc3dSmrg     {
10651debfc3dSmrg       symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
10661debfc3dSmrg       varpool_node *vnode = dyn_cast <varpool_node *> (snode);
1067*8feb0f0bSmrg       int id;
1068*8feb0f0bSmrg 
10691debfc3dSmrg       if (vnode
1070*8feb0f0bSmrg 	  && (id = ipa_reference_var_uid (vnode->decl)) != -1
10711debfc3dSmrg 	  && referenced_from_this_partition_p (vnode, encoder))
10721debfc3dSmrg 	{
10731debfc3dSmrg 	  tree decl = vnode->decl;
1074*8feb0f0bSmrg 	  bitmap_set_bit (ltrans_statics, id);
1075*8feb0f0bSmrg 	  (*reference_vars_to_consider)[id] = decl;
10761debfc3dSmrg 	  ltrans_statics_bitcount ++;
10771debfc3dSmrg 	}
10781debfc3dSmrg     }
10791debfc3dSmrg 
10801debfc3dSmrg 
10811debfc3dSmrg   if (ltrans_statics_bitcount)
10821debfc3dSmrg     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
10831debfc3dSmrg       {
10841debfc3dSmrg 	symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
10851debfc3dSmrg 	cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
10861debfc3dSmrg 	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
10871debfc3dSmrg 	  count++;
10881debfc3dSmrg       }
10891debfc3dSmrg 
10901debfc3dSmrg   streamer_write_uhwi_stream (ob->main_stream, count);
10911debfc3dSmrg   if (count)
10921debfc3dSmrg     stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
10931debfc3dSmrg 		       -1);
10941debfc3dSmrg 
10951debfc3dSmrg   /* Process all of the functions.  */
10961debfc3dSmrg   if (ltrans_statics_bitcount)
10971debfc3dSmrg     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
10981debfc3dSmrg       {
10991debfc3dSmrg 	symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
11001debfc3dSmrg 	cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
11011debfc3dSmrg 	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
11021debfc3dSmrg 	  {
11031debfc3dSmrg 	    ipa_reference_optimization_summary_t info;
11041debfc3dSmrg 	    int node_ref;
11051debfc3dSmrg 
11061debfc3dSmrg 	    info = get_reference_optimization_summary (cnode);
11071debfc3dSmrg 	    node_ref = lto_symtab_encoder_encode (encoder, snode);
11081debfc3dSmrg 	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
11091debfc3dSmrg 
1110*8feb0f0bSmrg 	    stream_out_bitmap (ob, info->statics_read, ltrans_statics,
11111debfc3dSmrg 			       ltrans_statics_bitcount);
1112*8feb0f0bSmrg 	    stream_out_bitmap (ob, info->statics_written, ltrans_statics,
11131debfc3dSmrg 			       ltrans_statics_bitcount);
11141debfc3dSmrg 	  }
11151debfc3dSmrg       }
11161debfc3dSmrg   lto_destroy_simple_output_block (ob);
1117*8feb0f0bSmrg   delete reference_vars_to_consider;
11181debfc3dSmrg }
11191debfc3dSmrg 
11201debfc3dSmrg /* Deserialize the ipa info for lto.  */
11211debfc3dSmrg 
11221debfc3dSmrg static void
ipa_reference_read_optimization_summary(void)11231debfc3dSmrg ipa_reference_read_optimization_summary (void)
11241debfc3dSmrg {
11251debfc3dSmrg   struct lto_file_decl_data ** file_data_vec
11261debfc3dSmrg     = lto_get_file_decl_data ();
11271debfc3dSmrg   struct lto_file_decl_data * file_data;
11281debfc3dSmrg   unsigned int j = 0;
11291debfc3dSmrg   bitmap_obstack_initialize (&optimization_summary_obstack);
11301debfc3dSmrg 
1131*8feb0f0bSmrg   gcc_checking_assert (ipa_ref_opt_sum_summaries == NULL);
1132c0a68be4Smrg   ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
1133*8feb0f0bSmrg   ipa_reference_vars_map = new reference_vars_map_t(257);
1134*8feb0f0bSmrg   varpool_node_hooks
1135*8feb0f0bSmrg 	 = symtab->add_varpool_removal_hook (varpool_removal_hook, NULL);
1136*8feb0f0bSmrg   ipa_reference_vars_uids = 0;
1137c0a68be4Smrg 
11381debfc3dSmrg   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1139*8feb0f0bSmrg   no_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
11401debfc3dSmrg 
11411debfc3dSmrg   while ((file_data = file_data_vec[j++]))
11421debfc3dSmrg     {
11431debfc3dSmrg       const char *data;
11441debfc3dSmrg       size_t len;
1145*8feb0f0bSmrg       class lto_input_block *ib
11461debfc3dSmrg 	= lto_create_simple_input_block (file_data,
11471debfc3dSmrg 					 LTO_section_ipa_reference,
11481debfc3dSmrg 					 &data, &len);
11491debfc3dSmrg       if (ib)
11501debfc3dSmrg 	{
11511debfc3dSmrg 	  unsigned int i;
11521debfc3dSmrg 	  unsigned int f_count = streamer_read_uhwi (ib);
11531debfc3dSmrg 	  int b_count;
11541debfc3dSmrg 	  if (!f_count)
11551debfc3dSmrg 	    continue;
11561debfc3dSmrg 	  b_count = streamer_read_hwi (ib);
11571debfc3dSmrg 	  if (dump_file)
11581debfc3dSmrg 	    fprintf (dump_file, "all module statics:");
11591debfc3dSmrg 	  for (i = 0; i < (unsigned int)b_count; i++)
11601debfc3dSmrg 	    {
11611debfc3dSmrg 	      unsigned int var_index = streamer_read_uhwi (ib);
11621debfc3dSmrg 	      tree v_decl = lto_file_decl_data_get_var_decl (file_data,
11631debfc3dSmrg 							     var_index);
1164*8feb0f0bSmrg 	      bool existed;
11651debfc3dSmrg 	      bitmap_set_bit (all_module_statics,
1166*8feb0f0bSmrg 			      ipa_reference_var_get_or_insert_uid
1167*8feb0f0bSmrg 				 (v_decl, &existed));
1168*8feb0f0bSmrg 	      gcc_checking_assert (!existed);
11691debfc3dSmrg 	      if (dump_file)
11701debfc3dSmrg 		fprintf (dump_file, " %s", fndecl_name (v_decl));
11711debfc3dSmrg 	    }
11721debfc3dSmrg 
11731debfc3dSmrg 	  for (i = 0; i < f_count; i++)
11741debfc3dSmrg 	    {
11751debfc3dSmrg 	      unsigned int j, index;
11761debfc3dSmrg 	      struct cgraph_node *node;
11771debfc3dSmrg 	      int v_count;
11781debfc3dSmrg 	      lto_symtab_encoder_t encoder;
11791debfc3dSmrg 
11801debfc3dSmrg 	      index = streamer_read_uhwi (ib);
11811debfc3dSmrg 	      encoder = file_data->symtab_node_encoder;
11821debfc3dSmrg 	      node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
11831debfc3dSmrg 		(encoder, index));
1184c0a68be4Smrg 
1185c0a68be4Smrg 	      ipa_reference_optimization_summary_d *info
1186c0a68be4Smrg 		= ipa_ref_opt_sum_summaries->get_create (node);
1187c0a68be4Smrg 
11881debfc3dSmrg 	      if (dump_file)
11891debfc3dSmrg 		fprintf (dump_file,
1190*8feb0f0bSmrg 			 "\nFunction name:%s:\n  static read:",
1191a2dc1f3fSmrg 			 node->dump_asm_name ());
11921debfc3dSmrg 
1193*8feb0f0bSmrg 	      /* Set the statics read.  */
11941debfc3dSmrg 	      v_count = streamer_read_hwi (ib);
11951debfc3dSmrg 	      if (v_count == -1)
11961debfc3dSmrg 		{
1197*8feb0f0bSmrg 		  info->statics_read = all_module_statics;
11981debfc3dSmrg 		  if (dump_file)
11991debfc3dSmrg 		    fprintf (dump_file, " all module statics");
12001debfc3dSmrg 		}
1201*8feb0f0bSmrg 	      else if (v_count == 0)
1202*8feb0f0bSmrg 		info->statics_read = no_module_statics;
12031debfc3dSmrg 	      else
1204*8feb0f0bSmrg 		{
1205*8feb0f0bSmrg 		  info->statics_read = BITMAP_ALLOC
1206*8feb0f0bSmrg 		    (&optimization_summary_obstack);
12071debfc3dSmrg 		  for (j = 0; j < (unsigned int)v_count; j++)
12081debfc3dSmrg 		    {
12091debfc3dSmrg 		      unsigned int var_index = streamer_read_uhwi (ib);
12101debfc3dSmrg 		      tree v_decl = lto_file_decl_data_get_var_decl (file_data,
12111debfc3dSmrg 								     var_index);
1212*8feb0f0bSmrg 		      bitmap_set_bit (info->statics_read,
12131debfc3dSmrg 				      ipa_reference_var_uid (v_decl));
12141debfc3dSmrg 		      if (dump_file)
12151debfc3dSmrg 			fprintf (dump_file, " %s", fndecl_name (v_decl));
12161debfc3dSmrg 		    }
1217*8feb0f0bSmrg 		}
12181debfc3dSmrg 
12191debfc3dSmrg 	      if (dump_file)
12201debfc3dSmrg 		fprintf (dump_file,
1221*8feb0f0bSmrg 			 "\n  static written:");
1222*8feb0f0bSmrg 	      /* Set the statics written.  */
12231debfc3dSmrg 	      v_count = streamer_read_hwi (ib);
12241debfc3dSmrg 	      if (v_count == -1)
12251debfc3dSmrg 		{
1226*8feb0f0bSmrg 		  info->statics_written = all_module_statics;
12271debfc3dSmrg 		  if (dump_file)
12281debfc3dSmrg 		    fprintf (dump_file, " all module statics");
12291debfc3dSmrg 		}
1230*8feb0f0bSmrg 	      else if (v_count == 0)
1231*8feb0f0bSmrg 		info->statics_written = no_module_statics;
12321debfc3dSmrg 	      else
1233*8feb0f0bSmrg 		{
1234*8feb0f0bSmrg 		  info->statics_written = BITMAP_ALLOC
1235*8feb0f0bSmrg 		    (&optimization_summary_obstack);
12361debfc3dSmrg 		  for (j = 0; j < (unsigned int)v_count; j++)
12371debfc3dSmrg 		    {
12381debfc3dSmrg 		      unsigned int var_index = streamer_read_uhwi (ib);
12391debfc3dSmrg 		      tree v_decl = lto_file_decl_data_get_var_decl (file_data,
12401debfc3dSmrg 								     var_index);
1241*8feb0f0bSmrg 		      bitmap_set_bit (info->statics_written,
12421debfc3dSmrg 				      ipa_reference_var_uid (v_decl));
12431debfc3dSmrg 		      if (dump_file)
12441debfc3dSmrg 			fprintf (dump_file, " %s", fndecl_name (v_decl));
12451debfc3dSmrg 		    }
1246*8feb0f0bSmrg 		}
12471debfc3dSmrg 	      if (dump_file)
12481debfc3dSmrg 		fprintf (dump_file, "\n");
12491debfc3dSmrg 	    }
12501debfc3dSmrg 
12511debfc3dSmrg 	  lto_destroy_simple_input_block (file_data,
12521debfc3dSmrg 					  LTO_section_ipa_reference,
12531debfc3dSmrg 					  ib, data, len);
12541debfc3dSmrg 	}
12551debfc3dSmrg       else
1256c0a68be4Smrg 	/* Fatal error here.  We do not want to support compiling ltrans units
1257c0a68be4Smrg 	   with different version of compiler or different flags than
1258c0a68be4Smrg 	   the WPA unit, so this should never happen.  */
12591debfc3dSmrg 	fatal_error (input_location,
12601debfc3dSmrg 		     "ipa reference summary is missing in ltrans unit");
12611debfc3dSmrg     }
12621debfc3dSmrg }
12631debfc3dSmrg 
12641debfc3dSmrg namespace {
12651debfc3dSmrg 
12661debfc3dSmrg const pass_data pass_data_ipa_reference =
12671debfc3dSmrg {
12681debfc3dSmrg   IPA_PASS, /* type */
12691debfc3dSmrg   "static-var", /* name */
12701debfc3dSmrg   OPTGROUP_NONE, /* optinfo_flags */
12711debfc3dSmrg   TV_IPA_REFERENCE, /* tv_id */
12721debfc3dSmrg   0, /* properties_required */
12731debfc3dSmrg   0, /* properties_provided */
12741debfc3dSmrg   0, /* properties_destroyed */
12751debfc3dSmrg   0, /* todo_flags_start */
12761debfc3dSmrg   0, /* todo_flags_finish */
12771debfc3dSmrg };
12781debfc3dSmrg 
12791debfc3dSmrg class pass_ipa_reference : public ipa_opt_pass_d
12801debfc3dSmrg {
12811debfc3dSmrg public:
pass_ipa_reference(gcc::context * ctxt)12821debfc3dSmrg   pass_ipa_reference (gcc::context *ctxt)
12831debfc3dSmrg     : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
12841debfc3dSmrg 		      NULL, /* generate_summary */
12851debfc3dSmrg 		      NULL, /* write_summary */
12861debfc3dSmrg 		      NULL, /* read_summary */
12871debfc3dSmrg 		      ipa_reference_write_optimization_summary, /*
12881debfc3dSmrg 		      write_optimization_summary */
12891debfc3dSmrg 		      ipa_reference_read_optimization_summary, /*
12901debfc3dSmrg 		      read_optimization_summary */
12911debfc3dSmrg 		      NULL, /* stmt_fixup */
12921debfc3dSmrg 		      0, /* function_transform_todo_flags_start */
12931debfc3dSmrg 		      NULL, /* function_transform */
12941debfc3dSmrg 		      NULL) /* variable_transform */
12951debfc3dSmrg     {}
12961debfc3dSmrg 
12971debfc3dSmrg   /* opt_pass methods: */
gate(function *)12981debfc3dSmrg   virtual bool gate (function *)
12991debfc3dSmrg     {
13001debfc3dSmrg       return ((in_lto_p || flag_ipa_reference)
13011debfc3dSmrg 	      /* Don't bother doing anything if the program has errors.  */
13021debfc3dSmrg 	      && !seen_error ());
13031debfc3dSmrg     }
13041debfc3dSmrg 
execute(function *)13051debfc3dSmrg   virtual unsigned int execute (function *) { return propagate (); }
13061debfc3dSmrg 
13071debfc3dSmrg }; // class pass_ipa_reference
13081debfc3dSmrg 
13091debfc3dSmrg } // anon namespace
13101debfc3dSmrg 
13111debfc3dSmrg ipa_opt_pass_d *
make_pass_ipa_reference(gcc::context * ctxt)13121debfc3dSmrg make_pass_ipa_reference (gcc::context *ctxt)
13131debfc3dSmrg {
13141debfc3dSmrg   return new pass_ipa_reference (ctxt);
13151debfc3dSmrg }
13161debfc3dSmrg 
13171debfc3dSmrg /* Reset all state within ipa-reference.c so that we can rerun the compiler
13181debfc3dSmrg    within the same process.  For use by toplev::finalize.  */
13191debfc3dSmrg 
13201debfc3dSmrg void
ipa_reference_c_finalize(void)13211debfc3dSmrg ipa_reference_c_finalize (void)
13221debfc3dSmrg {
1323c0a68be4Smrg   if (ipa_ref_opt_sum_summaries != NULL)
1324c0a68be4Smrg     {
1325c0a68be4Smrg       delete ipa_ref_opt_sum_summaries;
1326c0a68be4Smrg       ipa_ref_opt_sum_summaries = NULL;
1327*8feb0f0bSmrg       delete ipa_reference_vars_map;
1328*8feb0f0bSmrg       ipa_reference_vars_map = NULL;
1329*8feb0f0bSmrg       symtab->remove_varpool_removal_hook (varpool_node_hooks);
1330c0a68be4Smrg     }
1331c0a68be4Smrg 
13321debfc3dSmrg   if (ipa_init_p)
13331debfc3dSmrg     {
13341debfc3dSmrg       bitmap_obstack_release (&optimization_summary_obstack);
13351debfc3dSmrg       ipa_init_p = false;
13361debfc3dSmrg     }
13371debfc3dSmrg }
1338