Daily bump.
[official-gcc.git] / gcc / ipa-reference.c
blob8ad12d30bb22c0a97b19a7c91660a20b9bd1d1df
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2019 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5 This file is part of GCC.
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.
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.
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/>. */
21 /* This file gathers information about how variables whose scope is
22 confined to the compilation unit are used.
24 The transitive call site specific clobber effects are computed
25 for the variables whose scope is contained within this compilation
26 unit.
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. */
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 "splay-tree.h"
50 #include "ipa-utils.h"
51 #include "ipa-reference.h"
52 #include "symbol-summary.h"
54 /* The static variables defined within the compilation unit that are
55 loaded or stored directly by function that owns this structure. */
57 struct ipa_reference_local_vars_info_d
59 bitmap statics_read;
60 bitmap statics_written;
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. */
68 struct ipa_reference_global_vars_info_d
70 bitmap statics_read;
71 bitmap statics_written;
74 /* Information we save about every function after ipa-reference is completed. */
76 struct ipa_reference_optimization_summary_d
78 bitmap statics_not_read;
79 bitmap statics_not_written;
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;
87 struct ipa_reference_vars_info_d
89 struct ipa_reference_local_vars_info_d local;
90 struct ipa_reference_global_vars_info_d global;
93 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
95 /* This splay tree contains all of the static variables that are
96 being considered by the compilation level alias analysis. */
97 static splay_tree reference_vars_to_consider;
99 /* Set of all interesting module statics. A bit is set for every module
100 static we are considering. This is added to the local info when asm
101 code is found that clobbers all memory. */
102 static bitmap all_module_statics;
103 /* Set of all statics that should be ignored because they are touched by
104 -fno-ipa-reference code. */
105 static bitmap ignore_module_statics;
107 /* Obstack holding bitmaps of local analysis (live from analysis to
108 propagation) */
109 static bitmap_obstack local_info_obstack;
110 /* Obstack holding global analysis live forever. */
111 static bitmap_obstack optimization_summary_obstack;
113 class ipa_ref_var_info_summary_t: public function_summary
114 <ipa_reference_vars_info_d *>
116 public:
117 ipa_ref_var_info_summary_t (symbol_table *symtab):
118 function_summary <ipa_reference_vars_info_d *> (symtab) {}
121 static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL;
123 class ipa_ref_opt_summary_t: public function_summary
124 <ipa_reference_optimization_summary_d *>
126 public:
127 ipa_ref_opt_summary_t (symbol_table *symtab):
128 function_summary <ipa_reference_optimization_summary_d *> (symtab) {}
131 virtual void remove (cgraph_node *src_node,
132 ipa_reference_optimization_summary_d *data);
133 virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
134 ipa_reference_optimization_summary_d *src_data,
135 ipa_reference_optimization_summary_d *dst_data);
138 static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL;
140 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
141 static inline ipa_reference_vars_info_t
142 get_reference_vars_info (struct cgraph_node *node)
144 if (ipa_ref_var_info_summaries == NULL)
145 return NULL;
147 ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node);
148 return v == NULL ? NULL : v;
151 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
152 static inline ipa_reference_optimization_summary_t
153 get_reference_optimization_summary (struct cgraph_node *node)
155 if (ipa_ref_opt_sum_summaries == NULL)
156 return NULL;
158 ipa_reference_optimization_summary_t v
159 = ipa_ref_opt_sum_summaries->get (node);
161 return v == NULL ? NULL : v;
164 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
165 that are *not* read during the execution of the function FN. Returns
166 NULL if no data is available. */
168 bitmap
169 ipa_reference_get_not_read_global (struct cgraph_node *fn)
171 if (!opt_for_fn (current_function_decl, flag_ipa_reference))
172 return NULL;
174 enum availability avail;
175 struct cgraph_node *fn2 = fn->function_symbol (&avail);
176 ipa_reference_optimization_summary_t info =
177 get_reference_optimization_summary (fn2);
179 if (info
180 && (avail >= AVAIL_AVAILABLE
181 || (avail == AVAIL_INTERPOSABLE
182 && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
183 && opt_for_fn (fn2->decl, flag_ipa_reference))
184 return info->statics_not_read;
185 else if (avail == AVAIL_NOT_AVAILABLE
186 && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
187 return all_module_statics;
188 else
189 return NULL;
192 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
193 that are *not* written during the execution of the function FN. Note
194 that variables written may or may not be read during the function
195 call. Returns NULL if no data is available. */
197 bitmap
198 ipa_reference_get_not_written_global (struct cgraph_node *fn)
200 if (!opt_for_fn (current_function_decl, flag_ipa_reference))
201 return NULL;
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);
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_not_written;
214 else if (avail == AVAIL_NOT_AVAILABLE
215 && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
216 return all_module_statics;
217 else
218 return NULL;
222 /* Hepler for is_proper_for_analysis. */
223 static bool
224 is_improper (symtab_node *n, void *v ATTRIBUTE_UNUSED)
226 tree t = n->decl;
227 /* If the variable has the "used" attribute, treat it as if it had a
228 been touched by the devil. */
229 if (DECL_PRESERVE_P (t))
230 return true;
232 /* Do not want to do anything with volatile except mark any
233 function that uses one to be not const or pure. */
234 if (TREE_THIS_VOLATILE (t))
235 return true;
237 /* We do not need to analyze readonly vars, we already know they do not
238 alias. */
239 if (TREE_READONLY (t))
240 return true;
242 /* We cannot track variables with address taken. */
243 if (TREE_ADDRESSABLE (t))
244 return true;
246 /* TODO: We could track public variables that are not addressable, but
247 currently frontends don't give us those. */
248 if (TREE_PUBLIC (t))
249 return true;
251 return false;
254 /* Return true if the variable T is the right kind of static variable to
255 perform compilation unit scope escape analysis. */
257 static inline bool
258 is_proper_for_analysis (tree t)
260 if (bitmap_bit_p (ignore_module_statics, ipa_reference_var_uid (t)))
261 return false;
263 if (symtab_node::get (t)
264 ->call_for_symbol_and_aliases (is_improper, NULL, true))
265 return false;
267 return true;
270 /* Lookup the tree node for the static variable that has UID and
271 convert the name to a string for debugging. */
273 static const char *
274 get_static_name (int index)
276 splay_tree_node stn =
277 splay_tree_lookup (reference_vars_to_consider, index);
278 return fndecl_name ((tree)(stn->value));
281 /* Dump a set of static vars to FILE. */
282 static void
283 dump_static_vars_set_to_file (FILE *f, bitmap set)
285 unsigned int index;
286 bitmap_iterator bi;
287 if (set == NULL)
288 return;
289 else if (set == all_module_statics)
290 fprintf (f, "ALL");
291 else
292 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
294 fprintf (f, "%s ", get_static_name (index));
298 /* Compute X |= Y, taking into account the possibility that
299 either X or Y is already the maximum set.
300 Return true if X is the maximum set after taking the union with Y. */
302 static bool
303 union_static_var_sets (bitmap &x, bitmap y)
305 if (x != all_module_statics)
307 if (y == all_module_statics)
309 BITMAP_FREE (x);
310 x = all_module_statics;
312 else if (bitmap_ior_into (x, y))
314 /* The union may have reduced X to the maximum set.
315 In that case, we want to make that visible explicitly.
316 Even though bitmap_equal_p can be very expensive, it
317 turns out to be an overall win to check this here for
318 an LTO bootstrap of GCC itself. Liberally extrapoliate
319 that result to be applicable to all cases. */
320 if (bitmap_equal_p (x, all_module_statics))
322 BITMAP_FREE (x);
323 x = all_module_statics;
327 return x == all_module_statics;
330 /* Return a copy of SET on the bitmap obstack containing SET.
331 But if SET is NULL or the maximum set, return that instead. */
333 static bitmap
334 copy_static_var_set (bitmap set)
336 if (set == NULL || set == all_module_statics)
337 return set;
338 bitmap_obstack *o = set->obstack;
339 gcc_checking_assert (o);
340 bitmap copy = BITMAP_ALLOC (o);
341 bitmap_copy (copy, set);
342 return copy;
345 /* Compute the union all of the statics read and written by every callee of X
346 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
347 actually the set representing the cycle containing X. If the read and
348 written sets of X_GLOBAL has been reduced to the maximum set, we don't
349 have to look at the remaining callees. */
351 static void
352 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
354 struct cgraph_edge *e;
355 bool read_all = x_global->statics_read == all_module_statics;
356 bool write_all = x_global->statics_written == all_module_statics;
357 for (e = x->callees;
358 e && !(read_all && write_all);
359 e = e->next_callee)
361 enum availability avail;
362 struct cgraph_node *y = e->callee->function_symbol (&avail);
363 if (!y)
364 continue;
366 /* Only look into nodes we can propagate something. */
367 int flags = flags_from_decl_or_type (y->decl);
368 if (opt_for_fn (y->decl, flag_ipa_reference)
369 && (avail > AVAIL_INTERPOSABLE
370 || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
372 if (get_reference_vars_info (y))
374 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
375 ipa_reference_global_vars_info_t y_global = &y_info->global;
377 /* Calls in the current cycle do not have their global set
378 computed yet (but everything else does because we're
379 visiting nodes in topological order). */
380 if (!y_global->statics_read)
381 continue;
383 /* If the function is const, it reads no memory even if it
384 seems so to local analysis. */
385 if (flags & ECF_CONST)
386 continue;
388 union_static_var_sets (x_global->statics_read,
389 y_global->statics_read);
391 /* If the function is pure, it has no stores even if it
392 seems so to local analysis. If we cannot return from
393 the function, we can safely ignore the call. */
394 if ((flags & ECF_PURE)
395 || e->cannot_lead_to_return_p ())
396 continue;
398 union_static_var_sets (x_global->statics_written,
399 y_global->statics_written);
401 else
402 gcc_unreachable ();
407 static bool ipa_init_p = false;
409 /* The init routine for analyzing global static variable usage. See
410 comments at top for description. */
411 static void
412 ipa_init (void)
414 if (ipa_init_p)
415 return;
417 ipa_init_p = true;
419 if (dump_file)
420 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
422 bitmap_obstack_initialize (&local_info_obstack);
423 bitmap_obstack_initialize (&optimization_summary_obstack);
424 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
425 ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
427 if (ipa_ref_var_info_summaries == NULL)
428 ipa_ref_var_info_summaries = new ipa_ref_var_info_summary_t (symtab);
430 if (ipa_ref_opt_sum_summaries != NULL)
432 delete ipa_ref_opt_sum_summaries;
433 ipa_ref_opt_sum_summaries = NULL;
438 /* Set up the persistent info for FN. */
440 static ipa_reference_local_vars_info_t
441 init_function_info (struct cgraph_node *fn)
443 ipa_reference_vars_info_t info
444 = ipa_ref_var_info_summaries->get_create (fn);
446 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
447 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
449 return &info->local;
453 /* This is the main routine for finding the reference patterns for
454 global variables within a function FN. */
456 static void
457 analyze_function (struct cgraph_node *fn)
459 ipa_reference_local_vars_info_t local;
460 struct ipa_ref *ref = NULL;
461 int i;
462 tree var;
464 if (!opt_for_fn (fn->decl, flag_ipa_reference))
465 return;
466 local = init_function_info (fn);
467 for (i = 0; fn->iterate_reference (i, ref); i++)
469 if (!is_a <varpool_node *> (ref->referred))
470 continue;
471 var = ref->referred->decl;
472 if (!is_proper_for_analysis (var))
473 continue;
474 /* This is a variable we care about. Check if we have seen it
475 before, and if not add it the set of variables we care about. */
476 if (all_module_statics
477 && bitmap_set_bit (all_module_statics, ipa_reference_var_uid (var)))
479 if (dump_file)
480 splay_tree_insert (reference_vars_to_consider,
481 ipa_reference_var_uid (var),
482 (splay_tree_value)var);
484 switch (ref->use)
486 case IPA_REF_LOAD:
487 bitmap_set_bit (local->statics_read, ipa_reference_var_uid (var));
488 break;
489 case IPA_REF_STORE:
490 if (ref->cannot_lead_to_return ())
491 break;
492 bitmap_set_bit (local->statics_written, ipa_reference_var_uid (var));
493 break;
494 case IPA_REF_ADDR:
495 break;
496 default:
497 gcc_unreachable ();
501 if (fn->cannot_return_p ())
502 bitmap_clear (local->statics_written);
506 /* Called when new clone is inserted to callgraph late. */
508 void
509 ipa_ref_opt_summary_t::duplicate (cgraph_node *, cgraph_node *,
510 ipa_reference_optimization_summary_d *ginfo,
511 ipa_reference_optimization_summary_d
512 *dst_ginfo)
514 dst_ginfo->statics_not_read =
515 copy_static_var_set (ginfo->statics_not_read);
516 dst_ginfo->statics_not_written =
517 copy_static_var_set (ginfo->statics_not_written);
520 /* Called when node is removed. */
522 void
523 ipa_ref_opt_summary_t::remove (cgraph_node *,
524 ipa_reference_optimization_summary_d *ginfo)
526 if (ginfo->statics_not_read
527 && ginfo->statics_not_read != all_module_statics)
528 BITMAP_FREE (ginfo->statics_not_read);
530 if (ginfo->statics_not_written
531 && ginfo->statics_not_written != all_module_statics)
532 BITMAP_FREE (ginfo->statics_not_written);
535 /* Analyze each function in the cgraph to see which global or statics
536 are read or written. */
538 static void
539 generate_summary (void)
541 struct cgraph_node *node;
542 unsigned int index;
543 bitmap_iterator bi;
545 ipa_init ();
547 /* Process all of the functions next. */
548 FOR_EACH_DEFINED_FUNCTION (node)
549 if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
551 struct ipa_ref *ref = NULL;
552 int i;
553 tree var;
554 for (i = 0; node->iterate_reference (i, ref); i++)
556 if (!is_a <varpool_node *> (ref->referred))
557 continue;
558 var = ref->referred->decl;
559 if (!is_proper_for_analysis (var))
560 continue;
561 bitmap_set_bit (ignore_module_statics, ipa_reference_var_uid (var));
564 FOR_EACH_DEFINED_FUNCTION (node)
565 analyze_function (node);
567 if (dump_file)
568 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
570 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
571 get_static_name (index), index);
574 if (dump_file)
575 FOR_EACH_DEFINED_FUNCTION (node)
576 if (node->get_availability () >= AVAIL_INTERPOSABLE
577 && opt_for_fn (node->decl, flag_ipa_reference))
579 ipa_reference_local_vars_info_t l;
580 unsigned int index;
581 bitmap_iterator bi;
583 l = &get_reference_vars_info (node)->local;
584 fprintf (dump_file,
585 "\nFunction name:%s:", node->dump_name ());
586 fprintf (dump_file, "\n locals read: ");
587 if (l->statics_read)
588 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
589 0, index, bi)
591 fprintf (dump_file, "%s ",
592 get_static_name (index));
594 fprintf (dump_file, "\n locals written: ");
595 if (l->statics_written)
596 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
597 0, index, bi)
599 fprintf (dump_file, "%s ", get_static_name (index));
604 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
606 static void
607 read_write_all_from_decl (struct cgraph_node *node,
608 bool &read_all, bool &write_all)
610 tree decl = node->decl;
611 int flags = flags_from_decl_or_type (decl);
612 if ((flags & ECF_LEAF)
613 && node->get_availability () < AVAIL_INTERPOSABLE)
615 else if (flags & ECF_CONST)
617 else if ((flags & ECF_PURE) || node->cannot_return_p ())
619 read_all = true;
620 if (dump_file && (dump_flags & TDF_DETAILS))
621 fprintf (dump_file, " %s -> read all\n", node->dump_name ());
623 else
625 /* TODO: To be able to produce sane results, we should also handle
626 common builtins, in particular throw. */
627 read_all = true;
628 write_all = true;
629 if (dump_file && (dump_flags & TDF_DETAILS))
630 fprintf (dump_file, " %s -> read all, write all\n",
631 node->dump_name ());
635 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
636 in the cycle of NODE. */
638 static void
639 get_read_write_all_from_node (struct cgraph_node *node,
640 bool &read_all, bool &write_all)
642 struct cgraph_edge *e, *ie;
644 /* When function is overwritable, we cannot assume anything. */
645 if (node->get_availability () <= AVAIL_INTERPOSABLE
646 || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
647 read_write_all_from_decl (node, read_all, write_all);
649 for (e = node->callees;
650 e && !(read_all && write_all);
651 e = e->next_callee)
653 enum availability avail;
654 struct cgraph_node *callee = e->callee->function_symbol (&avail);
655 gcc_checking_assert (callee);
656 if (avail <= AVAIL_INTERPOSABLE
657 || (callee->analyzed && !opt_for_fn (callee->decl,
658 flag_ipa_reference)))
659 read_write_all_from_decl (callee, read_all, write_all);
662 for (ie = node->indirect_calls;
663 ie && !(read_all && write_all);
664 ie = ie->next_callee)
665 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
667 read_all = true;
668 if (dump_file && (dump_flags & TDF_DETAILS))
669 fprintf (dump_file, " indirect call -> read all\n");
670 if (!ie->cannot_lead_to_return_p ()
671 && !(ie->indirect_info->ecf_flags & ECF_PURE))
673 if (dump_file && (dump_flags & TDF_DETAILS))
674 fprintf (dump_file, " indirect call -> write all\n");
675 write_all = true;
680 /* Skip edges from and to nodes without ipa_reference enables. This leave
681 them out of strongy connected coponents and makes them easyto skip in the
682 propagation loop bellow. */
684 static bool
685 ignore_edge_p (cgraph_edge *e)
687 return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
688 || !opt_for_fn (e->callee->function_symbol ()->decl,
689 flag_ipa_reference));
692 /* Produce the global information by preforming a transitive closure
693 on the local information that was produced by ipa_analyze_function. */
695 static unsigned int
696 propagate (void)
698 struct cgraph_node *node;
699 struct cgraph_node **order =
700 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
701 int order_pos;
702 int i;
703 bool remove_p;
705 if (dump_file)
706 cgraph_node::dump_cgraph (dump_file);
708 remove_p = ipa_discover_variable_flags ();
709 generate_summary ();
711 /* Propagate the local information through the call graph to produce
712 the global information. All the nodes within a cycle will have
713 the same info so we collapse cycles first. Then we can do the
714 propagation in one pass from the leaves to the roots. */
715 order_pos = ipa_reduced_postorder (order, true, true, ignore_edge_p);
716 if (dump_file)
717 ipa_print_order (dump_file, "reduced", order, order_pos);
719 for (i = 0; i < order_pos; i++ )
721 unsigned x;
722 struct cgraph_node *w;
723 ipa_reference_vars_info_t node_info;
724 ipa_reference_global_vars_info_t node_g;
725 ipa_reference_local_vars_info_t node_l;
726 bool read_all = false;
727 bool write_all = false;
729 node = order[i];
730 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
731 continue;
733 node_info = get_reference_vars_info (node);
734 gcc_assert (node_info);
735 node_l = &node_info->local;
736 node_g = &node_info->global;
738 if (dump_file && (dump_flags & TDF_DETAILS))
739 fprintf (dump_file, "Starting cycle with %s\n", node->dump_name ());
741 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
743 /* If any node in a cycle is read_all or write_all, they all are. */
744 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
746 if (dump_file && (dump_flags & TDF_DETAILS))
747 fprintf (dump_file, " Visiting %s\n", w->dump_asm_name ());
748 get_read_write_all_from_node (w, read_all, write_all);
749 if (read_all && write_all)
750 break;
753 /* Initialized the bitmaps global sets for the reduced node. */
754 if (read_all)
755 node_g->statics_read = all_module_statics;
756 else
757 node_g->statics_read = copy_static_var_set (node_l->statics_read);
758 if (write_all)
759 node_g->statics_written = all_module_statics;
760 else
761 node_g->statics_written = copy_static_var_set (node_l->statics_written);
763 /* Merge the sets of this cycle with all sets of callees reached
764 from this cycle. */
765 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
767 if (read_all && write_all)
768 break;
770 if (w != node)
772 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
773 ipa_reference_local_vars_info_t w_l = &w_ri->local;
774 int flags = flags_from_decl_or_type (w->decl);
776 if (!(flags & ECF_CONST))
777 read_all = union_static_var_sets (node_g->statics_read,
778 w_l->statics_read);
779 if (!(flags & ECF_PURE)
780 && !w->cannot_return_p ())
781 write_all = union_static_var_sets (node_g->statics_written,
782 w_l->statics_written);
785 propagate_bits (node_g, w);
788 /* All nodes within a cycle have the same global info bitmaps. */
789 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
791 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
792 w_ri->global = *node_g;
795 cycle_nodes.release ();
798 if (dump_file)
800 for (i = 0; i < order_pos; i++)
802 unsigned x;
803 struct cgraph_node *w;
805 node = order[i];
806 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
807 continue;
809 fprintf (dump_file, "\nFunction name:%s:", node->dump_asm_name ());
811 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
812 ipa_reference_global_vars_info_t node_g = &node_info->global;
814 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
815 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
817 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
818 ipa_reference_local_vars_info_t w_l = &w_ri->local;
819 if (w != node)
820 fprintf (dump_file, "\n next cycle: %s ", w->dump_asm_name ());
821 fprintf (dump_file, "\n locals read: ");
822 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
823 fprintf (dump_file, "\n locals written: ");
824 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
826 cycle_nodes.release ();
828 fprintf (dump_file, "\n globals read: ");
829 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
830 fprintf (dump_file, "\n globals written: ");
831 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
832 fprintf (dump_file, "\n");
836 if (ipa_ref_opt_sum_summaries == NULL)
837 ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
839 /* Cleanup. */
840 FOR_EACH_DEFINED_FUNCTION (node)
842 ipa_reference_vars_info_t node_info;
843 ipa_reference_global_vars_info_t node_g;
845 node_info = get_reference_vars_info (node);
846 if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
847 && (node->get_availability () > AVAIL_INTERPOSABLE
848 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
850 node_g = &node_info->global;
852 ipa_reference_optimization_summary_d *opt
853 = ipa_ref_opt_sum_summaries->get_create (node);
855 /* Create the complimentary sets. */
857 if (bitmap_empty_p (node_g->statics_read))
858 opt->statics_not_read = all_module_statics;
859 else
861 opt->statics_not_read
862 = BITMAP_ALLOC (&optimization_summary_obstack);
863 if (node_g->statics_read != all_module_statics)
864 bitmap_and_compl (opt->statics_not_read,
865 all_module_statics,
866 node_g->statics_read);
869 if (bitmap_empty_p (node_g->statics_written))
870 opt->statics_not_written = all_module_statics;
871 else
873 opt->statics_not_written
874 = BITMAP_ALLOC (&optimization_summary_obstack);
875 if (node_g->statics_written != all_module_statics)
876 bitmap_and_compl (opt->statics_not_written,
877 all_module_statics,
878 node_g->statics_written);
883 ipa_free_postorder_info ();
884 free (order);
886 bitmap_obstack_release (&local_info_obstack);
888 if (ipa_ref_var_info_summaries == NULL)
890 delete ipa_ref_var_info_summaries;
891 ipa_ref_var_info_summaries = NULL;
894 ipa_ref_var_info_summaries = NULL;
895 if (dump_file)
896 splay_tree_delete (reference_vars_to_consider);
897 reference_vars_to_consider = NULL;
898 return remove_p ? TODO_remove_functions : 0;
901 /* Return true if we need to write summary of NODE. */
903 static bool
904 write_node_summary_p (struct cgraph_node *node,
905 lto_symtab_encoder_t encoder,
906 bitmap ltrans_statics)
908 ipa_reference_optimization_summary_t info;
910 /* See if we have (non-empty) info. */
911 if (!node->definition || node->global.inlined_to)
912 return false;
913 info = get_reference_optimization_summary (node);
914 if (!info
915 || (bitmap_empty_p (info->statics_not_read)
916 && bitmap_empty_p (info->statics_not_written)))
917 return false;
919 /* See if we want to encode it.
920 Encode also referenced functions since constant folding might turn it into
921 a direct call.
923 In future we might also want to include summaries of functions references
924 by initializers of constant variables references in current unit. */
925 if (!reachable_from_this_partition_p (node, encoder)
926 && !referenced_from_this_partition_p (node, encoder))
927 return false;
929 /* See if the info has non-empty intersections with vars we want to encode. */
930 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
931 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
932 return false;
933 return true;
936 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
937 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
938 or -1. When it is positive, just output -1 when
939 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
941 static void
942 stream_out_bitmap (struct lto_simple_output_block *ob,
943 bitmap bits, bitmap ltrans_statics,
944 int ltrans_statics_bitcount)
946 int count = 0;
947 unsigned int index;
948 bitmap_iterator bi;
949 if (bits == all_module_statics)
951 streamer_write_hwi_stream (ob->main_stream, -1);
952 return;
954 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
955 count ++;
956 if (count == ltrans_statics_bitcount)
958 streamer_write_hwi_stream (ob->main_stream, -1);
959 return;
961 streamer_write_hwi_stream (ob->main_stream, count);
962 if (!count)
963 return;
964 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
966 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider,
967 index)->value;
968 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
972 /* Serialize the ipa info for lto. */
974 static void
975 ipa_reference_write_optimization_summary (void)
977 struct lto_simple_output_block *ob
978 = lto_create_simple_output_block (LTO_section_ipa_reference);
979 unsigned int count = 0;
980 int ltrans_statics_bitcount = 0;
981 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
982 auto_bitmap ltrans_statics;
983 int i;
985 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
987 /* See what variables we are interested in. */
988 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
990 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
991 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
992 if (vnode
993 && bitmap_bit_p (all_module_statics,
994 ipa_reference_var_uid (vnode->decl))
995 && referenced_from_this_partition_p (vnode, encoder))
997 tree decl = vnode->decl;
998 bitmap_set_bit (ltrans_statics, ipa_reference_var_uid (decl));
999 splay_tree_insert (reference_vars_to_consider,
1000 ipa_reference_var_uid (decl),
1001 (splay_tree_value)decl);
1002 ltrans_statics_bitcount ++;
1007 if (ltrans_statics_bitcount)
1008 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1010 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1011 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1012 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1013 count++;
1016 streamer_write_uhwi_stream (ob->main_stream, count);
1017 if (count)
1018 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1019 -1);
1021 /* Process all of the functions. */
1022 if (ltrans_statics_bitcount)
1023 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1025 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1026 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1027 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1029 ipa_reference_optimization_summary_t info;
1030 int node_ref;
1032 info = get_reference_optimization_summary (cnode);
1033 node_ref = lto_symtab_encoder_encode (encoder, snode);
1034 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1036 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1037 ltrans_statics_bitcount);
1038 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1039 ltrans_statics_bitcount);
1042 lto_destroy_simple_output_block (ob);
1043 splay_tree_delete (reference_vars_to_consider);
1046 /* Deserialize the ipa info for lto. */
1048 static void
1049 ipa_reference_read_optimization_summary (void)
1051 struct lto_file_decl_data ** file_data_vec
1052 = lto_get_file_decl_data ();
1053 struct lto_file_decl_data * file_data;
1054 unsigned int j = 0;
1055 bitmap_obstack_initialize (&optimization_summary_obstack);
1057 if (ipa_ref_opt_sum_summaries == NULL)
1058 ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
1060 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1062 while ((file_data = file_data_vec[j++]))
1064 const char *data;
1065 size_t len;
1066 struct lto_input_block *ib
1067 = lto_create_simple_input_block (file_data,
1068 LTO_section_ipa_reference,
1069 &data, &len);
1070 if (ib)
1072 unsigned int i;
1073 unsigned int f_count = streamer_read_uhwi (ib);
1074 int b_count;
1075 if (!f_count)
1076 continue;
1077 b_count = streamer_read_hwi (ib);
1078 if (dump_file)
1079 fprintf (dump_file, "all module statics:");
1080 for (i = 0; i < (unsigned int)b_count; i++)
1082 unsigned int var_index = streamer_read_uhwi (ib);
1083 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1084 var_index);
1085 bitmap_set_bit (all_module_statics,
1086 ipa_reference_var_uid (v_decl));
1087 if (dump_file)
1088 fprintf (dump_file, " %s", fndecl_name (v_decl));
1091 for (i = 0; i < f_count; i++)
1093 unsigned int j, index;
1094 struct cgraph_node *node;
1095 int v_count;
1096 lto_symtab_encoder_t encoder;
1098 index = streamer_read_uhwi (ib);
1099 encoder = file_data->symtab_node_encoder;
1100 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1101 (encoder, index));
1103 ipa_reference_optimization_summary_d *info
1104 = ipa_ref_opt_sum_summaries->get_create (node);
1106 info->statics_not_read = BITMAP_ALLOC
1107 (&optimization_summary_obstack);
1108 info->statics_not_written = BITMAP_ALLOC
1109 (&optimization_summary_obstack);
1110 if (dump_file)
1111 fprintf (dump_file,
1112 "\nFunction name:%s:\n static not read:",
1113 node->dump_asm_name ());
1115 /* Set the statics not read. */
1116 v_count = streamer_read_hwi (ib);
1117 if (v_count == -1)
1119 info->statics_not_read = all_module_statics;
1120 if (dump_file)
1121 fprintf (dump_file, " all module statics");
1123 else
1124 for (j = 0; j < (unsigned int)v_count; j++)
1126 unsigned int var_index = streamer_read_uhwi (ib);
1127 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1128 var_index);
1129 bitmap_set_bit (info->statics_not_read,
1130 ipa_reference_var_uid (v_decl));
1131 if (dump_file)
1132 fprintf (dump_file, " %s", fndecl_name (v_decl));
1135 if (dump_file)
1136 fprintf (dump_file,
1137 "\n static not written:");
1138 /* Set the statics not written. */
1139 v_count = streamer_read_hwi (ib);
1140 if (v_count == -1)
1142 info->statics_not_written = all_module_statics;
1143 if (dump_file)
1144 fprintf (dump_file, " all module statics");
1146 else
1147 for (j = 0; j < (unsigned int)v_count; j++)
1149 unsigned int var_index = streamer_read_uhwi (ib);
1150 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1151 var_index);
1152 bitmap_set_bit (info->statics_not_written,
1153 ipa_reference_var_uid (v_decl));
1154 if (dump_file)
1155 fprintf (dump_file, " %s", fndecl_name (v_decl));
1157 if (dump_file)
1158 fprintf (dump_file, "\n");
1161 lto_destroy_simple_input_block (file_data,
1162 LTO_section_ipa_reference,
1163 ib, data, len);
1165 else
1166 /* Fatal error here. We do not want to support compiling ltrans units
1167 with different version of compiler or different flags than
1168 the WPA unit, so this should never happen. */
1169 fatal_error (input_location,
1170 "ipa reference summary is missing in ltrans unit");
1174 namespace {
1176 const pass_data pass_data_ipa_reference =
1178 IPA_PASS, /* type */
1179 "static-var", /* name */
1180 OPTGROUP_NONE, /* optinfo_flags */
1181 TV_IPA_REFERENCE, /* tv_id */
1182 0, /* properties_required */
1183 0, /* properties_provided */
1184 0, /* properties_destroyed */
1185 0, /* todo_flags_start */
1186 0, /* todo_flags_finish */
1189 class pass_ipa_reference : public ipa_opt_pass_d
1191 public:
1192 pass_ipa_reference (gcc::context *ctxt)
1193 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1194 NULL, /* generate_summary */
1195 NULL, /* write_summary */
1196 NULL, /* read_summary */
1197 ipa_reference_write_optimization_summary, /*
1198 write_optimization_summary */
1199 ipa_reference_read_optimization_summary, /*
1200 read_optimization_summary */
1201 NULL, /* stmt_fixup */
1202 0, /* function_transform_todo_flags_start */
1203 NULL, /* function_transform */
1204 NULL) /* variable_transform */
1207 /* opt_pass methods: */
1208 virtual bool gate (function *)
1210 return ((in_lto_p || flag_ipa_reference)
1211 /* Don't bother doing anything if the program has errors. */
1212 && !seen_error ());
1215 virtual unsigned int execute (function *) { return propagate (); }
1217 }; // class pass_ipa_reference
1219 } // anon namespace
1221 ipa_opt_pass_d *
1222 make_pass_ipa_reference (gcc::context *ctxt)
1224 return new pass_ipa_reference (ctxt);
1227 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1228 within the same process. For use by toplev::finalize. */
1230 void
1231 ipa_reference_c_finalize (void)
1233 if (ipa_ref_opt_sum_summaries != NULL)
1235 delete ipa_ref_opt_sum_summaries;
1236 ipa_ref_opt_sum_summaries = NULL;
1239 if (ipa_init_p)
1241 bitmap_obstack_release (&optimization_summary_obstack);
1242 ipa_init_p = false;