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