2014-04-15 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / ipa-reference.c
blobdbe32e4371a2dd331b7c9407082f3b0a8b3f72e6
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2014 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 "tree.h"
44 #include "calls.h"
45 #include "basic-block.h"
46 #include "tree-ssa-alias.h"
47 #include "internal-fn.h"
48 #include "gimple-expr.h"
49 #include "is-a.h"
50 #include "gimple.h"
51 #include "tree-inline.h"
52 #include "tree-pass.h"
53 #include "splay-tree.h"
54 #include "ipa-utils.h"
55 #include "ipa-reference.h"
56 #include "flags.h"
57 #include "diagnostic.h"
58 #include "data-streamer.h"
59 #include "lto-streamer.h"
61 static void remove_node_data (struct cgraph_node *node,
62 void *data ATTRIBUTE_UNUSED);
63 static void duplicate_node_data (struct cgraph_node *src,
64 struct cgraph_node *dst,
65 void *data ATTRIBUTE_UNUSED);
67 /* The static variables defined within the compilation unit that are
68 loaded or stored directly by function that owns this structure. */
70 struct ipa_reference_local_vars_info_d
72 bitmap statics_read;
73 bitmap statics_written;
76 /* Statics that are read and written by some set of functions. The
77 local ones are based on the loads and stores local to the function.
78 The global ones are based on the local info as well as the
79 transitive closure of the functions that are called. */
81 struct ipa_reference_global_vars_info_d
83 bitmap statics_read;
84 bitmap statics_written;
87 /* Information we save about every function after ipa-reference is completed. */
89 struct ipa_reference_optimization_summary_d
91 bitmap statics_not_read;
92 bitmap statics_not_written;
95 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
96 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
97 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
99 struct ipa_reference_vars_info_d
101 struct ipa_reference_local_vars_info_d local;
102 struct ipa_reference_global_vars_info_d global;
105 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
107 /* This splay tree contains all of the static variables that are
108 being considered by the compilation level alias analysis. */
109 static splay_tree reference_vars_to_consider;
111 /* Set of all interesting module statics. A bit is set for every module
112 static we are considering. This is added to the local info when asm
113 code is found that clobbers all memory. */
114 static bitmap all_module_statics;
116 /* Obstack holding bitmaps of local analysis (live from analysis to
117 propagation) */
118 static bitmap_obstack local_info_obstack;
119 /* Obstack holding global analysis live forever. */
120 static bitmap_obstack optimization_summary_obstack;
122 /* Holders of ipa cgraph hooks: */
123 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
124 static struct cgraph_node_hook_list *node_removal_hook_holder;
126 /* Vector where the reference var infos are actually stored.
127 Indexed by UID of call graph nodes. */
128 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
130 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
132 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
133 static inline ipa_reference_vars_info_t
134 get_reference_vars_info (struct cgraph_node *node)
136 if (!ipa_reference_vars_vector.exists ()
137 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
138 return NULL;
139 return ipa_reference_vars_vector[node->uid];
142 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
143 static inline ipa_reference_optimization_summary_t
144 get_reference_optimization_summary (struct cgraph_node *node)
146 if (!ipa_reference_opt_sum_vector.exists ()
147 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
148 return NULL;
149 return ipa_reference_opt_sum_vector[node->uid];
152 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
153 static inline void
154 set_reference_vars_info (struct cgraph_node *node,
155 ipa_reference_vars_info_t info)
157 if (!ipa_reference_vars_vector.exists ()
158 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
159 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
160 ipa_reference_vars_vector[node->uid] = info;
163 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
164 static inline void
165 set_reference_optimization_summary (struct cgraph_node *node,
166 ipa_reference_optimization_summary_t info)
168 if (!ipa_reference_opt_sum_vector.exists ()
169 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
170 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
171 ipa_reference_opt_sum_vector[node->uid] = info;
174 /* Return a bitmap indexed by DECL_UID for the static variables that
175 are *not* read during the execution of the function FN. Returns
176 NULL if no data is available. */
178 bitmap
179 ipa_reference_get_not_read_global (struct cgraph_node *fn)
181 ipa_reference_optimization_summary_t info =
182 get_reference_optimization_summary (cgraph_function_node (fn, NULL));
183 if (info)
184 return info->statics_not_read;
185 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
186 return all_module_statics;
187 else
188 return NULL;
191 /* Return a bitmap indexed by DECL_UID for the static variables that
192 are *not* written during the execution of the function FN. Note
193 that variables written may or may not be read during the function
194 call. Returns NULL if no data is available. */
196 bitmap
197 ipa_reference_get_not_written_global (struct cgraph_node *fn)
199 ipa_reference_optimization_summary_t info =
200 get_reference_optimization_summary (fn);
201 if (info)
202 return info->statics_not_written;
203 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
204 return all_module_statics;
205 else
206 return NULL;
211 /* Add VAR to all_module_statics and the two
212 reference_vars_to_consider* sets. */
214 static inline void
215 add_static_var (tree var)
217 int uid = DECL_UID (var);
218 gcc_assert (TREE_CODE (var) == VAR_DECL);
219 if (dump_file)
220 splay_tree_insert (reference_vars_to_consider,
221 uid, (splay_tree_value)var);
222 bitmap_set_bit (all_module_statics, uid);
225 /* Return true if the variable T is the right kind of static variable to
226 perform compilation unit scope escape analysis. */
228 static inline bool
229 is_proper_for_analysis (tree t)
231 /* If the variable has the "used" attribute, treat it as if it had a
232 been touched by the devil. */
233 if (DECL_PRESERVE_P (t))
234 return false;
236 /* Do not want to do anything with volatile except mark any
237 function that uses one to be not const or pure. */
238 if (TREE_THIS_VOLATILE (t))
239 return false;
241 /* We do not need to analyze readonly vars, we already know they do not
242 alias. */
243 if (TREE_READONLY (t))
244 return false;
246 /* This is a variable we care about. Check if we have seen it
247 before, and if not add it the set of variables we care about. */
248 if (all_module_statics
249 && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
250 add_static_var (t);
252 return true;
255 /* Lookup the tree node for the static variable that has UID and
256 convert the name to a string for debugging. */
258 static const char *
259 get_static_name (int index)
261 splay_tree_node stn =
262 splay_tree_lookup (reference_vars_to_consider, index);
263 return fndecl_name ((tree)(stn->value));
266 /* Dump a set of static vars to FILE. */
267 static void
268 dump_static_vars_set_to_file (FILE *f, bitmap set)
270 unsigned int index;
271 bitmap_iterator bi;
272 if (set == NULL)
273 return;
274 else if (set == all_module_statics)
275 fprintf (f, "ALL");
276 else
277 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
279 fprintf (f, "%s ", get_static_name (index));
283 /* Compute X |= Y, taking into account the possibility that
284 either X or Y is already the maximum set.
285 Return true if X is the maximum set after taking the union with Y. */
287 static bool
288 union_static_var_sets (bitmap &x, bitmap y)
290 if (x != all_module_statics)
292 if (y == all_module_statics)
294 BITMAP_FREE (x);
295 x = all_module_statics;
297 else if (bitmap_ior_into (x, y))
299 /* The union may have reduced X to the maximum set.
300 In that case, we want to make that visible explicitly.
301 Even though bitmap_equal_p can be very expensive, it
302 turns out to be an overall win to check this here for
303 an LTO bootstrap of GCC itself. Liberally extrapoliate
304 that result to be applicable to all cases. */
305 if (bitmap_equal_p (x, all_module_statics))
307 BITMAP_FREE (x);
308 x = all_module_statics;
312 return x == all_module_statics;
315 /* Compute X &= Y, taking into account the possibility that
316 X may become the maximum set. */
318 static bool
319 intersect_static_var_sets (bitmap &x, bitmap y)
321 if (x != all_module_statics)
323 bitmap_and_into (x, y);
324 /* As with union_static_var_sets, reducing to the maximum
325 set as early as possible is an overall win. */
326 if (bitmap_equal_p (x, all_module_statics))
328 BITMAP_FREE (x);
329 x = all_module_statics;
332 return x == all_module_statics;
335 /* Return a copy of SET on the bitmap obstack containing SET.
336 But if SET is NULL or the maximum set, return that instead. */
338 static bitmap
339 copy_static_var_set (bitmap set)
341 if (set == NULL || set == all_module_statics)
342 return set;
343 bitmap_obstack *o = set->obstack;
344 gcc_checking_assert (o);
345 bitmap copy = BITMAP_ALLOC (o);
346 bitmap_copy (copy, set);
347 return copy;
350 /* Compute the union all of the statics read and written by every callee of X
351 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
352 actually the set representing the cycle containing X. If the read and
353 written sets of X_GLOBAL has been reduced to the maximum set, we don't
354 have to look at the remaining callees. */
356 static void
357 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
359 struct cgraph_edge *e;
360 bool read_all = x_global->statics_read == all_module_statics;
361 bool write_all = x_global->statics_written == all_module_statics;
362 for (e = x->callees;
363 e && !(read_all && write_all);
364 e = e->next_callee)
366 enum availability avail;
367 struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
368 if (!y)
369 continue;
371 /* Only look into nodes we can propagate something. */
372 int flags = flags_from_decl_or_type (y->decl);
373 if (avail > AVAIL_OVERWRITABLE
374 || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF)))
376 if (get_reference_vars_info (y))
378 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
379 ipa_reference_global_vars_info_t y_global = &y_info->global;
381 /* Calls in the current cycle do not have their global set
382 computed yet (but everything else does because we're
383 visiting nodes in topological order). */
384 if (!y_global->statics_read)
385 continue;
387 /* If the function is const, it reads no memory even if it
388 seems so to local analysis. */
389 if (flags & ECF_CONST)
390 continue;
392 union_static_var_sets (x_global->statics_read,
393 y_global->statics_read);
395 /* If the function is pure, it has no stores even if it
396 seems so to local analysis. If we cannot return from
397 the function, we can safely ignore the call. */
398 if ((flags & ECF_PURE)
399 || cgraph_edge_cannot_lead_to_return (e))
400 continue;
402 union_static_var_sets (x_global->statics_written,
403 y_global->statics_written);
405 else
406 gcc_unreachable ();
411 /* The init routine for analyzing global static variable usage. See
412 comments at top for description. */
413 static void
414 ipa_init (void)
416 static bool init_p = false;
418 if (init_p)
419 return;
421 init_p = true;
423 if (dump_file)
424 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
426 bitmap_obstack_initialize (&local_info_obstack);
427 bitmap_obstack_initialize (&optimization_summary_obstack);
428 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
430 node_removal_hook_holder =
431 cgraph_add_node_removal_hook (&remove_node_data, NULL);
432 node_duplication_hook_holder =
433 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
437 /* Set up the persistent info for FN. */
439 static ipa_reference_local_vars_info_t
440 init_function_info (struct cgraph_node *fn)
442 ipa_reference_vars_info_t info
443 = XCNEW (struct ipa_reference_vars_info_d);
445 /* Add the info to the tree's annotation. */
446 set_reference_vars_info (fn, info);
448 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
449 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
451 return &info->local;
455 /* This is the main routine for finding the reference patterns for
456 global variables within a function FN. */
458 static void
459 analyze_function (struct cgraph_node *fn)
461 ipa_reference_local_vars_info_t local;
462 struct ipa_ref *ref;
463 int i;
464 tree var;
466 local = init_function_info (fn);
467 for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
469 if (!is_a <varpool_node> (ref->referred))
470 continue;
471 var = ipa_ref_varpool_node (ref)->decl;
472 if (!is_proper_for_analysis (var))
473 continue;
474 switch (ref->use)
476 case IPA_REF_LOAD:
477 bitmap_set_bit (local->statics_read, DECL_UID (var));
478 break;
479 case IPA_REF_STORE:
480 if (ipa_ref_cannot_lead_to_return (ref))
481 break;
482 bitmap_set_bit (local->statics_written, DECL_UID (var));
483 break;
484 case IPA_REF_ADDR:
485 break;
489 if (cgraph_node_cannot_return (fn))
490 bitmap_clear (local->statics_written);
494 /* Called when new clone is inserted to callgraph late. */
496 static void
497 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
498 void *data ATTRIBUTE_UNUSED)
500 ipa_reference_optimization_summary_t ginfo;
501 ipa_reference_optimization_summary_t dst_ginfo;
503 ginfo = get_reference_optimization_summary (src);
504 if (!ginfo)
505 return;
506 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
507 set_reference_optimization_summary (dst, dst_ginfo);
508 dst_ginfo->statics_not_read =
509 copy_static_var_set (ginfo->statics_not_read);
510 dst_ginfo->statics_not_written =
511 copy_static_var_set (ginfo->statics_not_written);
514 /* Called when node is removed. */
516 static void
517 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
519 ipa_reference_optimization_summary_t ginfo;
520 ginfo = get_reference_optimization_summary (node);
521 if (ginfo)
523 if (ginfo->statics_not_read
524 && ginfo->statics_not_read != all_module_statics)
525 BITMAP_FREE (ginfo->statics_not_read);
527 if (ginfo->statics_not_written
528 && ginfo->statics_not_written != all_module_statics)
529 BITMAP_FREE (ginfo->statics_not_written);
530 free (ginfo);
531 set_reference_optimization_summary (node, NULL);
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 analyze_function (node);
551 if (dump_file)
552 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
554 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
555 get_static_name (index), index);
558 if (dump_file)
559 FOR_EACH_DEFINED_FUNCTION (node)
560 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
562 ipa_reference_local_vars_info_t l;
563 unsigned int index;
564 bitmap_iterator bi;
566 l = &get_reference_vars_info (node)->local;
567 fprintf (dump_file,
568 "\nFunction name:%s/%i:",
569 node->asm_name (), node->order);
570 fprintf (dump_file, "\n locals read: ");
571 if (l->statics_read)
572 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
573 0, index, bi)
575 fprintf (dump_file, "%s ",
576 get_static_name (index));
578 fprintf (dump_file, "\n locals written: ");
579 if (l->statics_written)
580 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
581 0, index, bi)
583 fprintf (dump_file, "%s ", get_static_name (index));
588 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
590 static void
591 read_write_all_from_decl (struct cgraph_node *node,
592 bool &read_all, bool &write_all)
594 tree decl = node->decl;
595 int flags = flags_from_decl_or_type (decl);
596 if ((flags & ECF_LEAF)
597 && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
599 else if (flags & ECF_CONST)
601 else if ((flags & ECF_PURE)
602 || cgraph_node_cannot_return (node))
604 read_all = true;
605 if (dump_file && (dump_flags & TDF_DETAILS))
606 fprintf (dump_file, " %s/%i -> read all\n",
607 node->asm_name (), node->order);
609 else
611 /* TODO: To be able to produce sane results, we should also handle
612 common builtins, in particular throw. */
613 read_all = true;
614 write_all = true;
615 if (dump_file && (dump_flags & TDF_DETAILS))
616 fprintf (dump_file, " %s/%i -> read all, write all\n",
617 node->asm_name (), node->order);
621 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
622 in the cycle of NODE. */
624 static void
625 get_read_write_all_from_node (struct cgraph_node *node,
626 bool &read_all, bool &write_all)
628 struct cgraph_edge *e, *ie;
630 /* When function is overwritable, we can not assume anything. */
631 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
632 read_write_all_from_decl (node, read_all, write_all);
634 for (e = node->callees;
635 e && !(read_all && write_all);
636 e = e->next_callee)
638 enum availability avail;
639 struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
640 gcc_checking_assert (callee);
641 if (avail <= AVAIL_OVERWRITABLE)
642 read_write_all_from_decl (callee, read_all, write_all);
645 for (ie = node->indirect_calls;
646 ie && !(read_all && write_all);
647 ie = ie->next_callee)
648 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
650 read_all = true;
651 if (dump_file && (dump_flags & TDF_DETAILS))
652 fprintf (dump_file, " indirect call -> read all\n");
653 if (!cgraph_edge_cannot_lead_to_return (ie)
654 && !(ie->indirect_info->ecf_flags & ECF_PURE))
656 if (dump_file && (dump_flags & TDF_DETAILS))
657 fprintf (dump_file, " indirect call -> write all\n");
658 write_all = true;
663 /* Produce the global information by preforming a transitive closure
664 on the local information that was produced by ipa_analyze_function. */
666 static unsigned int
667 propagate (void)
669 struct cgraph_node *node;
670 varpool_node *vnode;
671 struct cgraph_node **order =
672 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
673 int order_pos;
674 int i;
676 if (dump_file)
677 dump_cgraph (dump_file);
679 ipa_discover_readonly_nonaddressable_vars ();
680 generate_summary ();
682 /* Now we know what vars are really statics; prune out those that aren't. */
683 FOR_EACH_VARIABLE (vnode)
684 if (vnode->externally_visible
685 || TREE_ADDRESSABLE (vnode->decl)
686 || TREE_READONLY (vnode->decl)
687 || !is_proper_for_analysis (vnode->decl)
688 || !vnode->definition)
689 bitmap_clear_bit (all_module_statics, DECL_UID (vnode->decl));
691 /* Forget info we collected "just for fun" on variables that turned out to be
692 non-local. */
693 FOR_EACH_DEFINED_FUNCTION (node)
695 ipa_reference_local_vars_info_t node_l;
696 node_l = &get_reference_vars_info (node)->local;
697 intersect_static_var_sets (node_l->statics_read, all_module_statics);
698 intersect_static_var_sets (node_l->statics_written, all_module_statics);
701 /* Propagate the local information through the call graph to produce
702 the global information. All the nodes within a cycle will have
703 the same info so we collapse cycles first. Then we can do the
704 propagation in one pass from the leaves to the roots. */
705 order_pos = ipa_reduced_postorder (order, true, true, NULL);
706 if (dump_file)
707 ipa_print_order (dump_file, "reduced", order, order_pos);
709 for (i = 0; i < order_pos; i++ )
711 unsigned x;
712 struct cgraph_node *w;
713 ipa_reference_vars_info_t node_info;
714 ipa_reference_global_vars_info_t node_g;
715 ipa_reference_local_vars_info_t node_l;
716 bool read_all = false;
717 bool write_all = false;
719 node = order[i];
720 if (node->alias)
721 continue;
723 node_info = get_reference_vars_info (node);
724 gcc_assert (node_info);
725 node_l = &node_info->local;
726 node_g = &node_info->global;
728 if (dump_file && (dump_flags & TDF_DETAILS))
729 fprintf (dump_file, "Starting cycle with %s/%i\n",
730 node->asm_name (), node->order);
732 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
734 /* If any node in a cycle is read_all or write_all, they all are. */
735 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
737 if (dump_file && (dump_flags & TDF_DETAILS))
738 fprintf (dump_file, " Visiting %s/%i\n",
739 w->asm_name (), w->order);
740 get_read_write_all_from_node (w, read_all, write_all);
741 if (read_all && write_all)
742 break;
745 /* Initialized the bitmaps global sets for the reduced node. */
746 if (read_all)
747 node_g->statics_read = all_module_statics;
748 else
749 node_g->statics_read = copy_static_var_set (node_l->statics_read);
750 if (write_all)
751 node_g->statics_written = all_module_statics;
752 else
753 node_g->statics_written = copy_static_var_set (node_l->statics_written);
755 /* Merge the sets of this cycle with all sets of callees reached
756 from this cycle. */
757 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
759 if (read_all && write_all)
760 break;
762 if (w != node)
764 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
765 ipa_reference_local_vars_info_t w_l = &w_ri->local;
766 int flags = flags_from_decl_or_type (w->decl);
768 if (!(flags & ECF_CONST))
769 read_all = union_static_var_sets (node_g->statics_read,
770 w_l->statics_read);
771 if (!(flags & ECF_PURE)
772 && !cgraph_node_cannot_return (w))
773 write_all = union_static_var_sets (node_g->statics_written,
774 w_l->statics_written);
777 propagate_bits (node_g, w);
780 /* All nodes within a cycle have the same global info bitmaps. */
781 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
783 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
784 w_ri->global = *node_g;
787 cycle_nodes.release ();
790 if (dump_file)
792 for (i = 0; i < order_pos; i++)
794 unsigned x;
795 struct cgraph_node *w;
797 node = order[i];
798 if (node->alias)
799 continue;
801 fprintf (dump_file,
802 "\nFunction name:%s/%i:",
803 node->asm_name (), node->order);
805 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
806 ipa_reference_global_vars_info_t node_g = &node_info->global;
808 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
809 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
811 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
812 ipa_reference_local_vars_info_t w_l = &w_ri->local;
813 if (w != node)
814 fprintf (dump_file, "\n next cycle: %s/%i ",
815 w->asm_name (), w->order);
816 fprintf (dump_file, "\n locals read: ");
817 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
818 fprintf (dump_file, "\n locals written: ");
819 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
821 cycle_nodes.release ();
823 fprintf (dump_file, "\n globals read: ");
824 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
825 fprintf (dump_file, "\n globals written: ");
826 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
827 fprintf (dump_file, "\n");
831 /* Cleanup. */
832 FOR_EACH_DEFINED_FUNCTION (node)
834 ipa_reference_vars_info_t node_info;
835 ipa_reference_global_vars_info_t node_g;
836 ipa_reference_optimization_summary_t opt;
838 node_info = get_reference_vars_info (node);
839 if (!node->alias
840 && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
841 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
843 node_g = &node_info->global;
845 opt = XCNEW (struct ipa_reference_optimization_summary_d);
846 set_reference_optimization_summary (node, opt);
848 /* Create the complimentary sets. */
850 if (bitmap_empty_p (node_g->statics_read))
851 opt->statics_not_read = all_module_statics;
852 else
854 opt->statics_not_read
855 = BITMAP_ALLOC (&optimization_summary_obstack);
856 if (node_g->statics_read != all_module_statics)
857 bitmap_and_compl (opt->statics_not_read,
858 all_module_statics,
859 node_g->statics_read);
862 if (bitmap_empty_p (node_g->statics_written))
863 opt->statics_not_written = all_module_statics;
864 else
866 opt->statics_not_written
867 = BITMAP_ALLOC (&optimization_summary_obstack);
868 if (node_g->statics_written != all_module_statics)
869 bitmap_and_compl (opt->statics_not_written,
870 all_module_statics,
871 node_g->statics_written);
874 free (node_info);
877 ipa_free_postorder_info ();
878 free (order);
880 bitmap_obstack_release (&local_info_obstack);
881 ipa_reference_vars_vector.release ();
882 if (dump_file)
883 splay_tree_delete (reference_vars_to_consider);
884 reference_vars_to_consider = NULL;
885 return 0;
888 /* Return true if we need to write summary of NODE. */
890 static bool
891 write_node_summary_p (struct cgraph_node *node,
892 lto_symtab_encoder_t encoder,
893 bitmap ltrans_statics)
895 ipa_reference_optimization_summary_t info;
897 /* See if we have (non-empty) info. */
898 if (!node->definition || node->global.inlined_to)
899 return false;
900 info = get_reference_optimization_summary (node);
901 if (!info || (bitmap_empty_p (info->statics_not_read)
902 && bitmap_empty_p (info->statics_not_written)))
903 return false;
905 /* See if we want to encode it.
906 Encode also referenced functions since constant folding might turn it into
907 a direct call.
909 In future we might also want to include summaries of functions references
910 by initializers of constant variables references in current unit. */
911 if (!reachable_from_this_partition_p (node, encoder)
912 && !referenced_from_this_partition_p (&node->ref_list, encoder))
913 return false;
915 /* See if the info has non-empty intersections with vars we want to encode. */
916 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
917 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
918 return false;
919 return true;
922 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
923 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
924 or -1. When it is positive, just output -1 when
925 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
927 static void
928 stream_out_bitmap (struct lto_simple_output_block *ob,
929 bitmap bits, bitmap ltrans_statics,
930 int ltrans_statics_bitcount)
932 int count = 0;
933 unsigned int index;
934 bitmap_iterator bi;
935 if (bits == all_module_statics)
937 streamer_write_hwi_stream (ob->main_stream, -1);
938 return;
940 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
941 count ++;
942 if (count == ltrans_statics_bitcount)
944 streamer_write_hwi_stream (ob->main_stream, -1);
945 return;
947 streamer_write_hwi_stream (ob->main_stream, count);
948 if (!count)
949 return;
950 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
952 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
953 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
957 /* Serialize the ipa info for lto. */
959 static void
960 ipa_reference_write_optimization_summary (void)
962 struct lto_simple_output_block *ob
963 = lto_create_simple_output_block (LTO_section_ipa_reference);
964 unsigned int count = 0;
965 int ltrans_statics_bitcount = 0;
966 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
967 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
968 int i;
970 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
972 /* See what variables we are interested in. */
973 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
975 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
976 varpool_node *vnode = dyn_cast <varpool_node> (snode);
977 if (vnode
978 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
979 && referenced_from_this_partition_p (&vnode->ref_list, encoder))
981 tree decl = vnode->decl;
982 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
983 splay_tree_insert (reference_vars_to_consider,
984 DECL_UID (decl), (splay_tree_value)decl);
985 ltrans_statics_bitcount ++;
990 if (ltrans_statics_bitcount)
991 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
993 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
994 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
995 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
996 count++;
999 streamer_write_uhwi_stream (ob->main_stream, count);
1000 if (count)
1001 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1002 -1);
1004 /* Process all of the functions. */
1005 if (ltrans_statics_bitcount)
1006 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1008 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1009 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
1010 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1012 ipa_reference_optimization_summary_t info;
1013 int node_ref;
1015 info = get_reference_optimization_summary (cnode);
1016 node_ref = lto_symtab_encoder_encode (encoder, snode);
1017 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1019 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1020 ltrans_statics_bitcount);
1021 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1022 ltrans_statics_bitcount);
1025 BITMAP_FREE (ltrans_statics);
1026 lto_destroy_simple_output_block (ob);
1027 splay_tree_delete (reference_vars_to_consider);
1030 /* Deserialize the ipa info for lto. */
1032 static void
1033 ipa_reference_read_optimization_summary (void)
1035 struct lto_file_decl_data ** file_data_vec
1036 = lto_get_file_decl_data ();
1037 struct lto_file_decl_data * file_data;
1038 unsigned int j = 0;
1039 bitmap_obstack_initialize (&optimization_summary_obstack);
1041 node_removal_hook_holder =
1042 cgraph_add_node_removal_hook (&remove_node_data, NULL);
1043 node_duplication_hook_holder =
1044 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1045 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1047 while ((file_data = file_data_vec[j++]))
1049 const char *data;
1050 size_t len;
1051 struct lto_input_block *ib
1052 = lto_create_simple_input_block (file_data,
1053 LTO_section_ipa_reference,
1054 &data, &len);
1055 if (ib)
1057 unsigned int i;
1058 unsigned int f_count = streamer_read_uhwi (ib);
1059 int b_count;
1060 if (!f_count)
1061 continue;
1062 b_count = streamer_read_hwi (ib);
1063 if (dump_file)
1064 fprintf (dump_file, "all module statics:");
1065 for (i = 0; i < (unsigned int)b_count; i++)
1067 unsigned int var_index = streamer_read_uhwi (ib);
1068 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1069 var_index);
1070 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1071 if (dump_file)
1072 fprintf (dump_file, " %s", fndecl_name (v_decl));
1075 for (i = 0; i < f_count; i++)
1077 unsigned int j, index;
1078 struct cgraph_node *node;
1079 ipa_reference_optimization_summary_t info;
1080 int v_count;
1081 lto_symtab_encoder_t encoder;
1083 index = streamer_read_uhwi (ib);
1084 encoder = file_data->symtab_node_encoder;
1085 node = cgraph (lto_symtab_encoder_deref (encoder, index));
1086 info = XCNEW (struct ipa_reference_optimization_summary_d);
1087 set_reference_optimization_summary (node, info);
1088 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1089 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1090 if (dump_file)
1091 fprintf (dump_file,
1092 "\nFunction name:%s/%i:\n static not read:",
1093 node->asm_name (), node->order);
1095 /* Set the statics not read. */
1096 v_count = streamer_read_hwi (ib);
1097 if (v_count == -1)
1099 info->statics_not_read = all_module_statics;
1100 if (dump_file)
1101 fprintf (dump_file, " all module statics");
1103 else
1104 for (j = 0; j < (unsigned int)v_count; j++)
1106 unsigned int var_index = streamer_read_uhwi (ib);
1107 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1108 var_index);
1109 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1110 if (dump_file)
1111 fprintf (dump_file, " %s", fndecl_name (v_decl));
1114 if (dump_file)
1115 fprintf (dump_file,
1116 "\n static not written:");
1117 /* Set the statics not written. */
1118 v_count = streamer_read_hwi (ib);
1119 if (v_count == -1)
1121 info->statics_not_written = 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_written, DECL_UID (v_decl));
1132 if (dump_file)
1133 fprintf (dump_file, " %s", fndecl_name (v_decl));
1135 if (dump_file)
1136 fprintf (dump_file, "\n");
1139 lto_destroy_simple_input_block (file_data,
1140 LTO_section_ipa_reference,
1141 ib, data, len);
1143 else
1144 /* Fatal error here. We do not want to support compiling ltrans units with
1145 different version of compiler or different flags than the WPA unit, so
1146 this should never happen. */
1147 fatal_error ("ipa reference summary is missing in ltrans unit");
1151 static bool
1152 gate_reference (void)
1154 return (flag_ipa_reference
1155 /* Don't bother doing anything if the program has errors. */
1156 && !seen_error ());
1159 namespace {
1161 const pass_data pass_data_ipa_reference =
1163 IPA_PASS, /* type */
1164 "static-var", /* name */
1165 OPTGROUP_NONE, /* optinfo_flags */
1166 true, /* has_gate */
1167 true, /* has_execute */
1168 TV_IPA_REFERENCE, /* tv_id */
1169 0, /* properties_required */
1170 0, /* properties_provided */
1171 0, /* properties_destroyed */
1172 0, /* todo_flags_start */
1173 0, /* todo_flags_finish */
1176 class pass_ipa_reference : public ipa_opt_pass_d
1178 public:
1179 pass_ipa_reference (gcc::context *ctxt)
1180 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1181 NULL, /* generate_summary */
1182 NULL, /* write_summary */
1183 NULL, /* read_summary */
1184 ipa_reference_write_optimization_summary, /*
1185 write_optimization_summary */
1186 ipa_reference_read_optimization_summary, /*
1187 read_optimization_summary */
1188 NULL, /* stmt_fixup */
1189 0, /* function_transform_todo_flags_start */
1190 NULL, /* function_transform */
1191 NULL) /* variable_transform */
1194 /* opt_pass methods: */
1195 bool gate () { return gate_reference (); }
1196 unsigned int execute () { return propagate (); }
1198 }; // class pass_ipa_reference
1200 } // anon namespace
1202 ipa_opt_pass_d *
1203 make_pass_ipa_reference (gcc::context *ctxt)
1205 return new pass_ipa_reference (ctxt);