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