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>
6 This file is part of GCC.
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
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
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/>. */
22 /* This file gathers information about how variables whose scope is
23 confined to the compilation unit are used.
25 The transitive call site specific clobber effects are computed
26 for the variables whose scope is contained within this compilation
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
42 #include "coretypes.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"
52 #include "ipa-utils.h"
53 #include "ipa-reference.h"
59 #include "diagnostic.h"
60 #include "langhooks.h"
61 #include "lto-streamer.h"
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
);
70 /* The static variables defined within the compilation unit that are
71 loaded or stored directly by function that owns this structure. */
73 struct ipa_reference_local_vars_info_d
76 bitmap statics_written
;
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. */
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. */
92 struct ipa_reference_global_vars_info_d
95 bitmap statics_written
;
98 /* Information we save about every function after ipa-reference is completted. */
100 struct ipa_reference_optimization_summary_d
102 bitmap statics_not_read
;
103 bitmap statics_not_written
;
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
;
110 struct ipa_reference_vars_info_d
112 struct ipa_reference_local_vars_info_d local
;
113 struct ipa_reference_global_vars_info_d global
;
116 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
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
;
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
125 static bitmap all_module_statics
;
127 /* Obstack holding bitmaps of local analysis (live from analysis to
129 static bitmap_obstack local_info_obstack
;
130 /* Obstack holding global analysis live forever. */
131 static bitmap_obstack optimization_summary_obstack
;
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
;
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
;
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
)
149 if (!ipa_reference_vars_vector
150 || VEC_length (ipa_reference_vars_info_t
,
151 ipa_reference_vars_vector
) <= (unsigned int) node
->uid
)
153 return VEC_index (ipa_reference_vars_info_t
, ipa_reference_vars_vector
,
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
)
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
))
166 return VEC_index (ipa_reference_optimization_summary_t
, ipa_reference_opt_sum_vector
,
170 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
172 set_reference_vars_info (struct cgraph_node
*node
,
173 ipa_reference_vars_info_t info
)
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
,
184 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
186 set_reference_optimization_summary (struct cgraph_node
*node
,
187 ipa_reference_optimization_summary_t info
)
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
);
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. */
204 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
206 ipa_reference_optimization_summary_t info
;
208 info
= get_reference_optimization_summary (fn
);
210 return info
->statics_not_read
;
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. */
221 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
223 ipa_reference_optimization_summary_t info
;
225 info
= get_reference_optimization_summary (fn
);
227 return info
->statics_not_written
;
234 /* Add VAR to all_module_statics and the two
235 reference_vars_to_consider* sets. */
238 add_static_var (tree var
)
240 int uid
= DECL_UID (var
);
241 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
243 splay_tree_insert (reference_vars_to_consider
,
244 uid
, (splay_tree_value
)var
);
245 bitmap_set_bit (all_module_statics
, uid
);
248 /* Return true if the variable T is the right kind of static variable to
249 perform compilation unit scope escape analysis. */
252 is_proper_for_analysis (tree t
)
254 /* We handle only variables whose address is never taken. */
255 if (TREE_ADDRESSABLE (t
))
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
))
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
))
267 /* We cannot touch decls where the type needs constructing. */
268 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t
)))
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
)))
280 /* Lookup the tree node for the static variable that has UID and
281 convert the name to a string for debugging. */
284 get_static_name (int index
)
286 splay_tree_node stn
=
287 splay_tree_lookup (reference_vars_to_consider
, index
);
289 return lang_hooks
.decl_printable_name ((tree
)(stn
->value
), 2);
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
298 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
300 struct cgraph_edge
*e
;
301 for (e
= x
->callees
; e
; e
= e
->next_callee
)
303 struct cgraph_node
*y
= e
->callee
;
305 /* Only look into nodes we can propagate something. */
306 if (cgraph_function_body_availability (e
->callee
) > AVAIL_OVERWRITABLE
)
308 if (get_reference_vars_info (y
))
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
;
314 /* Calls in current cycle do not have global computed yet. */
315 if (!y_global
->statics_read
)
318 if (x_global
->statics_read
319 != all_module_statics
)
321 if (y_global
->statics_read
322 == all_module_statics
)
324 BITMAP_FREE (x_global
->statics_read
);
325 x_global
->statics_read
326 = all_module_statics
;
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
);
336 if (x_global
->statics_written
337 != all_module_statics
)
339 if (y_global
->statics_written
340 == all_module_statics
)
342 BITMAP_FREE (x_global
->statics_written
);
343 x_global
->statics_written
344 = all_module_statics
;
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
);
360 /* The init routine for analyzing global static variable usage. See
361 comments at top for description. */
365 static bool init_p
= false;
373 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
375 bitmap_obstack_initialize (&local_info_obstack
);
376 bitmap_obstack_initialize (&optimization_summary_obstack
);
377 all_module_statics
= BITMAP_ALLOC (&local_info_obstack
);
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
);
386 /* Set up the persistent info for FN. */
388 static ipa_reference_local_vars_info_t
389 init_function_info (struct cgraph_node
*fn
)
391 ipa_reference_vars_info_t info
392 = XCNEW (struct ipa_reference_vars_info_d
);
394 /* Add the info to the tree's annotation. */
395 set_reference_vars_info (fn
, info
);
397 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
398 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
404 /* This is the main routine for finding the reference patterns for
405 global variables within a function FN. */
408 analyze_function (struct cgraph_node
*fn
)
410 ipa_reference_local_vars_info_t local
;
414 struct cgraph_edge
*ie
;
416 local
= init_function_info (fn
);
417 /* Process indirect calls. All direct calles are handled at propagation
419 for (ie
= fn
->indirect_calls
; ie
; ie
= ie
->next_callee
)
420 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
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;
428 for (i
= 0; ipa_ref_list_reference_iterate (&fn
->ref_list
, i
, ref
); i
++)
430 if (ref
->refered_type
!= IPA_REF_VARPOOL
)
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
))
440 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
443 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
450 if ((flags_from_decl_or_type (fn
->decl
) & (ECF_NOTHROW
| ECF_NORETURN
))
451 == (ECF_NOTHROW
| ECF_NORETURN
))
453 local
->calls_write_all
= false;
454 bitmap_clear (local
->statics_written
);
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
);
465 copy_global_bitmap (bitmap src
)
470 dst
= BITMAP_ALLOC (&optimization_summary_obstack
);
471 bitmap_copy (dst
, src
);
476 /* Called when new clone is inserted to callgraph late. */
479 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
480 void *data ATTRIBUTE_UNUSED
)
482 ipa_reference_optimization_summary_t ginfo
;
483 ipa_reference_optimization_summary_t dst_ginfo
;
485 ginfo
= get_reference_optimization_summary (src
);
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
);
494 /* Called when node is removed. */
497 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
499 ipa_reference_optimization_summary_t ginfo
;
500 ginfo
= get_reference_optimization_summary (node
);
503 if (ginfo
->statics_not_read
504 && ginfo
->statics_not_read
!= all_module_statics
)
505 BITMAP_FREE (ginfo
->statics_not_read
);
507 if (ginfo
->statics_not_written
508 && ginfo
->statics_not_written
!= all_module_statics
)
509 BITMAP_FREE (ginfo
->statics_not_written
);
511 set_reference_optimization_summary (node
, NULL
);
515 /* Analyze each function in the cgraph to see which global or statics
516 are read or written. */
519 generate_summary (void)
521 struct cgraph_node
*node
;
527 bm_temp
= BITMAP_ALLOC (&local_info_obstack
);
529 /* Process all of the functions next. */
530 for (node
= cgraph_nodes
; node
; node
= node
->next
)
532 analyze_function (node
);
535 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
537 fprintf (dump_file
, "\nPromotable global:%s",
538 get_static_name (index
));
541 BITMAP_FREE(bm_temp
);
544 for (node
= cgraph_nodes
; node
; node
= node
->next
)
545 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
547 ipa_reference_local_vars_info_t l
;
551 l
= &get_reference_vars_info (node
)->local
;
553 "\nFunction name:%s/%i:",
554 cgraph_node_name (node
), node
->uid
);
555 fprintf (dump_file
, "\n locals read: ");
557 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
560 fprintf (dump_file
, "%s ",
561 get_static_name (index
));
563 fprintf (dump_file
, "\n locals written: ");
564 if (l
->statics_written
)
565 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
568 fprintf(dump_file
, "%s ",
569 get_static_name (index
));
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: ");
578 /* Set READ_ALL/WRITE_ALL based on DECL flags. */
581 read_write_all_from_decl (tree decl
, bool * read_all
, bool * write_all
)
583 int flags
= flags_from_decl_or_type (decl
);
584 if (flags
& ECF_CONST
)
586 else if (flags
& ECF_PURE
)
590 /* TODO: To be able to produce sane results, we should also handle
591 common builtins, in particular throw. */
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
))
601 /* Produce the global information by preforming a transitive closure
602 on the local information that was produced by ipa_analyze_function */
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
);
615 dump_cgraph (dump_file
);
617 ipa_discover_readonly_nonaddressable_vars ();
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
);
626 ipa_utils_print_order(dump_file
, "reduced", order
, order_pos
);
628 for (i
= 0; i
< order_pos
; i
++ )
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
;
637 struct ipa_dfs_info
* w_info
;
640 node_info
= get_reference_vars_info (node
);
643 dump_cgraph_node (stderr
, node
);
644 dump_cgraph (stderr
);
648 node_l
= &node_info
->local
;
649 node_g
= &node_info
->global
;
651 read_all
= node_l
->calls_read_all
;
652 write_all
= node_l
->calls_write_all
;
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
);
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
);
663 /* If any node in a cycle is calls_read_all or calls_write_all
665 w_info
= (struct ipa_dfs_info
*) node
->aux
;
666 w
= w_info
->next_cycle
;
669 ipa_reference_local_vars_info_t w_l
=
670 &get_reference_vars_info (w
)->local
;
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
);
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
);
680 read_all
|= w_l
->calls_read_all
;
681 write_all
|= w_l
->calls_write_all
;
683 w_info
= (struct ipa_dfs_info
*) w
->aux
;
684 w
= w_info
->next_cycle
;
688 /* Initialized the bitmaps for the reduced nodes */
690 node_g
->statics_read
= all_module_statics
;
693 node_g
->statics_read
= BITMAP_ALLOC (&local_info_obstack
);
694 bitmap_copy (node_g
->statics_read
,
695 node_l
->statics_read
);
698 node_g
->statics_written
= all_module_statics
;
701 node_g
->statics_written
= BITMAP_ALLOC (&local_info_obstack
);
702 bitmap_copy (node_g
->statics_written
,
703 node_l
->statics_written
);
706 propagate_bits (node_g
, node
);
707 w_info
= (struct ipa_dfs_info
*) node
->aux
;
708 w
= w_info
->next_cycle
;
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
;
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. */
720 bitmap_ior_into (node_g
->statics_read
,
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
;
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
;
736 ipa_reference_vars_info_t w_ri
=
737 get_reference_vars_info (w
);
739 w_ri
->global
= *node_g
;
741 w_info
= (struct ipa_dfs_info
*) w
->aux
;
742 w
= w_info
->next_cycle
;
748 for (i
= 0; i
< order_pos
; i
++ )
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
;
755 struct ipa_dfs_info
* w_info
;
758 node_info
= get_reference_vars_info (node
);
759 node_g
= &node_info
->global
;
760 node_l
= &node_info
->local
;
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
,
769 fprintf (dump_file
, "%s ",
770 get_static_name (index
));
772 fprintf (dump_file
, "\n locals written: ");
773 if (node_l
->statics_written
)
774 EXECUTE_IF_SET_IN_BITMAP (node_l
->statics_written
,
777 fprintf(dump_file
, "%s ",
778 get_static_name (index
));
781 w_info
= (struct ipa_dfs_info
*) node
->aux
;
782 w
= w_info
->next_cycle
;
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
,
795 fprintf (dump_file
, "%s ",
796 get_static_name (index
));
799 fprintf (dump_file
, "\n locals written: ");
800 if (w_l
->statics_written
)
801 EXECUTE_IF_SET_IN_BITMAP (w_l
->statics_written
,
804 fprintf (dump_file
, "%s ",
805 get_static_name (index
));
808 w_info
= (struct ipa_dfs_info
*) w
->aux
;
809 w
= w_info
->next_cycle
;
811 fprintf (dump_file
, "\n globals read: ");
812 if (node_g
->statics_read
== all_module_statics
)
813 fprintf (dump_file
, "ALL");
815 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_read
,
818 fprintf (dump_file
, "%s ",
819 get_static_name (index
));
821 fprintf (dump_file
, "\n globals written: ");
822 if (node_g
->statics_written
== all_module_statics
)
823 fprintf (dump_file
, "ALL");
825 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_written
,
828 fprintf (dump_file
, "%s ",
829 get_static_name (index
));
835 for (node
= cgraph_nodes
; node
; node
= node
->next
)
837 ipa_reference_vars_info_t node_info
;
838 ipa_reference_global_vars_info_t node_g
;
839 ipa_reference_optimization_summary_t opt
;
844 node_info
= get_reference_vars_info (node
);
845 if (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
)
847 node_g
= &node_info
->global
;
849 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
850 set_reference_optimization_summary (node
, opt
);
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
);
856 if (node_g
->statics_read
!= all_module_statics
)
857 bitmap_and_compl (opt
->statics_not_read
,
859 node_g
->statics_read
);
861 if (node_g
->statics_written
862 != all_module_statics
)
863 bitmap_and_compl (opt
->statics_not_written
,
865 node_g
->statics_written
);
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
;
882 splay_tree_delete (reference_vars_to_consider
);
883 reference_vars_to_consider
= NULL
;
884 all_module_statics
= NULL
;
888 /* Return true if we need to write summary of NODE. */
891 write_node_summary_p (struct cgraph_node
*node
,
893 varpool_node_set vset
,
894 bitmap ltrans_statics
)
896 ipa_reference_optimization_summary_t info
;
898 /* See if we have (non-empty) info. */
899 if (!node
->analyzed
|| node
->global
.inlined_to
)
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
)))
906 /* See if we want to encode it.
907 Encode also referenced functions since constant folding might turn it into
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
))
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
))
923 /* Stream out BITS<RANS_STATICS as list of decls to OB. */
926 stream_out_bitmap (struct lto_simple_output_block
*ob
,
927 bitmap bits
, bitmap ltrans_statics
)
929 unsigned int count
= 0;
932 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
934 lto_output_uleb128_stream (ob
->main_stream
, count
);
937 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
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
);
944 /* Serialize the ipa info for lto. */
947 ipa_reference_write_optimization_summary (cgraph_node_set set
,
948 varpool_node_set vset
)
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
);
958 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
960 /* See what variables we are interested in. */
961 for (vnode
= varpool_nodes
; vnode
; vnode
= vnode
->next
)
962 if (!vnode
->externally_visible
964 && is_proper_for_analysis (vnode
->decl
)
965 && referenced_from_this_partition_p (&vnode
->ref_list
, set
, vset
))
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
);
973 for (node
= cgraph_nodes
; node
; node
= node
->next
)
974 if (write_node_summary_p (node
, set
, vset
, ltrans_statics
))
977 lto_output_uleb128_stream (ob
->main_stream
, count
);
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
))
983 ipa_reference_optimization_summary_t info
;
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
);
990 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
);
991 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
);
993 BITMAP_FREE (ltrans_statics
);
994 lto_destroy_simple_output_block (ob
);
995 splay_tree_delete (reference_vars_to_consider
);
998 /* Deserialize the ipa info for lto. */
1001 ipa_reference_read_optimization_summary (void)
1003 struct lto_file_decl_data
** file_data_vec
1004 = lto_get_file_decl_data ();
1005 struct lto_file_decl_data
* file_data
;
1007 bitmap_obstack_initialize (&optimization_summary_obstack
);
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
);
1014 while ((file_data
= file_data_vec
[j
++]))
1018 struct lto_input_block
*ib
1019 = lto_create_simple_input_block (file_data
,
1020 LTO_section_ipa_reference
,
1025 unsigned int f_count
= lto_input_uleb128 (ib
);
1027 for (i
= 0; i
< f_count
; i
++)
1029 unsigned int j
, index
;
1030 struct cgraph_node
*node
;
1031 ipa_reference_optimization_summary_t info
;
1033 lto_cgraph_encoder_t encoder
;
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
);
1044 "\nFunction name:%s/%i:\n static not read:",
1045 cgraph_node_name (node
), node
->uid
);
1047 /* Set the statics not read. */
1048 v_count
= lto_input_uleb128 (ib
);
1049 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1051 unsigned int var_index
= lto_input_uleb128 (ib
);
1052 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1054 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1056 fprintf (dump_file
, " %s",
1057 lang_hooks
.decl_printable_name (v_decl
, 2));
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
++)
1067 unsigned int var_index
= lto_input_uleb128 (ib
);
1068 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1070 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1072 fprintf (dump_file
, " %s",
1073 lang_hooks
.decl_printable_name (v_decl
, 2));
1076 fprintf (dump_file
, "\n");
1079 lto_destroy_simple_input_block (file_data
,
1080 LTO_section_ipa_reference
,
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");
1092 gate_reference (void)
1094 return (flag_ipa_reference
1095 /* Don't bother doing anything if the program has errors. */
1099 struct ipa_opt_pass_d pass_ipa_reference
=
1103 "static-var", /* name */
1104 gate_reference
, /* gate */
1105 propagate
, /* execute */
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 */
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 */
1123 NULL
, /* function_transform */
1124 NULL
/* variable_transform */