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