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