]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/ipa-reference.c
* doc/extend.texi: (attribute leaf): Document.
[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 "lto-streamer.h"
62 #include "toplev.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 completted. */
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 (fn);
201 if (info)
202 return info->statics_not_read;
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 /* 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->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 struct cgraph_node *y = e->callee;
306 enum availability avail;
307
308 avail = cgraph_function_body_availability (e->callee);
309 /* Only look into nodes we can propagate something. */
310 if (avail > AVAIL_OVERWRITABLE
311 || (avail == AVAIL_OVERWRITABLE
312 && (flags_from_decl_or_type (e->callee->decl) & ECF_LEAF)))
313 {
314 int flags = flags_from_decl_or_type (e->callee->decl);
315 if (get_reference_vars_info (y))
316 {
317 ipa_reference_vars_info_t y_info
318 = get_reference_vars_info (y);
319 ipa_reference_global_vars_info_t y_global = &y_info->global;
320
321 /* Calls in current cycle do not have global computed yet. */
322 if (!y_global->statics_read)
323 continue;
324
325 /* If function is declared const, it reads no memory even if it
326 seems so to local analysis. */
327 if (flags & ECF_CONST)
328 continue;
329
330 if (x_global->statics_read
331 != all_module_statics)
332 {
333 if (y_global->statics_read
334 == all_module_statics)
335 {
336 BITMAP_FREE (x_global->statics_read);
337 x_global->statics_read
338 = all_module_statics;
339 }
340 /* Skip bitmaps that are pointer equal to node's bitmap
341 (no reason to spin within the cycle). */
342 else if (x_global->statics_read
343 != y_global->statics_read)
344 bitmap_ior_into (x_global->statics_read,
345 y_global->statics_read);
346 }
347
348 /* If function is declared pure, it has no stores even if it
349 seems so to local analysis; If we can not return from here,
350 we can safely ignore the call. */
351 if ((flags & ECF_PURE)
352 || cgraph_edge_cannot_lead_to_return (e))
353 continue;
354
355 if (x_global->statics_written
356 != all_module_statics)
357 {
358 if (y_global->statics_written
359 == all_module_statics)
360 {
361 BITMAP_FREE (x_global->statics_written);
362 x_global->statics_written
363 = all_module_statics;
364 }
365 /* Skip bitmaps that are pointer equal to node's bitmap
366 (no reason to spin within the cycle). */
367 else if (x_global->statics_written
368 != y_global->statics_written)
369 bitmap_ior_into (x_global->statics_written,
370 y_global->statics_written);
371 }
372 }
373 else
374 gcc_unreachable ();
375 }
376 }
377 }
378
379 /* The init routine for analyzing global static variable usage. See
380 comments at top for description. */
381 static void
382 ipa_init (void)
383 {
384 static bool init_p = false;
385
386 if (init_p)
387 return;
388
389 init_p = true;
390
391 if (dump_file)
392 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
393
394 bitmap_obstack_initialize (&local_info_obstack);
395 bitmap_obstack_initialize (&optimization_summary_obstack);
396 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
397
398 node_removal_hook_holder =
399 cgraph_add_node_removal_hook (&remove_node_data, NULL);
400 node_duplication_hook_holder =
401 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
402 }
403
404
405 /* Set up the persistent info for FN. */
406
407 static ipa_reference_local_vars_info_t
408 init_function_info (struct cgraph_node *fn)
409 {
410 ipa_reference_vars_info_t info
411 = XCNEW (struct ipa_reference_vars_info_d);
412
413 /* Add the info to the tree's annotation. */
414 set_reference_vars_info (fn, info);
415
416 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
417 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
418
419 return &info->local;
420 }
421
422
423 /* This is the main routine for finding the reference patterns for
424 global variables within a function FN. */
425
426 static void
427 analyze_function (struct cgraph_node *fn)
428 {
429 ipa_reference_local_vars_info_t local;
430 struct ipa_ref *ref;
431 int i;
432 tree var;
433
434 local = init_function_info (fn);
435 for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
436 {
437 if (ref->refered_type != IPA_REF_VARPOOL)
438 continue;
439 var = ipa_ref_varpool_node (ref)->decl;
440 if (ipa_ref_varpool_node (ref)->externally_visible
441 || !ipa_ref_varpool_node (ref)->analyzed
442 || !is_proper_for_analysis (var))
443 continue;
444 switch (ref->use)
445 {
446 case IPA_REF_LOAD:
447 bitmap_set_bit (local->statics_read, DECL_UID (var));
448 break;
449 case IPA_REF_STORE:
450 if (ipa_ref_cannot_lead_to_return (ref))
451 break;
452 bitmap_set_bit (local->statics_written, DECL_UID (var));
453 break;
454 case IPA_REF_ADDR:
455 gcc_unreachable ();
456 break;
457 }
458 }
459
460 if (cgraph_node_cannot_return (fn))
461 bitmap_clear (local->statics_written);
462 }
463
464 static bitmap
465 copy_global_bitmap (bitmap src)
466 {
467 bitmap dst;
468 if (!src)
469 return NULL;
470 if (src == all_module_statics)
471 return all_module_statics;
472 dst = BITMAP_ALLOC (&optimization_summary_obstack);
473 bitmap_copy (dst, src);
474 return dst;
475 }
476
477
478 /* Called when new clone is inserted to callgraph late. */
479
480 static void
481 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
482 void *data ATTRIBUTE_UNUSED)
483 {
484 ipa_reference_optimization_summary_t ginfo;
485 ipa_reference_optimization_summary_t dst_ginfo;
486
487 ginfo = get_reference_optimization_summary (src);
488 if (!ginfo)
489 return;
490 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
491 set_reference_optimization_summary (dst, dst_ginfo);
492 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
493 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
494 }
495
496 /* Called when node is removed. */
497
498 static void
499 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
500 {
501 ipa_reference_optimization_summary_t ginfo;
502 ginfo = get_reference_optimization_summary (node);
503 if (ginfo)
504 {
505 if (ginfo->statics_not_read
506 && ginfo->statics_not_read != all_module_statics)
507 BITMAP_FREE (ginfo->statics_not_read);
508
509 if (ginfo->statics_not_written
510 && ginfo->statics_not_written != all_module_statics)
511 BITMAP_FREE (ginfo->statics_not_written);
512 free (ginfo);
513 set_reference_optimization_summary (node, NULL);
514 }
515 }
516
517 /* Analyze each function in the cgraph to see which global or statics
518 are read or written. */
519
520 static void
521 generate_summary (void)
522 {
523 struct cgraph_node *node;
524 unsigned int index;
525 bitmap_iterator bi;
526 bitmap bm_temp;
527
528 ipa_init ();
529 bm_temp = BITMAP_ALLOC (&local_info_obstack);
530
531 /* Process all of the functions next. */
532 for (node = cgraph_nodes; node; node = node->next)
533 if (node->analyzed)
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 (node = cgraph_nodes; node; node = node->next)
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->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 = ipa_utils_reduced_inorder (order, false, true, NULL);
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_utils_reduced_inorder (order, true, true, NULL);
633 if (dump_file)
634 ipa_utils_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 node_info = get_reference_vars_info (node);
649 gcc_assert (node_info);
650
651
652 if (dump_file && (dump_flags & TDF_DETAILS))
653 fprintf (dump_file, "Starting cycle with %s/%i\n",
654 cgraph_node_name (node), node->uid);
655
656 node_l = &node_info->local;
657 node_g = &node_info->global;
658
659 read_all = false;
660 write_all = false;
661
662 /* When function is overwrittable, we can not assume anything. */
663 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
664 read_write_all_from_decl (node, &read_all, &write_all);
665
666 for (e = node->callees; e; e = e->next_callee)
667 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
668 read_write_all_from_decl (e->callee, &read_all, &write_all);
669
670 for (ie = node->indirect_calls; ie; ie = ie->next_callee)
671 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
672 {
673 read_all = true;
674 if (dump_file && (dump_flags & TDF_DETAILS))
675 fprintf (dump_file, " indirect call -> read all\n");
676 if (!cgraph_edge_cannot_lead_to_return (ie)
677 && !(ie->indirect_info->ecf_flags & ECF_PURE))
678 {
679 if (dump_file && (dump_flags & TDF_DETAILS))
680 fprintf (dump_file, " indirect call -> write all\n");
681 write_all = true;
682 }
683 }
684
685
686 /* If any node in a cycle is read_all or write_all
687 they all are. */
688 w_info = (struct ipa_dfs_info *) node->aux;
689 w = w_info->next_cycle;
690 while (w && (!read_all || !write_all))
691 {
692 if (dump_file && (dump_flags & TDF_DETAILS))
693 fprintf (dump_file, " Visiting %s/%i\n",
694 cgraph_node_name (w), w->uid);
695 /* When function is overwrittable, we can not assume anything. */
696 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
697 read_write_all_from_decl (w, &read_all, &write_all);
698
699 for (e = w->callees; e; e = e->next_callee)
700 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
701 read_write_all_from_decl (e->callee, &read_all, &write_all);
702
703 for (ie = w->indirect_calls; ie; ie = ie->next_callee)
704 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
705 {
706 read_all = true;
707 if (dump_file && (dump_flags & TDF_DETAILS))
708 fprintf (dump_file, " indirect call -> read all\n");
709 if (!cgraph_edge_cannot_lead_to_return (ie)
710 && !(ie->indirect_info->ecf_flags & ECF_PURE))
711 {
712 write_all = true;
713 if (dump_file && (dump_flags & TDF_DETAILS))
714 fprintf (dump_file, " indirect call -> write all\n");
715 }
716 }
717
718 w_info = (struct ipa_dfs_info *) w->aux;
719 w = w_info->next_cycle;
720 }
721
722
723 /* Initialized the bitmaps for the reduced nodes */
724 if (read_all)
725 node_g->statics_read = all_module_statics;
726 else
727 {
728 node_g->statics_read = BITMAP_ALLOC (&local_info_obstack);
729 bitmap_copy (node_g->statics_read,
730 node_l->statics_read);
731 }
732 if (write_all)
733 node_g->statics_written = all_module_statics;
734 else
735 {
736 node_g->statics_written = BITMAP_ALLOC (&local_info_obstack);
737 bitmap_copy (node_g->statics_written,
738 node_l->statics_written);
739 }
740
741 propagate_bits (node_g, node);
742 w_info = (struct ipa_dfs_info *) node->aux;
743 w = w_info->next_cycle;
744 while (w && (!read_all || !write_all))
745 {
746 ipa_reference_vars_info_t w_ri =
747 get_reference_vars_info (w);
748 ipa_reference_local_vars_info_t w_l = &w_ri->local;
749 int flags = flags_from_decl_or_type (w->decl);
750
751 /* These global bitmaps are initialized from the local info
752 of all of the nodes in the region. However there is no
753 need to do any work if the bitmaps were set to
754 all_module_statics. */
755 if (!read_all && !(flags & ECF_CONST))
756 bitmap_ior_into (node_g->statics_read,
757 w_l->statics_read);
758 if (!write_all
759 && !(flags & ECF_PURE)
760 && !cgraph_node_cannot_return (w))
761 bitmap_ior_into (node_g->statics_written,
762 w_l->statics_written);
763 propagate_bits (node_g, w);
764 w_info = (struct ipa_dfs_info *) w->aux;
765 w = w_info->next_cycle;
766 }
767
768 /* All nodes within a cycle have the same global info bitmaps. */
769 node_info->global = *node_g;
770 w_info = (struct ipa_dfs_info *) node->aux;
771 w = w_info->next_cycle;
772 while (w)
773 {
774 ipa_reference_vars_info_t w_ri =
775 get_reference_vars_info (w);
776
777 w_ri->global = *node_g;
778
779 w_info = (struct ipa_dfs_info *) w->aux;
780 w = w_info->next_cycle;
781 }
782 }
783
784 if (dump_file)
785 {
786 for (i = 0; i < order_pos; i++ )
787 {
788 ipa_reference_vars_info_t node_info;
789 ipa_reference_global_vars_info_t node_g;
790 ipa_reference_local_vars_info_t node_l;
791 unsigned int index;
792 bitmap_iterator bi;
793 struct ipa_dfs_info * w_info;
794
795 node = order[i];
796 node_info = get_reference_vars_info (node);
797 node_g = &node_info->global;
798 node_l = &node_info->local;
799 fprintf (dump_file,
800 "\nFunction name:%s/%i:",
801 cgraph_node_name (node), node->uid);
802 fprintf (dump_file, "\n locals read: ");
803 if (node_l->statics_read)
804 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
805 0, index, bi)
806 {
807 fprintf (dump_file, "%s ",
808 get_static_name (index));
809 }
810 fprintf (dump_file, "\n locals written: ");
811 if (node_l->statics_written)
812 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
813 0, index, bi)
814 {
815 fprintf(dump_file, "%s ",
816 get_static_name (index));
817 }
818
819 w_info = (struct ipa_dfs_info *) node->aux;
820 w = w_info->next_cycle;
821 while (w)
822 {
823 ipa_reference_vars_info_t w_ri =
824 get_reference_vars_info (w);
825 ipa_reference_local_vars_info_t w_l = &w_ri->local;
826 fprintf (dump_file, "\n next cycle: %s/%i ",
827 cgraph_node_name (w), w->uid);
828 fprintf (dump_file, "\n locals read: ");
829 if (w_l->statics_read)
830 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
831 0, index, bi)
832 {
833 fprintf (dump_file, "%s ",
834 get_static_name (index));
835 }
836
837 fprintf (dump_file, "\n locals written: ");
838 if (w_l->statics_written)
839 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
840 0, index, bi)
841 {
842 fprintf (dump_file, "%s ",
843 get_static_name (index));
844 }
845
846 w_info = (struct ipa_dfs_info *) w->aux;
847 w = w_info->next_cycle;
848 }
849 fprintf (dump_file, "\n globals read: ");
850 if (node_g->statics_read == all_module_statics)
851 fprintf (dump_file, "ALL");
852 else
853 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
854 0, index, bi)
855 {
856 fprintf (dump_file, "%s ",
857 get_static_name (index));
858 }
859 fprintf (dump_file, "\n globals written: ");
860 if (node_g->statics_written == all_module_statics)
861 fprintf (dump_file, "ALL");
862 else
863 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
864 0, index, bi)
865 {
866 fprintf (dump_file, "%s ",
867 get_static_name (index));
868 }
869 }
870 }
871
872 /* Cleanup. */
873 for (node = cgraph_nodes; node; node = node->next)
874 {
875 ipa_reference_vars_info_t node_info;
876 ipa_reference_global_vars_info_t node_g;
877 ipa_reference_optimization_summary_t opt;
878
879 if (!node->analyzed)
880 continue;
881
882 node_info = get_reference_vars_info (node);
883 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE
884 || (flags_from_decl_or_type (node->decl) & ECF_LEAF))
885 {
886 node_g = &node_info->global;
887
888 opt = XCNEW (struct ipa_reference_optimization_summary_d);
889 set_reference_optimization_summary (node, opt);
890
891 /* Create the complimentary sets. */
892
893 if (bitmap_empty_p (node_g->statics_read))
894 opt->statics_not_read = all_module_statics;
895 else
896 {
897 opt->statics_not_read
898 = BITMAP_ALLOC (&optimization_summary_obstack);
899 if (node_g->statics_read != all_module_statics)
900 bitmap_and_compl (opt->statics_not_read,
901 all_module_statics,
902 node_g->statics_read);
903 }
904
905 if (bitmap_empty_p (node_g->statics_written))
906 opt->statics_not_written = all_module_statics;
907 else
908 {
909 opt->statics_not_written
910 = BITMAP_ALLOC (&optimization_summary_obstack);
911 if (node_g->statics_written != all_module_statics)
912 bitmap_and_compl (opt->statics_not_written,
913 all_module_statics,
914 node_g->statics_written);
915 }
916 }
917 if (node_info)
918 free (node_info);
919 if (node->aux)
920 {
921 free (node->aux);
922 node->aux = NULL;
923 }
924 }
925
926 free (order);
927
928 bitmap_obstack_release (&local_info_obstack);
929 VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector);
930 ipa_reference_vars_vector = NULL;
931 if (dump_file)
932 splay_tree_delete (reference_vars_to_consider);
933 reference_vars_to_consider = NULL;
934 return 0;
935 }
936
937 /* Return true if we need to write summary of NODE. */
938
939 static bool
940 write_node_summary_p (struct cgraph_node *node,
941 cgraph_node_set set,
942 varpool_node_set vset,
943 bitmap ltrans_statics)
944 {
945 ipa_reference_optimization_summary_t info;
946
947 /* See if we have (non-empty) info. */
948 if (!node->analyzed || node->global.inlined_to)
949 return false;
950 info = get_reference_optimization_summary (node);
951 if (!info || (bitmap_empty_p (info->statics_not_read)
952 && bitmap_empty_p (info->statics_not_written)))
953 return false;
954
955 /* See if we want to encode it.
956 Encode also referenced functions since constant folding might turn it into
957 a direct call.
958
959 In future we might also want to include summaries of functions references
960 by initializers of constant variables references in current unit. */
961 if (!reachable_from_this_partition_p (node, set)
962 && !referenced_from_this_partition_p (&node->ref_list, set, vset))
963 return false;
964
965 /* See if the info has non-empty intersections with vars we want to encode. */
966 if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
967 && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
968 return false;
969 return true;
970 }
971
972 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
973 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
974 or -1. When it is positive, just output -1 when
975 BITS&LTRANS_STATICS == BITS&LTRANS_STATICS. */
976
977 static void
978 stream_out_bitmap (struct lto_simple_output_block *ob,
979 bitmap bits, bitmap ltrans_statics,
980 int ltrans_statics_bitcount)
981 {
982 int count = 0;
983 unsigned int index;
984 bitmap_iterator bi;
985 if (bits == all_module_statics)
986 {
987 lto_output_sleb128_stream (ob->main_stream, -1);
988 return;
989 }
990 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
991 count ++;
992 if (count == ltrans_statics_bitcount)
993 {
994 lto_output_sleb128_stream (ob->main_stream, -1);
995 return;
996 }
997 lto_output_sleb128_stream (ob->main_stream, count);
998 if (!count)
999 return;
1000 EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
1001 {
1002 tree decl = (tree)splay_tree_lookup (reference_vars_to_consider, index)->value;
1003 lto_output_var_decl_index(ob->decl_state, ob->main_stream, decl);
1004 }
1005 }
1006
1007 /* Serialize the ipa info for lto. */
1008
1009 static void
1010 ipa_reference_write_optimization_summary (cgraph_node_set set,
1011 varpool_node_set vset)
1012 {
1013 struct cgraph_node *node;
1014 struct lto_simple_output_block *ob
1015 = lto_create_simple_output_block (LTO_section_ipa_reference);
1016 unsigned int count = 0;
1017 int ltrans_statics_bitcount = 0;
1018 lto_cgraph_encoder_t encoder = ob->decl_state->cgraph_node_encoder;
1019 lto_varpool_encoder_t varpool_encoder = ob->decl_state->varpool_node_encoder;
1020 bitmap ltrans_statics = BITMAP_ALLOC (NULL);
1021 int i;
1022
1023 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
1024
1025 /* See what variables we are interested in. */
1026 for (i = 0; i < lto_varpool_encoder_size (varpool_encoder); i++)
1027 {
1028 struct varpool_node *vnode = lto_varpool_encoder_deref (varpool_encoder, i);
1029 if (!vnode->externally_visible
1030 && vnode->analyzed
1031 && bitmap_bit_p (all_module_statics, DECL_UID (vnode->decl))
1032 && referenced_from_this_partition_p (&vnode->ref_list, set, vset))
1033 {
1034 tree decl = vnode->decl;
1035 bitmap_set_bit (ltrans_statics, DECL_UID (decl));
1036 splay_tree_insert (reference_vars_to_consider,
1037 DECL_UID (decl), (splay_tree_value)decl);
1038 ltrans_statics_bitcount ++;
1039 }
1040 }
1041
1042
1043 if (ltrans_statics_bitcount)
1044 for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1045 if (write_node_summary_p (lto_cgraph_encoder_deref (encoder, i),
1046 set, vset, ltrans_statics))
1047 count++;
1048
1049 lto_output_uleb128_stream (ob->main_stream, count);
1050 if (count)
1051 stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1052 -1);
1053
1054 /* Process all of the functions. */
1055 if (ltrans_statics_bitcount)
1056 for (i = 0; i < lto_cgraph_encoder_size (encoder); i++)
1057 {
1058 node = lto_cgraph_encoder_deref (encoder, i);
1059 if (write_node_summary_p (node, set, vset, ltrans_statics))
1060 {
1061 ipa_reference_optimization_summary_t info;
1062 int node_ref;
1063
1064 info = get_reference_optimization_summary (node);
1065 node_ref = lto_cgraph_encoder_encode (encoder, node);
1066 lto_output_uleb128_stream (ob->main_stream, node_ref);
1067
1068 stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1069 ltrans_statics_bitcount);
1070 stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1071 ltrans_statics_bitcount);
1072 }
1073 }
1074 BITMAP_FREE (ltrans_statics);
1075 lto_destroy_simple_output_block (ob);
1076 splay_tree_delete (reference_vars_to_consider);
1077 }
1078
1079 /* Deserialize the ipa info for lto. */
1080
1081 static void
1082 ipa_reference_read_optimization_summary (void)
1083 {
1084 struct lto_file_decl_data ** file_data_vec
1085 = lto_get_file_decl_data ();
1086 struct lto_file_decl_data * file_data;
1087 unsigned int j = 0;
1088 bitmap_obstack_initialize (&optimization_summary_obstack);
1089
1090 node_removal_hook_holder =
1091 cgraph_add_node_removal_hook (&remove_node_data, NULL);
1092 node_duplication_hook_holder =
1093 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
1094 all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1095
1096 while ((file_data = file_data_vec[j++]))
1097 {
1098 const char *data;
1099 size_t len;
1100 struct lto_input_block *ib
1101 = lto_create_simple_input_block (file_data,
1102 LTO_section_ipa_reference,
1103 &data, &len);
1104 if (ib)
1105 {
1106 unsigned int i;
1107 unsigned int f_count = lto_input_uleb128 (ib);
1108 int b_count;
1109 if (!f_count)
1110 continue;
1111 b_count = lto_input_sleb128 (ib);
1112 if (dump_file)
1113 fprintf (dump_file, "all module statics:");
1114 for (i = 0; i < (unsigned int)b_count; i++)
1115 {
1116 unsigned int var_index = lto_input_uleb128 (ib);
1117 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1118 var_index);
1119 bitmap_set_bit (all_module_statics, DECL_UID (v_decl));
1120 if (dump_file)
1121 fprintf (dump_file, " %s",
1122 lang_hooks.decl_printable_name (v_decl, 2));
1123 }
1124
1125 for (i = 0; i < f_count; i++)
1126 {
1127 unsigned int j, index;
1128 struct cgraph_node *node;
1129 ipa_reference_optimization_summary_t info;
1130 int v_count;
1131 lto_cgraph_encoder_t encoder;
1132
1133 index = lto_input_uleb128 (ib);
1134 encoder = file_data->cgraph_node_encoder;
1135 node = lto_cgraph_encoder_deref (encoder, index);
1136 info = XCNEW (struct ipa_reference_optimization_summary_d);
1137 set_reference_optimization_summary (node, info);
1138 info->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
1139 info->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
1140 if (dump_file)
1141 fprintf (dump_file,
1142 "\nFunction name:%s/%i:\n static not read:",
1143 cgraph_node_name (node), node->uid);
1144
1145 /* Set the statics not read. */
1146 v_count = lto_input_sleb128 (ib);
1147 if (v_count == -1)
1148 {
1149 info->statics_not_read = all_module_statics;
1150 if (dump_file)
1151 fprintf (dump_file, " all module statics");
1152 }
1153 else
1154 for (j = 0; j < (unsigned int)v_count; j++)
1155 {
1156 unsigned int var_index = lto_input_uleb128 (ib);
1157 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1158 var_index);
1159 bitmap_set_bit (info->statics_not_read, DECL_UID (v_decl));
1160 if (dump_file)
1161 fprintf (dump_file, " %s",
1162 lang_hooks.decl_printable_name (v_decl, 2));
1163 }
1164
1165 if (dump_file)
1166 fprintf (dump_file,
1167 "\n static not written:");
1168 /* Set the statics not written. */
1169 v_count = lto_input_sleb128 (ib);
1170 if (v_count == -1)
1171 {
1172 info->statics_not_written = all_module_statics;
1173 if (dump_file)
1174 fprintf (dump_file, " all module statics");
1175 }
1176 else
1177 for (j = 0; j < (unsigned int)v_count; j++)
1178 {
1179 unsigned int var_index = lto_input_uleb128 (ib);
1180 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1181 var_index);
1182 bitmap_set_bit (info->statics_not_written, DECL_UID (v_decl));
1183 if (dump_file)
1184 fprintf (dump_file, " %s",
1185 lang_hooks.decl_printable_name (v_decl, 2));
1186 }
1187 if (dump_file)
1188 fprintf (dump_file, "\n");
1189 }
1190
1191 lto_destroy_simple_input_block (file_data,
1192 LTO_section_ipa_reference,
1193 ib, data, len);
1194 }
1195 else
1196 /* Fatal error here. We do not want to support compiling ltrans units with
1197 different version of compiler or different flags than the WPA unit, so
1198 this should never happen. */
1199 fatal_error ("ipa reference summary is missing in ltrans unit");
1200 }
1201 }
1202
1203 static bool
1204 gate_reference (void)
1205 {
1206 return (flag_ipa_reference
1207 /* Don't bother doing anything if the program has errors. */
1208 && !seen_error ());
1209 }
1210
1211 struct ipa_opt_pass_d pass_ipa_reference =
1212 {
1213 {
1214 IPA_PASS,
1215 "static-var", /* name */
1216 gate_reference, /* gate */
1217 propagate, /* execute */
1218 NULL, /* sub */
1219 NULL, /* next */
1220 0, /* static_pass_number */
1221 TV_IPA_REFERENCE, /* tv_id */
1222 0, /* properties_required */
1223 0, /* properties_provided */
1224 0, /* properties_destroyed */
1225 0, /* todo_flags_start */
1226 0 /* todo_flags_finish */
1227 },
1228 NULL, /* generate_summary */
1229 NULL, /* write_summary */
1230 NULL, /* read_summary */
1231 ipa_reference_write_optimization_summary,/* write_optimization_summary */
1232 ipa_reference_read_optimization_summary,/* read_optimization_summary */
1233 NULL, /* stmt_fixup */
1234 0, /* TODOs */
1235 NULL, /* function_transform */
1236 NULL /* variable_transform */
1237 };