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"
45 #include "tree-inline.h"
46 #include "tree-pass.h"
47 #include "pointer-set.h"
48 #include "splay-tree.h"
50 #include "ipa-utils.h"
51 #include "ipa-reference.h"
53 #include "diagnostic.h"
54 #include "data-streamer.h"
55 #include "lto-streamer.h"
57 static void remove_node_data (struct cgraph_node
*node
,
58 void *data ATTRIBUTE_UNUSED
);
59 static void duplicate_node_data (struct cgraph_node
*src
,
60 struct cgraph_node
*dst
,
61 void *data ATTRIBUTE_UNUSED
);
63 /* The static variables defined within the compilation unit that are
64 loaded or stored directly by function that owns this structure. */
66 struct ipa_reference_local_vars_info_d
69 bitmap statics_written
;
72 /* Statics that are read and written by some set of functions. The
73 local ones are based on the loads and stores local to the function.
74 The global ones are based on the local info as well as the
75 transitive closure of the functions that are called. */
77 struct ipa_reference_global_vars_info_d
80 bitmap statics_written
;
83 /* Information we save about every function after ipa-reference is completed. */
85 struct ipa_reference_optimization_summary_d
87 bitmap statics_not_read
;
88 bitmap statics_not_written
;
91 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
92 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
93 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
95 struct ipa_reference_vars_info_d
97 struct ipa_reference_local_vars_info_d local
;
98 struct ipa_reference_global_vars_info_d global
;
101 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
103 /* This splay tree contains all of the static variables that are
104 being considered by the compilation level alias analysis. */
105 static splay_tree reference_vars_to_consider
;
107 /* Set of all interesting module statics. A bit is set for every module
108 static we are considering. This is added to the local info when asm
109 code is found that clobbers all memory. */
110 static bitmap all_module_statics
;
112 /* Obstack holding bitmaps of local analysis (live from analysis to
114 static bitmap_obstack local_info_obstack
;
115 /* Obstack holding global analysis live forever. */
116 static bitmap_obstack optimization_summary_obstack
;
118 /* Holders of ipa cgraph hooks: */
119 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
120 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
122 /* Vector where the reference var infos are actually stored.
123 Indexed by UID of call graph nodes. */
124 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
126 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
128 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
129 static inline ipa_reference_vars_info_t
130 get_reference_vars_info (struct cgraph_node
*node
)
132 if (!ipa_reference_vars_vector
.exists ()
133 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
135 return ipa_reference_vars_vector
[node
->uid
];
138 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
139 static inline ipa_reference_optimization_summary_t
140 get_reference_optimization_summary (struct cgraph_node
*node
)
142 if (!ipa_reference_opt_sum_vector
.exists ()
143 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
145 return ipa_reference_opt_sum_vector
[node
->uid
];
148 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
150 set_reference_vars_info (struct cgraph_node
*node
,
151 ipa_reference_vars_info_t info
)
153 if (!ipa_reference_vars_vector
.exists ()
154 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
155 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
156 ipa_reference_vars_vector
[node
->uid
] = info
;
159 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
161 set_reference_optimization_summary (struct cgraph_node
*node
,
162 ipa_reference_optimization_summary_t info
)
164 if (!ipa_reference_opt_sum_vector
.exists ()
165 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
166 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
167 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
170 /* Return a bitmap indexed by DECL_UID for the static variables that
171 are *not* read during the execution of the function FN. Returns
172 NULL if no data is available. */
175 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
177 ipa_reference_optimization_summary_t info
=
178 get_reference_optimization_summary (cgraph_function_node (fn
, NULL
));
180 return info
->statics_not_read
;
181 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
182 return all_module_statics
;
187 /* Return a bitmap indexed by DECL_UID for the static variables that
188 are *not* written during the execution of the function FN. Note
189 that variables written may or may not be read during the function
190 call. Returns NULL if no data is available. */
193 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
195 ipa_reference_optimization_summary_t info
=
196 get_reference_optimization_summary (fn
);
198 return info
->statics_not_written
;
199 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
200 return all_module_statics
;
207 /* Add VAR to all_module_statics and the two
208 reference_vars_to_consider* sets. */
211 add_static_var (tree var
)
213 int uid
= DECL_UID (var
);
214 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
216 splay_tree_insert (reference_vars_to_consider
,
217 uid
, (splay_tree_value
)var
);
218 bitmap_set_bit (all_module_statics
, uid
);
221 /* Return true if the variable T is the right kind of static variable to
222 perform compilation unit scope escape analysis. */
225 is_proper_for_analysis (tree t
)
227 /* If the variable has the "used" attribute, treat it as if it had a
228 been touched by the devil. */
229 if (DECL_PRESERVE_P (t
))
232 /* Do not want to do anything with volatile except mark any
233 function that uses one to be not const or pure. */
234 if (TREE_THIS_VOLATILE (t
))
237 /* We do not need to analyze readonly vars, we already know they do not
239 if (TREE_READONLY (t
))
242 /* This is a variable we care about. Check if we have seen it
243 before, and if not add it the set of variables we care about. */
244 if (all_module_statics
245 && !bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
251 /* Lookup the tree node for the static variable that has UID and
252 convert the name to a string for debugging. */
255 get_static_name (int index
)
257 splay_tree_node stn
=
258 splay_tree_lookup (reference_vars_to_consider
, index
);
259 return fndecl_name ((tree
)(stn
->value
));
262 /* Dump a set of static vars to FILE. */
264 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
270 else if (set
== all_module_statics
)
273 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
275 fprintf (f
, "%s ", get_static_name (index
));
279 /* Compute X |= Y, taking into account the possibility that
280 either X or Y is already the maximum set.
281 Return true if X is the maximum set after taking the union with Y. */
284 union_static_var_sets (bitmap
&x
, bitmap y
)
286 if (x
!= all_module_statics
)
288 if (y
== all_module_statics
)
291 x
= all_module_statics
;
293 else if (bitmap_ior_into (x
, y
))
295 /* The union may have reduced X to the maximum set.
296 In that case, we want to make that visible explicitly.
297 Even though bitmap_equal_p can be very expensive, it
298 turns out to be an overall win to check this here for
299 an LTO bootstrap of GCC itself. Liberally extrapoliate
300 that result to be applicable to all cases. */
301 if (bitmap_equal_p (x
, all_module_statics
))
304 x
= all_module_statics
;
308 return x
== all_module_statics
;
311 /* Compute X &= Y, taking into account the possibility that
312 X may become the maximum set. */
315 intersect_static_var_sets (bitmap
&x
, bitmap y
)
317 if (x
!= all_module_statics
)
319 bitmap_and_into (x
, y
);
320 /* As with union_static_var_sets, reducing to the maximum
321 set as early as possible is an overall win. */
322 if (bitmap_equal_p (x
, all_module_statics
))
325 x
= all_module_statics
;
328 return x
== all_module_statics
;
331 /* Return a copy of SET on the bitmap obstack containing SET.
332 But if SET is NULL or the maximum set, return that instead. */
335 copy_static_var_set (bitmap set
)
337 if (set
== NULL
|| set
== all_module_statics
)
339 bitmap_obstack
*o
= set
->obstack
;
340 gcc_checking_assert (o
);
341 bitmap copy
= BITMAP_ALLOC (o
);
342 bitmap_copy (copy
, set
);
346 /* Compute the union all of the statics read and written by every callee of X
347 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
348 actually the set representing the cycle containing X. If the read and
349 written sets of X_GLOBAL has been reduced to the maximum set, we don't
350 have to look at the remaining callees. */
353 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
355 struct cgraph_edge
*e
;
356 bool read_all
= x_global
->statics_read
== all_module_statics
;
357 bool write_all
= x_global
->statics_written
== all_module_statics
;
359 e
&& !(read_all
&& write_all
);
362 enum availability avail
;
363 struct cgraph_node
*y
= cgraph_function_node (e
->callee
, &avail
);
367 /* Only look into nodes we can propagate something. */
368 int flags
= flags_from_decl_or_type (y
->decl
);
369 if (avail
> AVAIL_OVERWRITABLE
370 || (avail
== AVAIL_OVERWRITABLE
&& (flags
& ECF_LEAF
)))
372 if (get_reference_vars_info (y
))
374 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
375 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
377 /* Calls in the current cycle do not have their global set
378 computed yet (but everything else does because we're
379 visiting nodes in topological order). */
380 if (!y_global
->statics_read
)
383 /* If the function is const, it reads no memory even if it
384 seems so to local analysis. */
385 if (flags
& ECF_CONST
)
388 union_static_var_sets (x_global
->statics_read
,
389 y_global
->statics_read
);
391 /* If the function is pure, it has no stores even if it
392 seems so to local analysis. If we cannot return from
393 the function, we can safely ignore the call. */
394 if ((flags
& ECF_PURE
)
395 || cgraph_edge_cannot_lead_to_return (e
))
398 union_static_var_sets (x_global
->statics_written
,
399 y_global
->statics_written
);
407 /* The init routine for analyzing global static variable usage. See
408 comments at top for description. */
412 static bool init_p
= false;
420 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
422 bitmap_obstack_initialize (&local_info_obstack
);
423 bitmap_obstack_initialize (&optimization_summary_obstack
);
424 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
426 node_removal_hook_holder
=
427 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
428 node_duplication_hook_holder
=
429 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
433 /* Set up the persistent info for FN. */
435 static ipa_reference_local_vars_info_t
436 init_function_info (struct cgraph_node
*fn
)
438 ipa_reference_vars_info_t info
439 = XCNEW (struct ipa_reference_vars_info_d
);
441 /* Add the info to the tree's annotation. */
442 set_reference_vars_info (fn
, info
);
444 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
445 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
451 /* This is the main routine for finding the reference patterns for
452 global variables within a function FN. */
455 analyze_function (struct cgraph_node
*fn
)
457 ipa_reference_local_vars_info_t local
;
462 local
= init_function_info (fn
);
463 for (i
= 0; ipa_ref_list_reference_iterate (&fn
->ref_list
, i
, ref
); i
++)
465 if (!is_a
<varpool_node
> (ref
->referred
))
467 var
= ipa_ref_varpool_node (ref
)->decl
;
468 if (!is_proper_for_analysis (var
))
473 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
476 if (ipa_ref_cannot_lead_to_return (ref
))
478 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
485 if (cgraph_node_cannot_return (fn
))
486 bitmap_clear (local
->statics_written
);
490 /* Called when new clone is inserted to callgraph late. */
493 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
494 void *data ATTRIBUTE_UNUSED
)
496 ipa_reference_optimization_summary_t ginfo
;
497 ipa_reference_optimization_summary_t dst_ginfo
;
499 ginfo
= get_reference_optimization_summary (src
);
502 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
503 set_reference_optimization_summary (dst
, dst_ginfo
);
504 dst_ginfo
->statics_not_read
=
505 copy_static_var_set (ginfo
->statics_not_read
);
506 dst_ginfo
->statics_not_written
=
507 copy_static_var_set (ginfo
->statics_not_written
);
510 /* Called when node is removed. */
513 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
515 ipa_reference_optimization_summary_t ginfo
;
516 ginfo
= get_reference_optimization_summary (node
);
519 if (ginfo
->statics_not_read
520 && ginfo
->statics_not_read
!= all_module_statics
)
521 BITMAP_FREE (ginfo
->statics_not_read
);
523 if (ginfo
->statics_not_written
524 && ginfo
->statics_not_written
!= all_module_statics
)
525 BITMAP_FREE (ginfo
->statics_not_written
);
527 set_reference_optimization_summary (node
, NULL
);
531 /* Analyze each function in the cgraph to see which global or statics
532 are read or written. */
535 generate_summary (void)
537 struct cgraph_node
*node
;
543 /* Process all of the functions next. */
544 FOR_EACH_DEFINED_FUNCTION (node
)
545 analyze_function (node
);
548 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
550 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
551 get_static_name (index
), index
);
555 FOR_EACH_DEFINED_FUNCTION (node
)
556 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
558 ipa_reference_local_vars_info_t l
;
562 l
= &get_reference_vars_info (node
)->local
;
564 "\nFunction name:%s/%i:",
565 cgraph_node_asm_name (node
), node
->order
);
566 fprintf (dump_file
, "\n locals read: ");
568 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
571 fprintf (dump_file
, "%s ",
572 get_static_name (index
));
574 fprintf (dump_file
, "\n locals written: ");
575 if (l
->statics_written
)
576 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
579 fprintf (dump_file
, "%s ", get_static_name (index
));
584 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
587 read_write_all_from_decl (struct cgraph_node
*node
,
588 bool &read_all
, bool &write_all
)
590 tree decl
= node
->decl
;
591 int flags
= flags_from_decl_or_type (decl
);
592 if ((flags
& ECF_LEAF
)
593 && cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
595 else if (flags
& ECF_CONST
)
597 else if ((flags
& ECF_PURE
)
598 || cgraph_node_cannot_return (node
))
601 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
602 fprintf (dump_file
, " %s/%i -> read all\n",
603 cgraph_node_asm_name (node
), node
->order
);
607 /* TODO: To be able to produce sane results, we should also handle
608 common builtins, in particular throw. */
611 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
612 fprintf (dump_file
, " %s/%i -> read all, write all\n",
613 cgraph_node_asm_name (node
), node
->order
);
617 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
618 in the cycle of NODE. */
621 get_read_write_all_from_node (struct cgraph_node
*node
,
622 bool &read_all
, bool &write_all
)
624 struct cgraph_edge
*e
, *ie
;
626 /* When function is overwritable, we can not assume anything. */
627 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
628 read_write_all_from_decl (node
, read_all
, write_all
);
630 for (e
= node
->callees
;
631 e
&& !(read_all
&& write_all
);
634 enum availability avail
;
635 struct cgraph_node
*callee
= cgraph_function_node (e
->callee
, &avail
);
636 gcc_checking_assert (callee
);
637 if (avail
<= AVAIL_OVERWRITABLE
)
638 read_write_all_from_decl (callee
, read_all
, write_all
);
641 for (ie
= node
->indirect_calls
;
642 ie
&& !(read_all
&& write_all
);
643 ie
= ie
->next_callee
)
644 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
647 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
648 fprintf (dump_file
, " indirect call -> read all\n");
649 if (!cgraph_edge_cannot_lead_to_return (ie
)
650 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
652 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
653 fprintf (dump_file
, " indirect call -> write all\n");
659 /* Produce the global information by preforming a transitive closure
660 on the local information that was produced by ipa_analyze_function. */
665 struct cgraph_node
*node
;
666 struct varpool_node
*vnode
;
667 struct cgraph_node
**order
=
668 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
673 dump_cgraph (dump_file
);
675 ipa_discover_readonly_nonaddressable_vars ();
678 /* Now we know what vars are really statics; prune out those that aren't. */
679 FOR_EACH_VARIABLE (vnode
)
680 if (vnode
->externally_visible
681 || TREE_ADDRESSABLE (vnode
->decl
)
682 || TREE_READONLY (vnode
->decl
)
683 || !is_proper_for_analysis (vnode
->decl
)
684 || !vnode
->definition
)
685 bitmap_clear_bit (all_module_statics
, DECL_UID (vnode
->decl
));
687 /* Forget info we collected "just for fun" on variables that turned out to be
689 FOR_EACH_DEFINED_FUNCTION (node
)
691 ipa_reference_local_vars_info_t node_l
;
692 node_l
= &get_reference_vars_info (node
)->local
;
693 intersect_static_var_sets (node_l
->statics_read
, all_module_statics
);
694 intersect_static_var_sets (node_l
->statics_written
, all_module_statics
);
697 /* Propagate the local information through the call graph to produce
698 the global information. All the nodes within a cycle will have
699 the same info so we collapse cycles first. Then we can do the
700 propagation in one pass from the leaves to the roots. */
701 order_pos
= ipa_reduced_postorder (order
, true, true, NULL
);
703 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
705 for (i
= 0; i
< order_pos
; i
++ )
708 struct cgraph_node
*w
;
709 ipa_reference_vars_info_t node_info
;
710 ipa_reference_global_vars_info_t node_g
;
711 ipa_reference_local_vars_info_t node_l
;
712 bool read_all
= false;
713 bool write_all
= false;
719 node_info
= get_reference_vars_info (node
);
720 gcc_assert (node_info
);
721 node_l
= &node_info
->local
;
722 node_g
= &node_info
->global
;
724 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
725 fprintf (dump_file
, "Starting cycle with %s/%i\n",
726 cgraph_node_asm_name (node
), node
->order
);
728 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
730 /* If any node in a cycle is read_all or write_all, they all are. */
731 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
733 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
734 fprintf (dump_file
, " Visiting %s/%i\n",
735 cgraph_node_asm_name (w
), w
->order
);
736 get_read_write_all_from_node (w
, read_all
, write_all
);
737 if (read_all
&& write_all
)
741 /* Initialized the bitmaps global sets for the reduced node. */
743 node_g
->statics_read
= all_module_statics
;
745 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
747 node_g
->statics_written
= all_module_statics
;
749 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
751 /* Merge the sets of this cycle with all sets of callees reached
753 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
755 if (read_all
&& write_all
)
760 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
761 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
762 int flags
= flags_from_decl_or_type (w
->decl
);
764 if (!(flags
& ECF_CONST
))
765 read_all
= union_static_var_sets (node_g
->statics_read
,
767 if (!(flags
& ECF_PURE
)
768 && !cgraph_node_cannot_return (w
))
769 write_all
= union_static_var_sets (node_g
->statics_written
,
770 w_l
->statics_written
);
773 propagate_bits (node_g
, w
);
776 /* All nodes within a cycle have the same global info bitmaps. */
777 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
779 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
780 w_ri
->global
= *node_g
;
783 cycle_nodes
.release ();
788 for (i
= 0; i
< order_pos
; i
++)
791 struct cgraph_node
*w
;
798 "\nFunction name:%s/%i:",
799 cgraph_node_asm_name (node
), node
->order
);
801 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
802 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
804 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
805 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
807 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
808 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
810 fprintf (dump_file
, "\n next cycle: %s/%i ",
811 cgraph_node_asm_name (w
), w
->order
);
812 fprintf (dump_file
, "\n locals read: ");
813 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
814 fprintf (dump_file
, "\n locals written: ");
815 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
817 cycle_nodes
.release ();
819 fprintf (dump_file
, "\n globals read: ");
820 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
821 fprintf (dump_file
, "\n globals written: ");
822 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
823 fprintf (dump_file
, "\n");
828 FOR_EACH_DEFINED_FUNCTION (node
)
830 ipa_reference_vars_info_t node_info
;
831 ipa_reference_global_vars_info_t node_g
;
832 ipa_reference_optimization_summary_t opt
;
834 node_info
= get_reference_vars_info (node
);
836 && (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
837 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
839 node_g
= &node_info
->global
;
841 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
842 set_reference_optimization_summary (node
, opt
);
844 /* Create the complimentary sets. */
846 if (bitmap_empty_p (node_g
->statics_read
))
847 opt
->statics_not_read
= all_module_statics
;
850 opt
->statics_not_read
851 = BITMAP_ALLOC (&optimization_summary_obstack
);
852 if (node_g
->statics_read
!= all_module_statics
)
853 bitmap_and_compl (opt
->statics_not_read
,
855 node_g
->statics_read
);
858 if (bitmap_empty_p (node_g
->statics_written
))
859 opt
->statics_not_written
= all_module_statics
;
862 opt
->statics_not_written
863 = BITMAP_ALLOC (&optimization_summary_obstack
);
864 if (node_g
->statics_written
!= all_module_statics
)
865 bitmap_and_compl (opt
->statics_not_written
,
867 node_g
->statics_written
);
873 ipa_free_postorder_info ();
876 bitmap_obstack_release (&local_info_obstack
);
877 ipa_reference_vars_vector
.release ();
879 splay_tree_delete (reference_vars_to_consider
);
880 reference_vars_to_consider
= NULL
;
884 /* Return true if we need to write summary of NODE. */
887 write_node_summary_p (struct cgraph_node
*node
,
888 lto_symtab_encoder_t encoder
,
889 bitmap ltrans_statics
)
891 ipa_reference_optimization_summary_t info
;
893 /* See if we have (non-empty) info. */
894 if (!node
->definition
|| node
->global
.inlined_to
)
896 info
= get_reference_optimization_summary (node
);
897 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
898 && bitmap_empty_p (info
->statics_not_written
)))
901 /* See if we want to encode it.
902 Encode also referenced functions since constant folding might turn it into
905 In future we might also want to include summaries of functions references
906 by initializers of constant variables references in current unit. */
907 if (!reachable_from_this_partition_p (node
, encoder
)
908 && !referenced_from_this_partition_p (&node
->ref_list
, encoder
))
911 /* See if the info has non-empty intersections with vars we want to encode. */
912 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
913 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
918 /* Stream out BITS<RANS_STATICS as list of decls to OB.
919 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
920 or -1. When it is positive, just output -1 when
921 BITS<RANS_STATICS == BITS<RANS_STATICS. */
924 stream_out_bitmap (struct lto_simple_output_block
*ob
,
925 bitmap bits
, bitmap ltrans_statics
,
926 int ltrans_statics_bitcount
)
931 if (bits
== all_module_statics
)
933 streamer_write_hwi_stream (ob
->main_stream
, -1);
936 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
938 if (count
== ltrans_statics_bitcount
)
940 streamer_write_hwi_stream (ob
->main_stream
, -1);
943 streamer_write_hwi_stream (ob
->main_stream
, count
);
946 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
948 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
949 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
953 /* Serialize the ipa info for lto. */
956 ipa_reference_write_optimization_summary (void)
958 struct lto_simple_output_block
*ob
959 = lto_create_simple_output_block (LTO_section_ipa_reference
);
960 unsigned int count
= 0;
961 int ltrans_statics_bitcount
= 0;
962 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
963 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
966 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
968 /* See what variables we are interested in. */
969 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
971 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
972 varpool_node
*vnode
= dyn_cast
<varpool_node
> (snode
);
974 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
975 && referenced_from_this_partition_p (&vnode
->ref_list
, encoder
))
977 tree decl
= vnode
->decl
;
978 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
979 splay_tree_insert (reference_vars_to_consider
,
980 DECL_UID (decl
), (splay_tree_value
)decl
);
981 ltrans_statics_bitcount
++;
986 if (ltrans_statics_bitcount
)
987 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
989 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
990 cgraph_node
*cnode
= dyn_cast
<cgraph_node
> (snode
);
991 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
995 streamer_write_uhwi_stream (ob
->main_stream
, count
);
997 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1000 /* Process all of the functions. */
1001 if (ltrans_statics_bitcount
)
1002 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1004 symtab_node snode
= lto_symtab_encoder_deref (encoder
, i
);
1005 cgraph_node
*cnode
= dyn_cast
<cgraph_node
> (snode
);
1006 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1008 ipa_reference_optimization_summary_t info
;
1011 info
= get_reference_optimization_summary (cnode
);
1012 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1013 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1015 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1016 ltrans_statics_bitcount
);
1017 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1018 ltrans_statics_bitcount
);
1021 BITMAP_FREE (ltrans_statics
);
1022 lto_destroy_simple_output_block (ob
);
1023 splay_tree_delete (reference_vars_to_consider
);
1026 /* Deserialize the ipa info for lto. */
1029 ipa_reference_read_optimization_summary (void)
1031 struct lto_file_decl_data
** file_data_vec
1032 = lto_get_file_decl_data ();
1033 struct lto_file_decl_data
* file_data
;
1035 bitmap_obstack_initialize (&optimization_summary_obstack
);
1037 node_removal_hook_holder
=
1038 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
1039 node_duplication_hook_holder
=
1040 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
1041 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1043 while ((file_data
= file_data_vec
[j
++]))
1047 struct lto_input_block
*ib
1048 = lto_create_simple_input_block (file_data
,
1049 LTO_section_ipa_reference
,
1054 unsigned int f_count
= streamer_read_uhwi (ib
);
1058 b_count
= streamer_read_hwi (ib
);
1060 fprintf (dump_file
, "all module statics:");
1061 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1063 unsigned int var_index
= streamer_read_uhwi (ib
);
1064 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1066 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1068 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1071 for (i
= 0; i
< f_count
; i
++)
1073 unsigned int j
, index
;
1074 struct cgraph_node
*node
;
1075 ipa_reference_optimization_summary_t info
;
1077 lto_symtab_encoder_t encoder
;
1079 index
= streamer_read_uhwi (ib
);
1080 encoder
= file_data
->symtab_node_encoder
;
1081 node
= cgraph (lto_symtab_encoder_deref (encoder
, index
));
1082 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1083 set_reference_optimization_summary (node
, info
);
1084 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1085 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1088 "\nFunction name:%s/%i:\n static not read:",
1089 cgraph_node_asm_name (node
), node
->order
);
1091 /* Set the statics not read. */
1092 v_count
= streamer_read_hwi (ib
);
1095 info
->statics_not_read
= all_module_statics
;
1097 fprintf (dump_file
, " all module statics");
1100 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1102 unsigned int var_index
= streamer_read_uhwi (ib
);
1103 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1105 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1107 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1112 "\n static not written:");
1113 /* Set the statics not written. */
1114 v_count
= streamer_read_hwi (ib
);
1117 info
->statics_not_written
= all_module_statics
;
1119 fprintf (dump_file
, " all module statics");
1122 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1124 unsigned int var_index
= streamer_read_uhwi (ib
);
1125 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1127 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1129 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1132 fprintf (dump_file
, "\n");
1135 lto_destroy_simple_input_block (file_data
,
1136 LTO_section_ipa_reference
,
1140 /* Fatal error here. We do not want to support compiling ltrans units with
1141 different version of compiler or different flags than the WPA unit, so
1142 this should never happen. */
1143 fatal_error ("ipa reference summary is missing in ltrans unit");
1148 gate_reference (void)
1150 return (flag_ipa_reference
1151 /* Don't bother doing anything if the program has errors. */
1157 const pass_data pass_data_ipa_reference
=
1159 IPA_PASS
, /* type */
1160 "static-var", /* name */
1161 OPTGROUP_NONE
, /* optinfo_flags */
1162 true, /* has_gate */
1163 true, /* has_execute */
1164 TV_IPA_REFERENCE
, /* tv_id */
1165 0, /* properties_required */
1166 0, /* properties_provided */
1167 0, /* properties_destroyed */
1168 0, /* todo_flags_start */
1169 0, /* todo_flags_finish */
1172 class pass_ipa_reference
: public ipa_opt_pass_d
1175 pass_ipa_reference (gcc::context
*ctxt
)
1176 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1177 NULL
, /* generate_summary */
1178 NULL
, /* write_summary */
1179 NULL
, /* read_summary */
1180 ipa_reference_write_optimization_summary
, /*
1181 write_optimization_summary */
1182 ipa_reference_read_optimization_summary
, /*
1183 read_optimization_summary */
1184 NULL
, /* stmt_fixup */
1185 0, /* function_transform_todo_flags_start */
1186 NULL
, /* function_transform */
1187 NULL
) /* variable_transform */
1190 /* opt_pass methods: */
1191 bool gate () { return gate_reference (); }
1192 unsigned int execute () { return propagate (); }
1194 }; // class pass_ipa_reference
1199 make_pass_ipa_reference (gcc::context
*ctxt
)
1201 return new pass_ipa_reference (ctxt
);