2013-09-20 Richard Biener <rguenther@suse.de>
[official-gcc.git] / gcc / ipa-reference.c
blobe6f19fdd1bf78573b0bd14ce21f021fbe93b8577
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2013 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 "tree-ssa.h"
45 #include "tree-inline.h"
46 #include "tree-pass.h"
47 #include "pointer-set.h"
48 #include "splay-tree.h"
49 #include "ggc.h"
50 #include "ipa-utils.h"
51 #include "ipa-reference.h"
52 #include "gimple.h"
53 #include "cgraph.h"
54 #include "flags.h"
55 #include "diagnostic.h"
56 #include "data-streamer.h"
57 #include "lto-streamer.h"
59 static void remove_node_data (struct cgraph_node *node,
60 void *data ATTRIBUTE_UNUSED);
61 static void duplicate_node_data (struct cgraph_node *src,
62 struct cgraph_node *dst,
63 void *data ATTRIBUTE_UNUSED);
65 /* The static variables defined within the compilation unit that are
66 loaded or stored directly by function that owns this structure. */
68 struct ipa_reference_local_vars_info_d
70 bitmap statics_read;
71 bitmap statics_written;
74 /* Statics that are read and written by some set of functions. The
75 local ones are based on the loads and stores local to the function.
76 The global ones are based on the local info as well as the
77 transitive closure of the functions that are called. */
79 struct ipa_reference_global_vars_info_d
81 bitmap statics_read;
82 bitmap statics_written;
85 /* Information we save about every function after ipa-reference is completed. */
87 struct ipa_reference_optimization_summary_d
89 bitmap statics_not_read;
90 bitmap statics_not_written;
93 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
94 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
95 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
97 struct ipa_reference_vars_info_d
99 struct ipa_reference_local_vars_info_d local;
100 struct ipa_reference_global_vars_info_d global;
103 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
105 /* This splay tree contains all of the static variables that are
106 being considered by the compilation level alias analysis. */
107 static splay_tree reference_vars_to_consider;
109 /* Set of all interesting module statics. A bit is set for every module
110 static we are considering. This is added to the local info when asm
111 code is found that clobbers all memory. */
112 static bitmap all_module_statics;
114 /* Obstack holding bitmaps of local analysis (live from analysis to
115 propagation) */
116 static bitmap_obstack local_info_obstack;
117 /* Obstack holding global analysis live forever. */
118 static bitmap_obstack optimization_summary_obstack;
120 /* Holders of ipa cgraph hooks: */
121 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
122 static struct cgraph_node_hook_list *node_removal_hook_holder;
124 /* Vector where the reference var infos are actually stored.
125 Indexed by UID of call graph nodes. */
126 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
128 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
130 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
131 static inline ipa_reference_vars_info_t
132 get_reference_vars_info (struct cgraph_node *node)
134 if (!ipa_reference_vars_vector.exists ()
135 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
136 return NULL;
137 return ipa_reference_vars_vector[node->uid];
140 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
141 static inline ipa_reference_optimization_summary_t
142 get_reference_optimization_summary (struct cgraph_node *node)
144 if (!ipa_reference_opt_sum_vector.exists ()
145 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
146 return NULL;
147 return ipa_reference_opt_sum_vector[node->uid];
150 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
151 static inline void
152 set_reference_vars_info (struct cgraph_node *node,
153 ipa_reference_vars_info_t info)
155 if (!ipa_reference_vars_vector.exists ()
156 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
157 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
158 ipa_reference_vars_vector[node->uid] = info;
161 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
162 static inline void
163 set_reference_optimization_summary (struct cgraph_node *node,
164 ipa_reference_optimization_summary_t info)
166 if (!ipa_reference_opt_sum_vector.exists ()
167 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
168 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
169 ipa_reference_opt_sum_vector[node->uid] = info;
172 /* Return a bitmap indexed by DECL_UID for the static variables that
173 are *not* read during the execution of the function FN. Returns
174 NULL if no data is available. */
176 bitmap
177 ipa_reference_get_not_read_global (struct cgraph_node *fn)
179 ipa_reference_optimization_summary_t info =
180 get_reference_optimization_summary (cgraph_function_node (fn, NULL));
181 if (info)
182 return info->statics_not_read;
183 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
184 return all_module_statics;
185 else
186 return NULL;
189 /* Return a bitmap indexed by DECL_UID for the static variables that
190 are *not* written during the execution of the function FN. Note
191 that variables written may or may not be read during the function
192 call. Returns NULL if no data is available. */
194 bitmap
195 ipa_reference_get_not_written_global (struct cgraph_node *fn)
197 ipa_reference_optimization_summary_t info =
198 get_reference_optimization_summary (fn);
199 if (info)
200 return info->statics_not_written;
201 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
202 return all_module_statics;
203 else
204 return NULL;
209 /* Add VAR to all_module_statics and the two
210 reference_vars_to_consider* sets. */
212 static inline void
213 add_static_var (tree var)
215 int uid = DECL_UID (var);
216 gcc_assert (TREE_CODE (var) == VAR_DECL);
217 if (dump_file)
218 splay_tree_insert (reference_vars_to_consider,
219 uid, (splay_tree_value)var);
220 bitmap_set_bit (all_module_statics, uid);
223 /* Return true if the variable T is the right kind of static variable to
224 perform compilation unit scope escape analysis. */
226 static inline bool
227 is_proper_for_analysis (tree t)
229 /* If the variable has the "used" attribute, treat it as if it had a
230 been touched by the devil. */
231 if (DECL_PRESERVE_P (t))
232 return false;
234 /* Do not want to do anything with volatile except mark any
235 function that uses one to be not const or pure. */
236 if (TREE_THIS_VOLATILE (t))
237 return false;
239 /* We do not need to analyze readonly vars, we already know they do not
240 alias. */
241 if (TREE_READONLY (t))
242 return false;
244 /* This is a variable we care about. Check if we have seen it
245 before, and if not add it the set of variables we care about. */
246 if (all_module_statics
247 && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
248 add_static_var (t);
250 return true;
253 /* Lookup the tree node for the static variable that has UID and
254 convert the name to a string for debugging. */
256 static const char *
257 get_static_name (int index)
259 splay_tree_node stn =
260 splay_tree_lookup (reference_vars_to_consider, index);
261 return fndecl_name ((tree)(stn->value));
264 /* Dump a set of static vars to FILE. */
265 static void
266 dump_static_vars_set_to_file (FILE *f, bitmap set)
268 unsigned int index;
269 bitmap_iterator bi;
270 if (set == NULL)
271 return;
272 else if (set == all_module_statics)
273 fprintf (f, "ALL");
274 else
275 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
277 fprintf (f, "%s ", get_static_name (index));
281 /* Compute X |= Y, taking into account the possibility that
282 either X or Y is already the maximum set.
283 Return true if X is the maximum set after taking the union with Y. */
285 static bool
286 union_static_var_sets (bitmap &x, bitmap y)
288 if (x != all_module_statics)
290 if (y == all_module_statics)
292 BITMAP_FREE (x);
293 x = all_module_statics;
295 else if (bitmap_ior_into (x, y))
297 /* The union may have reduced X to the maximum set.
298 In that case, we want to make that visible explicitly.
299 Even though bitmap_equal_p can be very expensive, it
300 turns out to be an overall win to check this here for
301 an LTO bootstrap of GCC itself. Liberally extrapoliate
302 that result to be applicable to all cases. */
303 if (bitmap_equal_p (x, all_module_statics))
305 BITMAP_FREE (x);
306 x = all_module_statics;
310 return x == all_module_statics;
313 /* Compute X &= Y, taking into account the possibility that
314 X may become the maximum set. */
316 static bool
317 intersect_static_var_sets (bitmap &x, bitmap y)
319 if (x != all_module_statics)
321 bitmap_and_into (x, y);
322 /* As with union_static_var_sets, reducing to the maximum
323 set as early as possible is an overall win. */
324 if (bitmap_equal_p (x, all_module_statics))
326 BITMAP_FREE (x);
327 x = all_module_statics;
330 return x == all_module_statics;
333 /* Return a copy of SET on the bitmap obstack containing SET.
334 But if SET is NULL or the maximum set, return that instead. */
336 static bitmap
337 copy_static_var_set (bitmap set)
339 if (set == NULL || set == all_module_statics)
340 return set;
341 bitmap_obstack *o = set->obstack;
342 gcc_checking_assert (o);
343 bitmap copy = BITMAP_ALLOC (o);
344 bitmap_copy (copy, set);
345 return copy;
348 /* Compute the union all of the statics read and written by every callee of X
349 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
350 actually the set representing the cycle containing X. If the read and
351 written sets of X_GLOBAL has been reduced to the maximum set, we don't
352 have to look at the remaining callees. */
354 static void
355 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
357 struct cgraph_edge *e;
358 bool read_all = x_global->statics_read == all_module_statics;
359 bool write_all = x_global->statics_written == all_module_statics;
360 for (e = x->callees;
361 e && !(read_all && write_all);
362 e = e->next_callee)
364 enum availability avail;
365 struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
366 if (!y)
367 continue;
369 /* Only look into nodes we can propagate something. */
370 int flags = flags_from_decl_or_type (y->symbol.decl);
371 if (avail > AVAIL_OVERWRITABLE
372 || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF)))
374 if (get_reference_vars_info (y))
376 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
377 ipa_reference_global_vars_info_t y_global = &y_info->global;
379 /* Calls in the current cycle do not have their global set
380 computed yet (but everything else does because we're
381 visiting nodes in topological order). */
382 if (!y_global->statics_read)
383 continue;
385 /* If the function is const, it reads no memory even if it
386 seems so to local analysis. */
387 if (flags & ECF_CONST)
388 continue;
390 union_static_var_sets (x_global->statics_read,
391 y_global->statics_read);
393 /* If the function is pure, it has no stores even if it
394 seems so to local analysis. If we cannot return from
395 the function, we can safely ignore the call. */
396 if ((flags & ECF_PURE)
397 || cgraph_edge_cannot_lead_to_return (e))
398 continue;
400 union_static_var_sets (x_global->statics_written,
401 y_global->statics_written);
403 else
404 gcc_unreachable ();
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 static bool init_p = false;
416 if (init_p)
417 return;
419 init_p = true;
421 if (dump_file)
422 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
424 bitmap_obstack_initialize (&local_info_obstack);
425 bitmap_obstack_initialize (&optimization_summary_obstack);
426 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
428 node_removal_hook_holder =
429 cgraph_add_node_removal_hook (&remove_node_data, NULL);
430 node_duplication_hook_holder =
431 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
435 /* Set up the persistent info for FN. */
437 static ipa_reference_local_vars_info_t
438 init_function_info (struct cgraph_node *fn)
440 ipa_reference_vars_info_t info
441 = XCNEW (struct ipa_reference_vars_info_d);
443 /* Add the info to the tree's annotation. */
444 set_reference_vars_info (fn, info);
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;
461 int i;
462 tree var;
464 local = init_function_info (fn);
465 for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++)
467 if (!is_a <varpool_node> (ref->referred))
468 continue;
469 var = ipa_ref_varpool_node (ref)->symbol.decl;
470 if (!is_proper_for_analysis (var))
471 continue;
472 switch (ref->use)
474 case IPA_REF_LOAD:
475 bitmap_set_bit (local->statics_read, DECL_UID (var));
476 break;
477 case IPA_REF_STORE:
478 if (ipa_ref_cannot_lead_to_return (ref))
479 break;
480 bitmap_set_bit (local->statics_written, DECL_UID (var));
481 break;
482 case IPA_REF_ADDR:
483 break;
487 if (cgraph_node_cannot_return (fn))
488 bitmap_clear (local->statics_written);
492 /* Called when new clone is inserted to callgraph late. */
494 static void
495 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
496 void *data ATTRIBUTE_UNUSED)
498 ipa_reference_optimization_summary_t ginfo;
499 ipa_reference_optimization_summary_t dst_ginfo;
501 ginfo = get_reference_optimization_summary (src);
502 if (!ginfo)
503 return;
504 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
505 set_reference_optimization_summary (dst, dst_ginfo);
506 dst_ginfo->statics_not_read =
507 copy_static_var_set (ginfo->statics_not_read);
508 dst_ginfo->statics_not_written =
509 copy_static_var_set (ginfo->statics_not_written);
512 /* Called when node is removed. */
514 static void
515 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
517 ipa_reference_optimization_summary_t ginfo;
518 ginfo = get_reference_optimization_summary (node);
519 if (ginfo)
521 if (ginfo->statics_not_read
522 && ginfo->statics_not_read != all_module_statics)
523 BITMAP_FREE (ginfo->statics_not_read);
525 if (ginfo->statics_not_written
526 && ginfo->statics_not_written != all_module_statics)
527 BITMAP_FREE (ginfo->statics_not_written);
528 free (ginfo);
529 set_reference_optimization_summary (node, NULL);
533 /* Analyze each function in the cgraph to see which global or statics
534 are read or written. */
536 static void
537 generate_summary (void)
539 struct cgraph_node *node;
540 unsigned int index;
541 bitmap_iterator bi;
543 ipa_init ();
545 /* Process all of the functions next. */
546 FOR_EACH_DEFINED_FUNCTION (node)
547 analyze_function (node);
549 if (dump_file)
550 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
552 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
553 get_static_name (index), index);
556 if (dump_file)
557 FOR_EACH_DEFINED_FUNCTION (node)
558 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
560 ipa_reference_local_vars_info_t l;
561 unsigned int index;
562 bitmap_iterator bi;
564 l = &get_reference_vars_info (node)->local;
565 fprintf (dump_file,
566 "\nFunction name:%s/%i:",
567 cgraph_node_asm_name (node), node->symbol.order);
568 fprintf (dump_file, "\n locals read: ");
569 if (l->statics_read)
570 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
571 0, index, bi)
573 fprintf (dump_file, "%s ",
574 get_static_name (index));
576 fprintf (dump_file, "\n locals written: ");
577 if (l->statics_written)
578 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
579 0, index, bi)
581 fprintf(dump_file, "%s ",
582 get_static_name (index));
587 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
589 static void
590 read_write_all_from_decl (struct cgraph_node *node,
591 bool &read_all, bool &write_all)
593 tree decl = node->symbol.decl;
594 int flags = flags_from_decl_or_type (decl);
595 if ((flags & ECF_LEAF)
596 && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
598 else if (flags & ECF_CONST)
600 else if ((flags & ECF_PURE)
601 || cgraph_node_cannot_return (node))
603 read_all = true;
604 if (dump_file && (dump_flags & TDF_DETAILS))
605 fprintf (dump_file, " %s/%i -> read all\n",
606 cgraph_node_asm_name (node), node->symbol.order);
608 else
610 /* TODO: To be able to produce sane results, we should also handle
611 common builtins, in particular throw. */
612 read_all = true;
613 write_all = true;
614 if (dump_file && (dump_flags & TDF_DETAILS))
615 fprintf (dump_file, " %s/%i -> read all, write all\n",
616 cgraph_node_asm_name (node), node->symbol.order);
620 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
621 in the cycle of NODE. */
623 static void
624 get_read_write_all_from_node (struct cgraph_node *node,
625 bool &read_all, bool &write_all)
627 struct cgraph_edge *e, *ie;
629 /* When function is overwritable, we can not assume anything. */
630 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
631 read_write_all_from_decl (node, read_all, write_all);
633 for (e = node->callees;
634 e && !(read_all && write_all);
635 e = e->next_callee)
637 enum availability avail;
638 struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
639 gcc_checking_assert (callee);
640 if (avail <= AVAIL_OVERWRITABLE)
641 read_write_all_from_decl (callee, read_all, write_all);
644 for (ie = node->indirect_calls;
645 ie && !(read_all && write_all);
646 ie = ie->next_callee)
647 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
649 read_all = true;
650 if (dump_file && (dump_flags & TDF_DETAILS))
651 fprintf (dump_file, " indirect call -> read all\n");
652 if (!cgraph_edge_cannot_lead_to_return (ie)
653 && !(ie->indirect_info->ecf_flags & ECF_PURE))
655 if (dump_file && (dump_flags & TDF_DETAILS))
656 fprintf (dump_file, " indirect call -> write all\n");
657 write_all = true;
662 /* Produce the global information by preforming a transitive closure
663 on the local information that was produced by ipa_analyze_function. */
665 static unsigned int
666 propagate (void)
668 struct cgraph_node *node;
669 struct varpool_node *vnode;
670 struct cgraph_node **order =
671 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
672 int order_pos;
673 int i;
675 if (dump_file)
676 dump_cgraph (dump_file);
678 ipa_discover_readonly_nonaddressable_vars ();
679 generate_summary ();
681 /* Now we know what vars are really statics; prune out those that aren't. */
682 FOR_EACH_VARIABLE (vnode)
683 if (vnode->symbol.externally_visible
684 || TREE_ADDRESSABLE (vnode->symbol.decl)
685 || TREE_READONLY (vnode->symbol.decl)
686 || !is_proper_for_analysis (vnode->symbol.decl)
687 || !vnode->symbol.definition)
688 bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
690 /* Forget info we collected "just for fun" on variables that turned out to be
691 non-local. */
692 FOR_EACH_DEFINED_FUNCTION (node)
694 ipa_reference_local_vars_info_t node_l;
695 node_l = &get_reference_vars_info (node)->local;
696 intersect_static_var_sets (node_l->statics_read, all_module_statics);
697 intersect_static_var_sets (node_l->statics_written, all_module_statics);
700 /* Propagate the local information through the call graph to produce
701 the global information. All the nodes within a cycle will have
702 the same info so we collapse cycles first. Then we can do the
703 propagation in one pass from the leaves to the roots. */
704 order_pos = ipa_reduced_postorder (order, true, true, NULL);
705 if (dump_file)
706 ipa_print_order (dump_file, "reduced", order, order_pos);
708 for (i = 0; i < order_pos; i++ )
710 unsigned x;
711 struct cgraph_node *w;
712 ipa_reference_vars_info_t node_info;
713 ipa_reference_global_vars_info_t node_g;
714 ipa_reference_local_vars_info_t node_l;
715 bool read_all = false;
716 bool write_all = false;
718 node = order[i];
719 if (node->symbol.alias)
720 continue;
722 node_info = get_reference_vars_info (node);
723 gcc_assert (node_info);
724 node_l = &node_info->local;
725 node_g = &node_info->global;
727 if (dump_file && (dump_flags & TDF_DETAILS))
728 fprintf (dump_file, "Starting cycle with %s/%i\n",
729 cgraph_node_asm_name (node), node->symbol.order);
731 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
733 /* If any node in a cycle is read_all or write_all, they all are. */
734 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
736 if (dump_file && (dump_flags & TDF_DETAILS))
737 fprintf (dump_file, " Visiting %s/%i\n",
738 cgraph_node_asm_name (w), w->symbol.order);
739 get_read_write_all_from_node (w, read_all, write_all);
740 if (read_all && write_all)
741 break;
744 /* Initialized the bitmaps global sets for the reduced node. */
745 if (read_all)
746 node_g->statics_read = all_module_statics;
747 else
748 node_g->statics_read = copy_static_var_set (node_l->statics_read);
749 if (write_all)
750 node_g->statics_written = all_module_statics;
751 else
752 node_g->statics_written = copy_static_var_set (node_l->statics_written);
754 /* Merge the sets of this cycle with all sets of callees reached
755 from this cycle. */
756 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
758 if (read_all && write_all)
759 break;
761 if (w != node)
763 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
764 ipa_reference_local_vars_info_t w_l = &w_ri->local;
765 int flags = flags_from_decl_or_type (w->symbol.decl);
767 if (!(flags & ECF_CONST))
768 read_all = union_static_var_sets (node_g->statics_read,
769 w_l->statics_read);
770 if (!(flags & ECF_PURE)
771 && !cgraph_node_cannot_return (w))
772 write_all = union_static_var_sets (node_g->statics_written,
773 w_l->statics_written);
776 propagate_bits (node_g, w);
779 /* All nodes within a cycle have the same global info bitmaps. */
780 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
782 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
783 w_ri->global = *node_g;
786 cycle_nodes.release ();
789 if (dump_file)
791 for (i = 0; i < order_pos; i++)
793 unsigned x;
794 struct cgraph_node *w;
796 node = order[i];
797 if (node->symbol.alias)
798 continue;
800 fprintf (dump_file,
801 "\nFunction name:%s/%i:",
802 cgraph_node_asm_name (node), node->symbol.order);
804 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
805 ipa_reference_global_vars_info_t node_g = &node_info->global;
807 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
808 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
810 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
811 ipa_reference_local_vars_info_t w_l = &w_ri->local;
812 if (w != node)
813 fprintf (dump_file, "\n next cycle: %s/%i ",
814 cgraph_node_asm_name (w), w->symbol.order);
815 fprintf (dump_file, "\n locals read: ");
816 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
817 fprintf (dump_file, "\n locals written: ");
818 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
820 cycle_nodes.release ();
822 fprintf (dump_file, "\n globals read: ");
823 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
824 fprintf (dump_file, "\n globals written: ");
825 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
826 fprintf (dump_file, "\n");
830 /* Cleanup. */
831 FOR_EACH_DEFINED_FUNCTION (node)
833 ipa_reference_vars_info_t node_info;
834 ipa_reference_global_vars_info_t node_g;
835 ipa_reference_optimization_summary_t opt;
837 node_info = get_reference_vars_info (node);
838 if (!node->symbol.alias
839 && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
840 || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
842 node_g = &node_info->global;
844 opt = XCNEW (struct ipa_reference_optimization_summary_d);
845 set_reference_optimization_summary (node, opt);
847 /* Create the complimentary sets. */
849 if (bitmap_empty_p (node_g->statics_read))
850 opt->statics_not_read = all_module_statics;
851 else
853 opt->statics_not_read
854 = BITMAP_ALLOC (&optimization_summary_obstack);
855 if (node_g->statics_read != all_module_statics)
856 bitmap_and_compl (opt->statics_not_read,
857 all_module_statics,
858 node_g->statics_read);
861 if (bitmap_empty_p (node_g->statics_written))
862 opt->statics_not_written = all_module_statics;
863 else
865 opt->statics_not_written
866 = BITMAP_ALLOC (&optimization_summary_obstack);
867 if (node_g->statics_written != all_module_statics)
868 bitmap_and_compl (opt->statics_not_written,
869 all_module_statics,
870 node_g->statics_written);
873 free (node_info);
876 ipa_free_postorder_info ();
877 free (order);
879 bitmap_obstack_release (&local_info_obstack);
880 ipa_reference_vars_vector.release ();
881 if (dump_file)
882 splay_tree_delete (reference_vars_to_consider);
883 reference_vars_to_consider = NULL;
884 return 0;
887 /* Return true if we need to write summary of NODE. */
889 static bool
890 write_node_summary_p (struct cgraph_node *node,
891 lto_symtab_encoder_t encoder,
892 bitmap ltrans_statics)
894 ipa_reference_optimization_summary_t info;
896 /* See if we have (non-empty) info. */
897 if (!node->symbol.definition || node->global.inlined_to)
898 return false;
899 info = get_reference_optimization_summary (node);
900 if (!info || (bitmap_empty_p (info->statics_not_read)
901 && bitmap_empty_p (info->statics_not_written)))
902 return false;
904 /* See if we want to encode it.
905 Encode also referenced functions since constant folding might turn it into
906 a direct call.
908 In future we might also want to include summaries of functions references
909 by initializers of constant variables references in current unit. */
910 if (!reachable_from_this_partition_p (node, encoder)
911 && !referenced_from_this_partition_p (&node->symbol.ref_list, encoder))
912 return false;
914 /* See if the info has non-empty intersections with vars we want to encode. */
915 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
916 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
917 return false;
918 return true;
921 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
922 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
923 or -1. When it is positive, just output -1 when
924 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
926 static void
927 stream_out_bitmap (struct lto_simple_output_block *ob,
928 bitmap bits, bitmap ltrans_statics,
929 int ltrans_statics_bitcount)
931 int count = 0;
932 unsigned int index;
933 bitmap_iterator bi;
934 if (bits == all_module_statics)
936 streamer_write_hwi_stream (ob->main_stream, -1);
937 return;
939 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
940 count ++;
941 if (count == ltrans_statics_bitcount)
943 streamer_write_hwi_stream (ob->main_stream, -1);
944 return;
946 streamer_write_hwi_stream (ob->main_stream, count);
947 if (!count)
948 return;
949 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
951 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
952 lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
956 /* Serialize the ipa info for lto. */
958 static void
959 ipa_reference_write_optimization_summary (void)
961 struct lto_simple_output_block *ob
962 = lto_create_simple_output_block (LTO_section_ipa_reference);
963 unsigned int count = 0;
964 int ltrans_statics_bitcount = 0;
965 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
966 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
967 int i;
969 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
971 /* See what variables we are interested in. */
972 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
974 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
975 varpool_node *vnode = dyn_cast <varpool_node> (snode);
976 if (vnode
977 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
978 && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
980 tree decl = vnode->symbol.decl;
981 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
982 splay_tree_insert (reference_vars_to_consider,
983 DECL_UID (decl), (splay_tree_value)decl);
984 ltrans_statics_bitcount ++;
989 if (ltrans_statics_bitcount)
990 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
992 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
993 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
994 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
995 count++;
998 streamer_write_uhwi_stream (ob->main_stream, count);
999 if (count)
1000 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1001 -1);
1003 /* Process all of the functions. */
1004 if (ltrans_statics_bitcount)
1005 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1007 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
1008 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
1009 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1011 ipa_reference_optimization_summary_t info;
1012 int node_ref;
1014 info = get_reference_optimization_summary (cnode);
1015 node_ref = lto_symtab_encoder_encode (encoder, snode);
1016 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1018 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1019 ltrans_statics_bitcount);
1020 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1021 ltrans_statics_bitcount);
1024 BITMAP_FREE (ltrans_statics);
1025 lto_destroy_simple_output_block (ob);
1026 splay_tree_delete (reference_vars_to_consider);
1029 /* Deserialize the ipa info for lto. */
1031 static void
1032 ipa_reference_read_optimization_summary (void)
1034 struct lto_file_decl_data ** file_data_vec
1035 = lto_get_file_decl_data ();
1036 struct lto_file_decl_data * file_data;
1037 unsigned int j = 0;
1038 bitmap_obstack_initialize (&optimization_summary_obstack);
1040 node_removal_hook_holder =
1041 cgraph_add_node_removal_hook (&remove_node_data, NULL);
1042 node_duplication_hook_holder =
1043 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1044 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1046 while ((file_data = file_data_vec[j++]))
1048 const char *data;
1049 size_t len;
1050 struct lto_input_block *ib
1051 = lto_create_simple_input_block (file_data,
1052 LTO_section_ipa_reference,
1053 &data, &len);
1054 if (ib)
1056 unsigned int i;
1057 unsigned int f_count = streamer_read_uhwi (ib);
1058 int b_count;
1059 if (!f_count)
1060 continue;
1061 b_count = streamer_read_hwi (ib);
1062 if (dump_file)
1063 fprintf (dump_file, "all module statics:");
1064 for (i = 0; i < (unsigned int)b_count; i++)
1066 unsigned int var_index = streamer_read_uhwi (ib);
1067 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1068 var_index);
1069 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1070 if (dump_file)
1071 fprintf (dump_file, " %s", fndecl_name (v_decl));
1074 for (i = 0; i < f_count; i++)
1076 unsigned int j, index;
1077 struct cgraph_node *node;
1078 ipa_reference_optimization_summary_t info;
1079 int v_count;
1080 lto_symtab_encoder_t encoder;
1082 index = streamer_read_uhwi (ib);
1083 encoder = file_data->symtab_node_encoder;
1084 node = cgraph (lto_symtab_encoder_deref (encoder, index));
1085 info = XCNEW (struct ipa_reference_optimization_summary_d);
1086 set_reference_optimization_summary (node, info);
1087 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1088 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1089 if (dump_file)
1090 fprintf (dump_file,
1091 "\nFunction name:%s/%i:\n static not read:",
1092 cgraph_node_asm_name (node), node->symbol.order);
1094 /* Set the statics not read. */
1095 v_count = streamer_read_hwi (ib);
1096 if (v_count == -1)
1098 info->statics_not_read = all_module_statics;
1099 if (dump_file)
1100 fprintf (dump_file, " all module statics");
1102 else
1103 for (j = 0; j < (unsigned int)v_count; j++)
1105 unsigned int var_index = streamer_read_uhwi (ib);
1106 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1107 var_index);
1108 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1109 if (dump_file)
1110 fprintf (dump_file, " %s", fndecl_name (v_decl));
1113 if (dump_file)
1114 fprintf (dump_file,
1115 "\n static not written:");
1116 /* Set the statics not written. */
1117 v_count = streamer_read_hwi (ib);
1118 if (v_count == -1)
1120 info->statics_not_written = all_module_statics;
1121 if (dump_file)
1122 fprintf (dump_file, " all module statics");
1124 else
1125 for (j = 0; j < (unsigned int)v_count; j++)
1127 unsigned int var_index = streamer_read_uhwi (ib);
1128 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1129 var_index);
1130 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1131 if (dump_file)
1132 fprintf (dump_file, " %s", fndecl_name (v_decl));
1134 if (dump_file)
1135 fprintf (dump_file, "\n");
1138 lto_destroy_simple_input_block (file_data,
1139 LTO_section_ipa_reference,
1140 ib, data, len);
1142 else
1143 /* Fatal error here. We do not want to support compiling ltrans units with
1144 different version of compiler or different flags than the WPA unit, so
1145 this should never happen. */
1146 fatal_error ("ipa reference summary is missing in ltrans unit");
1150 static bool
1151 gate_reference (void)
1153 return (flag_ipa_reference
1154 /* Don't bother doing anything if the program has errors. */
1155 && !seen_error ());
1158 namespace {
1160 const pass_data pass_data_ipa_reference =
1162 IPA_PASS, /* type */
1163 "static-var", /* name */
1164 OPTGROUP_NONE, /* optinfo_flags */
1165 true, /* has_gate */
1166 true, /* has_execute */
1167 TV_IPA_REFERENCE, /* tv_id */
1168 0, /* properties_required */
1169 0, /* properties_provided */
1170 0, /* properties_destroyed */
1171 0, /* todo_flags_start */
1172 0, /* todo_flags_finish */
1175 class pass_ipa_reference : public ipa_opt_pass_d
1177 public:
1178 pass_ipa_reference(gcc::context *ctxt)
1179 : ipa_opt_pass_d(pass_data_ipa_reference, ctxt,
1180 NULL, /* generate_summary */
1181 NULL, /* write_summary */
1182 NULL, /* read_summary */
1183 ipa_reference_write_optimization_summary, /*
1184 write_optimization_summary */
1185 ipa_reference_read_optimization_summary, /*
1186 read_optimization_summary */
1187 NULL, /* stmt_fixup */
1188 0, /* function_transform_todo_flags_start */
1189 NULL, /* function_transform */
1190 NULL) /* variable_transform */
1193 /* opt_pass methods: */
1194 bool gate () { return gate_reference (); }
1195 unsigned int execute () { return propagate (); }
1197 }; // class pass_ipa_reference
1199 } // anon namespace
1201 ipa_opt_pass_d *
1202 make_pass_ipa_reference (gcc::context *ctxt)
1204 return new pass_ipa_reference (ctxt);