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