2015-07-10 Paolo Carlini <paolo.carlini@oracle.com>
[official-gcc.git] / gcc / ipa-reference.c
blobc00fca34526b144fededf8a2956a56266bd4c340
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2015 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 "backend.h"
43 #include "tree.h"
44 #include "gimple.h"
45 #include "hard-reg-set.h"
46 #include "alias.h"
47 #include "options.h"
48 #include "fold-const.h"
49 #include "calls.h"
50 #include "internal-fn.h"
51 #include "tree-inline.h"
52 #include "tree-pass.h"
53 #include "splay-tree.h"
54 #include "cgraph.h"
55 #include "ipa-utils.h"
56 #include "ipa-reference.h"
57 #include "flags.h"
58 #include "diagnostic.h"
59 #include "data-streamer.h"
61 static void remove_node_data (struct cgraph_node *node,
62 void *data ATTRIBUTE_UNUSED);
63 static void duplicate_node_data (struct cgraph_node *src,
64 struct cgraph_node *dst,
65 void *data ATTRIBUTE_UNUSED);
67 /* The static variables defined within the compilation unit that are
68 loaded or stored directly by function that owns this structure. */
70 struct ipa_reference_local_vars_info_d
72 bitmap statics_read;
73 bitmap statics_written;
76 /* Statics that are read and written by some set of functions. The
77 local ones are based on the loads and stores local to the function.
78 The global ones are based on the local info as well as the
79 transitive closure of the functions that are called. */
81 struct ipa_reference_global_vars_info_d
83 bitmap statics_read;
84 bitmap statics_written;
87 /* Information we save about every function after ipa-reference is completed. */
89 struct ipa_reference_optimization_summary_d
91 bitmap statics_not_read;
92 bitmap statics_not_written;
95 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
96 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
97 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
99 struct ipa_reference_vars_info_d
101 struct ipa_reference_local_vars_info_d local;
102 struct ipa_reference_global_vars_info_d global;
105 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
107 /* This splay tree contains all of the static variables that are
108 being considered by the compilation level alias analysis. */
109 static splay_tree reference_vars_to_consider;
111 /* Set of all interesting module statics. A bit is set for every module
112 static we are considering. This is added to the local info when asm
113 code is found that clobbers all memory. */
114 static bitmap all_module_statics;
115 /* Set of all statics that should be ignored becuase they are touched by
116 -fno-ipa-reference code. */
117 static bitmap ignore_module_statics;
119 /* Obstack holding bitmaps of local analysis (live from analysis to
120 propagation) */
121 static bitmap_obstack local_info_obstack;
122 /* Obstack holding global analysis live forever. */
123 static bitmap_obstack optimization_summary_obstack;
125 /* Holders of ipa cgraph hooks: */
126 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
127 static struct cgraph_node_hook_list *node_removal_hook_holder;
129 /* Vector where the reference var infos are actually stored.
130 Indexed by UID of call graph nodes. */
131 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
133 /* TODO: find a place where we should release the vector. */
134 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
136 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
137 static inline ipa_reference_vars_info_t
138 get_reference_vars_info (struct cgraph_node *node)
140 if (!ipa_reference_vars_vector.exists ()
141 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
142 return NULL;
143 return ipa_reference_vars_vector[node->uid];
146 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
147 static inline ipa_reference_optimization_summary_t
148 get_reference_optimization_summary (struct cgraph_node *node)
150 if (!ipa_reference_opt_sum_vector.exists ()
151 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
152 return NULL;
153 return ipa_reference_opt_sum_vector[node->uid];
156 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
157 static inline void
158 set_reference_vars_info (struct cgraph_node *node,
159 ipa_reference_vars_info_t info)
161 if (!ipa_reference_vars_vector.exists ()
162 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
163 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
164 ipa_reference_vars_vector[node->uid] = info;
167 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
168 static inline void
169 set_reference_optimization_summary (struct cgraph_node *node,
170 ipa_reference_optimization_summary_t info)
172 if (!ipa_reference_opt_sum_vector.exists ()
173 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
174 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
175 ipa_reference_opt_sum_vector[node->uid] = info;
178 /* Return a bitmap indexed by DECL_UID for the static variables that
179 are *not* read during the execution of the function FN. Returns
180 NULL if no data is available. */
182 bitmap
183 ipa_reference_get_not_read_global (struct cgraph_node *fn)
185 if (!opt_for_fn (fn->decl, flag_ipa_reference)
186 || !opt_for_fn (current_function_decl, flag_ipa_reference))
187 return NULL;
188 ipa_reference_optimization_summary_t info =
189 get_reference_optimization_summary (fn->function_symbol (NULL));
190 if (info)
191 return info->statics_not_read;
192 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
193 return all_module_statics;
194 else
195 return NULL;
198 /* Return a bitmap indexed by DECL_UID for the static variables that
199 are *not* written during the execution of the function FN. Note
200 that variables written may or may not be read during the function
201 call. Returns NULL if no data is available. */
203 bitmap
204 ipa_reference_get_not_written_global (struct cgraph_node *fn)
206 if (!opt_for_fn (fn->decl, flag_ipa_reference)
207 || !opt_for_fn (current_function_decl, flag_ipa_reference))
208 return NULL;
209 ipa_reference_optimization_summary_t info =
210 get_reference_optimization_summary (fn);
211 if (info)
212 return info->statics_not_written;
213 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
214 return all_module_statics;
215 else
216 return NULL;
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 /* We can not track variables with address taken. */
242 if (TREE_ADDRESSABLE (t))
243 return false;
245 /* TODO: We could track public variables that are not addressable, but currently
246 frontends don't give us those. */
247 if (TREE_PUBLIC (t))
248 return false;
250 /* TODO: Check aliases. */
251 if (bitmap_bit_p (ignore_module_statics, DECL_UID (t)))
252 return false;
254 return true;
257 /* Lookup the tree node for the static variable that has UID and
258 convert the name to a string for debugging. */
260 static const char *
261 get_static_name (int index)
263 splay_tree_node stn =
264 splay_tree_lookup (reference_vars_to_consider, index);
265 return fndecl_name ((tree)(stn->value));
268 /* Dump a set of static vars to FILE. */
269 static void
270 dump_static_vars_set_to_file (FILE *f, bitmap set)
272 unsigned int index;
273 bitmap_iterator bi;
274 if (set == NULL)
275 return;
276 else if (set == all_module_statics)
277 fprintf (f, "ALL");
278 else
279 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
281 fprintf (f, "%s ", get_static_name (index));
285 /* Compute X |= Y, taking into account the possibility that
286 either X or Y is already the maximum set.
287 Return true if X is the maximum set after taking the union with Y. */
289 static bool
290 union_static_var_sets (bitmap &x, bitmap y)
292 if (x != all_module_statics)
294 if (y == all_module_statics)
296 BITMAP_FREE (x);
297 x = all_module_statics;
299 else if (bitmap_ior_into (x, y))
301 /* The union may have reduced X to the maximum set.
302 In that case, we want to make that visible explicitly.
303 Even though bitmap_equal_p can be very expensive, it
304 turns out to be an overall win to check this here for
305 an LTO bootstrap of GCC itself. Liberally extrapoliate
306 that result to be applicable to all cases. */
307 if (bitmap_equal_p (x, all_module_statics))
309 BITMAP_FREE (x);
310 x = all_module_statics;
314 return x == all_module_statics;
317 /* Return a copy of SET on the bitmap obstack containing SET.
318 But if SET is NULL or the maximum set, return that instead. */
320 static bitmap
321 copy_static_var_set (bitmap set)
323 if (set == NULL || set == all_module_statics)
324 return set;
325 bitmap_obstack *o = set->obstack;
326 gcc_checking_assert (o);
327 bitmap copy = BITMAP_ALLOC (o);
328 bitmap_copy (copy, set);
329 return copy;
332 /* Compute the union all of the statics read and written by every callee of X
333 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
334 actually the set representing the cycle containing X. If the read and
335 written sets of X_GLOBAL has been reduced to the maximum set, we don't
336 have to look at the remaining callees. */
338 static void
339 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
341 struct cgraph_edge *e;
342 bool read_all = x_global->statics_read == all_module_statics;
343 bool write_all = x_global->statics_written == all_module_statics;
344 for (e = x->callees;
345 e && !(read_all && write_all);
346 e = e->next_callee)
348 enum availability avail;
349 struct cgraph_node *y = e->callee->function_symbol (&avail);
350 if (!y)
351 continue;
353 /* Only look into nodes we can propagate something. */
354 int flags = flags_from_decl_or_type (y->decl);
355 if (opt_for_fn (y->decl, flag_ipa_reference)
356 && (avail > AVAIL_INTERPOSABLE
357 || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
359 if (get_reference_vars_info (y))
361 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
362 ipa_reference_global_vars_info_t y_global = &y_info->global;
364 /* Calls in the current cycle do not have their global set
365 computed yet (but everything else does because we're
366 visiting nodes in topological order). */
367 if (!y_global->statics_read)
368 continue;
370 /* If the function is const, it reads no memory even if it
371 seems so to local analysis. */
372 if (flags & ECF_CONST)
373 continue;
375 union_static_var_sets (x_global->statics_read,
376 y_global->statics_read);
378 /* If the function is pure, it has no stores even if it
379 seems so to local analysis. If we cannot return from
380 the function, we can safely ignore the call. */
381 if ((flags & ECF_PURE)
382 || e->cannot_lead_to_return_p ())
383 continue;
385 union_static_var_sets (x_global->statics_written,
386 y_global->statics_written);
388 else
389 gcc_unreachable ();
394 static bool ipa_init_p = false;
396 /* The init routine for analyzing global static variable usage. See
397 comments at top for description. */
398 static void
399 ipa_init (void)
401 if (ipa_init_p)
402 return;
404 ipa_init_p = true;
406 if (dump_file)
407 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
409 bitmap_obstack_initialize (&local_info_obstack);
410 bitmap_obstack_initialize (&optimization_summary_obstack);
411 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
412 ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
414 node_removal_hook_holder =
415 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
416 node_duplication_hook_holder =
417 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
421 /* Set up the persistent info for FN. */
423 static ipa_reference_local_vars_info_t
424 init_function_info (struct cgraph_node *fn)
426 ipa_reference_vars_info_t info
427 = XCNEW (struct ipa_reference_vars_info_d);
429 /* Add the info to the tree's annotation. */
430 set_reference_vars_info (fn, info);
432 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
433 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
435 return &info->local;
439 /* This is the main routine for finding the reference patterns for
440 global variables within a function FN. */
442 static void
443 analyze_function (struct cgraph_node *fn)
445 ipa_reference_local_vars_info_t local;
446 struct ipa_ref *ref = NULL;
447 int i;
448 tree var;
450 if (!opt_for_fn (fn->decl, flag_ipa_reference))
451 return;
452 local = init_function_info (fn);
453 for (i = 0; fn->iterate_reference (i, ref); i++)
455 if (!is_a <varpool_node *> (ref->referred))
456 continue;
457 var = ref->referred->decl;
458 if (!is_proper_for_analysis (var))
459 continue;
460 /* This is a variable we care about. Check if we have seen it
461 before, and if not add it the set of variables we care about. */
462 if (all_module_statics
463 && bitmap_set_bit (all_module_statics, DECL_UID (var)))
465 if (dump_file)
466 splay_tree_insert (reference_vars_to_consider,
467 DECL_UID (var), (splay_tree_value)var);
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 (ref->cannot_lead_to_return ())
476 break;
477 bitmap_set_bit (local->statics_written, DECL_UID (var));
478 break;
479 case IPA_REF_ADDR:
480 break;
481 default:
482 gcc_unreachable ();
486 if (fn->cannot_return_p ())
487 bitmap_clear (local->statics_written);
491 /* Called when new clone is inserted to callgraph late. */
493 static void
494 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
495 void *data ATTRIBUTE_UNUSED)
497 ipa_reference_optimization_summary_t ginfo;
498 ipa_reference_optimization_summary_t dst_ginfo;
500 ginfo = get_reference_optimization_summary (src);
501 if (!ginfo)
502 return;
503 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
504 set_reference_optimization_summary (dst, dst_ginfo);
505 dst_ginfo->statics_not_read =
506 copy_static_var_set (ginfo->statics_not_read);
507 dst_ginfo->statics_not_written =
508 copy_static_var_set (ginfo->statics_not_written);
511 /* Called when node is removed. */
513 static void
514 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
516 ipa_reference_optimization_summary_t ginfo;
517 ginfo = get_reference_optimization_summary (node);
518 if (ginfo)
520 if (ginfo->statics_not_read
521 && ginfo->statics_not_read != all_module_statics)
522 BITMAP_FREE (ginfo->statics_not_read);
524 if (ginfo->statics_not_written
525 && ginfo->statics_not_written != all_module_statics)
526 BITMAP_FREE (ginfo->statics_not_written);
527 free (ginfo);
528 set_reference_optimization_summary (node, NULL);
532 /* Analyze each function in the cgraph to see which global or statics
533 are read or written. */
535 static void
536 generate_summary (void)
538 struct cgraph_node *node;
539 unsigned int index;
540 bitmap_iterator bi;
542 ipa_init ();
544 /* Process all of the functions next. */
545 FOR_EACH_DEFINED_FUNCTION (node)
546 if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
548 struct ipa_ref *ref = NULL;
549 int i;
550 tree var;
551 for (i = 0; node->iterate_reference (i, ref); i++)
553 if (!is_a <varpool_node *> (ref->referred))
554 continue;
555 var = ref->referred->decl;
556 if (!is_proper_for_analysis (var))
557 continue;
558 bitmap_set_bit (ignore_module_statics, DECL_UID (var));
561 FOR_EACH_DEFINED_FUNCTION (node)
562 analyze_function (node);
564 if (dump_file)
565 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
567 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
568 get_static_name (index), index);
571 if (dump_file)
572 FOR_EACH_DEFINED_FUNCTION (node)
573 if (node->get_availability () >= AVAIL_INTERPOSABLE
574 && opt_for_fn (node->decl, flag_ipa_reference))
576 ipa_reference_local_vars_info_t l;
577 unsigned int index;
578 bitmap_iterator bi;
580 l = &get_reference_vars_info (node)->local;
581 fprintf (dump_file,
582 "\nFunction name:%s/%i:",
583 node->asm_name (), node->order);
584 fprintf (dump_file, "\n locals read: ");
585 if (l->statics_read)
586 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
587 0, index, bi)
589 fprintf (dump_file, "%s ",
590 get_static_name (index));
592 fprintf (dump_file, "\n locals written: ");
593 if (l->statics_written)
594 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
595 0, index, bi)
597 fprintf (dump_file, "%s ", get_static_name (index));
602 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
604 static void
605 read_write_all_from_decl (struct cgraph_node *node,
606 bool &read_all, bool &write_all)
608 tree decl = node->decl;
609 int flags = flags_from_decl_or_type (decl);
610 if ((flags & ECF_LEAF)
611 && node->get_availability () < AVAIL_INTERPOSABLE)
613 else if (flags & ECF_CONST)
615 else if ((flags & ECF_PURE) || node->cannot_return_p ())
617 read_all = true;
618 if (dump_file && (dump_flags & TDF_DETAILS))
619 fprintf (dump_file, " %s/%i -> read all\n",
620 node->asm_name (), node->order);
622 else
624 /* TODO: To be able to produce sane results, we should also handle
625 common builtins, in particular throw. */
626 read_all = true;
627 write_all = true;
628 if (dump_file && (dump_flags & TDF_DETAILS))
629 fprintf (dump_file, " %s/%i -> read all, write all\n",
630 node->asm_name (), node->order);
634 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
635 in the cycle of NODE. */
637 static void
638 get_read_write_all_from_node (struct cgraph_node *node,
639 bool &read_all, bool &write_all)
641 struct cgraph_edge *e, *ie;
643 /* When function is overwritable, we can not assume anything. */
644 if (node->get_availability () <= AVAIL_INTERPOSABLE
645 || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
646 read_write_all_from_decl (node, read_all, write_all);
648 for (e = node->callees;
649 e && !(read_all && write_all);
650 e = e->next_callee)
652 enum availability avail;
653 struct cgraph_node *callee = e->callee->function_symbol (&avail);
654 gcc_checking_assert (callee);
655 if (avail <= AVAIL_INTERPOSABLE
656 || (callee->analyzed && !opt_for_fn (callee->decl, flag_ipa_reference)))
657 read_write_all_from_decl (callee, read_all, write_all);
660 for (ie = node->indirect_calls;
661 ie && !(read_all && write_all);
662 ie = ie->next_callee)
663 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
665 read_all = true;
666 if (dump_file && (dump_flags & TDF_DETAILS))
667 fprintf (dump_file, " indirect call -> read all\n");
668 if (!ie->cannot_lead_to_return_p ()
669 && !(ie->indirect_info->ecf_flags & ECF_PURE))
671 if (dump_file && (dump_flags & TDF_DETAILS))
672 fprintf (dump_file, " indirect call -> write all\n");
673 write_all = true;
678 /* Skip edges from and to nodes without ipa_reference enables. This leave
679 them out of strongy connected coponents and makes them easyto skip in the
680 propagation loop bellow. */
682 static bool
683 ignore_edge_p (cgraph_edge *e)
685 return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
686 || !opt_for_fn (e->callee->function_symbol ()->decl,
687 flag_ipa_reference));
690 /* Produce the global information by preforming a transitive closure
691 on the local information that was produced by ipa_analyze_function. */
693 static unsigned int
694 propagate (void)
696 struct cgraph_node *node;
697 struct cgraph_node **order =
698 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
699 int order_pos;
700 int i;
701 bool remove_p;
703 if (dump_file)
704 cgraph_node::dump_cgraph (dump_file);
706 remove_p = ipa_discover_readonly_nonaddressable_vars ();
707 generate_summary ();
709 /* Propagate the local information through the call graph to produce
710 the global information. All the nodes within a cycle will have
711 the same info so we collapse cycles first. Then we can do the
712 propagation in one pass from the leaves to the roots. */
713 order_pos = ipa_reduced_postorder (order, true, true, ignore_edge_p);
714 if (dump_file)
715 ipa_print_order (dump_file, "reduced", order, order_pos);
717 for (i = 0; i < order_pos; i++ )
719 unsigned x;
720 struct cgraph_node *w;
721 ipa_reference_vars_info_t node_info;
722 ipa_reference_global_vars_info_t node_g;
723 ipa_reference_local_vars_info_t node_l;
724 bool read_all = false;
725 bool write_all = false;
727 node = order[i];
728 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
729 continue;
731 node_info = get_reference_vars_info (node);
732 gcc_assert (node_info);
733 node_l = &node_info->local;
734 node_g = &node_info->global;
736 if (dump_file && (dump_flags & TDF_DETAILS))
737 fprintf (dump_file, "Starting cycle with %s/%i\n",
738 node->asm_name (), node->order);
740 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
742 /* If any node in a cycle is read_all or write_all, they all are. */
743 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
745 if (dump_file && (dump_flags & TDF_DETAILS))
746 fprintf (dump_file, " Visiting %s/%i\n",
747 w->asm_name (), w->order);
748 get_read_write_all_from_node (w, read_all, write_all);
749 if (read_all && write_all)
750 break;
753 /* Initialized the bitmaps global sets for the reduced node. */
754 if (read_all)
755 node_g->statics_read = all_module_statics;
756 else
757 node_g->statics_read = copy_static_var_set (node_l->statics_read);
758 if (write_all)
759 node_g->statics_written = all_module_statics;
760 else
761 node_g->statics_written = copy_static_var_set (node_l->statics_written);
763 /* Merge the sets of this cycle with all sets of callees reached
764 from this cycle. */
765 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
767 if (read_all && write_all)
768 break;
770 if (w != node)
772 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
773 ipa_reference_local_vars_info_t w_l = &w_ri->local;
774 int flags = flags_from_decl_or_type (w->decl);
776 if (!(flags & ECF_CONST))
777 read_all = union_static_var_sets (node_g->statics_read,
778 w_l->statics_read);
779 if (!(flags & ECF_PURE)
780 && !w->cannot_return_p ())
781 write_all = union_static_var_sets (node_g->statics_written,
782 w_l->statics_written);
785 propagate_bits (node_g, w);
788 /* All nodes within a cycle have the same global info bitmaps. */
789 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
791 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
792 w_ri->global = *node_g;
795 cycle_nodes.release ();
798 if (dump_file)
800 for (i = 0; i < order_pos; i++)
802 unsigned x;
803 struct cgraph_node *w;
805 node = order[i];
806 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
807 continue;
809 fprintf (dump_file,
810 "\nFunction name:%s/%i:",
811 node->asm_name (), node->order);
813 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
814 ipa_reference_global_vars_info_t node_g = &node_info->global;
816 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
817 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
819 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
820 ipa_reference_local_vars_info_t w_l = &w_ri->local;
821 if (w != node)
822 fprintf (dump_file, "\n next cycle: %s/%i ",
823 w->asm_name (), w->order);
824 fprintf (dump_file, "\n locals read: ");
825 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
826 fprintf (dump_file, "\n locals written: ");
827 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
829 cycle_nodes.release ();
831 fprintf (dump_file, "\n globals read: ");
832 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
833 fprintf (dump_file, "\n globals written: ");
834 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
835 fprintf (dump_file, "\n");
839 /* Cleanup. */
840 FOR_EACH_DEFINED_FUNCTION (node)
842 ipa_reference_vars_info_t node_info;
843 ipa_reference_global_vars_info_t node_g;
844 ipa_reference_optimization_summary_t opt;
846 node_info = get_reference_vars_info (node);
847 if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
848 && (node->get_availability () > AVAIL_INTERPOSABLE
849 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
851 node_g = &node_info->global;
853 opt = XCNEW (struct ipa_reference_optimization_summary_d);
854 set_reference_optimization_summary (node, opt);
856 /* Create the complimentary sets. */
858 if (bitmap_empty_p (node_g->statics_read))
859 opt->statics_not_read = all_module_statics;
860 else
862 opt->statics_not_read
863 = BITMAP_ALLOC (&optimization_summary_obstack);
864 if (node_g->statics_read != all_module_statics)
865 bitmap_and_compl (opt->statics_not_read,
866 all_module_statics,
867 node_g->statics_read);
870 if (bitmap_empty_p (node_g->statics_written))
871 opt->statics_not_written = all_module_statics;
872 else
874 opt->statics_not_written
875 = BITMAP_ALLOC (&optimization_summary_obstack);
876 if (node_g->statics_written != all_module_statics)
877 bitmap_and_compl (opt->statics_not_written,
878 all_module_statics,
879 node_g->statics_written);
882 free (node_info);
885 ipa_free_postorder_info ();
886 free (order);
888 bitmap_obstack_release (&local_info_obstack);
889 ipa_reference_vars_vector.release ();
890 if (dump_file)
891 splay_tree_delete (reference_vars_to_consider);
892 reference_vars_to_consider = NULL;
893 return remove_p ? TODO_remove_functions : 0;
896 /* Return true if we need to write summary of NODE. */
898 static bool
899 write_node_summary_p (struct cgraph_node *node,
900 lto_symtab_encoder_t encoder,
901 bitmap ltrans_statics)
903 ipa_reference_optimization_summary_t info;
905 /* See if we have (non-empty) info. */
906 if (!node->definition || node->global.inlined_to)
907 return false;
908 info = get_reference_optimization_summary (node);
909 if (!info || (bitmap_empty_p (info->statics_not_read)
910 && bitmap_empty_p (info->statics_not_written)))
911 return false;
913 /* See if we want to encode it.
914 Encode also referenced functions since constant folding might turn it into
915 a direct call.
917 In future we might also want to include summaries of functions references
918 by initializers of constant variables references in current unit. */
919 if (!reachable_from_this_partition_p (node, encoder)
920 && !referenced_from_this_partition_p (node, encoder))
921 return false;
923 /* See if the info has non-empty intersections with vars we want to encode. */
924 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
925 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
926 return false;
927 return true;
930 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
931 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
932 or -1. When it is positive, just output -1 when
933 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
935 static void
936 stream_out_bitmap (struct lto_simple_output_block *ob,
937 bitmap bits, bitmap ltrans_statics,
938 int ltrans_statics_bitcount)
940 int count = 0;
941 unsigned int index;
942 bitmap_iterator bi;
943 if (bits == all_module_statics)
945 streamer_write_hwi_stream (ob->main_stream, -1);
946 return;
948 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
949 count ++;
950 if (count == ltrans_statics_bitcount)
952 streamer_write_hwi_stream (ob->main_stream, -1);
953 return;
955 streamer_write_hwi_stream (ob->main_stream, count);
956 if (!count)
957 return;
958 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
960 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
961 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
965 /* Serialize the ipa info for lto. */
967 static void
968 ipa_reference_write_optimization_summary (void)
970 struct lto_simple_output_block *ob
971 = lto_create_simple_output_block (LTO_section_ipa_reference);
972 unsigned int count = 0;
973 int ltrans_statics_bitcount = 0;
974 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
975 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
976 int i;
978 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
980 /* See what variables we are interested in. */
981 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
983 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
984 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
985 if (vnode
986 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
987 && referenced_from_this_partition_p (vnode, encoder))
989 tree decl = vnode->decl;
990 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
991 splay_tree_insert (reference_vars_to_consider,
992 DECL_UID (decl), (splay_tree_value)decl);
993 ltrans_statics_bitcount ++;
998 if (ltrans_statics_bitcount)
999 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1001 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1002 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1003 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1004 count++;
1007 streamer_write_uhwi_stream (ob->main_stream, count);
1008 if (count)
1009 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1010 -1);
1012 /* Process all of the functions. */
1013 if (ltrans_statics_bitcount)
1014 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1016 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1017 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1018 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1020 ipa_reference_optimization_summary_t info;
1021 int node_ref;
1023 info = get_reference_optimization_summary (cnode);
1024 node_ref = lto_symtab_encoder_encode (encoder, snode);
1025 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1027 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1028 ltrans_statics_bitcount);
1029 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1030 ltrans_statics_bitcount);
1033 BITMAP_FREE (ltrans_statics);
1034 lto_destroy_simple_output_block (ob);
1035 splay_tree_delete (reference_vars_to_consider);
1038 /* Deserialize the ipa info for lto. */
1040 static void
1041 ipa_reference_read_optimization_summary (void)
1043 struct lto_file_decl_data ** file_data_vec
1044 = lto_get_file_decl_data ();
1045 struct lto_file_decl_data * file_data;
1046 unsigned int j = 0;
1047 bitmap_obstack_initialize (&optimization_summary_obstack);
1049 node_removal_hook_holder =
1050 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
1051 node_duplication_hook_holder =
1052 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
1053 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1055 while ((file_data = file_data_vec[j++]))
1057 const char *data;
1058 size_t len;
1059 struct lto_input_block *ib
1060 = lto_create_simple_input_block (file_data,
1061 LTO_section_ipa_reference,
1062 &data, &len);
1063 if (ib)
1065 unsigned int i;
1066 unsigned int f_count = streamer_read_uhwi (ib);
1067 int b_count;
1068 if (!f_count)
1069 continue;
1070 b_count = streamer_read_hwi (ib);
1071 if (dump_file)
1072 fprintf (dump_file, "all module statics:");
1073 for (i = 0; i < (unsigned int)b_count; i++)
1075 unsigned int var_index = streamer_read_uhwi (ib);
1076 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1077 var_index);
1078 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1079 if (dump_file)
1080 fprintf (dump_file, " %s", fndecl_name (v_decl));
1083 for (i = 0; i < f_count; i++)
1085 unsigned int j, index;
1086 struct cgraph_node *node;
1087 ipa_reference_optimization_summary_t info;
1088 int v_count;
1089 lto_symtab_encoder_t encoder;
1091 index = streamer_read_uhwi (ib);
1092 encoder = file_data->symtab_node_encoder;
1093 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1094 (encoder, index));
1095 info = XCNEW (struct ipa_reference_optimization_summary_d);
1096 set_reference_optimization_summary (node, info);
1097 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1098 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1099 if (dump_file)
1100 fprintf (dump_file,
1101 "\nFunction name:%s/%i:\n static not read:",
1102 node->asm_name (), node->order);
1104 /* Set the statics not read. */
1105 v_count = streamer_read_hwi (ib);
1106 if (v_count == -1)
1108 info->statics_not_read = 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_read, DECL_UID (v_decl));
1119 if (dump_file)
1120 fprintf (dump_file, " %s", fndecl_name (v_decl));
1123 if (dump_file)
1124 fprintf (dump_file,
1125 "\n static not written:");
1126 /* Set the statics not written. */
1127 v_count = streamer_read_hwi (ib);
1128 if (v_count == -1)
1130 info->statics_not_written = all_module_statics;
1131 if (dump_file)
1132 fprintf (dump_file, " all module statics");
1134 else
1135 for (j = 0; j < (unsigned int)v_count; j++)
1137 unsigned int var_index = streamer_read_uhwi (ib);
1138 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1139 var_index);
1140 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1141 if (dump_file)
1142 fprintf (dump_file, " %s", fndecl_name (v_decl));
1144 if (dump_file)
1145 fprintf (dump_file, "\n");
1148 lto_destroy_simple_input_block (file_data,
1149 LTO_section_ipa_reference,
1150 ib, data, len);
1152 else
1153 /* Fatal error here. We do not want to support compiling ltrans units with
1154 different version of compiler or different flags than the WPA unit, so
1155 this should never happen. */
1156 fatal_error (input_location,
1157 "ipa reference summary is missing in ltrans unit");
1161 namespace {
1163 const pass_data pass_data_ipa_reference =
1165 IPA_PASS, /* type */
1166 "static-var", /* name */
1167 OPTGROUP_NONE, /* optinfo_flags */
1168 TV_IPA_REFERENCE, /* tv_id */
1169 0, /* properties_required */
1170 0, /* properties_provided */
1171 0, /* properties_destroyed */
1172 0, /* todo_flags_start */
1173 0, /* todo_flags_finish */
1176 class pass_ipa_reference : public ipa_opt_pass_d
1178 public:
1179 pass_ipa_reference (gcc::context *ctxt)
1180 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1181 NULL, /* generate_summary */
1182 NULL, /* write_summary */
1183 NULL, /* read_summary */
1184 ipa_reference_write_optimization_summary, /*
1185 write_optimization_summary */
1186 ipa_reference_read_optimization_summary, /*
1187 read_optimization_summary */
1188 NULL, /* stmt_fixup */
1189 0, /* function_transform_todo_flags_start */
1190 NULL, /* function_transform */
1191 NULL) /* variable_transform */
1194 /* opt_pass methods: */
1195 virtual bool gate (function *)
1197 return ((in_lto_p || flag_ipa_reference)
1198 /* Don't bother doing anything if the program has errors. */
1199 && !seen_error ());
1202 virtual unsigned int execute (function *) { return propagate (); }
1204 }; // class pass_ipa_reference
1206 } // anon namespace
1208 ipa_opt_pass_d *
1209 make_pass_ipa_reference (gcc::context *ctxt)
1211 return new pass_ipa_reference (ctxt);
1214 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1215 within the same process. For use by toplev::finalize. */
1217 void
1218 ipa_reference_c_finalize (void)
1220 if (ipa_init_p)
1222 bitmap_obstack_release (&optimization_summary_obstack);
1223 ipa_init_p = false;
1226 if (node_removal_hook_holder)
1228 symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
1229 node_removal_hook_holder = NULL;
1231 if (node_duplication_hook_holder)
1233 symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder);
1234 node_duplication_hook_holder = NULL;