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