* tree-ssa-loop-ivopts.c (strip_offset_1): Change parameter type.
[official-gcc.git] / gcc / ipa-reference.c
blobb3e137e10151b99829b7363de408053d14303ee8
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-inline.h"
45 #include "tree-pass.h"
46 #include "pointer-set.h"
47 #include "splay-tree.h"
48 #include "ggc.h"
49 #include "ipa-utils.h"
50 #include "ipa-reference.h"
51 #include "flags.h"
52 #include "diagnostic.h"
53 #include "data-streamer.h"
54 #include "lto-streamer.h"
56 static void remove_node_data (struct cgraph_node *node,
57 void *data ATTRIBUTE_UNUSED);
58 static void duplicate_node_data (struct cgraph_node *src,
59 struct cgraph_node *dst,
60 void *data ATTRIBUTE_UNUSED);
62 /* The static variables defined within the compilation unit that are
63 loaded or stored directly by function that owns this structure. */
65 struct ipa_reference_local_vars_info_d
67 bitmap statics_read;
68 bitmap statics_written;
71 /* Statics that are read and written by some set of functions. The
72 local ones are based on the loads and stores local to the function.
73 The global ones are based on the local info as well as the
74 transitive closure of the functions that are called. */
76 struct ipa_reference_global_vars_info_d
78 bitmap statics_read;
79 bitmap statics_written;
82 /* Information we save about every function after ipa-reference is completed. */
84 struct ipa_reference_optimization_summary_d
86 bitmap statics_not_read;
87 bitmap statics_not_written;
90 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
91 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
92 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
94 struct ipa_reference_vars_info_d
96 struct ipa_reference_local_vars_info_d local;
97 struct ipa_reference_global_vars_info_d global;
100 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
102 /* This splay tree contains all of the static variables that are
103 being considered by the compilation level alias analysis. */
104 static splay_tree reference_vars_to_consider;
106 /* Set of all interesting module statics. A bit is set for every module
107 static we are considering. This is added to the local info when asm
108 code is found that clobbers all memory. */
109 static bitmap all_module_statics;
111 /* Obstack holding bitmaps of local analysis (live from analysis to
112 propagation) */
113 static bitmap_obstack local_info_obstack;
114 /* Obstack holding global analysis live forever. */
115 static bitmap_obstack optimization_summary_obstack;
117 /* Holders of ipa cgraph hooks: */
118 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
119 static struct cgraph_node_hook_list *node_removal_hook_holder;
121 /* Vector where the reference var infos are actually stored.
122 Indexed by UID of call graph nodes. */
123 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
125 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
127 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
128 static inline ipa_reference_vars_info_t
129 get_reference_vars_info (struct cgraph_node *node)
131 if (!ipa_reference_vars_vector.exists ()
132 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
133 return NULL;
134 return ipa_reference_vars_vector[node->uid];
137 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
138 static inline ipa_reference_optimization_summary_t
139 get_reference_optimization_summary (struct cgraph_node *node)
141 if (!ipa_reference_opt_sum_vector.exists ()
142 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
143 return NULL;
144 return ipa_reference_opt_sum_vector[node->uid];
147 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
148 static inline void
149 set_reference_vars_info (struct cgraph_node *node,
150 ipa_reference_vars_info_t info)
152 if (!ipa_reference_vars_vector.exists ()
153 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
154 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
155 ipa_reference_vars_vector[node->uid] = info;
158 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
159 static inline void
160 set_reference_optimization_summary (struct cgraph_node *node,
161 ipa_reference_optimization_summary_t info)
163 if (!ipa_reference_opt_sum_vector.exists ()
164 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
165 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
166 ipa_reference_opt_sum_vector[node->uid] = info;
169 /* Return a bitmap indexed by DECL_UID for the static variables that
170 are *not* read during the execution of the function FN. Returns
171 NULL if no data is available. */
173 bitmap
174 ipa_reference_get_not_read_global (struct cgraph_node *fn)
176 ipa_reference_optimization_summary_t info =
177 get_reference_optimization_summary (cgraph_function_node (fn, NULL));
178 if (info)
179 return info->statics_not_read;
180 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
181 return all_module_statics;
182 else
183 return NULL;
186 /* Return a bitmap indexed by DECL_UID for the static variables that
187 are *not* written during the execution of the function FN. Note
188 that variables written may or may not be read during the function
189 call. Returns NULL if no data is available. */
191 bitmap
192 ipa_reference_get_not_written_global (struct cgraph_node *fn)
194 ipa_reference_optimization_summary_t info =
195 get_reference_optimization_summary (fn);
196 if (info)
197 return info->statics_not_written;
198 else if (flags_from_decl_or_type (fn->symbol.decl) & ECF_LEAF)
199 return all_module_statics;
200 else
201 return NULL;
206 /* Add VAR to all_module_statics and the two
207 reference_vars_to_consider* sets. */
209 static inline void
210 add_static_var (tree var)
212 int uid = DECL_UID (var);
213 gcc_assert (TREE_CODE (var) == VAR_DECL);
214 if (dump_file)
215 splay_tree_insert (reference_vars_to_consider,
216 uid, (splay_tree_value)var);
217 bitmap_set_bit (all_module_statics, uid);
220 /* Return true if the variable T is the right kind of static variable to
221 perform compilation unit scope escape analysis. */
223 static inline bool
224 is_proper_for_analysis (tree t)
226 /* If the variable has the "used" attribute, treat it as if it had a
227 been touched by the devil. */
228 if (DECL_PRESERVE_P (t))
229 return false;
231 /* Do not want to do anything with volatile except mark any
232 function that uses one to be not const or pure. */
233 if (TREE_THIS_VOLATILE (t))
234 return false;
236 /* We do not need to analyze readonly vars, we already know they do not
237 alias. */
238 if (TREE_READONLY (t))
239 return false;
241 /* This is a variable we care about. Check if we have seen it
242 before, and if not add it the set of variables we care about. */
243 if (all_module_statics
244 && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
245 add_static_var (t);
247 return true;
250 /* Lookup the tree node for the static variable that has UID and
251 convert the name to a string for debugging. */
253 static const char *
254 get_static_name (int index)
256 splay_tree_node stn =
257 splay_tree_lookup (reference_vars_to_consider, index);
258 return fndecl_name ((tree)(stn->value));
261 /* Dump a set of static vars to FILE. */
262 static void
263 dump_static_vars_set_to_file (FILE *f, bitmap set)
265 unsigned int index;
266 bitmap_iterator bi;
267 if (set == NULL)
268 return;
269 else if (set == all_module_statics)
270 fprintf (f, "ALL");
271 else
272 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
274 fprintf (f, "%s ", get_static_name (index));
278 /* Compute X |= Y, taking into account the possibility that
279 either X or Y is already the maximum set.
280 Return true if X is the maximum set after taking the union with Y. */
282 static bool
283 union_static_var_sets (bitmap &x, bitmap y)
285 if (x != all_module_statics)
287 if (y == all_module_statics)
289 BITMAP_FREE (x);
290 x = all_module_statics;
292 else if (bitmap_ior_into (x, y))
294 /* The union may have reduced X to the maximum set.
295 In that case, we want to make that visible explicitly.
296 Even though bitmap_equal_p can be very expensive, it
297 turns out to be an overall win to check this here for
298 an LTO bootstrap of GCC itself. Liberally extrapoliate
299 that result to be applicable to all cases. */
300 if (bitmap_equal_p (x, all_module_statics))
302 BITMAP_FREE (x);
303 x = all_module_statics;
307 return x == all_module_statics;
310 /* Compute X &= Y, taking into account the possibility that
311 X may become the maximum set. */
313 static bool
314 intersect_static_var_sets (bitmap &x, bitmap y)
316 if (x != all_module_statics)
318 bitmap_and_into (x, y);
319 /* As with union_static_var_sets, reducing to the maximum
320 set as early as possible is an overall win. */
321 if (bitmap_equal_p (x, all_module_statics))
323 BITMAP_FREE (x);
324 x = all_module_statics;
327 return x == all_module_statics;
330 /* Return a copy of SET on the bitmap obstack containing SET.
331 But if SET is NULL or the maximum set, return that instead. */
333 static bitmap
334 copy_static_var_set (bitmap set)
336 if (set == NULL || set == all_module_statics)
337 return set;
338 bitmap_obstack *o = set->obstack;
339 gcc_checking_assert (o);
340 bitmap copy = BITMAP_ALLOC (o);
341 bitmap_copy (copy, set);
342 return copy;
345 /* Compute the union all of the statics read and written by every callee of X
346 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
347 actually the set representing the cycle containing X. If the read and
348 written sets of X_GLOBAL has been reduced to the maximum set, we don't
349 have to look at the remaining callees. */
351 static void
352 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
354 struct cgraph_edge *e;
355 bool read_all = x_global->statics_read == all_module_statics;
356 bool write_all = x_global->statics_written == all_module_statics;
357 for (e = x->callees;
358 e && !(read_all && write_all);
359 e = e->next_callee)
361 enum availability avail;
362 struct cgraph_node *y = cgraph_function_node (e->callee, &avail);
363 if (!y)
364 continue;
366 /* Only look into nodes we can propagate something. */
367 int flags = flags_from_decl_or_type (y->symbol.decl);
368 if (avail > AVAIL_OVERWRITABLE
369 || (avail == AVAIL_OVERWRITABLE && (flags & ECF_LEAF)))
371 if (get_reference_vars_info (y))
373 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
374 ipa_reference_global_vars_info_t y_global = &y_info->global;
376 /* Calls in the current cycle do not have their global set
377 computed yet (but everything else does because we're
378 visiting nodes in topological order). */
379 if (!y_global->statics_read)
380 continue;
382 /* If the function is const, it reads no memory even if it
383 seems so to local analysis. */
384 if (flags & ECF_CONST)
385 continue;
387 union_static_var_sets (x_global->statics_read,
388 y_global->statics_read);
390 /* If the function is pure, it has no stores even if it
391 seems so to local analysis. If we cannot return from
392 the function, we can safely ignore the call. */
393 if ((flags & ECF_PURE)
394 || cgraph_edge_cannot_lead_to_return (e))
395 continue;
397 union_static_var_sets (x_global->statics_written,
398 y_global->statics_written);
400 else
401 gcc_unreachable ();
406 /* The init routine for analyzing global static variable usage. See
407 comments at top for description. */
408 static void
409 ipa_init (void)
411 static bool init_p = false;
413 if (init_p)
414 return;
416 init_p = true;
418 if (dump_file)
419 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
421 bitmap_obstack_initialize (&local_info_obstack);
422 bitmap_obstack_initialize (&optimization_summary_obstack);
423 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
425 node_removal_hook_holder =
426 cgraph_add_node_removal_hook (&remove_node_data, NULL);
427 node_duplication_hook_holder =
428 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
432 /* Set up the persistent info for FN. */
434 static ipa_reference_local_vars_info_t
435 init_function_info (struct cgraph_node *fn)
437 ipa_reference_vars_info_t info
438 = XCNEW (struct ipa_reference_vars_info_d);
440 /* Add the info to the tree's annotation. */
441 set_reference_vars_info (fn, info);
443 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
444 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
446 return &info->local;
450 /* This is the main routine for finding the reference patterns for
451 global variables within a function FN. */
453 static void
454 analyze_function (struct cgraph_node *fn)
456 ipa_reference_local_vars_info_t local;
457 struct ipa_ref *ref;
458 int i;
459 tree var;
461 local = init_function_info (fn);
462 for (i = 0; ipa_ref_list_reference_iterate (&fn->symbol.ref_list, i, ref); i++)
464 if (!is_a <varpool_node> (ref->referred))
465 continue;
466 var = ipa_ref_varpool_node (ref)->symbol.decl;
467 if (!is_proper_for_analysis (var))
468 continue;
469 switch (ref->use)
471 case IPA_REF_LOAD:
472 bitmap_set_bit (local->statics_read, DECL_UID (var));
473 break;
474 case IPA_REF_STORE:
475 if (ipa_ref_cannot_lead_to_return (ref))
476 break;
477 bitmap_set_bit (local->statics_written, DECL_UID (var));
478 break;
479 case IPA_REF_ADDR:
480 break;
484 if (cgraph_node_cannot_return (fn))
485 bitmap_clear (local->statics_written);
489 /* Called when new clone is inserted to callgraph late. */
491 static void
492 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
493 void *data ATTRIBUTE_UNUSED)
495 ipa_reference_optimization_summary_t ginfo;
496 ipa_reference_optimization_summary_t dst_ginfo;
498 ginfo = get_reference_optimization_summary (src);
499 if (!ginfo)
500 return;
501 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
502 set_reference_optimization_summary (dst, dst_ginfo);
503 dst_ginfo->statics_not_read =
504 copy_static_var_set (ginfo->statics_not_read);
505 dst_ginfo->statics_not_written =
506 copy_static_var_set (ginfo->statics_not_written);
509 /* Called when node is removed. */
511 static void
512 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
514 ipa_reference_optimization_summary_t ginfo;
515 ginfo = get_reference_optimization_summary (node);
516 if (ginfo)
518 if (ginfo->statics_not_read
519 && ginfo->statics_not_read != all_module_statics)
520 BITMAP_FREE (ginfo->statics_not_read);
522 if (ginfo->statics_not_written
523 && ginfo->statics_not_written != all_module_statics)
524 BITMAP_FREE (ginfo->statics_not_written);
525 free (ginfo);
526 set_reference_optimization_summary (node, NULL);
530 /* Analyze each function in the cgraph to see which global or statics
531 are read or written. */
533 static void
534 generate_summary (void)
536 struct cgraph_node *node;
537 unsigned int index;
538 bitmap_iterator bi;
540 ipa_init ();
542 /* Process all of the functions next. */
543 FOR_EACH_DEFINED_FUNCTION (node)
544 analyze_function (node);
546 if (dump_file)
547 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
549 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
550 get_static_name (index), index);
553 if (dump_file)
554 FOR_EACH_DEFINED_FUNCTION (node)
555 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
557 ipa_reference_local_vars_info_t l;
558 unsigned int index;
559 bitmap_iterator bi;
561 l = &get_reference_vars_info (node)->local;
562 fprintf (dump_file,
563 "\nFunction name:%s/%i:",
564 cgraph_node_asm_name (node), node->symbol.order);
565 fprintf (dump_file, "\n locals read: ");
566 if (l->statics_read)
567 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
568 0, index, bi)
570 fprintf (dump_file, "%s ",
571 get_static_name (index));
573 fprintf (dump_file, "\n locals written: ");
574 if (l->statics_written)
575 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
576 0, index, bi)
578 fprintf (dump_file, "%s ", get_static_name (index));
583 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
585 static void
586 read_write_all_from_decl (struct cgraph_node *node,
587 bool &read_all, bool &write_all)
589 tree decl = node->symbol.decl;
590 int flags = flags_from_decl_or_type (decl);
591 if ((flags & ECF_LEAF)
592 && cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
594 else if (flags & ECF_CONST)
596 else if ((flags & ECF_PURE)
597 || cgraph_node_cannot_return (node))
599 read_all = true;
600 if (dump_file && (dump_flags & TDF_DETAILS))
601 fprintf (dump_file, " %s/%i -> read all\n",
602 cgraph_node_asm_name (node), node->symbol.order);
604 else
606 /* TODO: To be able to produce sane results, we should also handle
607 common builtins, in particular throw. */
608 read_all = true;
609 write_all = true;
610 if (dump_file && (dump_flags & TDF_DETAILS))
611 fprintf (dump_file, " %s/%i -> read all, write all\n",
612 cgraph_node_asm_name (node), node->symbol.order);
616 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
617 in the cycle of NODE. */
619 static void
620 get_read_write_all_from_node (struct cgraph_node *node,
621 bool &read_all, bool &write_all)
623 struct cgraph_edge *e, *ie;
625 /* When function is overwritable, we can not assume anything. */
626 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
627 read_write_all_from_decl (node, read_all, write_all);
629 for (e = node->callees;
630 e && !(read_all && write_all);
631 e = e->next_callee)
633 enum availability avail;
634 struct cgraph_node *callee = cgraph_function_node (e->callee, &avail);
635 gcc_checking_assert (callee);
636 if (avail <= AVAIL_OVERWRITABLE)
637 read_write_all_from_decl (callee, read_all, write_all);
640 for (ie = node->indirect_calls;
641 ie && !(read_all && write_all);
642 ie = ie->next_callee)
643 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
645 read_all = true;
646 if (dump_file && (dump_flags & TDF_DETAILS))
647 fprintf (dump_file, " indirect call -> read all\n");
648 if (!cgraph_edge_cannot_lead_to_return (ie)
649 && !(ie->indirect_info->ecf_flags & ECF_PURE))
651 if (dump_file && (dump_flags & TDF_DETAILS))
652 fprintf (dump_file, " indirect call -> write all\n");
653 write_all = true;
658 /* Produce the global information by preforming a transitive closure
659 on the local information that was produced by ipa_analyze_function. */
661 static unsigned int
662 propagate (void)
664 struct cgraph_node *node;
665 struct varpool_node *vnode;
666 struct cgraph_node **order =
667 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
668 int order_pos;
669 int i;
671 if (dump_file)
672 dump_cgraph (dump_file);
674 ipa_discover_readonly_nonaddressable_vars ();
675 generate_summary ();
677 /* Now we know what vars are really statics; prune out those that aren't. */
678 FOR_EACH_VARIABLE (vnode)
679 if (vnode->symbol.externally_visible
680 || TREE_ADDRESSABLE (vnode->symbol.decl)
681 || TREE_READONLY (vnode->symbol.decl)
682 || !is_proper_for_analysis (vnode->symbol.decl)
683 || !vnode->symbol.definition)
684 bitmap_clear_bit (all_module_statics, DECL_UID (vnode->symbol.decl));
686 /* Forget info we collected "just for fun" on variables that turned out to be
687 non-local. */
688 FOR_EACH_DEFINED_FUNCTION (node)
690 ipa_reference_local_vars_info_t node_l;
691 node_l = &get_reference_vars_info (node)->local;
692 intersect_static_var_sets (node_l->statics_read, all_module_statics);
693 intersect_static_var_sets (node_l->statics_written, all_module_statics);
696 /* Propagate the local information through the call graph to produce
697 the global information. All the nodes within a cycle will have
698 the same info so we collapse cycles first. Then we can do the
699 propagation in one pass from the leaves to the roots. */
700 order_pos = ipa_reduced_postorder (order, true, true, NULL);
701 if (dump_file)
702 ipa_print_order (dump_file, "reduced", order, order_pos);
704 for (i = 0; i < order_pos; i++ )
706 unsigned x;
707 struct cgraph_node *w;
708 ipa_reference_vars_info_t node_info;
709 ipa_reference_global_vars_info_t node_g;
710 ipa_reference_local_vars_info_t node_l;
711 bool read_all = false;
712 bool write_all = false;
714 node = order[i];
715 if (node->symbol.alias)
716 continue;
718 node_info = get_reference_vars_info (node);
719 gcc_assert (node_info);
720 node_l = &node_info->local;
721 node_g = &node_info->global;
723 if (dump_file && (dump_flags & TDF_DETAILS))
724 fprintf (dump_file, "Starting cycle with %s/%i\n",
725 cgraph_node_asm_name (node), node->symbol.order);
727 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
729 /* If any node in a cycle is read_all or write_all, they all are. */
730 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
732 if (dump_file && (dump_flags & TDF_DETAILS))
733 fprintf (dump_file, " Visiting %s/%i\n",
734 cgraph_node_asm_name (w), w->symbol.order);
735 get_read_write_all_from_node (w, read_all, write_all);
736 if (read_all && write_all)
737 break;
740 /* Initialized the bitmaps global sets for the reduced node. */
741 if (read_all)
742 node_g->statics_read = all_module_statics;
743 else
744 node_g->statics_read = copy_static_var_set (node_l->statics_read);
745 if (write_all)
746 node_g->statics_written = all_module_statics;
747 else
748 node_g->statics_written = copy_static_var_set (node_l->statics_written);
750 /* Merge the sets of this cycle with all sets of callees reached
751 from this cycle. */
752 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
754 if (read_all && write_all)
755 break;
757 if (w != node)
759 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
760 ipa_reference_local_vars_info_t w_l = &w_ri->local;
761 int flags = flags_from_decl_or_type (w->symbol.decl);
763 if (!(flags & ECF_CONST))
764 read_all = union_static_var_sets (node_g->statics_read,
765 w_l->statics_read);
766 if (!(flags & ECF_PURE)
767 && !cgraph_node_cannot_return (w))
768 write_all = union_static_var_sets (node_g->statics_written,
769 w_l->statics_written);
772 propagate_bits (node_g, w);
775 /* All nodes within a cycle have the same global info bitmaps. */
776 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
778 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
779 w_ri->global = *node_g;
782 cycle_nodes.release ();
785 if (dump_file)
787 for (i = 0; i < order_pos; i++)
789 unsigned x;
790 struct cgraph_node *w;
792 node = order[i];
793 if (node->symbol.alias)
794 continue;
796 fprintf (dump_file,
797 "\nFunction name:%s/%i:",
798 cgraph_node_asm_name (node), node->symbol.order);
800 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
801 ipa_reference_global_vars_info_t node_g = &node_info->global;
803 vec<cgraph_node_ptr> cycle_nodes = ipa_get_nodes_in_cycle (node);
804 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
806 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
807 ipa_reference_local_vars_info_t w_l = &w_ri->local;
808 if (w != node)
809 fprintf (dump_file, "\n next cycle: %s/%i ",
810 cgraph_node_asm_name (w), w->symbol.order);
811 fprintf (dump_file, "\n locals read: ");
812 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
813 fprintf (dump_file, "\n locals written: ");
814 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
816 cycle_nodes.release ();
818 fprintf (dump_file, "\n globals read: ");
819 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
820 fprintf (dump_file, "\n globals written: ");
821 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
822 fprintf (dump_file, "\n");
826 /* Cleanup. */
827 FOR_EACH_DEFINED_FUNCTION (node)
829 ipa_reference_vars_info_t node_info;
830 ipa_reference_global_vars_info_t node_g;
831 ipa_reference_optimization_summary_t opt;
833 node_info = get_reference_vars_info (node);
834 if (!node->symbol.alias
835 && (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
836 || (flags_from_decl_or_type (node->symbol.decl) & ECF_LEAF)))
838 node_g = &node_info->global;
840 opt = XCNEW (struct ipa_reference_optimization_summary_d);
841 set_reference_optimization_summary (node, opt);
843 /* Create the complimentary sets. */
845 if (bitmap_empty_p (node_g->statics_read))
846 opt->statics_not_read = all_module_statics;
847 else
849 opt->statics_not_read
850 = BITMAP_ALLOC (&optimization_summary_obstack);
851 if (node_g->statics_read != all_module_statics)
852 bitmap_and_compl (opt->statics_not_read,
853 all_module_statics,
854 node_g->statics_read);
857 if (bitmap_empty_p (node_g->statics_written))
858 opt->statics_not_written = all_module_statics;
859 else
861 opt->statics_not_written
862 = BITMAP_ALLOC (&optimization_summary_obstack);
863 if (node_g->statics_written != all_module_statics)
864 bitmap_and_compl (opt->statics_not_written,
865 all_module_statics,
866 node_g->statics_written);
869 free (node_info);
872 ipa_free_postorder_info ();
873 free (order);
875 bitmap_obstack_release (&local_info_obstack);
876 ipa_reference_vars_vector.release ();
877 if (dump_file)
878 splay_tree_delete (reference_vars_to_consider);
879 reference_vars_to_consider = NULL;
880 return 0;
883 /* Return true if we need to write summary of NODE. */
885 static bool
886 write_node_summary_p (struct cgraph_node *node,
887 lto_symtab_encoder_t encoder,
888 bitmap ltrans_statics)
890 ipa_reference_optimization_summary_t info;
892 /* See if we have (non-empty) info. */
893 if (!node->symbol.definition || node->global.inlined_to)
894 return false;
895 info = get_reference_optimization_summary (node);
896 if (!info || (bitmap_empty_p (info->statics_not_read)
897 && bitmap_empty_p (info->statics_not_written)))
898 return false;
900 /* See if we want to encode it.
901 Encode also referenced functions since constant folding might turn it into
902 a direct call.
904 In future we might also want to include summaries of functions references
905 by initializers of constant variables references in current unit. */
906 if (!reachable_from_this_partition_p (node, encoder)
907 && !referenced_from_this_partition_p (&node->symbol.ref_list, encoder))
908 return false;
910 /* See if the info has non-empty intersections with vars we want to encode. */
911 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
912 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
913 return false;
914 return true;
917 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
918 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
919 or -1. When it is positive, just output -1 when
920 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
922 static void
923 stream_out_bitmap (struct lto_simple_output_block *ob,
924 bitmap bits, bitmap ltrans_statics,
925 int ltrans_statics_bitcount)
927 int count = 0;
928 unsigned int index;
929 bitmap_iterator bi;
930 if (bits == all_module_statics)
932 streamer_write_hwi_stream (ob->main_stream, -1);
933 return;
935 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
936 count ++;
937 if (count == ltrans_statics_bitcount)
939 streamer_write_hwi_stream (ob->main_stream, -1);
940 return;
942 streamer_write_hwi_stream (ob->main_stream, count);
943 if (!count)
944 return;
945 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
947 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
948 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
952 /* Serialize the ipa info for lto. */
954 static void
955 ipa_reference_write_optimization_summary (void)
957 struct lto_simple_output_block *ob
958 = lto_create_simple_output_block (LTO_section_ipa_reference);
959 unsigned int count = 0;
960 int ltrans_statics_bitcount = 0;
961 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
962 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
963 int i;
965 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
967 /* See what variables we are interested in. */
968 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
970 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
971 varpool_node *vnode = dyn_cast <varpool_node> (snode);
972 if (vnode
973 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->symbol.decl))
974 && referenced_from_this_partition_p (&vnode->symbol.ref_list, encoder))
976 tree decl = vnode->symbol.decl;
977 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
978 splay_tree_insert (reference_vars_to_consider,
979 DECL_UID (decl), (splay_tree_value)decl);
980 ltrans_statics_bitcount ++;
985 if (ltrans_statics_bitcount)
986 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
988 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
989 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
990 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
991 count++;
994 streamer_write_uhwi_stream (ob->main_stream, count);
995 if (count)
996 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
997 -1);
999 /* Process all of the functions. */
1000 if (ltrans_statics_bitcount)
1001 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1003 symtab_node snode = lto_symtab_encoder_deref (encoder, i);
1004 cgraph_node *cnode = dyn_cast <cgraph_node> (snode);
1005 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1007 ipa_reference_optimization_summary_t info;
1008 int node_ref;
1010 info = get_reference_optimization_summary (cnode);
1011 node_ref = lto_symtab_encoder_encode (encoder, snode);
1012 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1014 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1015 ltrans_statics_bitcount);
1016 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1017 ltrans_statics_bitcount);
1020 BITMAP_FREE (ltrans_statics);
1021 lto_destroy_simple_output_block (ob);
1022 splay_tree_delete (reference_vars_to_consider);
1025 /* Deserialize the ipa info for lto. */
1027 static void
1028 ipa_reference_read_optimization_summary (void)
1030 struct lto_file_decl_data ** file_data_vec
1031 = lto_get_file_decl_data ();
1032 struct lto_file_decl_data * file_data;
1033 unsigned int j = 0;
1034 bitmap_obstack_initialize (&optimization_summary_obstack);
1036 node_removal_hook_holder =
1037 cgraph_add_node_removal_hook (&remove_node_data, NULL);
1038 node_duplication_hook_holder =
1039 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1040 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1042 while ((file_data = file_data_vec[j++]))
1044 const char *data;
1045 size_t len;
1046 struct lto_input_block *ib
1047 = lto_create_simple_input_block (file_data,
1048 LTO_section_ipa_reference,
1049 &data, &len);
1050 if (ib)
1052 unsigned int i;
1053 unsigned int f_count = streamer_read_uhwi (ib);
1054 int b_count;
1055 if (!f_count)
1056 continue;
1057 b_count = streamer_read_hwi (ib);
1058 if (dump_file)
1059 fprintf (dump_file, "all module statics:");
1060 for (i = 0; i < (unsigned int)b_count; i++)
1062 unsigned int var_index = streamer_read_uhwi (ib);
1063 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1064 var_index);
1065 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1066 if (dump_file)
1067 fprintf (dump_file, " %s", fndecl_name (v_decl));
1070 for (i = 0; i < f_count; i++)
1072 unsigned int j, index;
1073 struct cgraph_node *node;
1074 ipa_reference_optimization_summary_t info;
1075 int v_count;
1076 lto_symtab_encoder_t encoder;
1078 index = streamer_read_uhwi (ib);
1079 encoder = file_data->symtab_node_encoder;
1080 node = cgraph (lto_symtab_encoder_deref (encoder, index));
1081 info = XCNEW (struct ipa_reference_optimization_summary_d);
1082 set_reference_optimization_summary (node, info);
1083 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1084 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1085 if (dump_file)
1086 fprintf (dump_file,
1087 "\nFunction name:%s/%i:\n static not read:",
1088 cgraph_node_asm_name (node), node->symbol.order);
1090 /* Set the statics not read. */
1091 v_count = streamer_read_hwi (ib);
1092 if (v_count == -1)
1094 info->statics_not_read = all_module_statics;
1095 if (dump_file)
1096 fprintf (dump_file, " all module statics");
1098 else
1099 for (j = 0; j < (unsigned int)v_count; j++)
1101 unsigned int var_index = streamer_read_uhwi (ib);
1102 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1103 var_index);
1104 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1105 if (dump_file)
1106 fprintf (dump_file, " %s", fndecl_name (v_decl));
1109 if (dump_file)
1110 fprintf (dump_file,
1111 "\n static not written:");
1112 /* Set the statics not written. */
1113 v_count = streamer_read_hwi (ib);
1114 if (v_count == -1)
1116 info->statics_not_written = all_module_statics;
1117 if (dump_file)
1118 fprintf (dump_file, " all module statics");
1120 else
1121 for (j = 0; j < (unsigned int)v_count; j++)
1123 unsigned int var_index = streamer_read_uhwi (ib);
1124 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1125 var_index);
1126 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1127 if (dump_file)
1128 fprintf (dump_file, " %s", fndecl_name (v_decl));
1130 if (dump_file)
1131 fprintf (dump_file, "\n");
1134 lto_destroy_simple_input_block (file_data,
1135 LTO_section_ipa_reference,
1136 ib, data, len);
1138 else
1139 /* Fatal error here. We do not want to support compiling ltrans units with
1140 different version of compiler or different flags than the WPA unit, so
1141 this should never happen. */
1142 fatal_error ("ipa reference summary is missing in ltrans unit");
1146 static bool
1147 gate_reference (void)
1149 return (flag_ipa_reference
1150 /* Don't bother doing anything if the program has errors. */
1151 && !seen_error ());
1154 namespace {
1156 const pass_data pass_data_ipa_reference =
1158 IPA_PASS, /* type */
1159 "static-var", /* name */
1160 OPTGROUP_NONE, /* optinfo_flags */
1161 true, /* has_gate */
1162 true, /* has_execute */
1163 TV_IPA_REFERENCE, /* tv_id */
1164 0, /* properties_required */
1165 0, /* properties_provided */
1166 0, /* properties_destroyed */
1167 0, /* todo_flags_start */
1168 0, /* todo_flags_finish */
1171 class pass_ipa_reference : public ipa_opt_pass_d
1173 public:
1174 pass_ipa_reference (gcc::context *ctxt)
1175 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1176 NULL, /* generate_summary */
1177 NULL, /* write_summary */
1178 NULL, /* read_summary */
1179 ipa_reference_write_optimization_summary, /*
1180 write_optimization_summary */
1181 ipa_reference_read_optimization_summary, /*
1182 read_optimization_summary */
1183 NULL, /* stmt_fixup */
1184 0, /* function_transform_todo_flags_start */
1185 NULL, /* function_transform */
1186 NULL) /* variable_transform */
1189 /* opt_pass methods: */
1190 bool gate () { return gate_reference (); }
1191 unsigned int execute () { return propagate (); }
1193 }; // class pass_ipa_reference
1195 } // anon namespace
1197 ipa_opt_pass_d *
1198 make_pass_ipa_reference (gcc::context *ctxt)
1200 return new pass_ipa_reference (ctxt);