1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2014 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"
50 #include "hard-reg-set.h"
53 #include "basic-block.h"
54 #include "tree-ssa-alias.h"
55 #include "internal-fn.h"
56 #include "gimple-expr.h"
59 #include "tree-inline.h"
60 #include "tree-pass.h"
61 #include "splay-tree.h"
63 #include "plugin-api.h"
66 #include "ipa-utils.h"
68 #include "ipa-reference.h"
70 #include "diagnostic.h"
71 #include "data-streamer.h"
72 #include "lto-streamer.h"
74 static void remove_node_data (struct cgraph_node
*node
,
75 void *data ATTRIBUTE_UNUSED
);
76 static void duplicate_node_data (struct cgraph_node
*src
,
77 struct cgraph_node
*dst
,
78 void *data ATTRIBUTE_UNUSED
);
80 /* The static variables defined within the compilation unit that are
81 loaded or stored directly by function that owns this structure. */
83 struct ipa_reference_local_vars_info_d
86 bitmap statics_written
;
89 /* Statics that are read and written by some set of functions. The
90 local ones are based on the loads and stores local to the function.
91 The global ones are based on the local info as well as the
92 transitive closure of the functions that are called. */
94 struct ipa_reference_global_vars_info_d
97 bitmap statics_written
;
100 /* Information we save about every function after ipa-reference is completed. */
102 struct ipa_reference_optimization_summary_d
104 bitmap statics_not_read
;
105 bitmap statics_not_written
;
108 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
109 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
110 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
112 struct ipa_reference_vars_info_d
114 struct ipa_reference_local_vars_info_d local
;
115 struct ipa_reference_global_vars_info_d global
;
118 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
120 /* This splay tree contains all of the static variables that are
121 being considered by the compilation level alias analysis. */
122 static splay_tree reference_vars_to_consider
;
124 /* Set of all interesting module statics. A bit is set for every module
125 static we are considering. This is added to the local info when asm
126 code is found that clobbers all memory. */
127 static bitmap all_module_statics
;
129 /* Obstack holding bitmaps of local analysis (live from analysis to
131 static bitmap_obstack local_info_obstack
;
132 /* Obstack holding global analysis live forever. */
133 static bitmap_obstack optimization_summary_obstack
;
135 /* Holders of ipa cgraph hooks: */
136 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
137 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
139 /* Vector where the reference var infos are actually stored.
140 Indexed by UID of call graph nodes. */
141 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
143 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
145 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
146 static inline ipa_reference_vars_info_t
147 get_reference_vars_info (struct cgraph_node
*node
)
149 if (!ipa_reference_vars_vector
.exists ()
150 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
152 return ipa_reference_vars_vector
[node
->uid
];
155 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
156 static inline ipa_reference_optimization_summary_t
157 get_reference_optimization_summary (struct cgraph_node
*node
)
159 if (!ipa_reference_opt_sum_vector
.exists ()
160 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
162 return ipa_reference_opt_sum_vector
[node
->uid
];
165 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
167 set_reference_vars_info (struct cgraph_node
*node
,
168 ipa_reference_vars_info_t info
)
170 if (!ipa_reference_vars_vector
.exists ()
171 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
172 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
173 ipa_reference_vars_vector
[node
->uid
] = info
;
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
.exists ()
182 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
183 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
184 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
187 /* Return a bitmap indexed by DECL_UID for the static variables that
188 are *not* read during the execution of the function FN. Returns
189 NULL if no data is available. */
192 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
194 ipa_reference_optimization_summary_t info
=
195 get_reference_optimization_summary (fn
->function_symbol (NULL
));
197 return info
->statics_not_read
;
198 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
199 return all_module_statics
;
204 /* Return a bitmap indexed by DECL_UID for the static variables that
205 are *not* written during the execution of the function FN. Note
206 that variables written may or may not be read during the function
207 call. Returns NULL if no data is available. */
210 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
212 ipa_reference_optimization_summary_t info
=
213 get_reference_optimization_summary (fn
);
215 return info
->statics_not_written
;
216 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
217 return all_module_statics
;
224 /* Add VAR to all_module_statics and the two
225 reference_vars_to_consider* sets. */
228 add_static_var (tree var
)
230 int uid
= DECL_UID (var
);
231 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
233 splay_tree_insert (reference_vars_to_consider
,
234 uid
, (splay_tree_value
)var
);
235 bitmap_set_bit (all_module_statics
, uid
);
238 /* Return true if the variable T is the right kind of static variable to
239 perform compilation unit scope escape analysis. */
242 is_proper_for_analysis (tree t
)
244 /* If the variable has the "used" attribute, treat it as if it had a
245 been touched by the devil. */
246 if (DECL_PRESERVE_P (t
))
249 /* Do not want to do anything with volatile except mark any
250 function that uses one to be not const or pure. */
251 if (TREE_THIS_VOLATILE (t
))
254 /* We do not need to analyze readonly vars, we already know they do not
256 if (TREE_READONLY (t
))
259 /* We can not track variables with address taken. */
260 if (TREE_ADDRESSABLE (t
))
263 /* TODO: We could track public variables that are not addressable, but currently
264 frontends don't give us those. */
268 /* TODO: Check aliases. */
270 /* This is a variable we care about. Check if we have seen it
271 before, and if not add it the set of variables we care about. */
272 if (all_module_statics
273 && !bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
279 /* Lookup the tree node for the static variable that has UID and
280 convert the name to a string for debugging. */
283 get_static_name (int index
)
285 splay_tree_node stn
=
286 splay_tree_lookup (reference_vars_to_consider
, index
);
287 return fndecl_name ((tree
)(stn
->value
));
290 /* Dump a set of static vars to FILE. */
292 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
298 else if (set
== all_module_statics
)
301 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
303 fprintf (f
, "%s ", get_static_name (index
));
307 /* Compute X |= Y, taking into account the possibility that
308 either X or Y is already the maximum set.
309 Return true if X is the maximum set after taking the union with Y. */
312 union_static_var_sets (bitmap
&x
, bitmap y
)
314 if (x
!= all_module_statics
)
316 if (y
== all_module_statics
)
319 x
= all_module_statics
;
321 else if (bitmap_ior_into (x
, y
))
323 /* The union may have reduced X to the maximum set.
324 In that case, we want to make that visible explicitly.
325 Even though bitmap_equal_p can be very expensive, it
326 turns out to be an overall win to check this here for
327 an LTO bootstrap of GCC itself. Liberally extrapoliate
328 that result to be applicable to all cases. */
329 if (bitmap_equal_p (x
, all_module_statics
))
332 x
= all_module_statics
;
336 return x
== all_module_statics
;
339 /* Return a copy of SET on the bitmap obstack containing SET.
340 But if SET is NULL or the maximum set, return that instead. */
343 copy_static_var_set (bitmap set
)
345 if (set
== NULL
|| set
== all_module_statics
)
347 bitmap_obstack
*o
= set
->obstack
;
348 gcc_checking_assert (o
);
349 bitmap copy
= BITMAP_ALLOC (o
);
350 bitmap_copy (copy
, set
);
354 /* Compute the union all of the statics read and written by every callee of X
355 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
356 actually the set representing the cycle containing X. If the read and
357 written sets of X_GLOBAL has been reduced to the maximum set, we don't
358 have to look at the remaining callees. */
361 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
363 struct cgraph_edge
*e
;
364 bool read_all
= x_global
->statics_read
== all_module_statics
;
365 bool write_all
= x_global
->statics_written
== all_module_statics
;
367 e
&& !(read_all
&& write_all
);
370 enum availability avail
;
371 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
375 /* Only look into nodes we can propagate something. */
376 int flags
= flags_from_decl_or_type (y
->decl
);
377 if (avail
> AVAIL_INTERPOSABLE
378 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
)))
380 if (get_reference_vars_info (y
))
382 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
383 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
385 /* Calls in the current cycle do not have their global set
386 computed yet (but everything else does because we're
387 visiting nodes in topological order). */
388 if (!y_global
->statics_read
)
391 /* If the function is const, it reads no memory even if it
392 seems so to local analysis. */
393 if (flags
& ECF_CONST
)
396 union_static_var_sets (x_global
->statics_read
,
397 y_global
->statics_read
);
399 /* If the function is pure, it has no stores even if it
400 seems so to local analysis. If we cannot return from
401 the function, we can safely ignore the call. */
402 if ((flags
& ECF_PURE
)
403 || e
->cannot_lead_to_return_p ())
406 union_static_var_sets (x_global
->statics_written
,
407 y_global
->statics_written
);
415 static bool ipa_init_p
= false;
417 /* The init routine for analyzing global static variable usage. See
418 comments at top for description. */
428 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
430 bitmap_obstack_initialize (&local_info_obstack
);
431 bitmap_obstack_initialize (&optimization_summary_obstack
);
432 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
434 node_removal_hook_holder
=
435 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
436 node_duplication_hook_holder
=
437 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
441 /* Set up the persistent info for FN. */
443 static ipa_reference_local_vars_info_t
444 init_function_info (struct cgraph_node
*fn
)
446 ipa_reference_vars_info_t info
447 = XCNEW (struct ipa_reference_vars_info_d
);
449 /* Add the info to the tree's annotation. */
450 set_reference_vars_info (fn
, info
);
452 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
453 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
459 /* This is the main routine for finding the reference patterns for
460 global variables within a function FN. */
463 analyze_function (struct cgraph_node
*fn
)
465 ipa_reference_local_vars_info_t local
;
466 struct ipa_ref
*ref
= NULL
;
470 local
= init_function_info (fn
);
471 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
473 if (!is_a
<varpool_node
*> (ref
->referred
))
475 var
= ref
->referred
->decl
;
476 if (!is_proper_for_analysis (var
))
481 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
484 if (ref
->cannot_lead_to_return ())
486 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
495 if (fn
->cannot_return_p ())
496 bitmap_clear (local
->statics_written
);
500 /* Called when new clone is inserted to callgraph late. */
503 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
504 void *data ATTRIBUTE_UNUSED
)
506 ipa_reference_optimization_summary_t ginfo
;
507 ipa_reference_optimization_summary_t dst_ginfo
;
509 ginfo
= get_reference_optimization_summary (src
);
512 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
513 set_reference_optimization_summary (dst
, dst_ginfo
);
514 dst_ginfo
->statics_not_read
=
515 copy_static_var_set (ginfo
->statics_not_read
);
516 dst_ginfo
->statics_not_written
=
517 copy_static_var_set (ginfo
->statics_not_written
);
520 /* Called when node is removed. */
523 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
525 ipa_reference_optimization_summary_t ginfo
;
526 ginfo
= get_reference_optimization_summary (node
);
529 if (ginfo
->statics_not_read
530 && ginfo
->statics_not_read
!= all_module_statics
)
531 BITMAP_FREE (ginfo
->statics_not_read
);
533 if (ginfo
->statics_not_written
534 && ginfo
->statics_not_written
!= all_module_statics
)
535 BITMAP_FREE (ginfo
->statics_not_written
);
537 set_reference_optimization_summary (node
, NULL
);
541 /* Analyze each function in the cgraph to see which global or statics
542 are read or written. */
545 generate_summary (void)
547 struct cgraph_node
*node
;
553 /* Process all of the functions next. */
554 FOR_EACH_DEFINED_FUNCTION (node
)
555 analyze_function (node
);
558 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
560 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
561 get_static_name (index
), index
);
565 FOR_EACH_DEFINED_FUNCTION (node
)
566 if (node
->get_availability () >= AVAIL_INTERPOSABLE
)
568 ipa_reference_local_vars_info_t l
;
572 l
= &get_reference_vars_info (node
)->local
;
574 "\nFunction name:%s/%i:",
575 node
->asm_name (), node
->order
);
576 fprintf (dump_file
, "\n locals read: ");
578 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
581 fprintf (dump_file
, "%s ",
582 get_static_name (index
));
584 fprintf (dump_file
, "\n locals written: ");
585 if (l
->statics_written
)
586 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
589 fprintf (dump_file
, "%s ", get_static_name (index
));
594 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
597 read_write_all_from_decl (struct cgraph_node
*node
,
598 bool &read_all
, bool &write_all
)
600 tree decl
= node
->decl
;
601 int flags
= flags_from_decl_or_type (decl
);
602 if ((flags
& ECF_LEAF
)
603 && node
->get_availability () <= AVAIL_INTERPOSABLE
)
605 else if (flags
& ECF_CONST
)
607 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
610 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
611 fprintf (dump_file
, " %s/%i -> read all\n",
612 node
->asm_name (), node
->order
);
616 /* TODO: To be able to produce sane results, we should also handle
617 common builtins, in particular throw. */
620 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
621 fprintf (dump_file
, " %s/%i -> read all, write all\n",
622 node
->asm_name (), node
->order
);
626 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
627 in the cycle of NODE. */
630 get_read_write_all_from_node (struct cgraph_node
*node
,
631 bool &read_all
, bool &write_all
)
633 struct cgraph_edge
*e
, *ie
;
635 /* When function is overwritable, we can not assume anything. */
636 if (node
->get_availability () <= AVAIL_INTERPOSABLE
)
637 read_write_all_from_decl (node
, read_all
, write_all
);
639 for (e
= node
->callees
;
640 e
&& !(read_all
&& write_all
);
643 enum availability avail
;
644 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
645 gcc_checking_assert (callee
);
646 if (avail
<= AVAIL_INTERPOSABLE
)
647 read_write_all_from_decl (callee
, read_all
, write_all
);
650 for (ie
= node
->indirect_calls
;
651 ie
&& !(read_all
&& write_all
);
652 ie
= ie
->next_callee
)
653 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
656 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
657 fprintf (dump_file
, " indirect call -> read all\n");
658 if (!ie
->cannot_lead_to_return_p ()
659 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
661 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
662 fprintf (dump_file
, " indirect call -> write all\n");
668 /* Produce the global information by preforming a transitive closure
669 on the local information that was produced by ipa_analyze_function. */
674 struct cgraph_node
*node
;
675 struct cgraph_node
**order
=
676 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
682 cgraph_node::dump_cgraph (dump_file
);
684 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
687 /* Propagate the local information through the call graph to produce
688 the global information. All the nodes within a cycle will have
689 the same info so we collapse cycles first. Then we can do the
690 propagation in one pass from the leaves to the roots. */
691 order_pos
= ipa_reduced_postorder (order
, true, true, NULL
);
693 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
695 for (i
= 0; i
< order_pos
; i
++ )
698 struct cgraph_node
*w
;
699 ipa_reference_vars_info_t node_info
;
700 ipa_reference_global_vars_info_t node_g
;
701 ipa_reference_local_vars_info_t node_l
;
702 bool read_all
= false;
703 bool write_all
= false;
709 node_info
= get_reference_vars_info (node
);
710 gcc_assert (node_info
);
711 node_l
= &node_info
->local
;
712 node_g
= &node_info
->global
;
714 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
715 fprintf (dump_file
, "Starting cycle with %s/%i\n",
716 node
->asm_name (), node
->order
);
718 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
720 /* If any node in a cycle is read_all or write_all, they all are. */
721 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
723 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
724 fprintf (dump_file
, " Visiting %s/%i\n",
725 w
->asm_name (), w
->order
);
726 get_read_write_all_from_node (w
, read_all
, write_all
);
727 if (read_all
&& write_all
)
731 /* Initialized the bitmaps global sets for the reduced node. */
733 node_g
->statics_read
= all_module_statics
;
735 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
737 node_g
->statics_written
= all_module_statics
;
739 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
741 /* Merge the sets of this cycle with all sets of callees reached
743 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
745 if (read_all
&& write_all
)
750 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
751 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
752 int flags
= flags_from_decl_or_type (w
->decl
);
754 if (!(flags
& ECF_CONST
))
755 read_all
= union_static_var_sets (node_g
->statics_read
,
757 if (!(flags
& ECF_PURE
)
758 && !w
->cannot_return_p ())
759 write_all
= union_static_var_sets (node_g
->statics_written
,
760 w_l
->statics_written
);
763 propagate_bits (node_g
, w
);
766 /* All nodes within a cycle have the same global info bitmaps. */
767 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
769 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
770 w_ri
->global
= *node_g
;
773 cycle_nodes
.release ();
778 for (i
= 0; i
< order_pos
; i
++)
781 struct cgraph_node
*w
;
788 "\nFunction name:%s/%i:",
789 node
->asm_name (), node
->order
);
791 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
792 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
794 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
795 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
797 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
798 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
800 fprintf (dump_file
, "\n next cycle: %s/%i ",
801 w
->asm_name (), w
->order
);
802 fprintf (dump_file
, "\n locals read: ");
803 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
804 fprintf (dump_file
, "\n locals written: ");
805 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
807 cycle_nodes
.release ();
809 fprintf (dump_file
, "\n globals read: ");
810 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
811 fprintf (dump_file
, "\n globals written: ");
812 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
813 fprintf (dump_file
, "\n");
818 FOR_EACH_DEFINED_FUNCTION (node
)
820 ipa_reference_vars_info_t node_info
;
821 ipa_reference_global_vars_info_t node_g
;
822 ipa_reference_optimization_summary_t opt
;
824 node_info
= get_reference_vars_info (node
);
826 && (node
->get_availability () > AVAIL_INTERPOSABLE
827 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
829 node_g
= &node_info
->global
;
831 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
832 set_reference_optimization_summary (node
, opt
);
834 /* Create the complimentary sets. */
836 if (bitmap_empty_p (node_g
->statics_read
))
837 opt
->statics_not_read
= all_module_statics
;
840 opt
->statics_not_read
841 = BITMAP_ALLOC (&optimization_summary_obstack
);
842 if (node_g
->statics_read
!= all_module_statics
)
843 bitmap_and_compl (opt
->statics_not_read
,
845 node_g
->statics_read
);
848 if (bitmap_empty_p (node_g
->statics_written
))
849 opt
->statics_not_written
= all_module_statics
;
852 opt
->statics_not_written
853 = BITMAP_ALLOC (&optimization_summary_obstack
);
854 if (node_g
->statics_written
!= all_module_statics
)
855 bitmap_and_compl (opt
->statics_not_written
,
857 node_g
->statics_written
);
863 ipa_free_postorder_info ();
866 bitmap_obstack_release (&local_info_obstack
);
867 ipa_reference_vars_vector
.release ();
869 splay_tree_delete (reference_vars_to_consider
);
870 reference_vars_to_consider
= NULL
;
871 return remove_p
? TODO_remove_functions
: 0;
874 /* Return true if we need to write summary of NODE. */
877 write_node_summary_p (struct cgraph_node
*node
,
878 lto_symtab_encoder_t encoder
,
879 bitmap ltrans_statics
)
881 ipa_reference_optimization_summary_t info
;
883 /* See if we have (non-empty) info. */
884 if (!node
->definition
|| node
->global
.inlined_to
)
886 info
= get_reference_optimization_summary (node
);
887 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
888 && bitmap_empty_p (info
->statics_not_written
)))
891 /* See if we want to encode it.
892 Encode also referenced functions since constant folding might turn it into
895 In future we might also want to include summaries of functions references
896 by initializers of constant variables references in current unit. */
897 if (!reachable_from_this_partition_p (node
, encoder
)
898 && !referenced_from_this_partition_p (node
, encoder
))
901 /* See if the info has non-empty intersections with vars we want to encode. */
902 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
903 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
908 /* Stream out BITS<RANS_STATICS as list of decls to OB.
909 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
910 or -1. When it is positive, just output -1 when
911 BITS<RANS_STATICS == BITS<RANS_STATICS. */
914 stream_out_bitmap (struct lto_simple_output_block
*ob
,
915 bitmap bits
, bitmap ltrans_statics
,
916 int ltrans_statics_bitcount
)
921 if (bits
== all_module_statics
)
923 streamer_write_hwi_stream (ob
->main_stream
, -1);
926 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
928 if (count
== ltrans_statics_bitcount
)
930 streamer_write_hwi_stream (ob
->main_stream
, -1);
933 streamer_write_hwi_stream (ob
->main_stream
, count
);
936 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
938 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
939 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
943 /* Serialize the ipa info for lto. */
946 ipa_reference_write_optimization_summary (void)
948 struct lto_simple_output_block
*ob
949 = lto_create_simple_output_block (LTO_section_ipa_reference
);
950 unsigned int count
= 0;
951 int ltrans_statics_bitcount
= 0;
952 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
953 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
956 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
958 /* See what variables we are interested in. */
959 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
961 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
962 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
964 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
965 && referenced_from_this_partition_p (vnode
, encoder
))
967 tree decl
= vnode
->decl
;
968 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
969 splay_tree_insert (reference_vars_to_consider
,
970 DECL_UID (decl
), (splay_tree_value
)decl
);
971 ltrans_statics_bitcount
++;
976 if (ltrans_statics_bitcount
)
977 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
979 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
980 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
981 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
985 streamer_write_uhwi_stream (ob
->main_stream
, count
);
987 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
990 /* Process all of the functions. */
991 if (ltrans_statics_bitcount
)
992 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
994 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
995 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
996 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
998 ipa_reference_optimization_summary_t info
;
1001 info
= get_reference_optimization_summary (cnode
);
1002 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1003 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1005 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1006 ltrans_statics_bitcount
);
1007 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1008 ltrans_statics_bitcount
);
1011 BITMAP_FREE (ltrans_statics
);
1012 lto_destroy_simple_output_block (ob
);
1013 splay_tree_delete (reference_vars_to_consider
);
1016 /* Deserialize the ipa info for lto. */
1019 ipa_reference_read_optimization_summary (void)
1021 struct lto_file_decl_data
** file_data_vec
1022 = lto_get_file_decl_data ();
1023 struct lto_file_decl_data
* file_data
;
1025 bitmap_obstack_initialize (&optimization_summary_obstack
);
1027 node_removal_hook_holder
=
1028 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1029 node_duplication_hook_holder
=
1030 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1031 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1033 while ((file_data
= file_data_vec
[j
++]))
1037 struct lto_input_block
*ib
1038 = lto_create_simple_input_block (file_data
,
1039 LTO_section_ipa_reference
,
1044 unsigned int f_count
= streamer_read_uhwi (ib
);
1048 b_count
= streamer_read_hwi (ib
);
1050 fprintf (dump_file
, "all module statics:");
1051 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1053 unsigned int var_index
= streamer_read_uhwi (ib
);
1054 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1056 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1058 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1061 for (i
= 0; i
< f_count
; i
++)
1063 unsigned int j
, index
;
1064 struct cgraph_node
*node
;
1065 ipa_reference_optimization_summary_t info
;
1067 lto_symtab_encoder_t encoder
;
1069 index
= streamer_read_uhwi (ib
);
1070 encoder
= file_data
->symtab_node_encoder
;
1071 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1073 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1074 set_reference_optimization_summary (node
, info
);
1075 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1076 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1079 "\nFunction name:%s/%i:\n static not read:",
1080 node
->asm_name (), node
->order
);
1082 /* Set the statics not read. */
1083 v_count
= streamer_read_hwi (ib
);
1086 info
->statics_not_read
= all_module_statics
;
1088 fprintf (dump_file
, " all module statics");
1091 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1093 unsigned int var_index
= streamer_read_uhwi (ib
);
1094 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1096 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1098 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1103 "\n static not written:");
1104 /* Set the statics not written. */
1105 v_count
= streamer_read_hwi (ib
);
1108 info
->statics_not_written
= all_module_statics
;
1110 fprintf (dump_file
, " all module statics");
1113 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1115 unsigned int var_index
= streamer_read_uhwi (ib
);
1116 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1118 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1120 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1123 fprintf (dump_file
, "\n");
1126 lto_destroy_simple_input_block (file_data
,
1127 LTO_section_ipa_reference
,
1131 /* Fatal error here. We do not want to support compiling ltrans units with
1132 different version of compiler or different flags than the WPA unit, so
1133 this should never happen. */
1134 fatal_error ("ipa reference summary is missing in ltrans unit");
1140 const pass_data pass_data_ipa_reference
=
1142 IPA_PASS
, /* type */
1143 "static-var", /* name */
1144 OPTGROUP_NONE
, /* optinfo_flags */
1145 TV_IPA_REFERENCE
, /* tv_id */
1146 0, /* properties_required */
1147 0, /* properties_provided */
1148 0, /* properties_destroyed */
1149 0, /* todo_flags_start */
1150 0, /* todo_flags_finish */
1153 class pass_ipa_reference
: public ipa_opt_pass_d
1156 pass_ipa_reference (gcc::context
*ctxt
)
1157 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1158 NULL
, /* generate_summary */
1159 NULL
, /* write_summary */
1160 NULL
, /* read_summary */
1161 ipa_reference_write_optimization_summary
, /*
1162 write_optimization_summary */
1163 ipa_reference_read_optimization_summary
, /*
1164 read_optimization_summary */
1165 NULL
, /* stmt_fixup */
1166 0, /* function_transform_todo_flags_start */
1167 NULL
, /* function_transform */
1168 NULL
) /* variable_transform */
1171 /* opt_pass methods: */
1172 virtual bool gate (function
*)
1174 return (flag_ipa_reference
1175 /* Don't bother doing anything if the program has errors. */
1179 virtual unsigned int execute (function
*) { return propagate (); }
1181 }; // class pass_ipa_reference
1186 make_pass_ipa_reference (gcc::context
*ctxt
)
1188 return new pass_ipa_reference (ctxt
);
1191 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1192 within the same process. For use by toplev::finalize. */
1195 ipa_reference_c_finalize (void)
1199 bitmap_obstack_release (&optimization_summary_obstack
);
1203 if (node_removal_hook_holder
)
1205 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1206 node_removal_hook_holder
= NULL
;
1208 if (node_duplication_hook_holder
)
1210 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1211 node_duplication_hook_holder
= NULL
;