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