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