2014-12-20 Martin Uecker <uecker@eecs.berkeley.edu>
[official-gcc.git] / gcc / ipa-reference.c
blob714a0ee2c5d46c244f70a7327d33b467715eb33b
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2014 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
10 version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file gathers information about how variables whose scope is
22 confined to the compilation unit are used.
24 The transitive call site specific clobber effects are computed
25 for the variables whose scope is contained within this compilation
26 unit.
28 First each function and static variable initialization is analyzed
29 to determine which local static variables are either read, written,
30 or have their address taken. Any local static that has its address
31 taken is removed from consideration. Once the local read and
32 writes are determined, a transitive closure of this information is
33 performed over the call graph to determine the worst case set of
34 side effects of each call. In later parts of the compiler, these
35 local and global sets are examined to make the call clobbering less
36 traumatic, promote some statics to registers, and improve aliasing
37 information. */
39 #include "config.h"
40 #include "system.h"
41 #include "coretypes.h"
42 #include "tm.h"
43 #include "tree.h"
44 #include "calls.h"
45 #include "predict.h"
46 #include "vec.h"
47 #include "hashtab.h"
48 #include "hash-set.h"
49 #include "machmode.h"
50 #include "hard-reg-set.h"
51 #include "input.h"
52 #include "function.h"
53 #include "basic-block.h"
54 #include "tree-ssa-alias.h"
55 #include "internal-fn.h"
56 #include "gimple-expr.h"
57 #include "is-a.h"
58 #include "gimple.h"
59 #include "tree-inline.h"
60 #include "tree-pass.h"
61 #include "splay-tree.h"
62 #include "hash-map.h"
63 #include "plugin-api.h"
64 #include "ipa-ref.h"
65 #include "cgraph.h"
66 #include "ipa-utils.h"
67 #include "bitmap.h"
68 #include "ipa-reference.h"
69 #include "flags.h"
70 #include "diagnostic.h"
71 #include "data-streamer.h"
72 #include "lto-streamer.h"
74 static void remove_node_data (struct cgraph_node *node,
75 void *data ATTRIBUTE_UNUSED);
76 static void duplicate_node_data (struct cgraph_node *src,
77 struct cgraph_node *dst,
78 void *data ATTRIBUTE_UNUSED);
80 /* The static variables defined within the compilation unit that are
81 loaded or stored directly by function that owns this structure. */
83 struct ipa_reference_local_vars_info_d
85 bitmap statics_read;
86 bitmap statics_written;
89 /* Statics that are read and written by some set of functions. The
90 local ones are based on the loads and stores local to the function.
91 The global ones are based on the local info as well as the
92 transitive closure of the functions that are called. */
94 struct ipa_reference_global_vars_info_d
96 bitmap statics_read;
97 bitmap statics_written;
100 /* Information we save about every function after ipa-reference is completed. */
102 struct ipa_reference_optimization_summary_d
104 bitmap statics_not_read;
105 bitmap statics_not_written;
108 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
109 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
110 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
112 struct ipa_reference_vars_info_d
114 struct ipa_reference_local_vars_info_d local;
115 struct ipa_reference_global_vars_info_d global;
118 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
120 /* This splay tree contains all of the static variables that are
121 being considered by the compilation level alias analysis. */
122 static splay_tree reference_vars_to_consider;
124 /* Set of all interesting module statics. A bit is set for every module
125 static we are considering. This is added to the local info when asm
126 code is found that clobbers all memory. */
127 static bitmap all_module_statics;
129 /* Obstack holding bitmaps of local analysis (live from analysis to
130 propagation) */
131 static bitmap_obstack local_info_obstack;
132 /* Obstack holding global analysis live forever. */
133 static bitmap_obstack optimization_summary_obstack;
135 /* Holders of ipa cgraph hooks: */
136 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
137 static struct cgraph_node_hook_list *node_removal_hook_holder;
139 /* Vector where the reference var infos are actually stored.
140 Indexed by UID of call graph nodes. */
141 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
143 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
145 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
146 static inline ipa_reference_vars_info_t
147 get_reference_vars_info (struct cgraph_node *node)
149 if (!ipa_reference_vars_vector.exists ()
150 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
151 return NULL;
152 return ipa_reference_vars_vector[node->uid];
155 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
156 static inline ipa_reference_optimization_summary_t
157 get_reference_optimization_summary (struct cgraph_node *node)
159 if (!ipa_reference_opt_sum_vector.exists ()
160 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
161 return NULL;
162 return ipa_reference_opt_sum_vector[node->uid];
165 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
166 static inline void
167 set_reference_vars_info (struct cgraph_node *node,
168 ipa_reference_vars_info_t info)
170 if (!ipa_reference_vars_vector.exists ()
171 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
172 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
173 ipa_reference_vars_vector[node->uid] = info;
176 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
177 static inline void
178 set_reference_optimization_summary (struct cgraph_node *node,
179 ipa_reference_optimization_summary_t info)
181 if (!ipa_reference_opt_sum_vector.exists ()
182 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
183 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
184 ipa_reference_opt_sum_vector[node->uid] = info;
187 /* Return a bitmap indexed by DECL_UID for the static variables that
188 are *not* read during the execution of the function FN. Returns
189 NULL if no data is available. */
191 bitmap
192 ipa_reference_get_not_read_global (struct cgraph_node *fn)
194 ipa_reference_optimization_summary_t info =
195 get_reference_optimization_summary (fn->function_symbol (NULL));
196 if (info)
197 return info->statics_not_read;
198 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
199 return all_module_statics;
200 else
201 return NULL;
204 /* Return a bitmap indexed by DECL_UID for the static variables that
205 are *not* written during the execution of the function FN. Note
206 that variables written may or may not be read during the function
207 call. Returns NULL if no data is available. */
209 bitmap
210 ipa_reference_get_not_written_global (struct cgraph_node *fn)
212 ipa_reference_optimization_summary_t info =
213 get_reference_optimization_summary (fn);
214 if (info)
215 return info->statics_not_written;
216 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
217 return all_module_statics;
218 else
219 return NULL;
224 /* Add VAR to all_module_statics and the two
225 reference_vars_to_consider* sets. */
227 static inline void
228 add_static_var (tree var)
230 int uid = DECL_UID (var);
231 gcc_assert (TREE_CODE (var) == VAR_DECL);
232 if (dump_file)
233 splay_tree_insert (reference_vars_to_consider,
234 uid, (splay_tree_value)var);
235 bitmap_set_bit (all_module_statics, uid);
238 /* Return true if the variable T is the right kind of static variable to
239 perform compilation unit scope escape analysis. */
241 static inline bool
242 is_proper_for_analysis (tree t)
244 /* If the variable has the "used" attribute, treat it as if it had a
245 been touched by the devil. */
246 if (DECL_PRESERVE_P (t))
247 return false;
249 /* Do not want to do anything with volatile except mark any
250 function that uses one to be not const or pure. */
251 if (TREE_THIS_VOLATILE (t))
252 return false;
254 /* We do not need to analyze readonly vars, we already know they do not
255 alias. */
256 if (TREE_READONLY (t))
257 return false;
259 /* We can not track variables with address taken. */
260 if (TREE_ADDRESSABLE (t))
261 return false;
263 /* TODO: We could track public variables that are not addressable, but currently
264 frontends don't give us those. */
265 if (TREE_PUBLIC (t))
266 return false;
268 /* TODO: Check aliases. */
270 /* This is a variable we care about. Check if we have seen it
271 before, and if not add it the set of variables we care about. */
272 if (all_module_statics
273 && !bitmap_bit_p (all_module_statics, DECL_UID (t)))
274 add_static_var (t);
276 return true;
279 /* Lookup the tree node for the static variable that has UID and
280 convert the name to a string for debugging. */
282 static const char *
283 get_static_name (int index)
285 splay_tree_node stn =
286 splay_tree_lookup (reference_vars_to_consider, index);
287 return fndecl_name ((tree)(stn->value));
290 /* Dump a set of static vars to FILE. */
291 static void
292 dump_static_vars_set_to_file (FILE *f, bitmap set)
294 unsigned int index;
295 bitmap_iterator bi;
296 if (set == NULL)
297 return;
298 else if (set == all_module_statics)
299 fprintf (f, "ALL");
300 else
301 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
303 fprintf (f, "%s ", get_static_name (index));
307 /* Compute X |= Y, taking into account the possibility that
308 either X or Y is already the maximum set.
309 Return true if X is the maximum set after taking the union with Y. */
311 static bool
312 union_static_var_sets (bitmap &x, bitmap y)
314 if (x != all_module_statics)
316 if (y == all_module_statics)
318 BITMAP_FREE (x);
319 x = all_module_statics;
321 else if (bitmap_ior_into (x, y))
323 /* The union may have reduced X to the maximum set.
324 In that case, we want to make that visible explicitly.
325 Even though bitmap_equal_p can be very expensive, it
326 turns out to be an overall win to check this here for
327 an LTO bootstrap of GCC itself. Liberally extrapoliate
328 that result to be applicable to all cases. */
329 if (bitmap_equal_p (x, all_module_statics))
331 BITMAP_FREE (x);
332 x = all_module_statics;
336 return x == all_module_statics;
339 /* Return a copy of SET on the bitmap obstack containing SET.
340 But if SET is NULL or the maximum set, return that instead. */
342 static bitmap
343 copy_static_var_set (bitmap set)
345 if (set == NULL || set == all_module_statics)
346 return set;
347 bitmap_obstack *o = set->obstack;
348 gcc_checking_assert (o);
349 bitmap copy = BITMAP_ALLOC (o);
350 bitmap_copy (copy, set);
351 return copy;
354 /* Compute the union all of the statics read and written by every callee of X
355 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
356 actually the set representing the cycle containing X. If the read and
357 written sets of X_GLOBAL has been reduced to the maximum set, we don't
358 have to look at the remaining callees. */
360 static void
361 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
363 struct cgraph_edge *e;
364 bool read_all = x_global->statics_read == all_module_statics;
365 bool write_all = x_global->statics_written == all_module_statics;
366 for (e = x->callees;
367 e && !(read_all && write_all);
368 e = e->next_callee)
370 enum availability avail;
371 struct cgraph_node *y = e->callee->function_symbol (&avail);
372 if (!y)
373 continue;
375 /* Only look into nodes we can propagate something. */
376 int flags = flags_from_decl_or_type (y->decl);
377 if (avail > AVAIL_INTERPOSABLE
378 || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF)))
380 if (get_reference_vars_info (y))
382 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
383 ipa_reference_global_vars_info_t y_global = &y_info->global;
385 /* Calls in the current cycle do not have their global set
386 computed yet (but everything else does because we're
387 visiting nodes in topological order). */
388 if (!y_global->statics_read)
389 continue;
391 /* If the function is const, it reads no memory even if it
392 seems so to local analysis. */
393 if (flags & ECF_CONST)
394 continue;
396 union_static_var_sets (x_global->statics_read,
397 y_global->statics_read);
399 /* If the function is pure, it has no stores even if it
400 seems so to local analysis. If we cannot return from
401 the function, we can safely ignore the call. */
402 if ((flags & ECF_PURE)
403 || e->cannot_lead_to_return_p ())
404 continue;
406 union_static_var_sets (x_global->statics_written,
407 y_global->statics_written);
409 else
410 gcc_unreachable ();
415 static bool ipa_init_p = false;
417 /* The init routine for analyzing global static variable usage. See
418 comments at top for description. */
419 static void
420 ipa_init (void)
422 if (ipa_init_p)
423 return;
425 ipa_init_p = true;
427 if (dump_file)
428 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
430 bitmap_obstack_initialize (&local_info_obstack);
431 bitmap_obstack_initialize (&optimization_summary_obstack);
432 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
434 node_removal_hook_holder =
435 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
436 node_duplication_hook_holder =
437 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
441 /* Set up the persistent info for FN. */
443 static ipa_reference_local_vars_info_t
444 init_function_info (struct cgraph_node *fn)
446 ipa_reference_vars_info_t info
447 = XCNEW (struct ipa_reference_vars_info_d);
449 /* Add the info to the tree's annotation. */
450 set_reference_vars_info (fn, info);
452 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
453 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
455 return &info->local;
459 /* This is the main routine for finding the reference patterns for
460 global variables within a function FN. */
462 static void
463 analyze_function (struct cgraph_node *fn)
465 ipa_reference_local_vars_info_t local;
466 struct ipa_ref *ref = NULL;
467 int i;
468 tree var;
470 local = init_function_info (fn);
471 for (i = 0; fn->iterate_reference (i, ref); i++)
473 if (!is_a <varpool_node *> (ref->referred))
474 continue;
475 var = ref->referred->decl;
476 if (!is_proper_for_analysis (var))
477 continue;
478 switch (ref->use)
480 case IPA_REF_LOAD:
481 bitmap_set_bit (local->statics_read, DECL_UID (var));
482 break;
483 case IPA_REF_STORE:
484 if (ref->cannot_lead_to_return ())
485 break;
486 bitmap_set_bit (local->statics_written, DECL_UID (var));
487 break;
488 case IPA_REF_ADDR:
489 break;
490 default:
491 gcc_unreachable ();
495 if (fn->cannot_return_p ())
496 bitmap_clear (local->statics_written);
500 /* Called when new clone is inserted to callgraph late. */
502 static void
503 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
504 void *data ATTRIBUTE_UNUSED)
506 ipa_reference_optimization_summary_t ginfo;
507 ipa_reference_optimization_summary_t dst_ginfo;
509 ginfo = get_reference_optimization_summary (src);
510 if (!ginfo)
511 return;
512 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
513 set_reference_optimization_summary (dst, dst_ginfo);
514 dst_ginfo->statics_not_read =
515 copy_static_var_set (ginfo->statics_not_read);
516 dst_ginfo->statics_not_written =
517 copy_static_var_set (ginfo->statics_not_written);
520 /* Called when node is removed. */
522 static void
523 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
525 ipa_reference_optimization_summary_t ginfo;
526 ginfo = get_reference_optimization_summary (node);
527 if (ginfo)
529 if (ginfo->statics_not_read
530 && ginfo->statics_not_read != all_module_statics)
531 BITMAP_FREE (ginfo->statics_not_read);
533 if (ginfo->statics_not_written
534 && ginfo->statics_not_written != all_module_statics)
535 BITMAP_FREE (ginfo->statics_not_written);
536 free (ginfo);
537 set_reference_optimization_summary (node, NULL);
541 /* Analyze each function in the cgraph to see which global or statics
542 are read or written. */
544 static void
545 generate_summary (void)
547 struct cgraph_node *node;
548 unsigned int index;
549 bitmap_iterator bi;
551 ipa_init ();
553 /* Process all of the functions next. */
554 FOR_EACH_DEFINED_FUNCTION (node)
555 analyze_function (node);
557 if (dump_file)
558 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
560 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
561 get_static_name (index), index);
564 if (dump_file)
565 FOR_EACH_DEFINED_FUNCTION (node)
566 if (node->get_availability () >= AVAIL_INTERPOSABLE)
568 ipa_reference_local_vars_info_t l;
569 unsigned int index;
570 bitmap_iterator bi;
572 l = &get_reference_vars_info (node)->local;
573 fprintf (dump_file,
574 "\nFunction name:%s/%i:",
575 node->asm_name (), node->order);
576 fprintf (dump_file, "\n locals read: ");
577 if (l->statics_read)
578 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
579 0, index, bi)
581 fprintf (dump_file, "%s ",
582 get_static_name (index));
584 fprintf (dump_file, "\n locals written: ");
585 if (l->statics_written)
586 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
587 0, index, bi)
589 fprintf (dump_file, "%s ", get_static_name (index));
594 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
596 static void
597 read_write_all_from_decl (struct cgraph_node *node,
598 bool &read_all, bool &write_all)
600 tree decl = node->decl;
601 int flags = flags_from_decl_or_type (decl);
602 if ((flags & ECF_LEAF)
603 && node->get_availability () <= AVAIL_INTERPOSABLE)
605 else if (flags & ECF_CONST)
607 else if ((flags & ECF_PURE) || node->cannot_return_p ())
609 read_all = true;
610 if (dump_file && (dump_flags & TDF_DETAILS))
611 fprintf (dump_file, " %s/%i -> read all\n",
612 node->asm_name (), node->order);
614 else
616 /* TODO: To be able to produce sane results, we should also handle
617 common builtins, in particular throw. */
618 read_all = true;
619 write_all = true;
620 if (dump_file && (dump_flags & TDF_DETAILS))
621 fprintf (dump_file, " %s/%i -> read all, write all\n",
622 node->asm_name (), node->order);
626 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
627 in the cycle of NODE. */
629 static void
630 get_read_write_all_from_node (struct cgraph_node *node,
631 bool &read_all, bool &write_all)
633 struct cgraph_edge *e, *ie;
635 /* When function is overwritable, we can not assume anything. */
636 if (node->get_availability () <= AVAIL_INTERPOSABLE)
637 read_write_all_from_decl (node, read_all, write_all);
639 for (e = node->callees;
640 e && !(read_all && write_all);
641 e = e->next_callee)
643 enum availability avail;
644 struct cgraph_node *callee = e->callee->function_symbol (&avail);
645 gcc_checking_assert (callee);
646 if (avail <= AVAIL_INTERPOSABLE)
647 read_write_all_from_decl (callee, read_all, write_all);
650 for (ie = node->indirect_calls;
651 ie && !(read_all && write_all);
652 ie = ie->next_callee)
653 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
655 read_all = true;
656 if (dump_file && (dump_flags & TDF_DETAILS))
657 fprintf (dump_file, " indirect call -> read all\n");
658 if (!ie->cannot_lead_to_return_p ()
659 && !(ie->indirect_info->ecf_flags & ECF_PURE))
661 if (dump_file && (dump_flags & TDF_DETAILS))
662 fprintf (dump_file, " indirect call -> write all\n");
663 write_all = true;
668 /* Produce the global information by preforming a transitive closure
669 on the local information that was produced by ipa_analyze_function. */
671 static unsigned int
672 propagate (void)
674 struct cgraph_node *node;
675 struct cgraph_node **order =
676 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
677 int order_pos;
678 int i;
679 bool remove_p;
681 if (dump_file)
682 cgraph_node::dump_cgraph (dump_file);
684 remove_p = ipa_discover_readonly_nonaddressable_vars ();
685 generate_summary ();
687 /* Propagate the local information through the call graph to produce
688 the global information. All the nodes within a cycle will have
689 the same info so we collapse cycles first. Then we can do the
690 propagation in one pass from the leaves to the roots. */
691 order_pos = ipa_reduced_postorder (order, true, true, NULL);
692 if (dump_file)
693 ipa_print_order (dump_file, "reduced", order, order_pos);
695 for (i = 0; i < order_pos; i++ )
697 unsigned x;
698 struct cgraph_node *w;
699 ipa_reference_vars_info_t node_info;
700 ipa_reference_global_vars_info_t node_g;
701 ipa_reference_local_vars_info_t node_l;
702 bool read_all = false;
703 bool write_all = false;
705 node = order[i];
706 if (node->alias)
707 continue;
709 node_info = get_reference_vars_info (node);
710 gcc_assert (node_info);
711 node_l = &node_info->local;
712 node_g = &node_info->global;
714 if (dump_file && (dump_flags & TDF_DETAILS))
715 fprintf (dump_file, "Starting cycle with %s/%i\n",
716 node->asm_name (), node->order);
718 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
720 /* If any node in a cycle is read_all or write_all, they all are. */
721 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
723 if (dump_file && (dump_flags & TDF_DETAILS))
724 fprintf (dump_file, " Visiting %s/%i\n",
725 w->asm_name (), w->order);
726 get_read_write_all_from_node (w, read_all, write_all);
727 if (read_all && write_all)
728 break;
731 /* Initialized the bitmaps global sets for the reduced node. */
732 if (read_all)
733 node_g->statics_read = all_module_statics;
734 else
735 node_g->statics_read = copy_static_var_set (node_l->statics_read);
736 if (write_all)
737 node_g->statics_written = all_module_statics;
738 else
739 node_g->statics_written = copy_static_var_set (node_l->statics_written);
741 /* Merge the sets of this cycle with all sets of callees reached
742 from this cycle. */
743 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
745 if (read_all && write_all)
746 break;
748 if (w != node)
750 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
751 ipa_reference_local_vars_info_t w_l = &w_ri->local;
752 int flags = flags_from_decl_or_type (w->decl);
754 if (!(flags & ECF_CONST))
755 read_all = union_static_var_sets (node_g->statics_read,
756 w_l->statics_read);
757 if (!(flags & ECF_PURE)
758 && !w->cannot_return_p ())
759 write_all = union_static_var_sets (node_g->statics_written,
760 w_l->statics_written);
763 propagate_bits (node_g, w);
766 /* All nodes within a cycle have the same global info bitmaps. */
767 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
769 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
770 w_ri->global = *node_g;
773 cycle_nodes.release ();
776 if (dump_file)
778 for (i = 0; i < order_pos; i++)
780 unsigned x;
781 struct cgraph_node *w;
783 node = order[i];
784 if (node->alias)
785 continue;
787 fprintf (dump_file,
788 "\nFunction name:%s/%i:",
789 node->asm_name (), node->order);
791 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
792 ipa_reference_global_vars_info_t node_g = &node_info->global;
794 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
795 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
797 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
798 ipa_reference_local_vars_info_t w_l = &w_ri->local;
799 if (w != node)
800 fprintf (dump_file, "\n next cycle: %s/%i ",
801 w->asm_name (), w->order);
802 fprintf (dump_file, "\n locals read: ");
803 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
804 fprintf (dump_file, "\n locals written: ");
805 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
807 cycle_nodes.release ();
809 fprintf (dump_file, "\n globals read: ");
810 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
811 fprintf (dump_file, "\n globals written: ");
812 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
813 fprintf (dump_file, "\n");
817 /* Cleanup. */
818 FOR_EACH_DEFINED_FUNCTION (node)
820 ipa_reference_vars_info_t node_info;
821 ipa_reference_global_vars_info_t node_g;
822 ipa_reference_optimization_summary_t opt;
824 node_info = get_reference_vars_info (node);
825 if (!node->alias
826 && (node->get_availability () > AVAIL_INTERPOSABLE
827 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
829 node_g = &node_info->global;
831 opt = XCNEW (struct ipa_reference_optimization_summary_d);
832 set_reference_optimization_summary (node, opt);
834 /* Create the complimentary sets. */
836 if (bitmap_empty_p (node_g->statics_read))
837 opt->statics_not_read = all_module_statics;
838 else
840 opt->statics_not_read
841 = BITMAP_ALLOC (&optimization_summary_obstack);
842 if (node_g->statics_read != all_module_statics)
843 bitmap_and_compl (opt->statics_not_read,
844 all_module_statics,
845 node_g->statics_read);
848 if (bitmap_empty_p (node_g->statics_written))
849 opt->statics_not_written = all_module_statics;
850 else
852 opt->statics_not_written
853 = BITMAP_ALLOC (&optimization_summary_obstack);
854 if (node_g->statics_written != all_module_statics)
855 bitmap_and_compl (opt->statics_not_written,
856 all_module_statics,
857 node_g->statics_written);
860 free (node_info);
863 ipa_free_postorder_info ();
864 free (order);
866 bitmap_obstack_release (&local_info_obstack);
867 ipa_reference_vars_vector.release ();
868 if (dump_file)
869 splay_tree_delete (reference_vars_to_consider);
870 reference_vars_to_consider = NULL;
871 return remove_p ? TODO_remove_functions : 0;
874 /* Return true if we need to write summary of NODE. */
876 static bool
877 write_node_summary_p (struct cgraph_node *node,
878 lto_symtab_encoder_t encoder,
879 bitmap ltrans_statics)
881 ipa_reference_optimization_summary_t info;
883 /* See if we have (non-empty) info. */
884 if (!node->definition || node->global.inlined_to)
885 return false;
886 info = get_reference_optimization_summary (node);
887 if (!info || (bitmap_empty_p (info->statics_not_read)
888 && bitmap_empty_p (info->statics_not_written)))
889 return false;
891 /* See if we want to encode it.
892 Encode also referenced functions since constant folding might turn it into
893 a direct call.
895 In future we might also want to include summaries of functions references
896 by initializers of constant variables references in current unit. */
897 if (!reachable_from_this_partition_p (node, encoder)
898 && !referenced_from_this_partition_p (node, encoder))
899 return false;
901 /* See if the info has non-empty intersections with vars we want to encode. */
902 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
903 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
904 return false;
905 return true;
908 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
909 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
910 or -1. When it is positive, just output -1 when
911 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
913 static void
914 stream_out_bitmap (struct lto_simple_output_block *ob,
915 bitmap bits, bitmap ltrans_statics,
916 int ltrans_statics_bitcount)
918 int count = 0;
919 unsigned int index;
920 bitmap_iterator bi;
921 if (bits == all_module_statics)
923 streamer_write_hwi_stream (ob->main_stream, -1);
924 return;
926 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
927 count ++;
928 if (count == ltrans_statics_bitcount)
930 streamer_write_hwi_stream (ob->main_stream, -1);
931 return;
933 streamer_write_hwi_stream (ob->main_stream, count);
934 if (!count)
935 return;
936 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
938 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
939 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
943 /* Serialize the ipa info for lto. */
945 static void
946 ipa_reference_write_optimization_summary (void)
948 struct lto_simple_output_block *ob
949 = lto_create_simple_output_block (LTO_section_ipa_reference);
950 unsigned int count = 0;
951 int ltrans_statics_bitcount = 0;
952 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
953 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
954 int i;
956 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
958 /* See what variables we are interested in. */
959 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
961 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
962 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
963 if (vnode
964 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
965 && referenced_from_this_partition_p (vnode, encoder))
967 tree decl = vnode->decl;
968 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
969 splay_tree_insert (reference_vars_to_consider,
970 DECL_UID (decl), (splay_tree_value)decl);
971 ltrans_statics_bitcount ++;
976 if (ltrans_statics_bitcount)
977 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
979 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
980 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
981 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
982 count++;
985 streamer_write_uhwi_stream (ob->main_stream, count);
986 if (count)
987 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
988 -1);
990 /* Process all of the functions. */
991 if (ltrans_statics_bitcount)
992 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
994 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
995 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
996 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
998 ipa_reference_optimization_summary_t info;
999 int node_ref;
1001 info = get_reference_optimization_summary (cnode);
1002 node_ref = lto_symtab_encoder_encode (encoder, snode);
1003 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1005 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1006 ltrans_statics_bitcount);
1007 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1008 ltrans_statics_bitcount);
1011 BITMAP_FREE (ltrans_statics);
1012 lto_destroy_simple_output_block (ob);
1013 splay_tree_delete (reference_vars_to_consider);
1016 /* Deserialize the ipa info for lto. */
1018 static void
1019 ipa_reference_read_optimization_summary (void)
1021 struct lto_file_decl_data ** file_data_vec
1022 = lto_get_file_decl_data ();
1023 struct lto_file_decl_data * file_data;
1024 unsigned int j = 0;
1025 bitmap_obstack_initialize (&optimization_summary_obstack);
1027 node_removal_hook_holder =
1028 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
1029 node_duplication_hook_holder =
1030 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
1031 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1033 while ((file_data = file_data_vec[j++]))
1035 const char *data;
1036 size_t len;
1037 struct lto_input_block *ib
1038 = lto_create_simple_input_block (file_data,
1039 LTO_section_ipa_reference,
1040 &data, &len);
1041 if (ib)
1043 unsigned int i;
1044 unsigned int f_count = streamer_read_uhwi (ib);
1045 int b_count;
1046 if (!f_count)
1047 continue;
1048 b_count = streamer_read_hwi (ib);
1049 if (dump_file)
1050 fprintf (dump_file, "all module statics:");
1051 for (i = 0; i < (unsigned int)b_count; i++)
1053 unsigned int var_index = streamer_read_uhwi (ib);
1054 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1055 var_index);
1056 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1057 if (dump_file)
1058 fprintf (dump_file, " %s", fndecl_name (v_decl));
1061 for (i = 0; i < f_count; i++)
1063 unsigned int j, index;
1064 struct cgraph_node *node;
1065 ipa_reference_optimization_summary_t info;
1066 int v_count;
1067 lto_symtab_encoder_t encoder;
1069 index = streamer_read_uhwi (ib);
1070 encoder = file_data->symtab_node_encoder;
1071 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1072 (encoder, index));
1073 info = XCNEW (struct ipa_reference_optimization_summary_d);
1074 set_reference_optimization_summary (node, info);
1075 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1076 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1077 if (dump_file)
1078 fprintf (dump_file,
1079 "\nFunction name:%s/%i:\n static not read:",
1080 node->asm_name (), node->order);
1082 /* Set the statics not read. */
1083 v_count = streamer_read_hwi (ib);
1084 if (v_count == -1)
1086 info->statics_not_read = all_module_statics;
1087 if (dump_file)
1088 fprintf (dump_file, " all module statics");
1090 else
1091 for (j = 0; j < (unsigned int)v_count; j++)
1093 unsigned int var_index = streamer_read_uhwi (ib);
1094 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1095 var_index);
1096 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1097 if (dump_file)
1098 fprintf (dump_file, " %s", fndecl_name (v_decl));
1101 if (dump_file)
1102 fprintf (dump_file,
1103 "\n static not written:");
1104 /* Set the statics not written. */
1105 v_count = streamer_read_hwi (ib);
1106 if (v_count == -1)
1108 info->statics_not_written = all_module_statics;
1109 if (dump_file)
1110 fprintf (dump_file, " all module statics");
1112 else
1113 for (j = 0; j < (unsigned int)v_count; j++)
1115 unsigned int var_index = streamer_read_uhwi (ib);
1116 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1117 var_index);
1118 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1119 if (dump_file)
1120 fprintf (dump_file, " %s", fndecl_name (v_decl));
1122 if (dump_file)
1123 fprintf (dump_file, "\n");
1126 lto_destroy_simple_input_block (file_data,
1127 LTO_section_ipa_reference,
1128 ib, data, len);
1130 else
1131 /* Fatal error here. We do not want to support compiling ltrans units with
1132 different version of compiler or different flags than the WPA unit, so
1133 this should never happen. */
1134 fatal_error ("ipa reference summary is missing in ltrans unit");
1138 namespace {
1140 const pass_data pass_data_ipa_reference =
1142 IPA_PASS, /* type */
1143 "static-var", /* name */
1144 OPTGROUP_NONE, /* optinfo_flags */
1145 TV_IPA_REFERENCE, /* tv_id */
1146 0, /* properties_required */
1147 0, /* properties_provided */
1148 0, /* properties_destroyed */
1149 0, /* todo_flags_start */
1150 0, /* todo_flags_finish */
1153 class pass_ipa_reference : public ipa_opt_pass_d
1155 public:
1156 pass_ipa_reference (gcc::context *ctxt)
1157 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1158 NULL, /* generate_summary */
1159 NULL, /* write_summary */
1160 NULL, /* read_summary */
1161 ipa_reference_write_optimization_summary, /*
1162 write_optimization_summary */
1163 ipa_reference_read_optimization_summary, /*
1164 read_optimization_summary */
1165 NULL, /* stmt_fixup */
1166 0, /* function_transform_todo_flags_start */
1167 NULL, /* function_transform */
1168 NULL) /* variable_transform */
1171 /* opt_pass methods: */
1172 virtual bool gate (function *)
1174 return (flag_ipa_reference
1175 /* Don't bother doing anything if the program has errors. */
1176 && !seen_error ());
1179 virtual unsigned int execute (function *) { return propagate (); }
1181 }; // class pass_ipa_reference
1183 } // anon namespace
1185 ipa_opt_pass_d *
1186 make_pass_ipa_reference (gcc::context *ctxt)
1188 return new pass_ipa_reference (ctxt);
1191 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1192 within the same process. For use by toplev::finalize. */
1194 void
1195 ipa_reference_c_finalize (void)
1197 if (ipa_init_p)
1199 bitmap_obstack_release (&optimization_summary_obstack);
1200 ipa_init_p = false;
1203 if (node_removal_hook_holder)
1205 symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
1206 node_removal_hook_holder = NULL;
1208 if (node_duplication_hook_holder)
1210 symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder);
1211 node_duplication_hook_holder = NULL;