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