2015-06-11 Paul Thomas <pault@gcc.gnu.org>
[official-gcc.git] / gcc / ipa-reference.c
blob0e5843cdd9389480c08da56c0da776f203863269
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2015 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 "tm.h"
43 #include "input.h"
44 #include "alias.h"
45 #include "symtab.h"
46 #include "options.h"
47 #include "tree.h"
48 #include "fold-const.h"
49 #include "calls.h"
50 #include "predict.h"
51 #include "hard-reg-set.h"
52 #include "input.h"
53 #include "function.h"
54 #include "basic-block.h"
55 #include "tree-ssa-alias.h"
56 #include "internal-fn.h"
57 #include "gimple-expr.h"
58 #include "is-a.h"
59 #include "gimple.h"
60 #include "tree-inline.h"
61 #include "tree-pass.h"
62 #include "splay-tree.h"
63 #include "plugin-api.h"
64 #include "ipa-ref.h"
65 #include "cgraph.h"
66 #include "ipa-utils.h"
67 #include "bitmap.h"
68 #include "ipa-reference.h"
69 #include "flags.h"
70 #include "diagnostic.h"
71 #include "data-streamer.h"
72 #include "lto-streamer.h"
74 static void remove_node_data (struct cgraph_node *node,
75 void *data ATTRIBUTE_UNUSED);
76 static void duplicate_node_data (struct cgraph_node *src,
77 struct cgraph_node *dst,
78 void *data ATTRIBUTE_UNUSED);
80 /* The static variables defined within the compilation unit that are
81 loaded or stored directly by function that owns this structure. */
83 struct ipa_reference_local_vars_info_d
85 bitmap statics_read;
86 bitmap statics_written;
89 /* Statics that are read and written by some set of functions. The
90 local ones are based on the loads and stores local to the function.
91 The global ones are based on the local info as well as the
92 transitive closure of the functions that are called. */
94 struct ipa_reference_global_vars_info_d
96 bitmap statics_read;
97 bitmap statics_written;
100 /* Information we save about every function after ipa-reference is completed. */
102 struct ipa_reference_optimization_summary_d
104 bitmap statics_not_read;
105 bitmap statics_not_written;
108 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
109 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
110 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
112 struct ipa_reference_vars_info_d
114 struct ipa_reference_local_vars_info_d local;
115 struct ipa_reference_global_vars_info_d global;
118 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
120 /* This splay tree contains all of the static variables that are
121 being considered by the compilation level alias analysis. */
122 static splay_tree reference_vars_to_consider;
124 /* Set of all interesting module statics. A bit is set for every module
125 static we are considering. This is added to the local info when asm
126 code is found that clobbers all memory. */
127 static bitmap all_module_statics;
128 /* Set of all statics that should be ignored becuase they are touched by
129 -fno-ipa-reference code. */
130 static bitmap ignore_module_statics;
132 /* Obstack holding bitmaps of local analysis (live from analysis to
133 propagation) */
134 static bitmap_obstack local_info_obstack;
135 /* Obstack holding global analysis live forever. */
136 static bitmap_obstack optimization_summary_obstack;
138 /* Holders of ipa cgraph hooks: */
139 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
140 static struct cgraph_node_hook_list *node_removal_hook_holder;
142 /* Vector where the reference var infos are actually stored.
143 Indexed by UID of call graph nodes. */
144 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
146 /* TODO: find a place where we should release the vector. */
147 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
149 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
150 static inline ipa_reference_vars_info_t
151 get_reference_vars_info (struct cgraph_node *node)
153 if (!ipa_reference_vars_vector.exists ()
154 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
155 return NULL;
156 return ipa_reference_vars_vector[node->uid];
159 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
160 static inline ipa_reference_optimization_summary_t
161 get_reference_optimization_summary (struct cgraph_node *node)
163 if (!ipa_reference_opt_sum_vector.exists ()
164 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
165 return NULL;
166 return ipa_reference_opt_sum_vector[node->uid];
169 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
170 static inline void
171 set_reference_vars_info (struct cgraph_node *node,
172 ipa_reference_vars_info_t info)
174 if (!ipa_reference_vars_vector.exists ()
175 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
176 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
177 ipa_reference_vars_vector[node->uid] = info;
180 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
181 static inline void
182 set_reference_optimization_summary (struct cgraph_node *node,
183 ipa_reference_optimization_summary_t info)
185 if (!ipa_reference_opt_sum_vector.exists ()
186 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
187 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
188 ipa_reference_opt_sum_vector[node->uid] = info;
191 /* Return a bitmap indexed by DECL_UID for the static variables that
192 are *not* read during the execution of the function FN. Returns
193 NULL if no data is available. */
195 bitmap
196 ipa_reference_get_not_read_global (struct cgraph_node *fn)
198 if (!opt_for_fn (fn->decl, flag_ipa_reference)
199 || !opt_for_fn (current_function_decl, flag_ipa_reference))
200 return NULL;
201 ipa_reference_optimization_summary_t info =
202 get_reference_optimization_summary (fn->function_symbol (NULL));
203 if (info)
204 return info->statics_not_read;
205 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
206 return all_module_statics;
207 else
208 return NULL;
211 /* Return a bitmap indexed by DECL_UID for the static variables that
212 are *not* written during the execution of the function FN. Note
213 that variables written may or may not be read during the function
214 call. Returns NULL if no data is available. */
216 bitmap
217 ipa_reference_get_not_written_global (struct cgraph_node *fn)
219 if (!opt_for_fn (fn->decl, flag_ipa_reference)
220 || !opt_for_fn (current_function_decl, flag_ipa_reference))
221 return NULL;
222 ipa_reference_optimization_summary_t info =
223 get_reference_optimization_summary (fn);
224 if (info)
225 return info->statics_not_written;
226 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
227 return all_module_statics;
228 else
229 return NULL;
233 /* Return true if the variable T is the right kind of static variable to
234 perform compilation unit scope escape analysis. */
236 static inline bool
237 is_proper_for_analysis (tree t)
239 /* If the variable has the "used" attribute, treat it as if it had a
240 been touched by the devil. */
241 if (DECL_PRESERVE_P (t))
242 return false;
244 /* Do not want to do anything with volatile except mark any
245 function that uses one to be not const or pure. */
246 if (TREE_THIS_VOLATILE (t))
247 return false;
249 /* We do not need to analyze readonly vars, we already know they do not
250 alias. */
251 if (TREE_READONLY (t))
252 return false;
254 /* We can not track variables with address taken. */
255 if (TREE_ADDRESSABLE (t))
256 return false;
258 /* TODO: We could track public variables that are not addressable, but currently
259 frontends don't give us those. */
260 if (TREE_PUBLIC (t))
261 return false;
263 /* TODO: Check aliases. */
264 if (bitmap_bit_p (ignore_module_statics, DECL_UID (t)))
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 node_removal_hook_holder =
428 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
429 node_duplication_hook_holder =
430 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
434 /* Set up the persistent info for FN. */
436 static ipa_reference_local_vars_info_t
437 init_function_info (struct cgraph_node *fn)
439 ipa_reference_vars_info_t info
440 = XCNEW (struct ipa_reference_vars_info_d);
442 /* Add the info to the tree's annotation. */
443 set_reference_vars_info (fn, info);
445 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
446 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
448 return &info->local;
452 /* This is the main routine for finding the reference patterns for
453 global variables within a function FN. */
455 static void
456 analyze_function (struct cgraph_node *fn)
458 ipa_reference_local_vars_info_t local;
459 struct ipa_ref *ref = NULL;
460 int i;
461 tree var;
463 if (!opt_for_fn (fn->decl, flag_ipa_reference))
464 return;
465 local = init_function_info (fn);
466 for (i = 0; fn->iterate_reference (i, ref); i++)
468 if (!is_a <varpool_node *> (ref->referred))
469 continue;
470 var = ref->referred->decl;
471 if (!is_proper_for_analysis (var))
472 continue;
473 /* This is a variable we care about. Check if we have seen it
474 before, and if not add it the set of variables we care about. */
475 if (all_module_statics
476 && bitmap_set_bit (all_module_statics, DECL_UID (var)))
478 if (dump_file)
479 splay_tree_insert (reference_vars_to_consider,
480 DECL_UID (var), (splay_tree_value)var);
482 switch (ref->use)
484 case IPA_REF_LOAD:
485 bitmap_set_bit (local->statics_read, DECL_UID (var));
486 break;
487 case IPA_REF_STORE:
488 if (ref->cannot_lead_to_return ())
489 break;
490 bitmap_set_bit (local->statics_written, DECL_UID (var));
491 break;
492 case IPA_REF_ADDR:
493 break;
494 default:
495 gcc_unreachable ();
499 if (fn->cannot_return_p ())
500 bitmap_clear (local->statics_written);
504 /* Called when new clone is inserted to callgraph late. */
506 static void
507 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
508 void *data ATTRIBUTE_UNUSED)
510 ipa_reference_optimization_summary_t ginfo;
511 ipa_reference_optimization_summary_t dst_ginfo;
513 ginfo = get_reference_optimization_summary (src);
514 if (!ginfo)
515 return;
516 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
517 set_reference_optimization_summary (dst, dst_ginfo);
518 dst_ginfo->statics_not_read =
519 copy_static_var_set (ginfo->statics_not_read);
520 dst_ginfo->statics_not_written =
521 copy_static_var_set (ginfo->statics_not_written);
524 /* Called when node is removed. */
526 static void
527 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
529 ipa_reference_optimization_summary_t ginfo;
530 ginfo = get_reference_optimization_summary (node);
531 if (ginfo)
533 if (ginfo->statics_not_read
534 && ginfo->statics_not_read != all_module_statics)
535 BITMAP_FREE (ginfo->statics_not_read);
537 if (ginfo->statics_not_written
538 && ginfo->statics_not_written != all_module_statics)
539 BITMAP_FREE (ginfo->statics_not_written);
540 free (ginfo);
541 set_reference_optimization_summary (node, NULL);
545 /* Analyze each function in the cgraph to see which global or statics
546 are read or written. */
548 static void
549 generate_summary (void)
551 struct cgraph_node *node;
552 unsigned int index;
553 bitmap_iterator bi;
555 ipa_init ();
557 /* Process all of the functions next. */
558 FOR_EACH_DEFINED_FUNCTION (node)
559 if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
561 struct ipa_ref *ref = NULL;
562 int i;
563 tree var;
564 for (i = 0; node->iterate_reference (i, ref); i++)
566 if (!is_a <varpool_node *> (ref->referred))
567 continue;
568 var = ref->referred->decl;
569 if (!is_proper_for_analysis (var))
570 continue;
571 bitmap_set_bit (ignore_module_statics, DECL_UID (var));
574 FOR_EACH_DEFINED_FUNCTION (node)
575 analyze_function (node);
577 if (dump_file)
578 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
580 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
581 get_static_name (index), index);
584 if (dump_file)
585 FOR_EACH_DEFINED_FUNCTION (node)
586 if (node->get_availability () >= AVAIL_INTERPOSABLE
587 && opt_for_fn (node->decl, flag_ipa_reference))
589 ipa_reference_local_vars_info_t l;
590 unsigned int index;
591 bitmap_iterator bi;
593 l = &get_reference_vars_info (node)->local;
594 fprintf (dump_file,
595 "\nFunction name:%s/%i:",
596 node->asm_name (), node->order);
597 fprintf (dump_file, "\n locals read: ");
598 if (l->statics_read)
599 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
600 0, index, bi)
602 fprintf (dump_file, "%s ",
603 get_static_name (index));
605 fprintf (dump_file, "\n locals written: ");
606 if (l->statics_written)
607 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
608 0, index, bi)
610 fprintf (dump_file, "%s ", get_static_name (index));
615 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
617 static void
618 read_write_all_from_decl (struct cgraph_node *node,
619 bool &read_all, bool &write_all)
621 tree decl = node->decl;
622 int flags = flags_from_decl_or_type (decl);
623 if ((flags & ECF_LEAF)
624 && node->get_availability () < AVAIL_INTERPOSABLE)
626 else if (flags & ECF_CONST)
628 else if ((flags & ECF_PURE) || node->cannot_return_p ())
630 read_all = true;
631 if (dump_file && (dump_flags & TDF_DETAILS))
632 fprintf (dump_file, " %s/%i -> read all\n",
633 node->asm_name (), node->order);
635 else
637 /* TODO: To be able to produce sane results, we should also handle
638 common builtins, in particular throw. */
639 read_all = true;
640 write_all = true;
641 if (dump_file && (dump_flags & TDF_DETAILS))
642 fprintf (dump_file, " %s/%i -> read all, write all\n",
643 node->asm_name (), node->order);
647 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
648 in the cycle of NODE. */
650 static void
651 get_read_write_all_from_node (struct cgraph_node *node,
652 bool &read_all, bool &write_all)
654 struct cgraph_edge *e, *ie;
656 /* When function is overwritable, we can not assume anything. */
657 if (node->get_availability () <= AVAIL_INTERPOSABLE
658 || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
659 read_write_all_from_decl (node, read_all, write_all);
661 for (e = node->callees;
662 e && !(read_all && write_all);
663 e = e->next_callee)
665 enum availability avail;
666 struct cgraph_node *callee = e->callee->function_symbol (&avail);
667 gcc_checking_assert (callee);
668 if (avail <= AVAIL_INTERPOSABLE
669 || (callee->analyzed && !opt_for_fn (callee->decl, flag_ipa_reference)))
670 read_write_all_from_decl (callee, read_all, write_all);
673 for (ie = node->indirect_calls;
674 ie && !(read_all && write_all);
675 ie = ie->next_callee)
676 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
678 read_all = true;
679 if (dump_file && (dump_flags & TDF_DETAILS))
680 fprintf (dump_file, " indirect call -> read all\n");
681 if (!ie->cannot_lead_to_return_p ()
682 && !(ie->indirect_info->ecf_flags & ECF_PURE))
684 if (dump_file && (dump_flags & TDF_DETAILS))
685 fprintf (dump_file, " indirect call -> write all\n");
686 write_all = true;
691 /* Skip edges from and to nodes without ipa_reference enables. This leave
692 them out of strongy connected coponents and makes them easyto skip in the
693 propagation loop bellow. */
695 static bool
696 ignore_edge_p (cgraph_edge *e)
698 return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
699 || !opt_for_fn (e->callee->function_symbol ()->decl,
700 flag_ipa_reference));
703 /* Produce the global information by preforming a transitive closure
704 on the local information that was produced by ipa_analyze_function. */
706 static unsigned int
707 propagate (void)
709 struct cgraph_node *node;
710 struct cgraph_node **order =
711 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
712 int order_pos;
713 int i;
714 bool remove_p;
716 if (dump_file)
717 cgraph_node::dump_cgraph (dump_file);
719 remove_p = ipa_discover_readonly_nonaddressable_vars ();
720 generate_summary ();
722 /* Propagate the local information through the call graph to produce
723 the global information. All the nodes within a cycle will have
724 the same info so we collapse cycles first. Then we can do the
725 propagation in one pass from the leaves to the roots. */
726 order_pos = ipa_reduced_postorder (order, true, true, ignore_edge_p);
727 if (dump_file)
728 ipa_print_order (dump_file, "reduced", order, order_pos);
730 for (i = 0; i < order_pos; i++ )
732 unsigned x;
733 struct cgraph_node *w;
734 ipa_reference_vars_info_t node_info;
735 ipa_reference_global_vars_info_t node_g;
736 ipa_reference_local_vars_info_t node_l;
737 bool read_all = false;
738 bool write_all = false;
740 node = order[i];
741 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
742 continue;
744 node_info = get_reference_vars_info (node);
745 gcc_assert (node_info);
746 node_l = &node_info->local;
747 node_g = &node_info->global;
749 if (dump_file && (dump_flags & TDF_DETAILS))
750 fprintf (dump_file, "Starting cycle with %s/%i\n",
751 node->asm_name (), node->order);
753 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
755 /* If any node in a cycle is read_all or write_all, they all are. */
756 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
758 if (dump_file && (dump_flags & TDF_DETAILS))
759 fprintf (dump_file, " Visiting %s/%i\n",
760 w->asm_name (), w->order);
761 get_read_write_all_from_node (w, read_all, write_all);
762 if (read_all && write_all)
763 break;
766 /* Initialized the bitmaps global sets for the reduced node. */
767 if (read_all)
768 node_g->statics_read = all_module_statics;
769 else
770 node_g->statics_read = copy_static_var_set (node_l->statics_read);
771 if (write_all)
772 node_g->statics_written = all_module_statics;
773 else
774 node_g->statics_written = copy_static_var_set (node_l->statics_written);
776 /* Merge the sets of this cycle with all sets of callees reached
777 from this cycle. */
778 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
780 if (read_all && write_all)
781 break;
783 if (w != node)
785 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
786 ipa_reference_local_vars_info_t w_l = &w_ri->local;
787 int flags = flags_from_decl_or_type (w->decl);
789 if (!(flags & ECF_CONST))
790 read_all = union_static_var_sets (node_g->statics_read,
791 w_l->statics_read);
792 if (!(flags & ECF_PURE)
793 && !w->cannot_return_p ())
794 write_all = union_static_var_sets (node_g->statics_written,
795 w_l->statics_written);
798 propagate_bits (node_g, w);
801 /* All nodes within a cycle have the same global info bitmaps. */
802 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
804 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
805 w_ri->global = *node_g;
808 cycle_nodes.release ();
811 if (dump_file)
813 for (i = 0; i < order_pos; i++)
815 unsigned x;
816 struct cgraph_node *w;
818 node = order[i];
819 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
820 continue;
822 fprintf (dump_file,
823 "\nFunction name:%s/%i:",
824 node->asm_name (), node->order);
826 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
827 ipa_reference_global_vars_info_t node_g = &node_info->global;
829 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
830 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
832 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
833 ipa_reference_local_vars_info_t w_l = &w_ri->local;
834 if (w != node)
835 fprintf (dump_file, "\n next cycle: %s/%i ",
836 w->asm_name (), w->order);
837 fprintf (dump_file, "\n locals read: ");
838 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
839 fprintf (dump_file, "\n locals written: ");
840 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
842 cycle_nodes.release ();
844 fprintf (dump_file, "\n globals read: ");
845 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
846 fprintf (dump_file, "\n globals written: ");
847 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
848 fprintf (dump_file, "\n");
852 /* Cleanup. */
853 FOR_EACH_DEFINED_FUNCTION (node)
855 ipa_reference_vars_info_t node_info;
856 ipa_reference_global_vars_info_t node_g;
857 ipa_reference_optimization_summary_t opt;
859 node_info = get_reference_vars_info (node);
860 if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
861 && (node->get_availability () > AVAIL_INTERPOSABLE
862 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
864 node_g = &node_info->global;
866 opt = XCNEW (struct ipa_reference_optimization_summary_d);
867 set_reference_optimization_summary (node, opt);
869 /* Create the complimentary sets. */
871 if (bitmap_empty_p (node_g->statics_read))
872 opt->statics_not_read = all_module_statics;
873 else
875 opt->statics_not_read
876 = BITMAP_ALLOC (&optimization_summary_obstack);
877 if (node_g->statics_read != all_module_statics)
878 bitmap_and_compl (opt->statics_not_read,
879 all_module_statics,
880 node_g->statics_read);
883 if (bitmap_empty_p (node_g->statics_written))
884 opt->statics_not_written = all_module_statics;
885 else
887 opt->statics_not_written
888 = BITMAP_ALLOC (&optimization_summary_obstack);
889 if (node_g->statics_written != all_module_statics)
890 bitmap_and_compl (opt->statics_not_written,
891 all_module_statics,
892 node_g->statics_written);
895 free (node_info);
898 ipa_free_postorder_info ();
899 free (order);
901 bitmap_obstack_release (&local_info_obstack);
902 ipa_reference_vars_vector.release ();
903 if (dump_file)
904 splay_tree_delete (reference_vars_to_consider);
905 reference_vars_to_consider = NULL;
906 return remove_p ? TODO_remove_functions : 0;
909 /* Return true if we need to write summary of NODE. */
911 static bool
912 write_node_summary_p (struct cgraph_node *node,
913 lto_symtab_encoder_t encoder,
914 bitmap ltrans_statics)
916 ipa_reference_optimization_summary_t info;
918 /* See if we have (non-empty) info. */
919 if (!node->definition || node->global.inlined_to)
920 return false;
921 info = get_reference_optimization_summary (node);
922 if (!info || (bitmap_empty_p (info->statics_not_read)
923 && bitmap_empty_p (info->statics_not_written)))
924 return false;
926 /* See if we want to encode it.
927 Encode also referenced functions since constant folding might turn it into
928 a direct call.
930 In future we might also want to include summaries of functions references
931 by initializers of constant variables references in current unit. */
932 if (!reachable_from_this_partition_p (node, encoder)
933 && !referenced_from_this_partition_p (node, encoder))
934 return false;
936 /* See if the info has non-empty intersections with vars we want to encode. */
937 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
938 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
939 return false;
940 return true;
943 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
944 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
945 or -1. When it is positive, just output -1 when
946 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
948 static void
949 stream_out_bitmap (struct lto_simple_output_block *ob,
950 bitmap bits, bitmap ltrans_statics,
951 int ltrans_statics_bitcount)
953 int count = 0;
954 unsigned int index;
955 bitmap_iterator bi;
956 if (bits == all_module_statics)
958 streamer_write_hwi_stream (ob->main_stream, -1);
959 return;
961 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
962 count ++;
963 if (count == ltrans_statics_bitcount)
965 streamer_write_hwi_stream (ob->main_stream, -1);
966 return;
968 streamer_write_hwi_stream (ob->main_stream, count);
969 if (!count)
970 return;
971 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
973 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
974 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
978 /* Serialize the ipa info for lto. */
980 static void
981 ipa_reference_write_optimization_summary (void)
983 struct lto_simple_output_block *ob
984 = lto_create_simple_output_block (LTO_section_ipa_reference);
985 unsigned int count = 0;
986 int ltrans_statics_bitcount = 0;
987 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
988 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
989 int i;
991 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
993 /* See what variables we are interested in. */
994 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
996 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
997 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
998 if (vnode
999 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
1000 && referenced_from_this_partition_p (vnode, encoder))
1002 tree decl = vnode->decl;
1003 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
1004 splay_tree_insert (reference_vars_to_consider,
1005 DECL_UID (decl), (splay_tree_value)decl);
1006 ltrans_statics_bitcount ++;
1011 if (ltrans_statics_bitcount)
1012 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1014 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1015 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1016 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1017 count++;
1020 streamer_write_uhwi_stream (ob->main_stream, count);
1021 if (count)
1022 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1023 -1);
1025 /* Process all of the functions. */
1026 if (ltrans_statics_bitcount)
1027 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1029 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1030 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1031 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1033 ipa_reference_optimization_summary_t info;
1034 int node_ref;
1036 info = get_reference_optimization_summary (cnode);
1037 node_ref = lto_symtab_encoder_encode (encoder, snode);
1038 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1040 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1041 ltrans_statics_bitcount);
1042 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1043 ltrans_statics_bitcount);
1046 BITMAP_FREE (ltrans_statics);
1047 lto_destroy_simple_output_block (ob);
1048 splay_tree_delete (reference_vars_to_consider);
1051 /* Deserialize the ipa info for lto. */
1053 static void
1054 ipa_reference_read_optimization_summary (void)
1056 struct lto_file_decl_data ** file_data_vec
1057 = lto_get_file_decl_data ();
1058 struct lto_file_decl_data * file_data;
1059 unsigned int j = 0;
1060 bitmap_obstack_initialize (&optimization_summary_obstack);
1062 node_removal_hook_holder =
1063 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
1064 node_duplication_hook_holder =
1065 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
1066 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1068 while ((file_data = file_data_vec[j++]))
1070 const char *data;
1071 size_t len;
1072 struct lto_input_block *ib
1073 = lto_create_simple_input_block (file_data,
1074 LTO_section_ipa_reference,
1075 &data, &len);
1076 if (ib)
1078 unsigned int i;
1079 unsigned int f_count = streamer_read_uhwi (ib);
1080 int b_count;
1081 if (!f_count)
1082 continue;
1083 b_count = streamer_read_hwi (ib);
1084 if (dump_file)
1085 fprintf (dump_file, "all module statics:");
1086 for (i = 0; i < (unsigned int)b_count; i++)
1088 unsigned int var_index = streamer_read_uhwi (ib);
1089 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1090 var_index);
1091 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1092 if (dump_file)
1093 fprintf (dump_file, " %s", fndecl_name (v_decl));
1096 for (i = 0; i < f_count; i++)
1098 unsigned int j, index;
1099 struct cgraph_node *node;
1100 ipa_reference_optimization_summary_t info;
1101 int v_count;
1102 lto_symtab_encoder_t encoder;
1104 index = streamer_read_uhwi (ib);
1105 encoder = file_data->symtab_node_encoder;
1106 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1107 (encoder, index));
1108 info = XCNEW (struct ipa_reference_optimization_summary_d);
1109 set_reference_optimization_summary (node, info);
1110 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1111 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1112 if (dump_file)
1113 fprintf (dump_file,
1114 "\nFunction name:%s/%i:\n static not read:",
1115 node->asm_name (), node->order);
1117 /* Set the statics not read. */
1118 v_count = streamer_read_hwi (ib);
1119 if (v_count == -1)
1121 info->statics_not_read = all_module_statics;
1122 if (dump_file)
1123 fprintf (dump_file, " all module statics");
1125 else
1126 for (j = 0; j < (unsigned int)v_count; j++)
1128 unsigned int var_index = streamer_read_uhwi (ib);
1129 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1130 var_index);
1131 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1132 if (dump_file)
1133 fprintf (dump_file, " %s", fndecl_name (v_decl));
1136 if (dump_file)
1137 fprintf (dump_file,
1138 "\n static not written:");
1139 /* Set the statics not written. */
1140 v_count = streamer_read_hwi (ib);
1141 if (v_count == -1)
1143 info->statics_not_written = all_module_statics;
1144 if (dump_file)
1145 fprintf (dump_file, " all module statics");
1147 else
1148 for (j = 0; j < (unsigned int)v_count; j++)
1150 unsigned int var_index = streamer_read_uhwi (ib);
1151 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1152 var_index);
1153 bitmap_set_bit (info->statics_not_written, DECL_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 with
1167 different version of compiler or different flags than the WPA unit, so
1168 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_init_p)
1235 bitmap_obstack_release (&optimization_summary_obstack);
1236 ipa_init_p = false;
1239 if (node_removal_hook_holder)
1241 symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
1242 node_removal_hook_holder = NULL;
1244 if (node_duplication_hook_holder)
1246 symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder);
1247 node_duplication_hook_holder = NULL;