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