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 "data-streamer.h"
62 #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
;
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. */
84 struct ipa_reference_global_vars_info_d
87 bitmap statics_written
;
90 /* Information we save about every function after ipa-reference is completed. */
92 struct ipa_reference_optimization_summary_d
94 bitmap statics_not_read
;
95 bitmap statics_not_written
;
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
;
102 struct ipa_reference_vars_info_d
104 struct ipa_reference_local_vars_info_d local
;
105 struct ipa_reference_global_vars_info_d global
;
108 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
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
;
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
117 static bitmap all_module_statics
;
119 /* Obstack holding bitmaps of local analysis (live from analysis to
121 static bitmap_obstack local_info_obstack
;
122 /* Obstack holding global analysis live forever. */
123 static bitmap_obstack optimization_summary_obstack
;
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
;
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
;
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
)
141 if (!ipa_reference_vars_vector
142 || VEC_length (ipa_reference_vars_info_t
,
143 ipa_reference_vars_vector
) <= (unsigned int) node
->uid
)
145 return VEC_index (ipa_reference_vars_info_t
, ipa_reference_vars_vector
,
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
)
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
))
158 return VEC_index (ipa_reference_optimization_summary_t
, ipa_reference_opt_sum_vector
,
162 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
164 set_reference_vars_info (struct cgraph_node
*node
,
165 ipa_reference_vars_info_t info
)
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
,
176 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
178 set_reference_optimization_summary (struct cgraph_node
*node
,
179 ipa_reference_optimization_summary_t info
)
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
);
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. */
196 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
198 ipa_reference_optimization_summary_t info
;
200 info
= get_reference_optimization_summary (cgraph_function_node (fn
, NULL
));
202 return info
->statics_not_read
;
203 else if (flags_from_decl_or_type (fn
->symbol
.decl
) & ECF_LEAF
)
204 return all_module_statics
;
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. */
215 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
217 ipa_reference_optimization_summary_t info
;
219 info
= get_reference_optimization_summary (fn
);
221 return info
->statics_not_written
;
222 else if (flags_from_decl_or_type (fn
->symbol
.decl
) & ECF_LEAF
)
223 return all_module_statics
;
230 /* Add VAR to all_module_statics and the two
231 reference_vars_to_consider* sets. */
234 add_static_var (tree var
)
236 int uid
= DECL_UID (var
);
237 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
239 splay_tree_insert (reference_vars_to_consider
,
240 uid
, (splay_tree_value
)var
);
241 bitmap_set_bit (all_module_statics
, uid
);
244 /* Return true if the variable T is the right kind of static variable to
245 perform compilation unit scope escape analysis. */
248 is_proper_for_analysis (tree t
)
250 /* If the variable has the "used" attribute, treat it as if it had a
251 been touched by the devil. */
252 if (DECL_PRESERVE_P (t
))
255 /* Do not want to do anything with volatile except mark any
256 function that uses one to be not const or pure. */
257 if (TREE_THIS_VOLATILE (t
))
260 /* We do not need to analyze readonly vars, we already know they do not
262 if (TREE_READONLY (t
))
265 /* This is a variable we care about. Check if we have seen it
266 before, and if not add it the set of variables we care about. */
267 if (all_module_statics
268 && !bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
274 /* Lookup the tree node for the static variable that has UID and
275 convert the name to a string for debugging. */
278 get_static_name (int index
)
280 splay_tree_node stn
=
281 splay_tree_lookup (reference_vars_to_consider
, index
);
283 return lang_hooks
.decl_printable_name ((tree
)(stn
->value
), 2);
287 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
288 bit vector. There are several cases to check to avoid the sparse
292 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
294 struct cgraph_edge
*e
;
295 for (e
= x
->callees
; e
; e
= e
->next_callee
)
297 enum availability avail
;
298 struct cgraph_node
*y
= cgraph_function_node (e
->callee
, &avail
);
302 /* Only look into nodes we can propagate something. */
303 if (avail
> AVAIL_OVERWRITABLE
304 || (avail
== AVAIL_OVERWRITABLE
305 && (flags_from_decl_or_type (y
->symbol
.decl
) & ECF_LEAF
)))
307 int flags
= flags_from_decl_or_type (y
->symbol
.decl
);
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 function is declared const, it reads no memory even if it
319 seems so to local analysis. */
320 if (flags
& ECF_CONST
)
323 if (x_global
->statics_read
324 != all_module_statics
)
326 if (y_global
->statics_read
327 == all_module_statics
)
329 BITMAP_FREE (x_global
->statics_read
);
330 x_global
->statics_read
331 = all_module_statics
;
333 /* Skip bitmaps that are pointer equal to node's bitmap
334 (no reason to spin within the cycle). */
335 else if (x_global
->statics_read
336 != y_global
->statics_read
)
337 bitmap_ior_into (x_global
->statics_read
,
338 y_global
->statics_read
);
341 /* If function is declared pure, it has no stores even if it
342 seems so to local analysis; If we can not return from here,
343 we can safely ignore the call. */
344 if ((flags
& ECF_PURE
)
345 || cgraph_edge_cannot_lead_to_return (e
))
348 if (x_global
->statics_written
349 != all_module_statics
)
351 if (y_global
->statics_written
352 == all_module_statics
)
354 BITMAP_FREE (x_global
->statics_written
);
355 x_global
->statics_written
356 = all_module_statics
;
358 /* Skip bitmaps that are pointer equal to node's bitmap
359 (no reason to spin within the cycle). */
360 else if (x_global
->statics_written
361 != y_global
->statics_written
)
362 bitmap_ior_into (x_global
->statics_written
,
363 y_global
->statics_written
);
372 /* The init routine for analyzing global static variable usage. See
373 comments at top for description. */
377 static bool init_p
= false;
385 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
387 bitmap_obstack_initialize (&local_info_obstack
);
388 bitmap_obstack_initialize (&optimization_summary_obstack
);
389 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
391 node_removal_hook_holder
=
392 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
393 node_duplication_hook_holder
=
394 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
398 /* Set up the persistent info for FN. */
400 static ipa_reference_local_vars_info_t
401 init_function_info (struct cgraph_node
*fn
)
403 ipa_reference_vars_info_t info
404 = XCNEW (struct ipa_reference_vars_info_d
);
406 /* Add the info to the tree's annotation. */
407 set_reference_vars_info (fn
, info
);
409 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
410 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
416 /* This is the main routine for finding the reference patterns for
417 global variables within a function FN. */
420 analyze_function (struct cgraph_node
*fn
)
422 ipa_reference_local_vars_info_t local
;
427 local
= init_function_info (fn
);
428 for (i
= 0; ipa_ref_list_reference_iterate (&fn
->symbol
.ref_list
, i
, ref
); i
++)
430 if (!symtab_variable_p (ref
->referred
))
432 var
= ipa_ref_varpool_node (ref
)->symbol
.decl
;
433 if (!is_proper_for_analysis (var
))
438 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
441 if (ipa_ref_cannot_lead_to_return (ref
))
443 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
450 if (cgraph_node_cannot_return (fn
))
451 bitmap_clear (local
->statics_written
);
455 copy_global_bitmap (bitmap src
)
460 if (src
== all_module_statics
)
461 return all_module_statics
;
462 dst
= BITMAP_ALLOC (&optimization_summary_obstack
);
463 bitmap_copy (dst
, src
);
468 /* Called when new clone is inserted to callgraph late. */
471 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
472 void *data ATTRIBUTE_UNUSED
)
474 ipa_reference_optimization_summary_t ginfo
;
475 ipa_reference_optimization_summary_t dst_ginfo
;
477 ginfo
= get_reference_optimization_summary (src
);
480 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
481 set_reference_optimization_summary (dst
, dst_ginfo
);
482 dst_ginfo
->statics_not_read
= copy_global_bitmap (ginfo
->statics_not_read
);
483 dst_ginfo
->statics_not_written
= copy_global_bitmap (ginfo
->statics_not_written
);
486 /* Called when node is removed. */
489 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
491 ipa_reference_optimization_summary_t ginfo
;
492 ginfo
= get_reference_optimization_summary (node
);
495 if (ginfo
->statics_not_read
496 && ginfo
->statics_not_read
!= all_module_statics
)
497 BITMAP_FREE (ginfo
->statics_not_read
);
499 if (ginfo
->statics_not_written
500 && ginfo
->statics_not_written
!= all_module_statics
)
501 BITMAP_FREE (ginfo
->statics_not_written
);
503 set_reference_optimization_summary (node
, NULL
);
507 /* Analyze each function in the cgraph to see which global or statics
508 are read or written. */
511 generate_summary (void)
513 struct cgraph_node
*node
;
519 bm_temp
= BITMAP_ALLOC (&local_info_obstack
);
521 /* Process all of the functions next. */
522 FOR_EACH_DEFINED_FUNCTION (node
)
523 analyze_function (node
);
526 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
528 fprintf (dump_file
, "\nPromotable global:%s",
529 get_static_name (index
));
532 BITMAP_FREE(bm_temp
);
535 FOR_EACH_DEFINED_FUNCTION (node
)
536 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
538 ipa_reference_local_vars_info_t l
;
542 l
= &get_reference_vars_info (node
)->local
;
544 "\nFunction name:%s/%i:",
545 cgraph_node_asm_name (node
), node
->symbol
.order
);
546 fprintf (dump_file
, "\n locals read: ");
548 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
551 fprintf (dump_file
, "%s ",
552 get_static_name (index
));
554 fprintf (dump_file
, "\n locals written: ");
555 if (l
->statics_written
)
556 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
559 fprintf(dump_file
, "%s ",
560 get_static_name (index
));
565 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
568 read_write_all_from_decl (struct cgraph_node
*node
, bool * read_all
,
571 tree decl
= node
->symbol
.decl
;
572 int flags
= flags_from_decl_or_type (decl
);
573 if ((flags
& ECF_LEAF
)
574 && cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
576 else if (flags
& ECF_CONST
)
578 else if ((flags
& ECF_PURE
)
579 || cgraph_node_cannot_return (node
))
582 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
583 fprintf (dump_file
, " %s/%i -> read all\n",
584 cgraph_node_asm_name (node
), node
->symbol
.order
);
588 /* TODO: To be able to produce sane results, we should also handle
589 common builtins, in particular throw. */
592 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
593 fprintf (dump_file
, " %s/%i -> read all, write all\n",
594 cgraph_node_asm_name (node
), node
->symbol
.order
);
598 /* Produce the global information by preforming a transitive closure
599 on the local information that was produced by ipa_analyze_function */
604 struct cgraph_node
*node
;
605 struct varpool_node
*vnode
;
606 struct cgraph_node
*w
;
607 struct cgraph_node
**order
=
608 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
613 dump_cgraph (dump_file
);
615 ipa_discover_readonly_nonaddressable_vars ();
618 /* Now we know what vars are realy statics; prune out those that aren't. */
619 FOR_EACH_VARIABLE (vnode
)
620 if (vnode
->symbol
.externally_visible
621 || TREE_ADDRESSABLE (vnode
->symbol
.decl
)
622 || TREE_READONLY (vnode
->symbol
.decl
)
623 || !is_proper_for_analysis (vnode
->symbol
.decl
)
625 bitmap_clear_bit (all_module_statics
, DECL_UID (vnode
->symbol
.decl
));
627 /* Forget info we collected "just for fun" on variables that turned out to be
629 FOR_EACH_DEFINED_FUNCTION (node
)
631 ipa_reference_local_vars_info_t node_l
;
633 node_l
= &get_reference_vars_info (node
)->local
;
634 if (node_l
->statics_read
!= all_module_statics
)
635 bitmap_and_into (node_l
->statics_read
, all_module_statics
);
636 if (node_l
->statics_written
!= all_module_statics
)
637 bitmap_and_into (node_l
->statics_written
, all_module_statics
);
640 /* Propagate the local information thru the call graph to produce
641 the global information. All the nodes within a cycle will have
642 the same info so we collapse cycles first. Then we can do the
643 propagation in one pass from the leaves to the roots. */
644 order_pos
= ipa_reduced_postorder (order
, true, true, NULL
);
646 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
648 for (i
= 0; i
< order_pos
; i
++ )
650 ipa_reference_vars_info_t node_info
;
651 ipa_reference_global_vars_info_t node_g
;
652 ipa_reference_local_vars_info_t node_l
;
653 struct cgraph_edge
*e
, *ie
;
657 struct ipa_dfs_info
* w_info
;
662 node_info
= get_reference_vars_info (node
);
663 gcc_assert (node_info
);
666 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
667 fprintf (dump_file
, "Starting cycle with %s/%i\n",
668 cgraph_node_asm_name (node
), node
->symbol
.order
);
670 node_l
= &node_info
->local
;
671 node_g
= &node_info
->global
;
676 /* When function is overwritable, we can not assume anything. */
677 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
678 read_write_all_from_decl (node
, &read_all
, &write_all
);
680 for (e
= node
->callees
; e
; e
= e
->next_callee
)
682 enum availability avail
;
683 struct cgraph_node
*callee
= cgraph_function_node (e
->callee
, &avail
);
684 if (!callee
|| avail
<= AVAIL_OVERWRITABLE
)
685 read_write_all_from_decl (callee
, &read_all
, &write_all
);
688 for (ie
= node
->indirect_calls
; ie
; ie
= ie
->next_callee
)
689 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
692 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
693 fprintf (dump_file
, " indirect call -> read all\n");
694 if (!cgraph_edge_cannot_lead_to_return (ie
)
695 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
697 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
698 fprintf (dump_file
, " indirect call -> write all\n");
704 /* If any node in a cycle is read_all or write_all
706 w_info
= (struct ipa_dfs_info
*) node
->symbol
.aux
;
707 w
= w_info
->next_cycle
;
708 while (w
&& (!read_all
|| !write_all
))
710 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
711 fprintf (dump_file
, " Visiting %s/%i\n",
712 cgraph_node_asm_name (w
), w
->symbol
.order
);
713 /* When function is overwritable, we can not assume anything. */
714 if (cgraph_function_body_availability (w
) <= AVAIL_OVERWRITABLE
)
715 read_write_all_from_decl (w
, &read_all
, &write_all
);
717 for (e
= w
->callees
; e
; e
= e
->next_callee
)
719 enum availability avail
;
720 struct cgraph_node
*callee
= cgraph_function_node (e
->callee
, &avail
);
722 if (avail
<= AVAIL_OVERWRITABLE
)
723 read_write_all_from_decl (callee
, &read_all
, &write_all
);
726 for (ie
= w
->indirect_calls
; ie
; ie
= ie
->next_callee
)
727 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
730 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
731 fprintf (dump_file
, " indirect call -> read all\n");
732 if (!cgraph_edge_cannot_lead_to_return (ie
)
733 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
736 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
737 fprintf (dump_file
, " indirect call -> write all\n");
741 w_info
= (struct ipa_dfs_info
*) w
->symbol
.aux
;
742 w
= w_info
->next_cycle
;
746 /* Initialized the bitmaps for the reduced nodes */
748 node_g
->statics_read
= all_module_statics
;
751 node_g
->statics_read
= BITMAP_ALLOC (&local_info_obstack
);
752 bitmap_copy (node_g
->statics_read
,
753 node_l
->statics_read
);
756 node_g
->statics_written
= all_module_statics
;
759 node_g
->statics_written
= BITMAP_ALLOC (&local_info_obstack
);
760 bitmap_copy (node_g
->statics_written
,
761 node_l
->statics_written
);
764 propagate_bits (node_g
, node
);
765 w_info
= (struct ipa_dfs_info
*) node
->symbol
.aux
;
766 w
= w_info
->next_cycle
;
767 while (w
&& (!read_all
|| !write_all
))
769 ipa_reference_vars_info_t w_ri
=
770 get_reference_vars_info (w
);
771 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
772 int flags
= flags_from_decl_or_type (w
->symbol
.decl
);
774 /* These global bitmaps are initialized from the local info
775 of all of the nodes in the region. However there is no
776 need to do any work if the bitmaps were set to
777 all_module_statics. */
778 if (!read_all
&& !(flags
& ECF_CONST
))
779 bitmap_ior_into (node_g
->statics_read
,
782 && !(flags
& ECF_PURE
)
783 && !cgraph_node_cannot_return (w
))
784 bitmap_ior_into (node_g
->statics_written
,
785 w_l
->statics_written
);
786 propagate_bits (node_g
, w
);
787 w_info
= (struct ipa_dfs_info
*) w
->symbol
.aux
;
788 w
= w_info
->next_cycle
;
791 /* All nodes within a cycle have the same global info bitmaps. */
792 node_info
->global
= *node_g
;
793 w_info
= (struct ipa_dfs_info
*) node
->symbol
.aux
;
794 w
= w_info
->next_cycle
;
797 ipa_reference_vars_info_t w_ri
=
798 get_reference_vars_info (w
);
800 w_ri
->global
= *node_g
;
802 w_info
= (struct ipa_dfs_info
*) w
->symbol
.aux
;
803 w
= w_info
->next_cycle
;
809 for (i
= 0; i
< order_pos
; i
++ )
811 ipa_reference_vars_info_t node_info
;
812 ipa_reference_global_vars_info_t node_g
;
813 ipa_reference_local_vars_info_t node_l
;
816 struct ipa_dfs_info
* w_info
;
821 node_info
= get_reference_vars_info (node
);
822 node_g
= &node_info
->global
;
823 node_l
= &node_info
->local
;
825 "\nFunction name:%s/%i:",
826 cgraph_node_asm_name (node
), node
->symbol
.order
);
827 fprintf (dump_file
, "\n locals read: ");
828 if (node_l
->statics_read
)
829 EXECUTE_IF_SET_IN_BITMAP (node_l
->statics_read
,
832 fprintf (dump_file
, "%s ",
833 get_static_name (index
));
835 fprintf (dump_file
, "\n locals written: ");
836 if (node_l
->statics_written
)
837 EXECUTE_IF_SET_IN_BITMAP (node_l
->statics_written
,
840 fprintf(dump_file
, "%s ",
841 get_static_name (index
));
844 w_info
= (struct ipa_dfs_info
*) node
->symbol
.aux
;
845 w
= w_info
->next_cycle
;
848 ipa_reference_vars_info_t w_ri
=
849 get_reference_vars_info (w
);
850 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
851 fprintf (dump_file
, "\n next cycle: %s/%i ",
852 cgraph_node_asm_name (w
), w
->symbol
.order
);
853 fprintf (dump_file
, "\n locals read: ");
854 if (w_l
->statics_read
)
855 EXECUTE_IF_SET_IN_BITMAP (w_l
->statics_read
,
858 fprintf (dump_file
, "%s ",
859 get_static_name (index
));
862 fprintf (dump_file
, "\n locals written: ");
863 if (w_l
->statics_written
)
864 EXECUTE_IF_SET_IN_BITMAP (w_l
->statics_written
,
867 fprintf (dump_file
, "%s ",
868 get_static_name (index
));
871 w_info
= (struct ipa_dfs_info
*) w
->symbol
.aux
;
872 w
= w_info
->next_cycle
;
874 fprintf (dump_file
, "\n globals read: ");
875 if (node_g
->statics_read
== all_module_statics
)
876 fprintf (dump_file
, "ALL");
878 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_read
,
881 fprintf (dump_file
, "%s ",
882 get_static_name (index
));
884 fprintf (dump_file
, "\n globals written: ");
885 if (node_g
->statics_written
== all_module_statics
)
886 fprintf (dump_file
, "ALL");
888 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_written
,
891 fprintf (dump_file
, "%s ",
892 get_static_name (index
));
898 FOR_EACH_DEFINED_FUNCTION (node
)
900 ipa_reference_vars_info_t node_info
;
901 ipa_reference_global_vars_info_t node_g
;
902 ipa_reference_optimization_summary_t opt
;
907 node_info
= get_reference_vars_info (node
);
908 if (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
909 || (flags_from_decl_or_type (node
->symbol
.decl
) & ECF_LEAF
))
911 node_g
= &node_info
->global
;
913 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
914 set_reference_optimization_summary (node
, opt
);
916 /* Create the complimentary sets. */
918 if (bitmap_empty_p (node_g
->statics_read
))
919 opt
->statics_not_read
= all_module_statics
;
922 opt
->statics_not_read
923 = BITMAP_ALLOC (&optimization_summary_obstack
);
924 if (node_g
->statics_read
!= all_module_statics
)
925 bitmap_and_compl (opt
->statics_not_read
,
927 node_g
->statics_read
);
930 if (bitmap_empty_p (node_g
->statics_written
))
931 opt
->statics_not_written
= all_module_statics
;
934 opt
->statics_not_written
935 = BITMAP_ALLOC (&optimization_summary_obstack
);
936 if (node_g
->statics_written
!= all_module_statics
)
937 bitmap_and_compl (opt
->statics_not_written
,
939 node_g
->statics_written
);
945 ipa_free_postorder_info ();
948 bitmap_obstack_release (&local_info_obstack
);
949 VEC_free (ipa_reference_vars_info_t
, heap
, ipa_reference_vars_vector
);
950 ipa_reference_vars_vector
= NULL
;
952 splay_tree_delete (reference_vars_to_consider
);
953 reference_vars_to_consider
= NULL
;
957 /* Return true if we need to write summary of NODE. */
960 write_node_summary_p (struct cgraph_node
*node
,
962 varpool_node_set vset
,
963 bitmap ltrans_statics
)
965 ipa_reference_optimization_summary_t info
;
967 /* See if we have (non-empty) info. */
968 if (!node
->analyzed
|| node
->global
.inlined_to
)
970 info
= get_reference_optimization_summary (node
);
971 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
972 && bitmap_empty_p (info
->statics_not_written
)))
975 /* See if we want to encode it.
976 Encode also referenced functions since constant folding might turn it into
979 In future we might also want to include summaries of functions references
980 by initializers of constant variables references in current unit. */
981 if (!reachable_from_this_partition_p (node
, set
)
982 && !referenced_from_this_partition_p (&node
->symbol
.ref_list
, set
, vset
))
985 /* See if the info has non-empty intersections with vars we want to encode. */
986 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
987 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
992 /* Stream out BITS<RANS_STATICS as list of decls to OB.
993 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
994 or -1. When it is positive, just output -1 when
995 BITS<RANS_STATICS == BITS<RANS_STATICS. */
998 stream_out_bitmap (struct lto_simple_output_block
*ob
,
999 bitmap bits
, bitmap ltrans_statics
,
1000 int ltrans_statics_bitcount
)
1005 if (bits
== all_module_statics
)
1007 streamer_write_hwi_stream (ob
->main_stream
, -1);
1010 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1012 if (count
== ltrans_statics_bitcount
)
1014 streamer_write_hwi_stream (ob
->main_stream
, -1);
1017 streamer_write_hwi_stream (ob
->main_stream
, count
);
1020 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1022 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
1023 lto_output_var_decl_index(ob
->decl_state
, ob
->main_stream
, decl
);
1027 /* Serialize the ipa info for lto. */
1030 ipa_reference_write_optimization_summary (cgraph_node_set set
,
1031 varpool_node_set vset
)
1033 struct cgraph_node
*node
;
1034 struct lto_simple_output_block
*ob
1035 = lto_create_simple_output_block (LTO_section_ipa_reference
);
1036 unsigned int count
= 0;
1037 int ltrans_statics_bitcount
= 0;
1038 lto_cgraph_encoder_t encoder
= ob
->decl_state
->cgraph_node_encoder
;
1039 lto_varpool_encoder_t varpool_encoder
= ob
->decl_state
->varpool_node_encoder
;
1040 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
1043 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
1045 /* See what variables we are interested in. */
1046 for (i
= 0; i
< lto_varpool_encoder_size (varpool_encoder
); i
++)
1048 struct varpool_node
*vnode
= lto_varpool_encoder_deref (varpool_encoder
, i
);
1049 if (bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->symbol
.decl
))
1050 && referenced_from_this_partition_p (&vnode
->symbol
.ref_list
, set
, vset
))
1052 tree decl
= vnode
->symbol
.decl
;
1053 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
1054 splay_tree_insert (reference_vars_to_consider
,
1055 DECL_UID (decl
), (splay_tree_value
)decl
);
1056 ltrans_statics_bitcount
++;
1061 if (ltrans_statics_bitcount
)
1062 for (i
= 0; i
< lto_cgraph_encoder_size (encoder
); i
++)
1063 if (write_node_summary_p (lto_cgraph_encoder_deref (encoder
, i
),
1064 set
, vset
, ltrans_statics
))
1067 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1069 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1072 /* Process all of the functions. */
1073 if (ltrans_statics_bitcount
)
1074 for (i
= 0; i
< lto_cgraph_encoder_size (encoder
); i
++)
1076 node
= lto_cgraph_encoder_deref (encoder
, i
);
1077 if (write_node_summary_p (node
, set
, vset
, ltrans_statics
))
1079 ipa_reference_optimization_summary_t info
;
1082 info
= get_reference_optimization_summary (node
);
1083 node_ref
= lto_cgraph_encoder_encode (encoder
, node
);
1084 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1086 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1087 ltrans_statics_bitcount
);
1088 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1089 ltrans_statics_bitcount
);
1092 BITMAP_FREE (ltrans_statics
);
1093 lto_destroy_simple_output_block (ob
);
1094 splay_tree_delete (reference_vars_to_consider
);
1097 /* Deserialize the ipa info for lto. */
1100 ipa_reference_read_optimization_summary (void)
1102 struct lto_file_decl_data
** file_data_vec
1103 = lto_get_file_decl_data ();
1104 struct lto_file_decl_data
* file_data
;
1106 bitmap_obstack_initialize (&optimization_summary_obstack
);
1108 node_removal_hook_holder
=
1109 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
1110 node_duplication_hook_holder
=
1111 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
1112 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1114 while ((file_data
= file_data_vec
[j
++]))
1118 struct lto_input_block
*ib
1119 = lto_create_simple_input_block (file_data
,
1120 LTO_section_ipa_reference
,
1125 unsigned int f_count
= streamer_read_uhwi (ib
);
1129 b_count
= streamer_read_hwi (ib
);
1131 fprintf (dump_file
, "all module statics:");
1132 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1134 unsigned int var_index
= streamer_read_uhwi (ib
);
1135 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1137 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1139 fprintf (dump_file
, " %s",
1140 lang_hooks
.decl_printable_name (v_decl
, 2));
1143 for (i
= 0; i
< f_count
; i
++)
1145 unsigned int j
, index
;
1146 struct cgraph_node
*node
;
1147 ipa_reference_optimization_summary_t info
;
1149 lto_cgraph_encoder_t encoder
;
1151 index
= streamer_read_uhwi (ib
);
1152 encoder
= file_data
->cgraph_node_encoder
;
1153 node
= lto_cgraph_encoder_deref (encoder
, index
);
1154 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1155 set_reference_optimization_summary (node
, info
);
1156 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1157 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1160 "\nFunction name:%s/%i:\n static not read:",
1161 cgraph_node_asm_name (node
), node
->symbol
.order
);
1163 /* Set the statics not read. */
1164 v_count
= streamer_read_hwi (ib
);
1167 info
->statics_not_read
= all_module_statics
;
1169 fprintf (dump_file
, " all module statics");
1172 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1174 unsigned int var_index
= streamer_read_uhwi (ib
);
1175 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1177 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1179 fprintf (dump_file
, " %s",
1180 lang_hooks
.decl_printable_name (v_decl
, 2));
1185 "\n static not written:");
1186 /* Set the statics not written. */
1187 v_count
= streamer_read_hwi (ib
);
1190 info
->statics_not_written
= all_module_statics
;
1192 fprintf (dump_file
, " all module statics");
1195 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1197 unsigned int var_index
= streamer_read_uhwi (ib
);
1198 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1200 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1202 fprintf (dump_file
, " %s",
1203 lang_hooks
.decl_printable_name (v_decl
, 2));
1206 fprintf (dump_file
, "\n");
1209 lto_destroy_simple_input_block (file_data
,
1210 LTO_section_ipa_reference
,
1214 /* Fatal error here. We do not want to support compiling ltrans units with
1215 different version of compiler or different flags than the WPA unit, so
1216 this should never happen. */
1217 fatal_error ("ipa reference summary is missing in ltrans unit");
1222 gate_reference (void)
1224 return (flag_ipa_reference
1225 /* Don't bother doing anything if the program has errors. */
1229 struct ipa_opt_pass_d pass_ipa_reference
=
1233 "static-var", /* name */
1234 gate_reference
, /* gate */
1235 propagate
, /* execute */
1238 0, /* static_pass_number */
1239 TV_IPA_REFERENCE
, /* tv_id */
1240 0, /* properties_required */
1241 0, /* properties_provided */
1242 0, /* properties_destroyed */
1243 0, /* todo_flags_start */
1244 0 /* todo_flags_finish */
1246 NULL
, /* generate_summary */
1247 NULL
, /* write_summary */
1248 NULL
, /* read_summary */
1249 ipa_reference_write_optimization_summary
,/* write_optimization_summary */
1250 ipa_reference_read_optimization_summary
,/* read_optimization_summary */
1251 NULL
, /* stmt_fixup */
1253 NULL
, /* function_transform */
1254 NULL
/* variable_transform */