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<RANS_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<RANS_STATICS == BITS<RANS_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