Check int_size_in_bytes in ix86_return_in_memory
[official-gcc.git] / gcc / ipa-reference.c
blob465a74bcc9f64d68aebb78aa3b9ac16cad92fa8c
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"
60 #include "lto-streamer.h"
62 static void remove_node_data (struct cgraph_node *node,
63 void *data ATTRIBUTE_UNUSED);
64 static void duplicate_node_data (struct cgraph_node *src,
65 struct cgraph_node *dst,
66 void *data ATTRIBUTE_UNUSED);
68 /* The static variables defined within the compilation unit that are
69 loaded or stored directly by function that owns this structure. */
71 struct ipa_reference_local_vars_info_d
73 bitmap statics_read;
74 bitmap statics_written;
77 /* Statics that are read and written by some set of functions. The
78 local ones are based on the loads and stores local to the function.
79 The global ones are based on the local info as well as the
80 transitive closure of the functions that are called. */
82 struct ipa_reference_global_vars_info_d
84 bitmap statics_read;
85 bitmap statics_written;
88 /* Information we save about every function after ipa-reference is completed. */
90 struct ipa_reference_optimization_summary_d
92 bitmap statics_not_read;
93 bitmap statics_not_written;
96 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
97 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
98 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
100 struct ipa_reference_vars_info_d
102 struct ipa_reference_local_vars_info_d local;
103 struct ipa_reference_global_vars_info_d global;
106 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
108 /* This splay tree contains all of the static variables that are
109 being considered by the compilation level alias analysis. */
110 static splay_tree reference_vars_to_consider;
112 /* Set of all interesting module statics. A bit is set for every module
113 static we are considering. This is added to the local info when asm
114 code is found that clobbers all memory. */
115 static bitmap all_module_statics;
116 /* Set of all statics that should be ignored becuase they are touched by
117 -fno-ipa-reference code. */
118 static bitmap ignore_module_statics;
120 /* Obstack holding bitmaps of local analysis (live from analysis to
121 propagation) */
122 static bitmap_obstack local_info_obstack;
123 /* Obstack holding global analysis live forever. */
124 static bitmap_obstack optimization_summary_obstack;
126 /* Holders of ipa cgraph hooks: */
127 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
128 static struct cgraph_node_hook_list *node_removal_hook_holder;
130 /* Vector where the reference var infos are actually stored.
131 Indexed by UID of call graph nodes. */
132 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
134 /* TODO: find a place where we should release the vector. */
135 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
137 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
138 static inline ipa_reference_vars_info_t
139 get_reference_vars_info (struct cgraph_node *node)
141 if (!ipa_reference_vars_vector.exists ()
142 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
143 return NULL;
144 return ipa_reference_vars_vector[node->uid];
147 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
148 static inline ipa_reference_optimization_summary_t
149 get_reference_optimization_summary (struct cgraph_node *node)
151 if (!ipa_reference_opt_sum_vector.exists ()
152 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
153 return NULL;
154 return ipa_reference_opt_sum_vector[node->uid];
157 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
158 static inline void
159 set_reference_vars_info (struct cgraph_node *node,
160 ipa_reference_vars_info_t info)
162 if (!ipa_reference_vars_vector.exists ()
163 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
164 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
165 ipa_reference_vars_vector[node->uid] = info;
168 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
169 static inline void
170 set_reference_optimization_summary (struct cgraph_node *node,
171 ipa_reference_optimization_summary_t info)
173 if (!ipa_reference_opt_sum_vector.exists ()
174 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
175 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
176 ipa_reference_opt_sum_vector[node->uid] = info;
179 /* Return a bitmap indexed by DECL_UID for the static variables that
180 are *not* read during the execution of the function FN. Returns
181 NULL if no data is available. */
183 bitmap
184 ipa_reference_get_not_read_global (struct cgraph_node *fn)
186 if (!opt_for_fn (fn->decl, flag_ipa_reference)
187 || !opt_for_fn (current_function_decl, flag_ipa_reference))
188 return NULL;
189 ipa_reference_optimization_summary_t info =
190 get_reference_optimization_summary (fn->function_symbol (NULL));
191 if (info)
192 return info->statics_not_read;
193 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
194 return all_module_statics;
195 else
196 return NULL;
199 /* Return a bitmap indexed by DECL_UID for the static variables that
200 are *not* written during the execution of the function FN. Note
201 that variables written may or may not be read during the function
202 call. Returns NULL if no data is available. */
204 bitmap
205 ipa_reference_get_not_written_global (struct cgraph_node *fn)
207 if (!opt_for_fn (fn->decl, flag_ipa_reference)
208 || !opt_for_fn (current_function_decl, flag_ipa_reference))
209 return NULL;
210 ipa_reference_optimization_summary_t info =
211 get_reference_optimization_summary (fn);
212 if (info)
213 return info->statics_not_written;
214 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
215 return all_module_statics;
216 else
217 return NULL;
221 /* Return true if the variable T is the right kind of static variable to
222 perform compilation unit scope escape analysis. */
224 static inline bool
225 is_proper_for_analysis (tree t)
227 /* If the variable has the "used" attribute, treat it as if it had a
228 been touched by the devil. */
229 if (DECL_PRESERVE_P (t))
230 return false;
232 /* Do not want to do anything with volatile except mark any
233 function that uses one to be not const or pure. */
234 if (TREE_THIS_VOLATILE (t))
235 return false;
237 /* We do not need to analyze readonly vars, we already know they do not
238 alias. */
239 if (TREE_READONLY (t))
240 return false;
242 /* We can not track variables with address taken. */
243 if (TREE_ADDRESSABLE (t))
244 return false;
246 /* TODO: We could track public variables that are not addressable, but currently
247 frontends don't give us those. */
248 if (TREE_PUBLIC (t))
249 return false;
251 /* TODO: Check aliases. */
252 if (bitmap_bit_p (ignore_module_statics, DECL_UID (t)))
253 return false;
255 return true;
258 /* Lookup the tree node for the static variable that has UID and
259 convert the name to a string for debugging. */
261 static const char *
262 get_static_name (int index)
264 splay_tree_node stn =
265 splay_tree_lookup (reference_vars_to_consider, index);
266 return fndecl_name ((tree)(stn->value));
269 /* Dump a set of static vars to FILE. */
270 static void
271 dump_static_vars_set_to_file (FILE *f, bitmap set)
273 unsigned int index;
274 bitmap_iterator bi;
275 if (set == NULL)
276 return;
277 else if (set == all_module_statics)
278 fprintf (f, "ALL");
279 else
280 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
282 fprintf (f, "%s ", get_static_name (index));
286 /* Compute X |= Y, taking into account the possibility that
287 either X or Y is already the maximum set.
288 Return true if X is the maximum set after taking the union with Y. */
290 static bool
291 union_static_var_sets (bitmap &x, bitmap y)
293 if (x != all_module_statics)
295 if (y == all_module_statics)
297 BITMAP_FREE (x);
298 x = all_module_statics;
300 else if (bitmap_ior_into (x, y))
302 /* The union may have reduced X to the maximum set.
303 In that case, we want to make that visible explicitly.
304 Even though bitmap_equal_p can be very expensive, it
305 turns out to be an overall win to check this here for
306 an LTO bootstrap of GCC itself. Liberally extrapoliate
307 that result to be applicable to all cases. */
308 if (bitmap_equal_p (x, all_module_statics))
310 BITMAP_FREE (x);
311 x = all_module_statics;
315 return x == all_module_statics;
318 /* Return a copy of SET on the bitmap obstack containing SET.
319 But if SET is NULL or the maximum set, return that instead. */
321 static bitmap
322 copy_static_var_set (bitmap set)
324 if (set == NULL || set == all_module_statics)
325 return set;
326 bitmap_obstack *o = set->obstack;
327 gcc_checking_assert (o);
328 bitmap copy = BITMAP_ALLOC (o);
329 bitmap_copy (copy, set);
330 return copy;
333 /* Compute the union all of the statics read and written by every callee of X
334 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
335 actually the set representing the cycle containing X. If the read and
336 written sets of X_GLOBAL has been reduced to the maximum set, we don't
337 have to look at the remaining callees. */
339 static void
340 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
342 struct cgraph_edge *e;
343 bool read_all = x_global->statics_read == all_module_statics;
344 bool write_all = x_global->statics_written == all_module_statics;
345 for (e = x->callees;
346 e && !(read_all && write_all);
347 e = e->next_callee)
349 enum availability avail;
350 struct cgraph_node *y = e->callee->function_symbol (&avail);
351 if (!y)
352 continue;
354 /* Only look into nodes we can propagate something. */
355 int flags = flags_from_decl_or_type (y->decl);
356 if (opt_for_fn (y->decl, flag_ipa_reference)
357 && (avail > AVAIL_INTERPOSABLE
358 || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
360 if (get_reference_vars_info (y))
362 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
363 ipa_reference_global_vars_info_t y_global = &y_info->global;
365 /* Calls in the current cycle do not have their global set
366 computed yet (but everything else does because we're
367 visiting nodes in topological order). */
368 if (!y_global->statics_read)
369 continue;
371 /* If the function is const, it reads no memory even if it
372 seems so to local analysis. */
373 if (flags & ECF_CONST)
374 continue;
376 union_static_var_sets (x_global->statics_read,
377 y_global->statics_read);
379 /* If the function is pure, it has no stores even if it
380 seems so to local analysis. If we cannot return from
381 the function, we can safely ignore the call. */
382 if ((flags & ECF_PURE)
383 || e->cannot_lead_to_return_p ())
384 continue;
386 union_static_var_sets (x_global->statics_written,
387 y_global->statics_written);
389 else
390 gcc_unreachable ();
395 static bool ipa_init_p = false;
397 /* The init routine for analyzing global static variable usage. See
398 comments at top for description. */
399 static void
400 ipa_init (void)
402 if (ipa_init_p)
403 return;
405 ipa_init_p = true;
407 if (dump_file)
408 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
410 bitmap_obstack_initialize (&local_info_obstack);
411 bitmap_obstack_initialize (&optimization_summary_obstack);
412 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
413 ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
415 node_removal_hook_holder =
416 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
417 node_duplication_hook_holder =
418 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
422 /* Set up the persistent info for FN. */
424 static ipa_reference_local_vars_info_t
425 init_function_info (struct cgraph_node *fn)
427 ipa_reference_vars_info_t info
428 = XCNEW (struct ipa_reference_vars_info_d);
430 /* Add the info to the tree's annotation. */
431 set_reference_vars_info (fn, info);
433 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
434 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
436 return &info->local;
440 /* This is the main routine for finding the reference patterns for
441 global variables within a function FN. */
443 static void
444 analyze_function (struct cgraph_node *fn)
446 ipa_reference_local_vars_info_t local;
447 struct ipa_ref *ref = NULL;
448 int i;
449 tree var;
451 if (!opt_for_fn (fn->decl, flag_ipa_reference))
452 return;
453 local = init_function_info (fn);
454 for (i = 0; fn->iterate_reference (i, ref); i++)
456 if (!is_a <varpool_node *> (ref->referred))
457 continue;
458 var = ref->referred->decl;
459 if (!is_proper_for_analysis (var))
460 continue;
461 /* This is a variable we care about. Check if we have seen it
462 before, and if not add it the set of variables we care about. */
463 if (all_module_statics
464 && bitmap_set_bit (all_module_statics, DECL_UID (var)))
466 if (dump_file)
467 splay_tree_insert (reference_vars_to_consider,
468 DECL_UID (var), (splay_tree_value)var);
470 switch (ref->use)
472 case IPA_REF_LOAD:
473 bitmap_set_bit (local->statics_read, DECL_UID (var));
474 break;
475 case IPA_REF_STORE:
476 if (ref->cannot_lead_to_return ())
477 break;
478 bitmap_set_bit (local->statics_written, DECL_UID (var));
479 break;
480 case IPA_REF_ADDR:
481 break;
482 default:
483 gcc_unreachable ();
487 if (fn->cannot_return_p ())
488 bitmap_clear (local->statics_written);
492 /* Called when new clone is inserted to callgraph late. */
494 static void
495 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
496 void *data ATTRIBUTE_UNUSED)
498 ipa_reference_optimization_summary_t ginfo;
499 ipa_reference_optimization_summary_t dst_ginfo;
501 ginfo = get_reference_optimization_summary (src);
502 if (!ginfo)
503 return;
504 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
505 set_reference_optimization_summary (dst, dst_ginfo);
506 dst_ginfo->statics_not_read =
507 copy_static_var_set (ginfo->statics_not_read);
508 dst_ginfo->statics_not_written =
509 copy_static_var_set (ginfo->statics_not_written);
512 /* Called when node is removed. */
514 static void
515 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
517 ipa_reference_optimization_summary_t ginfo;
518 ginfo = get_reference_optimization_summary (node);
519 if (ginfo)
521 if (ginfo->statics_not_read
522 && ginfo->statics_not_read != all_module_statics)
523 BITMAP_FREE (ginfo->statics_not_read);
525 if (ginfo->statics_not_written
526 && ginfo->statics_not_written != all_module_statics)
527 BITMAP_FREE (ginfo->statics_not_written);
528 free (ginfo);
529 set_reference_optimization_summary (node, NULL);
533 /* Analyze each function in the cgraph to see which global or statics
534 are read or written. */
536 static void
537 generate_summary (void)
539 struct cgraph_node *node;
540 unsigned int index;
541 bitmap_iterator bi;
543 ipa_init ();
545 /* Process all of the functions next. */
546 FOR_EACH_DEFINED_FUNCTION (node)
547 if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
549 struct ipa_ref *ref = NULL;
550 int i;
551 tree var;
552 for (i = 0; node->iterate_reference (i, ref); i++)
554 if (!is_a <varpool_node *> (ref->referred))
555 continue;
556 var = ref->referred->decl;
557 if (!is_proper_for_analysis (var))
558 continue;
559 bitmap_set_bit (ignore_module_statics, DECL_UID (var));
562 FOR_EACH_DEFINED_FUNCTION (node)
563 analyze_function (node);
565 if (dump_file)
566 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
568 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
569 get_static_name (index), index);
572 if (dump_file)
573 FOR_EACH_DEFINED_FUNCTION (node)
574 if (node->get_availability () >= AVAIL_INTERPOSABLE
575 && opt_for_fn (node->decl, flag_ipa_reference))
577 ipa_reference_local_vars_info_t l;
578 unsigned int index;
579 bitmap_iterator bi;
581 l = &get_reference_vars_info (node)->local;
582 fprintf (dump_file,
583 "\nFunction name:%s/%i:",
584 node->asm_name (), node->order);
585 fprintf (dump_file, "\n locals read: ");
586 if (l->statics_read)
587 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
588 0, index, bi)
590 fprintf (dump_file, "%s ",
591 get_static_name (index));
593 fprintf (dump_file, "\n locals written: ");
594 if (l->statics_written)
595 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
596 0, index, bi)
598 fprintf (dump_file, "%s ", get_static_name (index));
603 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
605 static void
606 read_write_all_from_decl (struct cgraph_node *node,
607 bool &read_all, bool &write_all)
609 tree decl = node->decl;
610 int flags = flags_from_decl_or_type (decl);
611 if ((flags & ECF_LEAF)
612 && node->get_availability () < AVAIL_INTERPOSABLE)
614 else if (flags & ECF_CONST)
616 else if ((flags & ECF_PURE) || node->cannot_return_p ())
618 read_all = true;
619 if (dump_file && (dump_flags & TDF_DETAILS))
620 fprintf (dump_file, " %s/%i -> read all\n",
621 node->asm_name (), node->order);
623 else
625 /* TODO: To be able to produce sane results, we should also handle
626 common builtins, in particular throw. */
627 read_all = true;
628 write_all = true;
629 if (dump_file && (dump_flags & TDF_DETAILS))
630 fprintf (dump_file, " %s/%i -> read all, write all\n",
631 node->asm_name (), node->order);
635 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
636 in the cycle of NODE. */
638 static void
639 get_read_write_all_from_node (struct cgraph_node *node,
640 bool &read_all, bool &write_all)
642 struct cgraph_edge *e, *ie;
644 /* When function is overwritable, we can not assume anything. */
645 if (node->get_availability () <= AVAIL_INTERPOSABLE
646 || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
647 read_write_all_from_decl (node, read_all, write_all);
649 for (e = node->callees;
650 e && !(read_all && write_all);
651 e = e->next_callee)
653 enum availability avail;
654 struct cgraph_node *callee = e->callee->function_symbol (&avail);
655 gcc_checking_assert (callee);
656 if (avail <= AVAIL_INTERPOSABLE
657 || (callee->analyzed && !opt_for_fn (callee->decl, flag_ipa_reference)))
658 read_write_all_from_decl (callee, read_all, write_all);
661 for (ie = node->indirect_calls;
662 ie && !(read_all && write_all);
663 ie = ie->next_callee)
664 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
666 read_all = true;
667 if (dump_file && (dump_flags & TDF_DETAILS))
668 fprintf (dump_file, " indirect call -> read all\n");
669 if (!ie->cannot_lead_to_return_p ()
670 && !(ie->indirect_info->ecf_flags & ECF_PURE))
672 if (dump_file && (dump_flags & TDF_DETAILS))
673 fprintf (dump_file, " indirect call -> write all\n");
674 write_all = true;
679 /* Skip edges from and to nodes without ipa_reference enables. This leave
680 them out of strongy connected coponents and makes them easyto skip in the
681 propagation loop bellow. */
683 static bool
684 ignore_edge_p (cgraph_edge *e)
686 return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
687 || !opt_for_fn (e->callee->function_symbol ()->decl,
688 flag_ipa_reference));
691 /* Produce the global information by preforming a transitive closure
692 on the local information that was produced by ipa_analyze_function. */
694 static unsigned int
695 propagate (void)
697 struct cgraph_node *node;
698 struct cgraph_node **order =
699 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
700 int order_pos;
701 int i;
702 bool remove_p;
704 if (dump_file)
705 cgraph_node::dump_cgraph (dump_file);
707 remove_p = ipa_discover_readonly_nonaddressable_vars ();
708 generate_summary ();
710 /* Propagate the local information through the call graph to produce
711 the global information. All the nodes within a cycle will have
712 the same info so we collapse cycles first. Then we can do the
713 propagation in one pass from the leaves to the roots. */
714 order_pos = ipa_reduced_postorder (order, true, true, ignore_edge_p);
715 if (dump_file)
716 ipa_print_order (dump_file, "reduced", order, order_pos);
718 for (i = 0; i < order_pos; i++ )
720 unsigned x;
721 struct cgraph_node *w;
722 ipa_reference_vars_info_t node_info;
723 ipa_reference_global_vars_info_t node_g;
724 ipa_reference_local_vars_info_t node_l;
725 bool read_all = false;
726 bool write_all = false;
728 node = order[i];
729 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
730 continue;
732 node_info = get_reference_vars_info (node);
733 gcc_assert (node_info);
734 node_l = &node_info->local;
735 node_g = &node_info->global;
737 if (dump_file && (dump_flags & TDF_DETAILS))
738 fprintf (dump_file, "Starting cycle with %s/%i\n",
739 node->asm_name (), node->order);
741 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
743 /* If any node in a cycle is read_all or write_all, they all are. */
744 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
746 if (dump_file && (dump_flags & TDF_DETAILS))
747 fprintf (dump_file, " Visiting %s/%i\n",
748 w->asm_name (), w->order);
749 get_read_write_all_from_node (w, read_all, write_all);
750 if (read_all && write_all)
751 break;
754 /* Initialized the bitmaps global sets for the reduced node. */
755 if (read_all)
756 node_g->statics_read = all_module_statics;
757 else
758 node_g->statics_read = copy_static_var_set (node_l->statics_read);
759 if (write_all)
760 node_g->statics_written = all_module_statics;
761 else
762 node_g->statics_written = copy_static_var_set (node_l->statics_written);
764 /* Merge the sets of this cycle with all sets of callees reached
765 from this cycle. */
766 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
768 if (read_all && write_all)
769 break;
771 if (w != node)
773 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
774 ipa_reference_local_vars_info_t w_l = &w_ri->local;
775 int flags = flags_from_decl_or_type (w->decl);
777 if (!(flags & ECF_CONST))
778 read_all = union_static_var_sets (node_g->statics_read,
779 w_l->statics_read);
780 if (!(flags & ECF_PURE)
781 && !w->cannot_return_p ())
782 write_all = union_static_var_sets (node_g->statics_written,
783 w_l->statics_written);
786 propagate_bits (node_g, w);
789 /* All nodes within a cycle have the same global info bitmaps. */
790 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
792 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
793 w_ri->global = *node_g;
796 cycle_nodes.release ();
799 if (dump_file)
801 for (i = 0; i < order_pos; i++)
803 unsigned x;
804 struct cgraph_node *w;
806 node = order[i];
807 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
808 continue;
810 fprintf (dump_file,
811 "\nFunction name:%s/%i:",
812 node->asm_name (), node->order);
814 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
815 ipa_reference_global_vars_info_t node_g = &node_info->global;
817 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
818 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
820 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
821 ipa_reference_local_vars_info_t w_l = &w_ri->local;
822 if (w != node)
823 fprintf (dump_file, "\n next cycle: %s/%i ",
824 w->asm_name (), w->order);
825 fprintf (dump_file, "\n locals read: ");
826 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
827 fprintf (dump_file, "\n locals written: ");
828 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
830 cycle_nodes.release ();
832 fprintf (dump_file, "\n globals read: ");
833 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
834 fprintf (dump_file, "\n globals written: ");
835 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
836 fprintf (dump_file, "\n");
840 /* Cleanup. */
841 FOR_EACH_DEFINED_FUNCTION (node)
843 ipa_reference_vars_info_t node_info;
844 ipa_reference_global_vars_info_t node_g;
845 ipa_reference_optimization_summary_t opt;
847 node_info = get_reference_vars_info (node);
848 if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
849 && (node->get_availability () > AVAIL_INTERPOSABLE
850 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
852 node_g = &node_info->global;
854 opt = XCNEW (struct ipa_reference_optimization_summary_d);
855 set_reference_optimization_summary (node, opt);
857 /* Create the complimentary sets. */
859 if (bitmap_empty_p (node_g->statics_read))
860 opt->statics_not_read = all_module_statics;
861 else
863 opt->statics_not_read
864 = BITMAP_ALLOC (&optimization_summary_obstack);
865 if (node_g->statics_read != all_module_statics)
866 bitmap_and_compl (opt->statics_not_read,
867 all_module_statics,
868 node_g->statics_read);
871 if (bitmap_empty_p (node_g->statics_written))
872 opt->statics_not_written = all_module_statics;
873 else
875 opt->statics_not_written
876 = BITMAP_ALLOC (&optimization_summary_obstack);
877 if (node_g->statics_written != all_module_statics)
878 bitmap_and_compl (opt->statics_not_written,
879 all_module_statics,
880 node_g->statics_written);
883 free (node_info);
886 ipa_free_postorder_info ();
887 free (order);
889 bitmap_obstack_release (&local_info_obstack);
890 ipa_reference_vars_vector.release ();
891 if (dump_file)
892 splay_tree_delete (reference_vars_to_consider);
893 reference_vars_to_consider = NULL;
894 return remove_p ? TODO_remove_functions : 0;
897 /* Return true if we need to write summary of NODE. */
899 static bool
900 write_node_summary_p (struct cgraph_node *node,
901 lto_symtab_encoder_t encoder,
902 bitmap ltrans_statics)
904 ipa_reference_optimization_summary_t info;
906 /* See if we have (non-empty) info. */
907 if (!node->definition || node->global.inlined_to)
908 return false;
909 info = get_reference_optimization_summary (node);
910 if (!info || (bitmap_empty_p (info->statics_not_read)
911 && bitmap_empty_p (info->statics_not_written)))
912 return false;
914 /* See if we want to encode it.
915 Encode also referenced functions since constant folding might turn it into
916 a direct call.
918 In future we might also want to include summaries of functions references
919 by initializers of constant variables references in current unit. */
920 if (!reachable_from_this_partition_p (node, encoder)
921 && !referenced_from_this_partition_p (node, encoder))
922 return false;
924 /* See if the info has non-empty intersections with vars we want to encode. */
925 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
926 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
927 return false;
928 return true;
931 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
932 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
933 or -1. When it is positive, just output -1 when
934 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
936 static void
937 stream_out_bitmap (struct lto_simple_output_block *ob,
938 bitmap bits, bitmap ltrans_statics,
939 int ltrans_statics_bitcount)
941 int count = 0;
942 unsigned int index;
943 bitmap_iterator bi;
944 if (bits == all_module_statics)
946 streamer_write_hwi_stream (ob->main_stream, -1);
947 return;
949 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
950 count ++;
951 if (count == ltrans_statics_bitcount)
953 streamer_write_hwi_stream (ob->main_stream, -1);
954 return;
956 streamer_write_hwi_stream (ob->main_stream, count);
957 if (!count)
958 return;
959 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
961 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
962 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
966 /* Serialize the ipa info for lto. */
968 static void
969 ipa_reference_write_optimization_summary (void)
971 struct lto_simple_output_block *ob
972 = lto_create_simple_output_block (LTO_section_ipa_reference);
973 unsigned int count = 0;
974 int ltrans_statics_bitcount = 0;
975 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
976 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
977 int i;
979 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
981 /* See what variables we are interested in. */
982 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
984 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
985 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
986 if (vnode
987 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
988 && referenced_from_this_partition_p (vnode, encoder))
990 tree decl = vnode->decl;
991 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
992 splay_tree_insert (reference_vars_to_consider,
993 DECL_UID (decl), (splay_tree_value)decl);
994 ltrans_statics_bitcount ++;
999 if (ltrans_statics_bitcount)
1000 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1002 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1003 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1004 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1005 count++;
1008 streamer_write_uhwi_stream (ob->main_stream, count);
1009 if (count)
1010 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1011 -1);
1013 /* Process all of the functions. */
1014 if (ltrans_statics_bitcount)
1015 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1017 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1018 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1019 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1021 ipa_reference_optimization_summary_t info;
1022 int node_ref;
1024 info = get_reference_optimization_summary (cnode);
1025 node_ref = lto_symtab_encoder_encode (encoder, snode);
1026 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1028 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1029 ltrans_statics_bitcount);
1030 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1031 ltrans_statics_bitcount);
1034 BITMAP_FREE (ltrans_statics);
1035 lto_destroy_simple_output_block (ob);
1036 splay_tree_delete (reference_vars_to_consider);
1039 /* Deserialize the ipa info for lto. */
1041 static void
1042 ipa_reference_read_optimization_summary (void)
1044 struct lto_file_decl_data ** file_data_vec
1045 = lto_get_file_decl_data ();
1046 struct lto_file_decl_data * file_data;
1047 unsigned int j = 0;
1048 bitmap_obstack_initialize (&optimization_summary_obstack);
1050 node_removal_hook_holder =
1051 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
1052 node_duplication_hook_holder =
1053 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
1054 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1056 while ((file_data = file_data_vec[j++]))
1058 const char *data;
1059 size_t len;
1060 struct lto_input_block *ib
1061 = lto_create_simple_input_block (file_data,
1062 LTO_section_ipa_reference,
1063 &data, &len);
1064 if (ib)
1066 unsigned int i;
1067 unsigned int f_count = streamer_read_uhwi (ib);
1068 int b_count;
1069 if (!f_count)
1070 continue;
1071 b_count = streamer_read_hwi (ib);
1072 if (dump_file)
1073 fprintf (dump_file, "all module statics:");
1074 for (i = 0; i < (unsigned int)b_count; i++)
1076 unsigned int var_index = streamer_read_uhwi (ib);
1077 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1078 var_index);
1079 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1080 if (dump_file)
1081 fprintf (dump_file, " %s", fndecl_name (v_decl));
1084 for (i = 0; i < f_count; i++)
1086 unsigned int j, index;
1087 struct cgraph_node *node;
1088 ipa_reference_optimization_summary_t info;
1089 int v_count;
1090 lto_symtab_encoder_t encoder;
1092 index = streamer_read_uhwi (ib);
1093 encoder = file_data->symtab_node_encoder;
1094 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1095 (encoder, index));
1096 info = XCNEW (struct ipa_reference_optimization_summary_d);
1097 set_reference_optimization_summary (node, info);
1098 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1099 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1100 if (dump_file)
1101 fprintf (dump_file,
1102 "\nFunction name:%s/%i:\n static not read:",
1103 node->asm_name (), node->order);
1105 /* Set the statics not read. */
1106 v_count = streamer_read_hwi (ib);
1107 if (v_count == -1)
1109 info->statics_not_read = all_module_statics;
1110 if (dump_file)
1111 fprintf (dump_file, " all module statics");
1113 else
1114 for (j = 0; j < (unsigned int)v_count; j++)
1116 unsigned int var_index = streamer_read_uhwi (ib);
1117 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1118 var_index);
1119 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1120 if (dump_file)
1121 fprintf (dump_file, " %s", fndecl_name (v_decl));
1124 if (dump_file)
1125 fprintf (dump_file,
1126 "\n static not written:");
1127 /* Set the statics not written. */
1128 v_count = streamer_read_hwi (ib);
1129 if (v_count == -1)
1131 info->statics_not_written = all_module_statics;
1132 if (dump_file)
1133 fprintf (dump_file, " all module statics");
1135 else
1136 for (j = 0; j < (unsigned int)v_count; j++)
1138 unsigned int var_index = streamer_read_uhwi (ib);
1139 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1140 var_index);
1141 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1142 if (dump_file)
1143 fprintf (dump_file, " %s", fndecl_name (v_decl));
1145 if (dump_file)
1146 fprintf (dump_file, "\n");
1149 lto_destroy_simple_input_block (file_data,
1150 LTO_section_ipa_reference,
1151 ib, data, len);
1153 else
1154 /* Fatal error here. We do not want to support compiling ltrans units with
1155 different version of compiler or different flags than the WPA unit, so
1156 this should never happen. */
1157 fatal_error (input_location,
1158 "ipa reference summary is missing in ltrans unit");
1162 namespace {
1164 const pass_data pass_data_ipa_reference =
1166 IPA_PASS, /* type */
1167 "static-var", /* name */
1168 OPTGROUP_NONE, /* optinfo_flags */
1169 TV_IPA_REFERENCE, /* tv_id */
1170 0, /* properties_required */
1171 0, /* properties_provided */
1172 0, /* properties_destroyed */
1173 0, /* todo_flags_start */
1174 0, /* todo_flags_finish */
1177 class pass_ipa_reference : public ipa_opt_pass_d
1179 public:
1180 pass_ipa_reference (gcc::context *ctxt)
1181 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1182 NULL, /* generate_summary */
1183 NULL, /* write_summary */
1184 NULL, /* read_summary */
1185 ipa_reference_write_optimization_summary, /*
1186 write_optimization_summary */
1187 ipa_reference_read_optimization_summary, /*
1188 read_optimization_summary */
1189 NULL, /* stmt_fixup */
1190 0, /* function_transform_todo_flags_start */
1191 NULL, /* function_transform */
1192 NULL) /* variable_transform */
1195 /* opt_pass methods: */
1196 virtual bool gate (function *)
1198 return ((in_lto_p || flag_ipa_reference)
1199 /* Don't bother doing anything if the program has errors. */
1200 && !seen_error ());
1203 virtual unsigned int execute (function *) { return propagate (); }
1205 }; // class pass_ipa_reference
1207 } // anon namespace
1209 ipa_opt_pass_d *
1210 make_pass_ipa_reference (gcc::context *ctxt)
1212 return new pass_ipa_reference (ctxt);
1215 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1216 within the same process. For use by toplev::finalize. */
1218 void
1219 ipa_reference_c_finalize (void)
1221 if (ipa_init_p)
1223 bitmap_obstack_release (&optimization_summary_obstack);
1224 ipa_init_p = false;
1227 if (node_removal_hook_holder)
1229 symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
1230 node_removal_hook_holder = NULL;
1232 if (node_duplication_hook_holder)
1234 symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder);
1235 node_duplication_hook_holder = NULL;