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