1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2013 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it under
8 the terms of the GNU General Public License as published by the Free
9 Software Foundation; either version 3, or (at your option) any later
12 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 /* This file gathers information about how variables whose scope is
22 confined to the compilation unit are used.
24 The transitive call site specific clobber effects are computed
25 for the variables whose scope is contained within this compilation
28 First each function and static variable initialization is analyzed
29 to determine which local static variables are either read, written,
30 or have their address taken. Any local static that has its address
31 taken is removed from consideration. Once the local read and
32 writes are determined, a transitive closure of this information is
33 performed over the call graph to determine the worst case set of
34 side effects of each call. In later parts of the compiler, these
35 local and global sets are examined to make the call clobbering less
36 traumatic, promote some statics to registers, and improve aliasing
41 #include "coretypes.h"
44 #include "tree-inline.h"
45 #include "tree-pass.h"
46 #include "pointer-set.h"
47 #include "splay-tree.h"
49 #include "ipa-utils.h"
50 #include "ipa-reference.h"
52 #include "diagnostic.h"
53 #include "data-streamer.h"
54 #include "lto-streamer.h"
56 static void remove_node_data (struct cgraph_node
*node
,
57 void *data ATTRIBUTE_UNUSED
);
58 static void duplicate_node_data (struct cgraph_node
*src
,
59 struct cgraph_node
*dst
,
60 void *data ATTRIBUTE_UNUSED
);
62 /* The static variables defined within the compilation unit that are
63 loaded or stored directly by function that owns this structure. */
65 struct ipa_reference_local_vars_info_d
68 bitmap statics_written
;
71 /* Statics that are read and written by some set of functions. The
72 local ones are based on the loads and stores local to the function.
73 The global ones are based on the local info as well as the
74 transitive closure of the functions that are called. */
76 struct ipa_reference_global_vars_info_d
79 bitmap statics_written
;
82 /* Information we save about every function after ipa-reference is completed. */
84 struct ipa_reference_optimization_summary_d
86 bitmap statics_not_read
;
87 bitmap statics_not_written
;
90 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
91 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
92 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
94 struct ipa_reference_vars_info_d
96 struct ipa_reference_local_vars_info_d local
;
97 struct ipa_reference_global_vars_info_d global
;
100 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
102 /* This splay tree contains all of the static variables that are
103 being considered by the compilation level alias analysis. */
104 static splay_tree reference_vars_to_consider
;
106 /* Set of all interesting module statics. A bit is set for every module
107 static we are considering. This is added to the local info when asm
108 code is found that clobbers all memory. */
109 static bitmap all_module_statics
;
111 /* Obstack holding bitmaps of local analysis (live from analysis to
113 static bitmap_obstack local_info_obstack
;
114 /* Obstack holding global analysis live forever. */
115 static bitmap_obstack optimization_summary_obstack
;
117 /* Holders of ipa cgraph hooks: */
118 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
119 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
121 /* Vector where the reference var infos are actually stored.
122 Indexed by UID of call graph nodes. */
123 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
125 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
127 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
128 static inline ipa_reference_vars_info_t
129 get_reference_vars_info (struct cgraph_node
*node
)
131 if (!ipa_reference_vars_vector
.exists ()
132 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
134 return ipa_reference_vars_vector
[node
->uid
];
137 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
138 static inline ipa_reference_optimization_summary_t
139 get_reference_optimization_summary (struct cgraph_node
*node
)
141 if (!ipa_reference_opt_sum_vector
.exists ()
142 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
144 return ipa_reference_opt_sum_vector
[node
->uid
];
147 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
149 set_reference_vars_info (struct cgraph_node
*node
,
150 ipa_reference_vars_info_t info
)
152 if (!ipa_reference_vars_vector
.exists ()
153 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
154 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
155 ipa_reference_vars_vector
[node
->uid
] = info
;
158 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
160 set_reference_optimization_summary (struct cgraph_node
*node
,
161 ipa_reference_optimization_summary_t info
)
163 if (!ipa_reference_opt_sum_vector
.exists ()
164 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
165 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
166 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
169 /* Return a bitmap indexed by DECL_UID for the static variables that
170 are *not* read during the execution of the function FN. Returns
171 NULL if no data is available. */
174 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
176 ipa_reference_optimization_summary_t info
=
177 get_reference_optimization_summary (cgraph_function_node (fn
, NULL
));
179 return info
->statics_not_read
;
180 else if (flags_from_decl_or_type (fn
->symbol
.decl
) & ECF_LEAF
)
181 return all_module_statics
;
186 /* Return a bitmap indexed by DECL_UID for the static variables that
187 are *not* written during the execution of the function FN. Note
188 that variables written may or may not be read during the function
189 call. Returns NULL if no data is available. */
192 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
194 ipa_reference_optimization_summary_t info
=
195 get_reference_optimization_summary (fn
);
197 return info
->statics_not_written
;
198 else if (flags_from_decl_or_type (fn
->symbol
.decl
) & ECF_LEAF
)
199 return all_module_statics
;
206 /* Add VAR to all_module_statics and the two
207 reference_vars_to_consider* sets. */
210 add_static_var (tree var
)
212 int uid
= DECL_UID (var
);
213 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
215 splay_tree_insert (reference_vars_to_consider
,
216 uid
, (splay_tree_value
)var
);
217 bitmap_set_bit (all_module_statics
, uid
);
220 /* Return true if the variable T is the right kind of static variable to
221 perform compilation unit scope escape analysis. */
224 is_proper_for_analysis (tree t
)
226 /* If the variable has the "used" attribute, treat it as if it had a
227 been touched by the devil. */
228 if (DECL_PRESERVE_P (t
))
231 /* Do not want to do anything with volatile except mark any
232 function that uses one to be not const or pure. */
233 if (TREE_THIS_VOLATILE (t
))
236 /* We do not need to analyze readonly vars, we already know they do not
238 if (TREE_READONLY (t
))
241 /* This is a variable we care about. Check if we have seen it
242 before, and if not add it the set of variables we care about. */
243 if (all_module_statics
244 && !bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
250 /* Lookup the tree node for the static variable that has UID and
251 convert the name to a string for debugging. */
254 get_static_name (int index
)
256 splay_tree_node stn
=
257 splay_tree_lookup (reference_vars_to_consider
, index
);
258 return fndecl_name ((tree
)(stn
->value
));
261 /* Dump a set of static vars to FILE. */
263 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
269 else if (set
== all_module_statics
)
272 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
274 fprintf (f
, "%s ", get_static_name (index
));
278 /* Compute X |= Y, taking into account the possibility that
279 either X or Y is already the maximum set.
280 Return true if X is the maximum set after taking the union with Y. */
283 union_static_var_sets (bitmap
&x
, bitmap y
)
285 if (x
!= all_module_statics
)
287 if (y
== all_module_statics
)
290 x
= all_module_statics
;
292 else if (bitmap_ior_into (x
, y
))
294 /* The union may have reduced X to the maximum set.
295 In that case, we want to make that visible explicitly.
296 Even though bitmap_equal_p can be very expensive, it
297 turns out to be an overall win to check this here for
298 an LTO bootstrap of GCC itself. Liberally extrapoliate
299 that result to be applicable to all cases. */
300 if (bitmap_equal_p (x
, all_module_statics
))
303 x
= all_module_statics
;
307 return x
== all_module_statics
;
310 /* Compute X &= Y, taking into account the possibility that
311 X may become the maximum set. */
314 intersect_static_var_sets (bitmap
&x
, bitmap y
)
316 if (x
!= all_module_statics
)
318 bitmap_and_into (x
, y
);
319 /* As with union_static_var_sets, reducing to the maximum
320 set as early as possible is an overall win. */
321 if (bitmap_equal_p (x
, all_module_statics
))
324 x
= all_module_statics
;
327 return x
== all_module_statics
;
330 /* Return a copy of SET on the bitmap obstack containing SET.
331 But if SET is NULL or the maximum set, return that instead. */
334 copy_static_var_set (bitmap set
)
336 if (set
== NULL
|| set
== all_module_statics
)
338 bitmap_obstack
*o
= set
->obstack
;
339 gcc_checking_assert (o
);
340 bitmap copy
= BITMAP_ALLOC (o
);
341 bitmap_copy (copy
, set
);
345 /* Compute the union all of the statics read and written by every callee of X
346 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
347 actually the set representing the cycle containing X. If the read and
348 written sets of X_GLOBAL has been reduced to the maximum set, we don't
349 have to look at the remaining callees. */
352 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
354 struct cgraph_edge
*e
;
355 bool read_all
= x_global
->statics_read
== all_module_statics
;
356 bool write_all
= x_global
->statics_written
== all_module_statics
;
358 e
&& !(read_all
&& write_all
);
361 enum availability avail
;
362 struct cgraph_node
*y
= cgraph_function_node (e
->callee
, &avail
);
366 /* Only look into nodes we can propagate something. */
367 int flags
= flags_from_decl_or_type (y
->symbol
.decl
);
368 if (avail
> AVAIL_OVERWRITABLE
369 || (avail
== AVAIL_OVERWRITABLE
&& (flags
& ECF_LEAF
)))
371 if (get_reference_vars_info (y
))
373 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
374 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
376 /* Calls in the current cycle do not have their global set
377 computed yet (but everything else does because we're
378 visiting nodes in topological order). */
379 if (!y_global
->statics_read
)
382 /* If the function is const, it reads no memory even if it
383 seems so to local analysis. */
384 if (flags
& ECF_CONST
)
387 union_static_var_sets (x_global
->statics_read
,
388 y_global
->statics_read
);
390 /* If the function is pure, it has no stores even if it
391 seems so to local analysis. If we cannot return from
392 the function, we can safely ignore the call. */
393 if ((flags
& ECF_PURE
)
394 || cgraph_edge_cannot_lead_to_return (e
))
397 union_static_var_sets (x_global
->statics_written
,
398 y_global
->statics_written
);
406 /* The init routine for analyzing global static variable usage. See
407 comments at top for description. */
411 static bool init_p
= false;
419 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
421 bitmap_obstack_initialize (&local_info_obstack
);
422 bitmap_obstack_initialize (&optimization_summary_obstack
);
423 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
425 node_removal_hook_holder
=
426 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
427 node_duplication_hook_holder
=
428 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
432 /* Set up the persistent info for FN. */
434 static ipa_reference_local_vars_info_t
435 init_function_info (struct cgraph_node
*fn
)
437 ipa_reference_vars_info_t info
438 = XCNEW (struct ipa_reference_vars_info_d
);
440 /* Add the info to the tree's annotation. */
441 set_reference_vars_info (fn
, info
);
443 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
444 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
450 /* This is the main routine for finding the reference patterns for
451 global variables within a function FN. */
454 analyze_function (struct cgraph_node
*fn
)
456 ipa_reference_local_vars_info_t local
;
461 local
= init_function_info (fn
);
462 for (i
= 0; ipa_ref_list_reference_iterate (&fn
->symbol
.ref_list
, i
, ref
); i
++)
464 if (!is_a
<varpool_node
> (ref
->referred
))
466 var
= ipa_ref_varpool_node (ref
)->symbol
.decl
;
467 if (!is_proper_for_analysis (var
))
472 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
475 if (ipa_ref_cannot_lead_to_return (ref
))
477 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
484 if (cgraph_node_cannot_return (fn
))
485 bitmap_clear (local
->statics_written
);
489 /* Called when new clone is inserted to callgraph late. */
492 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
493 void *data ATTRIBUTE_UNUSED
)
495 ipa_reference_optimization_summary_t ginfo
;
496 ipa_reference_optimization_summary_t dst_ginfo
;
498 ginfo
= get_reference_optimization_summary (src
);
501 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
502 set_reference_optimization_summary (dst
, dst_ginfo
);
503 dst_ginfo
->statics_not_read
=
504 copy_static_var_set (ginfo
->statics_not_read
);
505 dst_ginfo
->statics_not_written
=
506 copy_static_var_set (ginfo
->statics_not_written
);
509 /* Called when node is removed. */
512 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
514 ipa_reference_optimization_summary_t ginfo
;
515 ginfo
= get_reference_optimization_summary (node
);
518 if (ginfo
->statics_not_read
519 && ginfo
->statics_not_read
!= all_module_statics
)
520 BITMAP_FREE (ginfo
->statics_not_read
);
522 if (ginfo
->statics_not_written
523 && ginfo
->statics_not_written
!= all_module_statics
)
524 BITMAP_FREE (ginfo
->statics_not_written
);
526 set_reference_optimization_summary (node
, NULL
);
530 /* Analyze each function in the cgraph to see which global or statics
531 are read or written. */
534 generate_summary (void)
536 struct cgraph_node
*node
;
542 /* Process all of the functions next. */
543 FOR_EACH_DEFINED_FUNCTION (node
)
544 analyze_function (node
);
547 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
549 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
550 get_static_name (index
), index
);
554 FOR_EACH_DEFINED_FUNCTION (node
)
555 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
557 ipa_reference_local_vars_info_t l
;
561 l
= &get_reference_vars_info (node
)->local
;
563 "\nFunction name:%s/%i:",
564 cgraph_node_asm_name (node
), node
->symbol
.order
);
565 fprintf (dump_file
, "\n locals read: ");
567 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
570 fprintf (dump_file
, "%s ",
571 get_static_name (index
));
573 fprintf (dump_file
, "\n locals written: ");
574 if (l
->statics_written
)
575 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
578 fprintf (dump_file
, "%s ", get_static_name (index
));
583 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
586 read_write_all_from_decl (struct cgraph_node
*node
,
587 bool &read_all
, bool &write_all
)
589 tree decl
= node
->symbol
.decl
;
590 int flags
= flags_from_decl_or_type (decl
);
591 if ((flags
& ECF_LEAF
)
592 && cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
594 else if (flags
& ECF_CONST
)
596 else if ((flags
& ECF_PURE
)
597 || cgraph_node_cannot_return (node
))
600 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
601 fprintf (dump_file
, " %s/%i -> read all\n",
602 cgraph_node_asm_name (node
), node
->symbol
.order
);
606 /* TODO: To be able to produce sane results, we should also handle
607 common builtins, in particular throw. */
610 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
611 fprintf (dump_file
, " %s/%i -> read all, write all\n",
612 cgraph_node_asm_name (node
), node
->symbol
.order
);
616 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
617 in the cycle of NODE. */
620 get_read_write_all_from_node (struct cgraph_node
*node
,
621 bool &read_all
, bool &write_all
)
623 struct cgraph_edge
*e
, *ie
;
625 /* When function is overwritable, we can not assume anything. */
626 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
627 read_write_all_from_decl (node
, read_all
, write_all
);
629 for (e
= node
->callees
;
630 e
&& !(read_all
&& write_all
);
633 enum availability avail
;
634 struct cgraph_node
*callee
= cgraph_function_node (e
->callee
, &avail
);
635 gcc_checking_assert (callee
);
636 if (avail
<= AVAIL_OVERWRITABLE
)
637 read_write_all_from_decl (callee
, read_all
, write_all
);
640 for (ie
= node
->indirect_calls
;
641 ie
&& !(read_all
&& write_all
);
642 ie
= ie
->next_callee
)
643 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
646 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
647 fprintf (dump_file
, " indirect call -> read all\n");
648 if (!cgraph_edge_cannot_lead_to_return (ie
)
649 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
651 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
652 fprintf (dump_file
, " indirect call -> write all\n");
658 /* Produce the global information by preforming a transitive closure
659 on the local information that was produced by ipa_analyze_function. */
664 struct cgraph_node
*node
;
665 struct varpool_node
*vnode
;
666 struct cgraph_node
**order
=
667 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
672 dump_cgraph (dump_file
);
674 ipa_discover_readonly_nonaddressable_vars ();
677 /* Now we know what vars are really statics; prune out those that aren't. */
678 FOR_EACH_VARIABLE (vnode
)
679 if (vnode
->symbol
.externally_visible
680 || TREE_ADDRESSABLE (vnode
->symbol
.decl
)
681 || TREE_READONLY (vnode
->symbol
.decl
)
682 || !is_proper_for_analysis (vnode
->symbol
.decl
)
683 || !vnode
->symbol
.definition
)
684 bitmap_clear_bit (all_module_statics
, DECL_UID (vnode
->symbol
.decl
));
686 /* Forget info we collected "just for fun" on variables that turned out to be
688 FOR_EACH_DEFINED_FUNCTION (node
)
690 ipa_reference_local_vars_info_t node_l
;
691 node_l
= &get_reference_vars_info (node
)->local
;
692 intersect_static_var_sets (node_l
->statics_read
, all_module_statics
);
693 intersect_static_var_sets (node_l
->statics_written
, all_module_statics
);
696 /* Propagate the local information through the call graph to produce
697 the global information. All the nodes within a cycle will have
698 the same info so we collapse cycles first. Then we can do the
699 propagation in one pass from the leaves to the roots. */
700 order_pos
= ipa_reduced_postorder (order
, true, true, NULL
);
702 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
704 for (i
= 0; i
< order_pos
; i
++ )
707 struct cgraph_node
*w
;
708 ipa_reference_vars_info_t node_info
;
709 ipa_reference_global_vars_info_t node_g
;
710 ipa_reference_local_vars_info_t node_l
;
711 bool read_all
= false;
712 bool write_all
= false;
715 if (node
->symbol
.alias
)
718 node_info
= get_reference_vars_info (node
);
719 gcc_assert (node_info
);
720 node_l
= &node_info
->local
;
721 node_g
= &node_info
->global
;
723 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
724 fprintf (dump_file
, "Starting cycle with %s/%i\n",
725 cgraph_node_asm_name (node
), node
->symbol
.order
);
727 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
729 /* If any node in a cycle is read_all or write_all, they all are. */
730 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
732 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
733 fprintf (dump_file
, " Visiting %s/%i\n",
734 cgraph_node_asm_name (w
), w
->symbol
.order
);
735 get_read_write_all_from_node (w
, read_all
, write_all
);
736 if (read_all
&& write_all
)
740 /* Initialized the bitmaps global sets for the reduced node. */
742 node_g
->statics_read
= all_module_statics
;
744 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
746 node_g
->statics_written
= all_module_statics
;
748 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
750 /* Merge the sets of this cycle with all sets of callees reached
752 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
754 if (read_all
&& write_all
)
759 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
760 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
761 int flags
= flags_from_decl_or_type (w
->symbol
.decl
);
763 if (!(flags
& ECF_CONST
))
764 read_all
= union_static_var_sets (node_g
->statics_read
,
766 if (!(flags
& ECF_PURE
)
767 && !cgraph_node_cannot_return (w
))
768 write_all
= union_static_var_sets (node_g
->statics_written
,
769 w_l
->statics_written
);
772 propagate_bits (node_g
, w
);
775 /* All nodes within a cycle have the same global info bitmaps. */
776 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
778 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
779 w_ri
->global
= *node_g
;
782 cycle_nodes
.release ();
787 for (i
= 0; i
< order_pos
; i
++)
790 struct cgraph_node
*w
;
793 if (node
->symbol
.alias
)
797 "\nFunction name:%s/%i:",
798 cgraph_node_asm_name (node
), node
->symbol
.order
);
800 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
801 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
803 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
804 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
806 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
807 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
809 fprintf (dump_file
, "\n next cycle: %s/%i ",
810 cgraph_node_asm_name (w
), w
->symbol
.order
);
811 fprintf (dump_file
, "\n locals read: ");
812 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
813 fprintf (dump_file
, "\n locals written: ");
814 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
816 cycle_nodes
.release ();
818 fprintf (dump_file
, "\n globals read: ");
819 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
820 fprintf (dump_file
, "\n globals written: ");
821 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
822 fprintf (dump_file
, "\n");
827 FOR_EACH_DEFINED_FUNCTION (node
)
829 ipa_reference_vars_info_t node_info
;
830 ipa_reference_global_vars_info_t node_g
;
831 ipa_reference_optimization_summary_t opt
;
833 node_info
= get_reference_vars_info (node
);
834 if (!node
->symbol
.alias
835 && (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
836 || (flags_from_decl_or_type (node
->symbol
.decl
) & ECF_LEAF
)))
838 node_g
= &node_info
->global
;
840 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
841 set_reference_optimization_summary (node
, opt
);
843 /* Create the complimentary sets. */
845 if (bitmap_empty_p (node_g
->statics_read
))
846 opt
->statics_not_read
= all_module_statics
;
849 opt
->statics_not_read
850 = BITMAP_ALLOC (&optimization_summary_obstack
);
851 if (node_g
->statics_read
!= all_module_statics
)
852 bitmap_and_compl (opt
->statics_not_read
,
854 node_g
->statics_read
);
857 if (bitmap_empty_p (node_g
->statics_written
))
858 opt
->statics_not_written
= all_module_statics
;
861 opt
->statics_not_written
862 = BITMAP_ALLOC (&optimization_summary_obstack
);
863 if (node_g
->statics_written
!= all_module_statics
)
864 bitmap_and_compl (opt
->statics_not_written
,
866 node_g
->statics_written
);
872 ipa_free_postorder_info ();
875 bitmap_obstack_release (&local_info_obstack
);
876 ipa_reference_vars_vector
.release ();
878 splay_tree_delete (reference_vars_to_consider
);
879 reference_vars_to_consider
= NULL
;
883 /* Return true if we need to write summary of NODE. */
886 write_node_summary_p (struct cgraph_node
*node
,
887 lto_symtab_encoder_t encoder
,
888 bitmap ltrans_statics
)
890 ipa_reference_optimization_summary_t info
;
892 /* See if we have (non-empty) info. */
893 if (!node
->symbol
.definition
|| node
->global
.inlined_to
)
895 info
= get_reference_optimization_summary (node
);
896 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
897 && bitmap_empty_p (info
->statics_not_written
)))
900 /* See if we want to encode it.
901 Encode also referenced functions since constant folding might turn it into
904 In future we might also want to include summaries of functions references
905 by initializers of constant variables references in current unit. */
906 if (!reachable_from_this_partition_p (node
, encoder
)
907 && !referenced_from_this_partition_p (&node
->symbol
.ref_list
, encoder
))
910 /* See if the info has non-empty intersections with vars we want to encode. */
911 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
912 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
917 /* Stream out BITS<RANS_STATICS as list of decls to OB.
918 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
919 or -1. When it is positive, just output -1 when
920 BITS<RANS_STATICS == BITS<RANS_STATICS. */
923 stream_out_bitmap (struct lto_simple_output_block
*ob
,
924 bitmap bits
, bitmap ltrans_statics
,
925 int ltrans_statics_bitcount
)
930 if (bits
== all_module_statics
)
932 streamer_write_hwi_stream (ob
->main_stream
, -1);
935 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
937 if (count
== ltrans_statics_bitcount
)
939 streamer_write_hwi_stream (ob
->main_stream
, -1);
942 streamer_write_hwi_stream (ob
->main_stream
, count
);
945 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
947 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
948 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
952 /* Serialize the ipa info for lto. */
955 ipa_reference_write_optimization_summary (void)
957 struct lto_simple_output_block
*ob
958 = lto_create_simple_output_block (LTO_section_ipa_reference
);
959 unsigned int count
= 0;
960 int ltrans_statics_bitcount
= 0;
961 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
962 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
965 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
967 /* See what variables we are interested in. */
968 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
970 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
971 varpool_node
*vnode
= dyn_cast
<varpool_node
> (snode
);
973 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->symbol
.decl
))
974 && referenced_from_this_partition_p (&vnode
->symbol
.ref_list
, encoder
))
976 tree decl
= vnode
->symbol
.decl
;
977 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
978 splay_tree_insert (reference_vars_to_consider
,
979 DECL_UID (decl
), (splay_tree_value
)decl
);
980 ltrans_statics_bitcount
++;
985 if (ltrans_statics_bitcount
)
986 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
988 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
989 cgraph_node
*cnode
= dyn_cast
<cgraph_node
> (snode
);
990 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
994 streamer_write_uhwi_stream (ob
->main_stream
, count
);
996 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
999 /* Process all of the functions. */
1000 if (ltrans_statics_bitcount
)
1001 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1003 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
1004 cgraph_node
*cnode
= dyn_cast
<cgraph_node
> (snode
);
1005 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1007 ipa_reference_optimization_summary_t info
;
1010 info
= get_reference_optimization_summary (cnode
);
1011 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1012 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1014 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1015 ltrans_statics_bitcount
);
1016 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1017 ltrans_statics_bitcount
);
1020 BITMAP_FREE (ltrans_statics
);
1021 lto_destroy_simple_output_block (ob
);
1022 splay_tree_delete (reference_vars_to_consider
);
1025 /* Deserialize the ipa info for lto. */
1028 ipa_reference_read_optimization_summary (void)
1030 struct lto_file_decl_data
** file_data_vec
1031 = lto_get_file_decl_data ();
1032 struct lto_file_decl_data
* file_data
;
1034 bitmap_obstack_initialize (&optimization_summary_obstack
);
1036 node_removal_hook_holder
=
1037 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
1038 node_duplication_hook_holder
=
1039 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
1040 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1042 while ((file_data
= file_data_vec
[j
++]))
1046 struct lto_input_block
*ib
1047 = lto_create_simple_input_block (file_data
,
1048 LTO_section_ipa_reference
,
1053 unsigned int f_count
= streamer_read_uhwi (ib
);
1057 b_count
= streamer_read_hwi (ib
);
1059 fprintf (dump_file
, "all module statics:");
1060 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1062 unsigned int var_index
= streamer_read_uhwi (ib
);
1063 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1065 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1067 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1070 for (i
= 0; i
< f_count
; i
++)
1072 unsigned int j
, index
;
1073 struct cgraph_node
*node
;
1074 ipa_reference_optimization_summary_t info
;
1076 lto_symtab_encoder_t encoder
;
1078 index
= streamer_read_uhwi (ib
);
1079 encoder
= file_data
->symtab_node_encoder
;
1080 node
= cgraph (lto_symtab_encoder_deref (encoder
, index
));
1081 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1082 set_reference_optimization_summary (node
, info
);
1083 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1084 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1087 "\nFunction name:%s/%i:\n static not read:",
1088 cgraph_node_asm_name (node
), node
->symbol
.order
);
1090 /* Set the statics not read. */
1091 v_count
= streamer_read_hwi (ib
);
1094 info
->statics_not_read
= all_module_statics
;
1096 fprintf (dump_file
, " all module statics");
1099 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1101 unsigned int var_index
= streamer_read_uhwi (ib
);
1102 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1104 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1106 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1111 "\n static not written:");
1112 /* Set the statics not written. */
1113 v_count
= streamer_read_hwi (ib
);
1116 info
->statics_not_written
= all_module_statics
;
1118 fprintf (dump_file
, " all module statics");
1121 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1123 unsigned int var_index
= streamer_read_uhwi (ib
);
1124 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1126 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1128 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1131 fprintf (dump_file
, "\n");
1134 lto_destroy_simple_input_block (file_data
,
1135 LTO_section_ipa_reference
,
1139 /* Fatal error here. We do not want to support compiling ltrans units with
1140 different version of compiler or different flags than the WPA unit, so
1141 this should never happen. */
1142 fatal_error ("ipa reference summary is missing in ltrans unit");
1147 gate_reference (void)
1149 return (flag_ipa_reference
1150 /* Don't bother doing anything if the program has errors. */
1156 const pass_data pass_data_ipa_reference
=
1158 IPA_PASS
, /* type */
1159 "static-var", /* name */
1160 OPTGROUP_NONE
, /* optinfo_flags */
1161 true, /* has_gate */
1162 true, /* has_execute */
1163 TV_IPA_REFERENCE
, /* tv_id */
1164 0, /* properties_required */
1165 0, /* properties_provided */
1166 0, /* properties_destroyed */
1167 0, /* todo_flags_start */
1168 0, /* todo_flags_finish */
1171 class pass_ipa_reference
: public ipa_opt_pass_d
1174 pass_ipa_reference (gcc::context
*ctxt
)
1175 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1176 NULL
, /* generate_summary */
1177 NULL
, /* write_summary */
1178 NULL
, /* read_summary */
1179 ipa_reference_write_optimization_summary
, /*
1180 write_optimization_summary */
1181 ipa_reference_read_optimization_summary
, /*
1182 read_optimization_summary */
1183 NULL
, /* stmt_fixup */
1184 0, /* function_transform_todo_flags_start */
1185 NULL
, /* function_transform */
1186 NULL
) /* variable_transform */
1189 /* opt_pass methods: */
1190 bool gate () { return gate_reference (); }
1191 unsigned int execute () { return propagate (); }
1193 }; // class pass_ipa_reference
1198 make_pass_ipa_reference (gcc::context
*ctxt
)
1200 return new pass_ipa_reference (ctxt
);