2012-12-14 Steve Ellcey <sellcey@mips.com>
[official-gcc.git] / gcc / ipa-reference.c
blobca05a3988419bab4c7abd7712ffc2244954cdaea
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This file gathers information about how variables whose scope is
23 confined to the compilation unit are used.
25 The transitive call site specific clobber effects are computed
26 for the variables whose scope is contained within this compilation
27 unit.
29 First each function and static variable initialization is analyzed
30 to determine which local static variables are either read, written,
31 or have their address taken. Any local static that has its address
32 taken is removed from consideration. Once the local read and
33 writes are determined, a transitive closure of this information is
34 performed over the call graph to determine the worst case set of
35 side effects of each call. In later parts of the compiler, these
36 local and global sets are examined to make the call clobbering less
37 traumatic, promote some statics to registers, and improve aliasing
38 information. */
40 #include "config.h"
41 #include "system.h"
42 #include "coretypes.h"
43 #include "tm.h"
44 #include "tree.h"
45 #include "tree-flow.h"
46 #include "tree-inline.h"
47 #include "tree-pass.h"
48 #include "pointer-set.h"
49 #include "splay-tree.h"
50 #include "ggc.h"
51 #include "ipa-utils.h"
52 #include "ipa-reference.h"
53 #include "gimple.h"
54 #include "cgraph.h"
55 #include "flags.h"
56 #include "diagnostic.h"
57 #include "data-streamer.h"
58 #include "lto-streamer.h"
60 static void remove_node_data (struct cgraph_node *node,
61 void *data ATTRIBUTE_UNUSED);
62 static void duplicate_node_data (struct cgraph_node *src,
63 struct cgraph_node *dst,
64 void *data ATTRIBUTE_UNUSED);
66 /* The static variables defined within the compilation unit that are
67 loaded or stored directly by function that owns this structure. */
69 struct ipa_reference_local_vars_info_d
71 bitmap statics_read;
72 bitmap statics_written;
75 /* Statics that are read and written by some set of functions. The
76 local ones are based on the loads and stores local to the function.
77 The global ones are based on the local info as well as the
78 transitive closure of the functions that are called. */
80 struct ipa_reference_global_vars_info_d
82 bitmap statics_read;
83 bitmap statics_written;
86 /* Information we save about every function after ipa-reference is completed. */
88 struct ipa_reference_optimization_summary_d
90 bitmap statics_not_read;
91 bitmap statics_not_written;
94 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
95 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
96 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
98 struct ipa_reference_vars_info_d
100 struct ipa_reference_local_vars_info_d local;
101 struct ipa_reference_global_vars_info_d global;
104 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
106 /* This splay tree contains all of the static variables that are
107 being considered by the compilation level alias analysis. */
108 static splay_tree reference_vars_to_consider;
110 /* Set of all interesting module statics. A bit is set for every module
111 static we are considering. This is added to the local info when asm
112 code is found that clobbers all memory. */
113 static bitmap all_module_statics;
115 /* Obstack holding bitmaps of local analysis (live from analysis to
116 propagation) */
117 static bitmap_obstack local_info_obstack;
118 /* Obstack holding global analysis live forever. */
119 static bitmap_obstack optimization_summary_obstack;
121 /* Holders of ipa cgraph hooks: */
122 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
123 static struct cgraph_node_hook_list *node_removal_hook_holder;
125 /* Vector where the reference var infos are actually stored.
126 Indexed by UID of call graph nodes. */
127 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
129 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
131 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
132 static inline ipa_reference_vars_info_t
133 get_reference_vars_info (struct cgraph_node *node)
135 if (!ipa_reference_vars_vector.exists ()
136 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
137 return NULL;
138 return ipa_reference_vars_vector[node->uid];
141 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
142 static inline ipa_reference_optimization_summary_t
143 get_reference_optimization_summary (struct cgraph_node *node)
145 if (!ipa_reference_opt_sum_vector.exists ()
146 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
147 return NULL;
148 return ipa_reference_opt_sum_vector[node->uid];
151 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
152 static inline void
153 set_reference_vars_info (struct cgraph_node *node,
154 ipa_reference_vars_info_t info)
156 if (!ipa_reference_vars_vector.exists ()
157 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
158 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
159 ipa_reference_vars_vector[node->uid] = info;
162 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
163 static inline void
164 set_reference_optimization_summary (struct cgraph_node *node,
165 ipa_reference_optimization_summary_t info)
167 if (!ipa_reference_opt_sum_vector.exists ()
168 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
169 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
170 ipa_reference_opt_sum_vector[node->uid] = info;
173 /* Return a bitmap indexed by DECL_UID for the static variables that
174 are *not* read during the execution of the function FN. Returns
175 NULL if no data is available. */
177 bitmap
178 ipa_reference_get_not_read_global (struct cgraph_node *fn)
180 ipa_reference_optimization_summary_t info =
181 get_reference_optimization_summary (cgraph_function_node (fn, NULL));
182 if (info)
183 return info->statics_not_read;
184 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
185 return all_module_statics;
186 else
187 return NULL;
190 /* Return a bitmap indexed by DECL_UID for the static variables that
191 are *not* written during the execution of the function FN. Note
192 that variables written may or may not be read during the function
193 call. Returns NULL if no data is available. */
195 bitmap
196 ipa_reference_get_not_written_global (struct cgraph_node *fn)
198 ipa_reference_optimization_summary_t info =
199 get_reference_optimization_summary (fn);
200 if (info)
201 return info->statics_not_written;
202 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
203 return all_module_statics;
204 else
205 return NULL;
210 /* Add VAR to all_module_statics and the two
211 reference_vars_to_consider* sets. */
213 static inline void
214 add_static_var (tree var)
216 int uid = DECL_UID (var);
217 gcc_assert (TREE_CODE (var) == VAR_DECL);
218 if (dump_file)
219 splay_tree_insert (reference_vars_to_consider,
220 uid, (splay_tree_value)var);
221 bitmap_set_bit (all_module_statics, uid);
224 /* Return true if the variable T is the right kind of static variable to
225 perform compilation unit scope escape analysis. */
227 static inline bool
228 is_proper_for_analysis (tree t)
230 /* If the variable has the "used" attribute, treat it as if it had a
231 been touched by the devil. */
232 if (DECL_PRESERVE_P (t))
233 return false;
235 /* Do not want to do anything with volatile except mark any
236 function that uses one to be not const or pure. */
237 if (TREE_THIS_VOLATILE (t))
238 return false;
240 /* We do not need to analyze readonly vars, we already know they do not
241 alias. */
242 if (TREE_READONLY (t))
243 return false;
245 /* This is a variable we care about. Check if we have seen it
246 before, and if not add it the set of variables we care about. */
247 if (all_module_statics
248 && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
249 add_static_var (t);
251 return true;
254 /* Lookup the tree node for the static variable that has UID and
255 convert the name to a string for debugging. */
257 static const char *
258 get_static_name (int index)
260 splay_tree_node stn =
261 splay_tree_lookup (reference_vars_to_consider, index);
262 return fndecl_name ((tree)(stn->value));
265 /* Dump a set of static vars to FILE. */
266 static void
267 dump_static_vars_set_to_file (FILE *f, bitmap set)
269 unsigned int index;
270 bitmap_iterator bi;
271 if (set == NULL)
272 return;
273 else if (set == all_module_statics)
274 fprintf (f, "ALL");
275 else
276 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
278 fprintf (f, "%s ", get_static_name (index));
282 /* Compute X |= Y, taking into account the possibility that
283 either X or Y is already the maximum set.
284 Return true if X is the maximum set after taking the union with Y. */
286 static bool
287 union_static_var_sets (bitmap &x, bitmap y)
289 if (x != all_module_statics)
291 if (y == all_module_statics)
293 BITMAP_FREE (x);
294 x = all_module_statics;
296 else if (bitmap_ior_into (x, y))
298 /* The union may have reduced X to the maximum set.
299 In that case, we want to make that visible explicitly.
300 Even though bitmap_equal_p can be very expensive, it
301 turns out to be an overall win to check this here for
302 an LTO bootstrap of GCC itself. Liberally extrapoliate
303 that result to be applicable to all cases. */
304 if (bitmap_equal_p (x, all_module_statics))
306 BITMAP_FREE (x);
307 x = all_module_statics;
311 return x == all_module_statics;
314 /* Compute X &= Y, taking into account the possibility that
315 X may become the maximum set. */
317 static bool
318 intersect_static_var_sets (bitmap &x, bitmap y)
320 if (x != all_module_statics)
322 bitmap_and_into (x, y);
323 /* As with union_static_var_sets, reducing to the maximum
324 set as early as possible is an overall win. */
325 if (bitmap_equal_p (x, all_module_statics))
327 BITMAP_FREE (x);
328 x = all_module_statics;
331 return x == all_module_statics;
334 /* Return a copy of SET on the bitmap obstack containing SET.
335 But if SET is NULL or the maximum set, return that instead. */
337 static bitmap
338 copy_static_var_set (bitmap set)
340 if (set == NULL || set == all_module_statics)
341 return set;
342 bitmap_obstack *o = set->obstack;
343 gcc_checking_assert (o);
344 bitmap copy = BITMAP_ALLOC (o);
345 bitmap_copy (copy, set);
346 return copy;
349 /* Compute the union all of the statics read and written by every callee of X
350 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
351 actually the set representing the cycle containing X. If the read and
352 written sets of X_GLOBAL has been reduced to the maximum set, we don't
353 have to look at the remaining callees. */
355 static void
356 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
358 struct cgraph_edge *e;
359 bool read_all = x_global->statics_read == all_module_statics;
360 bool write_all = x_global->statics_written == all_module_statics;
361 for (e = x->callees;
362 e && !(read_all && write_all);
363 e = e->next_callee)
365 enum availability avail;
366 struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
367 if (!y)
368 continue;
370 /* Only look into nodes we can propagate something. */
371 int flags = flags_from_decl_or_type (y->symbol.decl);
372 if (avail > AVAIL_OVERWRITABLE
373 || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF)))
375 if (get_reference_vars_info (y))
377 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
378 ipa_reference_global_vars_info_t y_global = &y_info->global;
380 /* Calls in the current cycle do not have their global set
381 computed yet (but everything else does because we're
382 visiting nodes in topological order). */
383 if (!y_global->statics_read)
384 continue;
386 /* If the function is const, it reads no memory even if it
387 seems so to local analysis. */
388 if (flags & ECF_CONST)
389 continue;
391 union_static_var_sets (x_global->statics_read,
392 y_global->statics_read);
394 /* If the function is pure, it has no stores even if it
395 seems so to local analysis. If we cannot return from
396 the function, we can safely ignore the call. */
397 if ((flags & ECF_PURE)
398 || cgraph_edge_cannot_lead_to_return (e))
399 continue;
401 union_static_var_sets (x_global->statics_written,
402 y_global->statics_written);
404 else
405 gcc_unreachable ();
410 /* The init routine for analyzing global static variable usage. See
411 comments at top for description. */
412 static void
413 ipa_init (void)
415 static bool init_p = false;
417 if (init_p)
418 return;
420 init_p = true;
422 if (dump_file)
423 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
425 bitmap_obstack_initialize (&local_info_obstack);
426 bitmap_obstack_initialize (&optimization_summary_obstack);
427 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
429 node_removal_hook_holder =
430 cgraph_add_node_removal_hook (&remove_node_data, NULL);
431 node_duplication_hook_holder =
432 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
436 /* Set up the persistent info for FN. */
438 static ipa_reference_local_vars_info_t
439 init_function_info (struct cgraph_node *fn)
441 ipa_reference_vars_info_t info
442 = XCNEW (struct ipa_reference_vars_info_d);
444 /* Add the info to the tree's annotation. */
445 set_reference_vars_info (fn, info);
447 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
448 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
450 return &info->local;
454 /* This is the main routine for finding the reference patterns for
455 global variables within a function FN. */
457 static void
458 analyze_function (struct cgraph_node *fn)
460 ipa_reference_local_vars_info_t local;
461 struct ipa_ref *ref;
462 int i;
463 tree var;
465 local = init_function_info (fn);
466 for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++)
468 if (!is_a <varpool_node> (ref->referred))
469 continue;
470 var = ipa_ref_varpool_node (ref)->symbol.decl;
471 if (!is_proper_for_analysis (var))
472 continue;
473 switch (ref->use)
475 case IPA_REF_LOAD:
476 bitmap_set_bit (local->statics_read, DECL_UID (var));
477 break;
478 case IPA_REF_STORE:
479 if (ipa_ref_cannot_lead_to_return (ref))
480 break;
481 bitmap_set_bit (local->statics_written, DECL_UID (var));
482 break;
483 case IPA_REF_ADDR:
484 break;
488 if (cgraph_node_cannot_return (fn))
489 bitmap_clear (local->statics_written);
493 /* Called when new clone is inserted to callgraph late. */
495 static void
496 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
497 void *data ATTRIBUTE_UNUSED)
499 ipa_reference_optimization_summary_t ginfo;
500 ipa_reference_optimization_summary_t dst_ginfo;
502 ginfo = get_reference_optimization_summary (src);
503 if (!ginfo)
504 return;
505 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
506 set_reference_optimization_summary (dst, dst_ginfo);
507 dst_ginfo->statics_not_read =
508 copy_static_var_set (ginfo->statics_not_read);
509 dst_ginfo->statics_not_written =
510 copy_static_var_set (ginfo->statics_not_written);
513 /* Called when node is removed. */
515 static void
516 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
518 ipa_reference_optimization_summary_t ginfo;
519 ginfo = get_reference_optimization_summary (node);
520 if (ginfo)
522 if (ginfo->statics_not_read
523 && ginfo->statics_not_read != all_module_statics)
524 BITMAP_FREE (ginfo->statics_not_read);
526 if (ginfo->statics_not_written
527 && ginfo->statics_not_written != all_module_statics)
528 BITMAP_FREE (ginfo->statics_not_written);
529 free (ginfo);
530 set_reference_optimization_summary (node, NULL);
534 /* Analyze each function in the cgraph to see which global or statics
535 are read or written. */
537 static void
538 generate_summary (void)
540 struct cgraph_node *node;
541 unsigned int index;
542 bitmap_iterator bi;
544 ipa_init ();
546 /* Process all of the functions next. */
547 FOR_EACH_DEFINED_FUNCTION (node)
548 analyze_function (node);
550 if (dump_file)
551 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
553 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
554 get_static_name (index), index);
557 if (dump_file)
558 FOR_EACH_DEFINED_FUNCTION (node)
559 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
561 ipa_reference_local_vars_info_t l;
562 unsigned int index;
563 bitmap_iterator bi;
565 l = &get_reference_vars_info (node)->local;
566 fprintf (dump_file,
567 "\nFunction name:%s/%i:",
568 cgraph_node_asm_name (node), node->symbol.order);
569 fprintf (dump_file, "\n locals read: ");
570 if (l->statics_read)
571 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
572 0, index, bi)
574 fprintf (dump_file, "%s ",
575 get_static_name (index));
577 fprintf (dump_file, "\n locals written: ");
578 if (l->statics_written)
579 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
580 0, index, bi)
582 fprintf(dump_file, "%s ",
583 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->symbol.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 cgraph_node_asm_name (node), node->symbol.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 cgraph_node_asm_name (node), node->symbol.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 struct 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->symbol.externally_visible
685 || TREE_ADDRESSABLE (vnode->symbol.decl)
686 || TREE_READONLY (vnode->symbol.decl)
687 || !is_proper_for_analysis (vnode->symbol.decl)
688 || !vnode->analyzed)
689 bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.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 cgraph_node_asm_name (node), node->symbol.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 cgraph_node_asm_name (w), w->symbol.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->symbol.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 cgraph_node_asm_name (node), node->symbol.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 cgraph_node_asm_name (w), w->symbol.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 if (node->alias)
839 continue;
841 node_info = get_reference_vars_info (node);
842 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
843 || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF))
845 node_g = &node_info->global;
847 opt = XCNEW (struct ipa_reference_optimization_summary_d);
848 set_reference_optimization_summary (node, opt);
850 /* Create the complimentary sets. */
852 if (bitmap_empty_p (node_g->statics_read))
853 opt->statics_not_read = all_module_statics;
854 else
856 opt->statics_not_read
857 = BITMAP_ALLOC (&optimization_summary_obstack);
858 if (node_g->statics_read != all_module_statics)
859 bitmap_and_compl (opt->statics_not_read,
860 all_module_statics,
861 node_g->statics_read);
864 if (bitmap_empty_p (node_g->statics_written))
865 opt->statics_not_written = all_module_statics;
866 else
868 opt->statics_not_written
869 = BITMAP_ALLOC (&optimization_summary_obstack);
870 if (node_g->statics_written != all_module_statics)
871 bitmap_and_compl (opt->statics_not_written,
872 all_module_statics,
873 node_g->statics_written);
876 free (node_info);
879 ipa_free_postorder_info ();
880 free (order);
882 bitmap_obstack_release (&local_info_obstack);
883 ipa_reference_vars_vector.release ();
884 if (dump_file)
885 splay_tree_delete (reference_vars_to_consider);
886 reference_vars_to_consider = NULL;
887 return 0;
890 /* Return true if we need to write summary of NODE. */
892 static bool
893 write_node_summary_p (struct cgraph_node *node,
894 lto_symtab_encoder_t encoder,
895 bitmap ltrans_statics)
897 ipa_reference_optimization_summary_t info;
899 /* See if we have (non-empty) info. */
900 if (!node->analyzed || node->global.inlined_to)
901 return false;
902 info = get_reference_optimization_summary (node);
903 if (!info || (bitmap_empty_p (info->statics_not_read)
904 && bitmap_empty_p (info->statics_not_written)))
905 return false;
907 /* See if we want to encode it.
908 Encode also referenced functions since constant folding might turn it into
909 a direct call.
911 In future we might also want to include summaries of functions references
912 by initializers of constant variables references in current unit. */
913 if (!reachable_from_this_partition_p (node, encoder)
914 && !referenced_from_this_partition_p (&node->symbol.ref_list, encoder))
915 return false;
917 /* See if the info has non-empty intersections with vars we want to encode. */
918 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
919 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
920 return false;
921 return true;
924 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
925 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
926 or -1. When it is positive, just output -1 when
927 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
929 static void
930 stream_out_bitmap (struct lto_simple_output_block *ob,
931 bitmap bits, bitmap ltrans_statics,
932 int ltrans_statics_bitcount)
934 int count = 0;
935 unsigned int index;
936 bitmap_iterator bi;
937 if (bits == all_module_statics)
939 streamer_write_hwi_stream (ob->main_stream, -1);
940 return;
942 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
943 count ++;
944 if (count == ltrans_statics_bitcount)
946 streamer_write_hwi_stream (ob->main_stream, -1);
947 return;
949 streamer_write_hwi_stream (ob->main_stream, count);
950 if (!count)
951 return;
952 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
954 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
955 lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
959 /* Serialize the ipa info for lto. */
961 static void
962 ipa_reference_write_optimization_summary (void)
964 struct lto_simple_output_block *ob
965 = lto_create_simple_output_block (LTO_section_ipa_reference);
966 unsigned int count = 0;
967 int ltrans_statics_bitcount = 0;
968 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
969 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
970 int i;
972 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
974 /* See what variables we are interested in. */
975 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
977 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
978 varpool_node *vnode = dyn_cast <varpool_node> (snode);
979 if (vnode
980 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
981 && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
983 tree decl = vnode->symbol.decl;
984 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
985 splay_tree_insert (reference_vars_to_consider,
986 DECL_UID (decl), (splay_tree_value)decl);
987 ltrans_statics_bitcount ++;
992 if (ltrans_statics_bitcount)
993 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
995 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
996 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
997 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
998 count++;
1001 streamer_write_uhwi_stream (ob->main_stream, count);
1002 if (count)
1003 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1004 -1);
1006 /* Process all of the functions. */
1007 if (ltrans_statics_bitcount)
1008 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1010 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
1011 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
1012 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1014 ipa_reference_optimization_summary_t info;
1015 int node_ref;
1017 info = get_reference_optimization_summary (cnode);
1018 node_ref = lto_symtab_encoder_encode (encoder, snode);
1019 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1021 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1022 ltrans_statics_bitcount);
1023 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1024 ltrans_statics_bitcount);
1027 BITMAP_FREE (ltrans_statics);
1028 lto_destroy_simple_output_block (ob);
1029 splay_tree_delete (reference_vars_to_consider);
1032 /* Deserialize the ipa info for lto. */
1034 static void
1035 ipa_reference_read_optimization_summary (void)
1037 struct lto_file_decl_data ** file_data_vec
1038 = lto_get_file_decl_data ();
1039 struct lto_file_decl_data * file_data;
1040 unsigned int j = 0;
1041 bitmap_obstack_initialize (&optimization_summary_obstack);
1043 node_removal_hook_holder =
1044 cgraph_add_node_removal_hook (&remove_node_data, NULL);
1045 node_duplication_hook_holder =
1046 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1047 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1049 while ((file_data = file_data_vec[j++]))
1051 const char *data;
1052 size_t len;
1053 struct lto_input_block *ib
1054 = lto_create_simple_input_block (file_data,
1055 LTO_section_ipa_reference,
1056 &data, &len);
1057 if (ib)
1059 unsigned int i;
1060 unsigned int f_count = streamer_read_uhwi (ib);
1061 int b_count;
1062 if (!f_count)
1063 continue;
1064 b_count = streamer_read_hwi (ib);
1065 if (dump_file)
1066 fprintf (dump_file, "all module statics:");
1067 for (i = 0; i < (unsigned int)b_count; i++)
1069 unsigned int var_index = streamer_read_uhwi (ib);
1070 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1071 var_index);
1072 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1073 if (dump_file)
1074 fprintf (dump_file, " %s", fndecl_name (v_decl));
1077 for (i = 0; i < f_count; i++)
1079 unsigned int j, index;
1080 struct cgraph_node *node;
1081 ipa_reference_optimization_summary_t info;
1082 int v_count;
1083 lto_symtab_encoder_t encoder;
1085 index = streamer_read_uhwi (ib);
1086 encoder = file_data->symtab_node_encoder;
1087 node = cgraph (lto_symtab_encoder_deref (encoder, index));
1088 info = XCNEW (struct ipa_reference_optimization_summary_d);
1089 set_reference_optimization_summary (node, info);
1090 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1091 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1092 if (dump_file)
1093 fprintf (dump_file,
1094 "\nFunction name:%s/%i:\n static not read:",
1095 cgraph_node_asm_name (node), node->symbol.order);
1097 /* Set the statics not read. */
1098 v_count = streamer_read_hwi (ib);
1099 if (v_count == -1)
1101 info->statics_not_read = all_module_statics;
1102 if (dump_file)
1103 fprintf (dump_file, " all module statics");
1105 else
1106 for (j = 0; j < (unsigned int)v_count; j++)
1108 unsigned int var_index = streamer_read_uhwi (ib);
1109 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1110 var_index);
1111 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1112 if (dump_file)
1113 fprintf (dump_file, " %s", fndecl_name (v_decl));
1116 if (dump_file)
1117 fprintf (dump_file,
1118 "\n static not written:");
1119 /* Set the statics not written. */
1120 v_count = streamer_read_hwi (ib);
1121 if (v_count == -1)
1123 info->statics_not_written = all_module_statics;
1124 if (dump_file)
1125 fprintf (dump_file, " all module statics");
1127 else
1128 for (j = 0; j < (unsigned int)v_count; j++)
1130 unsigned int var_index = streamer_read_uhwi (ib);
1131 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1132 var_index);
1133 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1134 if (dump_file)
1135 fprintf (dump_file, " %s", fndecl_name (v_decl));
1137 if (dump_file)
1138 fprintf (dump_file, "\n");
1141 lto_destroy_simple_input_block (file_data,
1142 LTO_section_ipa_reference,
1143 ib, data, len);
1145 else
1146 /* Fatal error here. We do not want to support compiling ltrans units with
1147 different version of compiler or different flags than the WPA unit, so
1148 this should never happen. */
1149 fatal_error ("ipa reference summary is missing in ltrans unit");
1153 static bool
1154 gate_reference (void)
1156 return (flag_ipa_reference
1157 /* Don't bother doing anything if the program has errors. */
1158 && !seen_error ());
1161 struct ipa_opt_pass_d pass_ipa_reference =
1164 IPA_PASS,
1165 "static-var", /* name */
1166 OPTGROUP_NONE, /* optinfo_flags */
1167 gate_reference, /* gate */
1168 propagate, /* execute */
1169 NULL, /* sub */
1170 NULL, /* next */
1171 0, /* static_pass_number */
1172 TV_IPA_REFERENCE, /* tv_id */
1173 0, /* properties_required */
1174 0, /* properties_provided */
1175 0, /* properties_destroyed */
1176 0, /* todo_flags_start */
1177 0 /* todo_flags_finish */
1179 NULL, /* generate_summary */
1180 NULL, /* write_summary */
1181 NULL, /* read_summary */
1182 ipa_reference_write_optimization_summary,/* write_optimization_summary */
1183 ipa_reference_read_optimization_summary,/* read_optimization_summary */
1184 NULL, /* stmt_fixup */
1185 0, /* TODOs */
1186 NULL, /* function_transform */
1187 NULL /* variable_transform */