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