alias.c: Remove unused headers.
[gcc.git] / gcc / ipa-reference.c
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2015 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 /* This file gathers information about how variables whose scope is
22 confined to the compilation unit are used.
23
24 The transitive call site specific clobber effects are computed
25 for the variables whose scope is contained within this compilation
26 unit.
27
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. */
38
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 "tree-pass.h"
46 #include "cgraph.h"
47 #include "data-streamer.h"
48 #include "calls.h"
49 #include "splay-tree.h"
50 #include "ipa-utils.h"
51 #include "ipa-reference.h"
52
53 static void remove_node_data (struct cgraph_node *node,
54 void *data ATTRIBUTE_UNUSED);
55 static void duplicate_node_data (struct cgraph_node *src,
56 struct cgraph_node *dst,
57 void *data ATTRIBUTE_UNUSED);
58
59 /* The static variables defined within the compilation unit that are
60 loaded or stored directly by function that owns this structure. */
61
62 struct ipa_reference_local_vars_info_d
63 {
64 bitmap statics_read;
65 bitmap statics_written;
66 };
67
68 /* Statics that are read and written by some set of functions. The
69 local ones are based on the loads and stores local to the function.
70 The global ones are based on the local info as well as the
71 transitive closure of the functions that are called. */
72
73 struct ipa_reference_global_vars_info_d
74 {
75 bitmap statics_read;
76 bitmap statics_written;
77 };
78
79 /* Information we save about every function after ipa-reference is completed. */
80
81 struct ipa_reference_optimization_summary_d
82 {
83 bitmap statics_not_read;
84 bitmap statics_not_written;
85 };
86
87 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
88 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
89 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
90
91 struct ipa_reference_vars_info_d
92 {
93 struct ipa_reference_local_vars_info_d local;
94 struct ipa_reference_global_vars_info_d global;
95 };
96
97 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
98
99 /* This splay tree contains all of the static variables that are
100 being considered by the compilation level alias analysis. */
101 static splay_tree reference_vars_to_consider;
102
103 /* Set of all interesting module statics. A bit is set for every module
104 static we are considering. This is added to the local info when asm
105 code is found that clobbers all memory. */
106 static bitmap all_module_statics;
107 /* Set of all statics that should be ignored becuase they are touched by
108 -fno-ipa-reference code. */
109 static bitmap ignore_module_statics;
110
111 /* Obstack holding bitmaps of local analysis (live from analysis to
112 propagation) */
113 static bitmap_obstack local_info_obstack;
114 /* Obstack holding global analysis live forever. */
115 static bitmap_obstack optimization_summary_obstack;
116
117 /* Holders of ipa cgraph hooks: */
118 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
119 static struct cgraph_node_hook_list *node_removal_hook_holder;
120
121 /* Vector where the reference var infos are actually stored.
122 Indexed by UID of call graph nodes. */
123 static vec<ipa_reference_vars_info_t> ipa_reference_vars_vector;
124
125 /* TODO: find a place where we should release the vector. */
126 static vec<ipa_reference_optimization_summary_t> ipa_reference_opt_sum_vector;
127
128 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
129 static inline ipa_reference_vars_info_t
130 get_reference_vars_info (struct cgraph_node *node)
131 {
132 if (!ipa_reference_vars_vector.exists ()
133 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
134 return NULL;
135 return ipa_reference_vars_vector[node->uid];
136 }
137
138 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
139 static inline ipa_reference_optimization_summary_t
140 get_reference_optimization_summary (struct cgraph_node *node)
141 {
142 if (!ipa_reference_opt_sum_vector.exists ()
143 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
144 return NULL;
145 return ipa_reference_opt_sum_vector[node->uid];
146 }
147
148 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
149 static inline void
150 set_reference_vars_info (struct cgraph_node *node,
151 ipa_reference_vars_info_t info)
152 {
153 if (!ipa_reference_vars_vector.exists ()
154 || ipa_reference_vars_vector.length () <= (unsigned int) node->uid)
155 ipa_reference_vars_vector.safe_grow_cleared (node->uid + 1);
156 ipa_reference_vars_vector[node->uid] = info;
157 }
158
159 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
160 static inline void
161 set_reference_optimization_summary (struct cgraph_node *node,
162 ipa_reference_optimization_summary_t info)
163 {
164 if (!ipa_reference_opt_sum_vector.exists ()
165 || (ipa_reference_opt_sum_vector.length () <= (unsigned int) node->uid))
166 ipa_reference_opt_sum_vector.safe_grow_cleared (node->uid + 1);
167 ipa_reference_opt_sum_vector[node->uid] = info;
168 }
169
170 /* Return a bitmap indexed by DECL_UID for the static variables that
171 are *not* read during the execution of the function FN. Returns
172 NULL if no data is available. */
173
174 bitmap
175 ipa_reference_get_not_read_global (struct cgraph_node *fn)
176 {
177 if (!opt_for_fn (fn->decl, flag_ipa_reference)
178 || !opt_for_fn (current_function_decl, flag_ipa_reference))
179 return NULL;
180 ipa_reference_optimization_summary_t info =
181 get_reference_optimization_summary (fn->function_symbol (NULL));
182 if (info)
183 return info->statics_not_read;
184 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
185 return all_module_statics;
186 else
187 return NULL;
188 }
189
190 /* Return a bitmap indexed by DECL_UID for the static variables that
191 are *not* written during the execution of the function FN. Note
192 that variables written may or may not be read during the function
193 call. Returns NULL if no data is available. */
194
195 bitmap
196 ipa_reference_get_not_written_global (struct cgraph_node *fn)
197 {
198 if (!opt_for_fn (fn->decl, flag_ipa_reference)
199 || !opt_for_fn (current_function_decl, flag_ipa_reference))
200 return NULL;
201 ipa_reference_optimization_summary_t info =
202 get_reference_optimization_summary (fn);
203 if (info)
204 return info->statics_not_written;
205 else if (flags_from_decl_or_type (fn->decl) & ECF_LEAF)
206 return all_module_statics;
207 else
208 return NULL;
209 }
210
211 \f
212 /* Return true if the variable T is the right kind of static variable to
213 perform compilation unit scope escape analysis. */
214
215 static inline bool
216 is_proper_for_analysis (tree t)
217 {
218 /* If the variable has the "used" attribute, treat it as if it had a
219 been touched by the devil. */
220 if (DECL_PRESERVE_P (t))
221 return false;
222
223 /* Do not want to do anything with volatile except mark any
224 function that uses one to be not const or pure. */
225 if (TREE_THIS_VOLATILE (t))
226 return false;
227
228 /* We do not need to analyze readonly vars, we already know they do not
229 alias. */
230 if (TREE_READONLY (t))
231 return false;
232
233 /* We can not track variables with address taken. */
234 if (TREE_ADDRESSABLE (t))
235 return false;
236
237 /* TODO: We could track public variables that are not addressable, but currently
238 frontends don't give us those. */
239 if (TREE_PUBLIC (t))
240 return false;
241
242 /* TODO: Check aliases. */
243 if (bitmap_bit_p (ignore_module_statics, DECL_UID (t)))
244 return false;
245
246 return true;
247 }
248
249 /* Lookup the tree node for the static variable that has UID and
250 convert the name to a string for debugging. */
251
252 static const char *
253 get_static_name (int index)
254 {
255 splay_tree_node stn =
256 splay_tree_lookup (reference_vars_to_consider, index);
257 return fndecl_name ((tree)(stn->value));
258 }
259
260 /* Dump a set of static vars to FILE. */
261 static void
262 dump_static_vars_set_to_file (FILE *f, bitmap set)
263 {
264 unsigned int index;
265 bitmap_iterator bi;
266 if (set == NULL)
267 return;
268 else if (set == all_module_statics)
269 fprintf (f, "ALL");
270 else
271 EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
272 {
273 fprintf (f, "%s ", get_static_name (index));
274 }
275 }
276
277 /* Compute X |= Y, taking into account the possibility that
278 either X or Y is already the maximum set.
279 Return true if X is the maximum set after taking the union with Y. */
280
281 static bool
282 union_static_var_sets (bitmap &x, bitmap y)
283 {
284 if (x != all_module_statics)
285 {
286 if (y == all_module_statics)
287 {
288 BITMAP_FREE (x);
289 x = all_module_statics;
290 }
291 else if (bitmap_ior_into (x, y))
292 {
293 /* The union may have reduced X to the maximum set.
294 In that case, we want to make that visible explicitly.
295 Even though bitmap_equal_p can be very expensive, it
296 turns out to be an overall win to check this here for
297 an LTO bootstrap of GCC itself. Liberally extrapoliate
298 that result to be applicable to all cases. */
299 if (bitmap_equal_p (x, all_module_statics))
300 {
301 BITMAP_FREE (x);
302 x = all_module_statics;
303 }
304 }
305 }
306 return x == all_module_statics;
307 }
308
309 /* Return a copy of SET on the bitmap obstack containing SET.
310 But if SET is NULL or the maximum set, return that instead. */
311
312 static bitmap
313 copy_static_var_set (bitmap set)
314 {
315 if (set == NULL || set == all_module_statics)
316 return set;
317 bitmap_obstack *o = set->obstack;
318 gcc_checking_assert (o);
319 bitmap copy = BITMAP_ALLOC (o);
320 bitmap_copy (copy, set);
321 return copy;
322 }
323
324 /* Compute the union all of the statics read and written by every callee of X
325 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
326 actually the set representing the cycle containing X. If the read and
327 written sets of X_GLOBAL has been reduced to the maximum set, we don't
328 have to look at the remaining callees. */
329
330 static void
331 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
332 {
333 struct cgraph_edge *e;
334 bool read_all = x_global->statics_read == all_module_statics;
335 bool write_all = x_global->statics_written == all_module_statics;
336 for (e = x->callees;
337 e && !(read_all && write_all);
338 e = e->next_callee)
339 {
340 enum availability avail;
341 struct cgraph_node *y = e->callee->function_symbol (&avail);
342 if (!y)
343 continue;
344
345 /* Only look into nodes we can propagate something. */
346 int flags = flags_from_decl_or_type (y->decl);
347 if (opt_for_fn (y->decl, flag_ipa_reference)
348 && (avail > AVAIL_INTERPOSABLE
349 || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
350 {
351 if (get_reference_vars_info (y))
352 {
353 ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
354 ipa_reference_global_vars_info_t y_global = &y_info->global;
355
356 /* Calls in the current cycle do not have their global set
357 computed yet (but everything else does because we're
358 visiting nodes in topological order). */
359 if (!y_global->statics_read)
360 continue;
361
362 /* If the function is const, it reads no memory even if it
363 seems so to local analysis. */
364 if (flags & ECF_CONST)
365 continue;
366
367 union_static_var_sets (x_global->statics_read,
368 y_global->statics_read);
369
370 /* If the function is pure, it has no stores even if it
371 seems so to local analysis. If we cannot return from
372 the function, we can safely ignore the call. */
373 if ((flags & ECF_PURE)
374 || e->cannot_lead_to_return_p ())
375 continue;
376
377 union_static_var_sets (x_global->statics_written,
378 y_global->statics_written);
379 }
380 else
381 gcc_unreachable ();
382 }
383 }
384 }
385
386 static bool ipa_init_p = false;
387
388 /* The init routine for analyzing global static variable usage. See
389 comments at top for description. */
390 static void
391 ipa_init (void)
392 {
393 if (ipa_init_p)
394 return;
395
396 ipa_init_p = true;
397
398 if (dump_file)
399 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
400
401 bitmap_obstack_initialize (&local_info_obstack);
402 bitmap_obstack_initialize (&optimization_summary_obstack);
403 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
404 ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
405
406 node_removal_hook_holder =
407 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
408 node_duplication_hook_holder =
409 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
410 }
411
412
413 /* Set up the persistent info for FN. */
414
415 static ipa_reference_local_vars_info_t
416 init_function_info (struct cgraph_node *fn)
417 {
418 ipa_reference_vars_info_t info
419 = XCNEW (struct ipa_reference_vars_info_d);
420
421 /* Add the info to the tree's annotation. */
422 set_reference_vars_info (fn, info);
423
424 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
425 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
426
427 return &info->local;
428 }
429
430
431 /* This is the main routine for finding the reference patterns for
432 global variables within a function FN. */
433
434 static void
435 analyze_function (struct cgraph_node *fn)
436 {
437 ipa_reference_local_vars_info_t local;
438 struct ipa_ref *ref = NULL;
439 int i;
440 tree var;
441
442 if (!opt_for_fn (fn->decl, flag_ipa_reference))
443 return;
444 local = init_function_info (fn);
445 for (i = 0; fn->iterate_reference (i, ref); i++)
446 {
447 if (!is_a <varpool_node *> (ref->referred))
448 continue;
449 var = ref->referred->decl;
450 if (!is_proper_for_analysis (var))
451 continue;
452 /* This is a variable we care about. Check if we have seen it
453 before, and if not add it the set of variables we care about. */
454 if (all_module_statics
455 && bitmap_set_bit (all_module_statics, DECL_UID (var)))
456 {
457 if (dump_file)
458 splay_tree_insert (reference_vars_to_consider,
459 DECL_UID (var), (splay_tree_value)var);
460 }
461 switch (ref->use)
462 {
463 case IPA_REF_LOAD:
464 bitmap_set_bit (local->statics_read, DECL_UID (var));
465 break;
466 case IPA_REF_STORE:
467 if (ref->cannot_lead_to_return ())
468 break;
469 bitmap_set_bit (local->statics_written, DECL_UID (var));
470 break;
471 case IPA_REF_ADDR:
472 break;
473 default:
474 gcc_unreachable ();
475 }
476 }
477
478 if (fn->cannot_return_p ())
479 bitmap_clear (local->statics_written);
480 }
481
482
483 /* Called when new clone is inserted to callgraph late. */
484
485 static void
486 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
487 void *data ATTRIBUTE_UNUSED)
488 {
489 ipa_reference_optimization_summary_t ginfo;
490 ipa_reference_optimization_summary_t dst_ginfo;
491
492 ginfo = get_reference_optimization_summary (src);
493 if (!ginfo)
494 return;
495 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
496 set_reference_optimization_summary (dst, dst_ginfo);
497 dst_ginfo->statics_not_read =
498 copy_static_var_set (ginfo->statics_not_read);
499 dst_ginfo->statics_not_written =
500 copy_static_var_set (ginfo->statics_not_written);
501 }
502
503 /* Called when node is removed. */
504
505 static void
506 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
507 {
508 ipa_reference_optimization_summary_t ginfo;
509 ginfo = get_reference_optimization_summary (node);
510 if (ginfo)
511 {
512 if (ginfo->statics_not_read
513 && ginfo->statics_not_read != all_module_statics)
514 BITMAP_FREE (ginfo->statics_not_read);
515
516 if (ginfo->statics_not_written
517 && ginfo->statics_not_written != all_module_statics)
518 BITMAP_FREE (ginfo->statics_not_written);
519 free (ginfo);
520 set_reference_optimization_summary (node, NULL);
521 }
522 }
523
524 /* Analyze each function in the cgraph to see which global or statics
525 are read or written. */
526
527 static void
528 generate_summary (void)
529 {
530 struct cgraph_node *node;
531 unsigned int index;
532 bitmap_iterator bi;
533
534 ipa_init ();
535
536 /* Process all of the functions next. */
537 FOR_EACH_DEFINED_FUNCTION (node)
538 if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
539 {
540 struct ipa_ref *ref = NULL;
541 int i;
542 tree var;
543 for (i = 0; node->iterate_reference (i, ref); i++)
544 {
545 if (!is_a <varpool_node *> (ref->referred))
546 continue;
547 var = ref->referred->decl;
548 if (!is_proper_for_analysis (var))
549 continue;
550 bitmap_set_bit (ignore_module_statics, DECL_UID (var));
551 }
552 }
553 FOR_EACH_DEFINED_FUNCTION (node)
554 analyze_function (node);
555
556 if (dump_file)
557 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
558 {
559 fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
560 get_static_name (index), index);
561 }
562
563 if (dump_file)
564 FOR_EACH_DEFINED_FUNCTION (node)
565 if (node->get_availability () >= AVAIL_INTERPOSABLE
566 && opt_for_fn (node->decl, flag_ipa_reference))
567 {
568 ipa_reference_local_vars_info_t l;
569 unsigned int index;
570 bitmap_iterator bi;
571
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)
580 {
581 fprintf (dump_file, "%s ",
582 get_static_name (index));
583 }
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)
588 {
589 fprintf (dump_file, "%s ", get_static_name (index));
590 }
591 }
592 }
593 \f
594 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
595
596 static void
597 read_write_all_from_decl (struct cgraph_node *node,
598 bool &read_all, bool &write_all)
599 {
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)
604 ;
605 else if (flags & ECF_CONST)
606 ;
607 else if ((flags & ECF_PURE) || node->cannot_return_p ())
608 {
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);
613 }
614 else
615 {
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);
623 }
624 }
625
626 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
627 in the cycle of NODE. */
628
629 static void
630 get_read_write_all_from_node (struct cgraph_node *node,
631 bool &read_all, bool &write_all)
632 {
633 struct cgraph_edge *e, *ie;
634
635 /* When function is overwritable, we can not assume anything. */
636 if (node->get_availability () <= AVAIL_INTERPOSABLE
637 || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
638 read_write_all_from_decl (node, read_all, write_all);
639
640 for (e = node->callees;
641 e && !(read_all && write_all);
642 e = e->next_callee)
643 {
644 enum availability avail;
645 struct cgraph_node *callee = e->callee->function_symbol (&avail);
646 gcc_checking_assert (callee);
647 if (avail <= AVAIL_INTERPOSABLE
648 || (callee->analyzed && !opt_for_fn (callee->decl, flag_ipa_reference)))
649 read_write_all_from_decl (callee, read_all, write_all);
650 }
651
652 for (ie = node->indirect_calls;
653 ie && !(read_all && write_all);
654 ie = ie->next_callee)
655 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
656 {
657 read_all = true;
658 if (dump_file && (dump_flags & TDF_DETAILS))
659 fprintf (dump_file, " indirect call -> read all\n");
660 if (!ie->cannot_lead_to_return_p ()
661 && !(ie->indirect_info->ecf_flags & ECF_PURE))
662 {
663 if (dump_file && (dump_flags & TDF_DETAILS))
664 fprintf (dump_file, " indirect call -> write all\n");
665 write_all = true;
666 }
667 }
668 }
669
670 /* Skip edges from and to nodes without ipa_reference enables. This leave
671 them out of strongy connected coponents and makes them easyto skip in the
672 propagation loop bellow. */
673
674 static bool
675 ignore_edge_p (cgraph_edge *e)
676 {
677 return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
678 || !opt_for_fn (e->callee->function_symbol ()->decl,
679 flag_ipa_reference));
680 }
681
682 /* Produce the global information by preforming a transitive closure
683 on the local information that was produced by ipa_analyze_function. */
684
685 static unsigned int
686 propagate (void)
687 {
688 struct cgraph_node *node;
689 struct cgraph_node **order =
690 XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
691 int order_pos;
692 int i;
693 bool remove_p;
694
695 if (dump_file)
696 cgraph_node::dump_cgraph (dump_file);
697
698 remove_p = ipa_discover_readonly_nonaddressable_vars ();
699 generate_summary ();
700
701 /* Propagate the local information through the call graph to produce
702 the global information. All the nodes within a cycle will have
703 the same info so we collapse cycles first. Then we can do the
704 propagation in one pass from the leaves to the roots. */
705 order_pos = ipa_reduced_postorder (order, true, true, ignore_edge_p);
706 if (dump_file)
707 ipa_print_order (dump_file, "reduced", order, order_pos);
708
709 for (i = 0; i < order_pos; i++ )
710 {
711 unsigned x;
712 struct cgraph_node *w;
713 ipa_reference_vars_info_t node_info;
714 ipa_reference_global_vars_info_t node_g;
715 ipa_reference_local_vars_info_t node_l;
716 bool read_all = false;
717 bool write_all = false;
718
719 node = order[i];
720 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
721 continue;
722
723 node_info = get_reference_vars_info (node);
724 gcc_assert (node_info);
725 node_l = &node_info->local;
726 node_g = &node_info->global;
727
728 if (dump_file && (dump_flags & TDF_DETAILS))
729 fprintf (dump_file, "Starting cycle with %s/%i\n",
730 node->asm_name (), node->order);
731
732 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
733
734 /* If any node in a cycle is read_all or write_all, they all are. */
735 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
736 {
737 if (dump_file && (dump_flags & TDF_DETAILS))
738 fprintf (dump_file, " Visiting %s/%i\n",
739 w->asm_name (), w->order);
740 get_read_write_all_from_node (w, read_all, write_all);
741 if (read_all && write_all)
742 break;
743 }
744
745 /* Initialized the bitmaps global sets for the reduced node. */
746 if (read_all)
747 node_g->statics_read = all_module_statics;
748 else
749 node_g->statics_read = copy_static_var_set (node_l->statics_read);
750 if (write_all)
751 node_g->statics_written = all_module_statics;
752 else
753 node_g->statics_written = copy_static_var_set (node_l->statics_written);
754
755 /* Merge the sets of this cycle with all sets of callees reached
756 from this cycle. */
757 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
758 {
759 if (read_all && write_all)
760 break;
761
762 if (w != node)
763 {
764 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
765 ipa_reference_local_vars_info_t w_l = &w_ri->local;
766 int flags = flags_from_decl_or_type (w->decl);
767
768 if (!(flags & ECF_CONST))
769 read_all = union_static_var_sets (node_g->statics_read,
770 w_l->statics_read);
771 if (!(flags & ECF_PURE)
772 && !w->cannot_return_p ())
773 write_all = union_static_var_sets (node_g->statics_written,
774 w_l->statics_written);
775 }
776
777 propagate_bits (node_g, w);
778 }
779
780 /* All nodes within a cycle have the same global info bitmaps. */
781 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
782 {
783 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
784 w_ri->global = *node_g;
785 }
786
787 cycle_nodes.release ();
788 }
789
790 if (dump_file)
791 {
792 for (i = 0; i < order_pos; i++)
793 {
794 unsigned x;
795 struct cgraph_node *w;
796
797 node = order[i];
798 if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
799 continue;
800
801 fprintf (dump_file,
802 "\nFunction name:%s/%i:",
803 node->asm_name (), node->order);
804
805 ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
806 ipa_reference_global_vars_info_t node_g = &node_info->global;
807
808 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
809 FOR_EACH_VEC_ELT (cycle_nodes, x, w)
810 {
811 ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
812 ipa_reference_local_vars_info_t w_l = &w_ri->local;
813 if (w != node)
814 fprintf (dump_file, "\n next cycle: %s/%i ",
815 w->asm_name (), w->order);
816 fprintf (dump_file, "\n locals read: ");
817 dump_static_vars_set_to_file (dump_file, w_l->statics_read);
818 fprintf (dump_file, "\n locals written: ");
819 dump_static_vars_set_to_file (dump_file, w_l->statics_written);
820 }
821 cycle_nodes.release ();
822
823 fprintf (dump_file, "\n globals read: ");
824 dump_static_vars_set_to_file (dump_file, node_g->statics_read);
825 fprintf (dump_file, "\n globals written: ");
826 dump_static_vars_set_to_file (dump_file, node_g->statics_written);
827 fprintf (dump_file, "\n");
828 }
829 }
830
831 /* Cleanup. */
832 FOR_EACH_DEFINED_FUNCTION (node)
833 {
834 ipa_reference_vars_info_t node_info;
835 ipa_reference_global_vars_info_t node_g;
836 ipa_reference_optimization_summary_t opt;
837
838 node_info = get_reference_vars_info (node);
839 if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
840 && (node->get_availability () > AVAIL_INTERPOSABLE
841 || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
842 {
843 node_g = &node_info->global;
844
845 opt = XCNEW (struct ipa_reference_optimization_summary_d);
846 set_reference_optimization_summary (node, opt);
847
848 /* Create the complimentary sets. */
849
850 if (bitmap_empty_p (node_g->statics_read))
851 opt->statics_not_read = all_module_statics;
852 else
853 {
854 opt->statics_not_read
855 = BITMAP_ALLOC (&optimization_summary_obstack);
856 if (node_g->statics_read != all_module_statics)
857 bitmap_and_compl (opt->statics_not_read,
858 all_module_statics,
859 node_g->statics_read);
860 }
861
862 if (bitmap_empty_p (node_g->statics_written))
863 opt->statics_not_written = all_module_statics;
864 else
865 {
866 opt->statics_not_written
867 = BITMAP_ALLOC (&optimization_summary_obstack);
868 if (node_g->statics_written != all_module_statics)
869 bitmap_and_compl (opt->statics_not_written,
870 all_module_statics,
871 node_g->statics_written);
872 }
873 }
874 free (node_info);
875 }
876
877 ipa_free_postorder_info ();
878 free (order);
879
880 bitmap_obstack_release (&local_info_obstack);
881 ipa_reference_vars_vector.release ();
882 if (dump_file)
883 splay_tree_delete (reference_vars_to_consider);
884 reference_vars_to_consider = NULL;
885 return remove_p ? TODO_remove_functions : 0;
886 }
887
888 /* Return true if we need to write summary of NODE. */
889
890 static bool
891 write_node_summary_p (struct cgraph_node *node,
892 lto_symtab_encoder_t encoder,
893 bitmap ltrans_statics)
894 {
895 ipa_reference_optimization_summary_t info;
896
897 /* See if we have (non-empty) info. */
898 if (!node->definition || node->global.inlined_to)
899 return false;
900 info = get_reference_optimization_summary (node);
901 if (!info || (bitmap_empty_p (info->statics_not_read)
902 && bitmap_empty_p (info->statics_not_written)))
903 return false;
904
905 /* See if we want to encode it.
906 Encode also referenced functions since constant folding might turn it into
907 a direct call.
908
909 In future we might also want to include summaries of functions references
910 by initializers of constant variables references in current unit. */
911 if (!reachable_from_this_partition_p (node, encoder)
912 && !referenced_from_this_partition_p (node, encoder))
913 return false;
914
915 /* See if the info has non-empty intersections with vars we want to encode. */
916 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
917 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
918 return false;
919 return true;
920 }
921
922 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
923 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
924 or -1. When it is positive, just output -1 when
925 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
926
927 static void
928 stream_out_bitmap (struct lto_simple_output_block *ob,
929 bitmap bits, bitmap ltrans_statics,
930 int ltrans_statics_bitcount)
931 {
932 int count = 0;
933 unsigned int index;
934 bitmap_iterator bi;
935 if (bits == all_module_statics)
936 {
937 streamer_write_hwi_stream (ob->main_stream, -1);
938 return;
939 }
940 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
941 count ++;
942 if (count == ltrans_statics_bitcount)
943 {
944 streamer_write_hwi_stream (ob->main_stream, -1);
945 return;
946 }
947 streamer_write_hwi_stream (ob->main_stream, count);
948 if (!count)
949 return;
950 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
951 {
952 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
953 lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
954 }
955 }
956
957 /* Serialize the ipa info for lto. */
958
959 static void
960 ipa_reference_write_optimization_summary (void)
961 {
962 struct lto_simple_output_block *ob
963 = lto_create_simple_output_block (LTO_section_ipa_reference);
964 unsigned int count = 0;
965 int ltrans_statics_bitcount = 0;
966 lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
967 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
968 int i;
969
970 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
971
972 /* See what variables we are interested in. */
973 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
974 {
975 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
976 varpool_node *vnode = dyn_cast <varpool_node *> (snode);
977 if (vnode
978 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
979 && referenced_from_this_partition_p (vnode, encoder))
980 {
981 tree decl = vnode->decl;
982 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
983 splay_tree_insert (reference_vars_to_consider,
984 DECL_UID (decl), (splay_tree_value)decl);
985 ltrans_statics_bitcount ++;
986 }
987 }
988
989
990 if (ltrans_statics_bitcount)
991 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
992 {
993 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
994 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
995 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
996 count++;
997 }
998
999 streamer_write_uhwi_stream (ob->main_stream, count);
1000 if (count)
1001 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1002 -1);
1003
1004 /* Process all of the functions. */
1005 if (ltrans_statics_bitcount)
1006 for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1007 {
1008 symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1009 cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1010 if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1011 {
1012 ipa_reference_optimization_summary_t info;
1013 int node_ref;
1014
1015 info = get_reference_optimization_summary (cnode);
1016 node_ref = lto_symtab_encoder_encode (encoder, snode);
1017 streamer_write_uhwi_stream (ob->main_stream, node_ref);
1018
1019 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1020 ltrans_statics_bitcount);
1021 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1022 ltrans_statics_bitcount);
1023 }
1024 }
1025 BITMAP_FREE (ltrans_statics);
1026 lto_destroy_simple_output_block (ob);
1027 splay_tree_delete (reference_vars_to_consider);
1028 }
1029
1030 /* Deserialize the ipa info for lto. */
1031
1032 static void
1033 ipa_reference_read_optimization_summary (void)
1034 {
1035 struct lto_file_decl_data ** file_data_vec
1036 = lto_get_file_decl_data ();
1037 struct lto_file_decl_data * file_data;
1038 unsigned int j = 0;
1039 bitmap_obstack_initialize (&optimization_summary_obstack);
1040
1041 node_removal_hook_holder =
1042 symtab->add_cgraph_removal_hook (&remove_node_data, NULL);
1043 node_duplication_hook_holder =
1044 symtab->add_cgraph_duplication_hook (&duplicate_node_data, NULL);
1045 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1046
1047 while ((file_data = file_data_vec[j++]))
1048 {
1049 const char *data;
1050 size_t len;
1051 struct lto_input_block *ib
1052 = lto_create_simple_input_block (file_data,
1053 LTO_section_ipa_reference,
1054 &data, &len);
1055 if (ib)
1056 {
1057 unsigned int i;
1058 unsigned int f_count = streamer_read_uhwi (ib);
1059 int b_count;
1060 if (!f_count)
1061 continue;
1062 b_count = streamer_read_hwi (ib);
1063 if (dump_file)
1064 fprintf (dump_file, "all module statics:");
1065 for (i = 0; i < (unsigned int)b_count; i++)
1066 {
1067 unsigned int var_index = streamer_read_uhwi (ib);
1068 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1069 var_index);
1070 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1071 if (dump_file)
1072 fprintf (dump_file, " %s", fndecl_name (v_decl));
1073 }
1074
1075 for (i = 0; i < f_count; i++)
1076 {
1077 unsigned int j, index;
1078 struct cgraph_node *node;
1079 ipa_reference_optimization_summary_t info;
1080 int v_count;
1081 lto_symtab_encoder_t encoder;
1082
1083 index = streamer_read_uhwi (ib);
1084 encoder = file_data->symtab_node_encoder;
1085 node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1086 (encoder, index));
1087 info = XCNEW (struct ipa_reference_optimization_summary_d);
1088 set_reference_optimization_summary (node, info);
1089 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1090 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1091 if (dump_file)
1092 fprintf (dump_file,
1093 "\nFunction name:%s/%i:\n static not read:",
1094 node->asm_name (), node->order);
1095
1096 /* Set the statics not read. */
1097 v_count = streamer_read_hwi (ib);
1098 if (v_count == -1)
1099 {
1100 info->statics_not_read = all_module_statics;
1101 if (dump_file)
1102 fprintf (dump_file, " all module statics");
1103 }
1104 else
1105 for (j = 0; j < (unsigned int)v_count; j++)
1106 {
1107 unsigned int var_index = streamer_read_uhwi (ib);
1108 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1109 var_index);
1110 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1111 if (dump_file)
1112 fprintf (dump_file, " %s", fndecl_name (v_decl));
1113 }
1114
1115 if (dump_file)
1116 fprintf (dump_file,
1117 "\n static not written:");
1118 /* Set the statics not written. */
1119 v_count = streamer_read_hwi (ib);
1120 if (v_count == -1)
1121 {
1122 info->statics_not_written = all_module_statics;
1123 if (dump_file)
1124 fprintf (dump_file, " all module statics");
1125 }
1126 else
1127 for (j = 0; j < (unsigned int)v_count; j++)
1128 {
1129 unsigned int var_index = streamer_read_uhwi (ib);
1130 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1131 var_index);
1132 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1133 if (dump_file)
1134 fprintf (dump_file, " %s", fndecl_name (v_decl));
1135 }
1136 if (dump_file)
1137 fprintf (dump_file, "\n");
1138 }
1139
1140 lto_destroy_simple_input_block (file_data,
1141 LTO_section_ipa_reference,
1142 ib, data, len);
1143 }
1144 else
1145 /* Fatal error here. We do not want to support compiling ltrans units with
1146 different version of compiler or different flags than the WPA unit, so
1147 this should never happen. */
1148 fatal_error (input_location,
1149 "ipa reference summary is missing in ltrans unit");
1150 }
1151 }
1152
1153 namespace {
1154
1155 const pass_data pass_data_ipa_reference =
1156 {
1157 IPA_PASS, /* type */
1158 "static-var", /* name */
1159 OPTGROUP_NONE, /* optinfo_flags */
1160 TV_IPA_REFERENCE, /* tv_id */
1161 0, /* properties_required */
1162 0, /* properties_provided */
1163 0, /* properties_destroyed */
1164 0, /* todo_flags_start */
1165 0, /* todo_flags_finish */
1166 };
1167
1168 class pass_ipa_reference : public ipa_opt_pass_d
1169 {
1170 public:
1171 pass_ipa_reference (gcc::context *ctxt)
1172 : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1173 NULL, /* generate_summary */
1174 NULL, /* write_summary */
1175 NULL, /* read_summary */
1176 ipa_reference_write_optimization_summary, /*
1177 write_optimization_summary */
1178 ipa_reference_read_optimization_summary, /*
1179 read_optimization_summary */
1180 NULL, /* stmt_fixup */
1181 0, /* function_transform_todo_flags_start */
1182 NULL, /* function_transform */
1183 NULL) /* variable_transform */
1184 {}
1185
1186 /* opt_pass methods: */
1187 virtual bool gate (function *)
1188 {
1189 return ((in_lto_p || flag_ipa_reference)
1190 /* Don't bother doing anything if the program has errors. */
1191 && !seen_error ());
1192 }
1193
1194 virtual unsigned int execute (function *) { return propagate (); }
1195
1196 }; // class pass_ipa_reference
1197
1198 } // anon namespace
1199
1200 ipa_opt_pass_d *
1201 make_pass_ipa_reference (gcc::context *ctxt)
1202 {
1203 return new pass_ipa_reference (ctxt);
1204 }
1205
1206 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1207 within the same process. For use by toplev::finalize. */
1208
1209 void
1210 ipa_reference_c_finalize (void)
1211 {
1212 if (ipa_init_p)
1213 {
1214 bitmap_obstack_release (&optimization_summary_obstack);
1215 ipa_init_p = false;
1216 }
1217
1218 if (node_removal_hook_holder)
1219 {
1220 symtab->remove_cgraph_removal_hook (node_removal_hook_holder);
1221 node_removal_hook_holder = NULL;
1222 }
1223 if (node_duplication_hook_holder)
1224 {
1225 symtab->remove_cgraph_duplication_hook (node_duplication_hook_holder);
1226 node_duplication_hook_holder = NULL;
1227 }
1228 }