1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2015 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"
47 #include "fold-const.h"
50 #include "hard-reg-set.h"
52 #include "basic-block.h"
53 #include "tree-ssa-alias.h"
54 #include "internal-fn.h"
55 #include "gimple-expr.h"
57 #include "tree-inline.h"
58 #include "tree-pass.h"
59 #include "splay-tree.h"
60 #include "plugin-api.h"
63 #include "ipa-utils.h"
65 #include "ipa-reference.h"
67 #include "diagnostic.h"
68 #include "data-streamer.h"
69 #include "lto-streamer.h"
71 static void remove_node_data (struct cgraph_node
*node
,
72 void *data ATTRIBUTE_UNUSED
);
73 static void duplicate_node_data (struct cgraph_node
*src
,
74 struct cgraph_node
*dst
,
75 void *data ATTRIBUTE_UNUSED
);
77 /* The static variables defined within the compilation unit that are
78 loaded or stored directly by function that owns this structure. */
80 struct ipa_reference_local_vars_info_d
83 bitmap statics_written
;
86 /* Statics that are read and written by some set of functions. The
87 local ones are based on the loads and stores local to the function.
88 The global ones are based on the local info as well as the
89 transitive closure of the functions that are called. */
91 struct ipa_reference_global_vars_info_d
94 bitmap statics_written
;
97 /* Information we save about every function after ipa-reference is completed. */
99 struct ipa_reference_optimization_summary_d
101 bitmap statics_not_read
;
102 bitmap statics_not_written
;
105 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
106 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
107 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
109 struct ipa_reference_vars_info_d
111 struct ipa_reference_local_vars_info_d local
;
112 struct ipa_reference_global_vars_info_d global
;
115 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
117 /* This splay tree contains all of the static variables that are
118 being considered by the compilation level alias analysis. */
119 static splay_tree reference_vars_to_consider
;
121 /* Set of all interesting module statics. A bit is set for every module
122 static we are considering. This is added to the local info when asm
123 code is found that clobbers all memory. */
124 static bitmap all_module_statics
;
125 /* Set of all statics that should be ignored becuase they are touched by
126 -fno-ipa-reference code. */
127 static bitmap ignore_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 /* TODO: find a place where we should release the vector. */
144 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
146 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
147 static inline ipa_reference_vars_info_t
148 get_reference_vars_info (struct cgraph_node
*node
)
150 if (!ipa_reference_vars_vector
.exists ()
151 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
153 return ipa_reference_vars_vector
[node
->uid
];
156 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
157 static inline ipa_reference_optimization_summary_t
158 get_reference_optimization_summary (struct cgraph_node
*node
)
160 if (!ipa_reference_opt_sum_vector
.exists ()
161 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
163 return ipa_reference_opt_sum_vector
[node
->uid
];
166 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
168 set_reference_vars_info (struct cgraph_node
*node
,
169 ipa_reference_vars_info_t info
)
171 if (!ipa_reference_vars_vector
.exists ()
172 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
173 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
174 ipa_reference_vars_vector
[node
->uid
] = info
;
177 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
179 set_reference_optimization_summary (struct cgraph_node
*node
,
180 ipa_reference_optimization_summary_t info
)
182 if (!ipa_reference_opt_sum_vector
.exists ()
183 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
184 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
185 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
188 /* Return a bitmap indexed by DECL_UID for the static variables that
189 are *not* read during the execution of the function FN. Returns
190 NULL if no data is available. */
193 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
195 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
196 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
198 ipa_reference_optimization_summary_t info
=
199 get_reference_optimization_summary (fn
->function_symbol (NULL
));
201 return info
->statics_not_read
;
202 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
203 return all_module_statics
;
208 /* Return a bitmap indexed by DECL_UID for the static variables that
209 are *not* written during the execution of the function FN. Note
210 that variables written may or may not be read during the function
211 call. Returns NULL if no data is available. */
214 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
216 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
217 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
219 ipa_reference_optimization_summary_t info
=
220 get_reference_optimization_summary (fn
);
222 return info
->statics_not_written
;
223 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
224 return all_module_statics
;
230 /* Return true if the variable T is the right kind of static variable to
231 perform compilation unit scope escape analysis. */
234 is_proper_for_analysis (tree t
)
236 /* If the variable has the "used" attribute, treat it as if it had a
237 been touched by the devil. */
238 if (DECL_PRESERVE_P (t
))
241 /* Do not want to do anything with volatile except mark any
242 function that uses one to be not const or pure. */
243 if (TREE_THIS_VOLATILE (t
))
246 /* We do not need to analyze readonly vars, we already know they do not
248 if (TREE_READONLY (t
))
251 /* We can not track variables with address taken. */
252 if (TREE_ADDRESSABLE (t
))
255 /* TODO: We could track public variables that are not addressable, but currently
256 frontends don't give us those. */
260 /* TODO: Check aliases. */
261 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
267 /* Lookup the tree node for the static variable that has UID and
268 convert the name to a string for debugging. */
271 get_static_name (int index
)
273 splay_tree_node stn
=
274 splay_tree_lookup (reference_vars_to_consider
, index
);
275 return fndecl_name ((tree
)(stn
->value
));
278 /* Dump a set of static vars to FILE. */
280 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
286 else if (set
== all_module_statics
)
289 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
291 fprintf (f
, "%s ", get_static_name (index
));
295 /* Compute X |= Y, taking into account the possibility that
296 either X or Y is already the maximum set.
297 Return true if X is the maximum set after taking the union with Y. */
300 union_static_var_sets (bitmap
&x
, bitmap y
)
302 if (x
!= all_module_statics
)
304 if (y
== all_module_statics
)
307 x
= all_module_statics
;
309 else if (bitmap_ior_into (x
, y
))
311 /* The union may have reduced X to the maximum set.
312 In that case, we want to make that visible explicitly.
313 Even though bitmap_equal_p can be very expensive, it
314 turns out to be an overall win to check this here for
315 an LTO bootstrap of GCC itself. Liberally extrapoliate
316 that result to be applicable to all cases. */
317 if (bitmap_equal_p (x
, all_module_statics
))
320 x
= all_module_statics
;
324 return x
== all_module_statics
;
327 /* Return a copy of SET on the bitmap obstack containing SET.
328 But if SET is NULL or the maximum set, return that instead. */
331 copy_static_var_set (bitmap set
)
333 if (set
== NULL
|| set
== all_module_statics
)
335 bitmap_obstack
*o
= set
->obstack
;
336 gcc_checking_assert (o
);
337 bitmap copy
= BITMAP_ALLOC (o
);
338 bitmap_copy (copy
, set
);
342 /* Compute the union all of the statics read and written by every callee of X
343 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
344 actually the set representing the cycle containing X. If the read and
345 written sets of X_GLOBAL has been reduced to the maximum set, we don't
346 have to look at the remaining callees. */
349 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
351 struct cgraph_edge
*e
;
352 bool read_all
= x_global
->statics_read
== all_module_statics
;
353 bool write_all
= x_global
->statics_written
== all_module_statics
;
355 e
&& !(read_all
&& write_all
);
358 enum availability avail
;
359 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
363 /* Only look into nodes we can propagate something. */
364 int flags
= flags_from_decl_or_type (y
->decl
);
365 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
366 && (avail
> AVAIL_INTERPOSABLE
367 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
369 if (get_reference_vars_info (y
))
371 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
372 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
374 /* Calls in the current cycle do not have their global set
375 computed yet (but everything else does because we're
376 visiting nodes in topological order). */
377 if (!y_global
->statics_read
)
380 /* If the function is const, it reads no memory even if it
381 seems so to local analysis. */
382 if (flags
& ECF_CONST
)
385 union_static_var_sets (x_global
->statics_read
,
386 y_global
->statics_read
);
388 /* If the function is pure, it has no stores even if it
389 seems so to local analysis. If we cannot return from
390 the function, we can safely ignore the call. */
391 if ((flags
& ECF_PURE
)
392 || e
->cannot_lead_to_return_p ())
395 union_static_var_sets (x_global
->statics_written
,
396 y_global
->statics_written
);
404 static bool ipa_init_p
= false;
406 /* The init routine for analyzing global static variable usage. See
407 comments at top for description. */
417 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
419 bitmap_obstack_initialize (&local_info_obstack
);
420 bitmap_obstack_initialize (&optimization_summary_obstack
);
421 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
422 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
424 node_removal_hook_holder
=
425 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
426 node_duplication_hook_holder
=
427 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
431 /* Set up the persistent info for FN. */
433 static ipa_reference_local_vars_info_t
434 init_function_info (struct cgraph_node
*fn
)
436 ipa_reference_vars_info_t info
437 = XCNEW (struct ipa_reference_vars_info_d
);
439 /* Add the info to the tree's annotation. */
440 set_reference_vars_info (fn
, info
);
442 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
443 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
449 /* This is the main routine for finding the reference patterns for
450 global variables within a function FN. */
453 analyze_function (struct cgraph_node
*fn
)
455 ipa_reference_local_vars_info_t local
;
456 struct ipa_ref
*ref
= NULL
;
460 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
462 local
= init_function_info (fn
);
463 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
465 if (!is_a
<varpool_node
*> (ref
->referred
))
467 var
= ref
->referred
->decl
;
468 if (!is_proper_for_analysis (var
))
470 /* This is a variable we care about. Check if we have seen it
471 before, and if not add it the set of variables we care about. */
472 if (all_module_statics
473 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
476 splay_tree_insert (reference_vars_to_consider
,
477 DECL_UID (var
), (splay_tree_value
)var
);
482 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
485 if (ref
->cannot_lead_to_return ())
487 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
496 if (fn
->cannot_return_p ())
497 bitmap_clear (local
->statics_written
);
501 /* Called when new clone is inserted to callgraph late. */
504 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
505 void *data ATTRIBUTE_UNUSED
)
507 ipa_reference_optimization_summary_t ginfo
;
508 ipa_reference_optimization_summary_t dst_ginfo
;
510 ginfo
= get_reference_optimization_summary (src
);
513 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
514 set_reference_optimization_summary (dst
, dst_ginfo
);
515 dst_ginfo
->statics_not_read
=
516 copy_static_var_set (ginfo
->statics_not_read
);
517 dst_ginfo
->statics_not_written
=
518 copy_static_var_set (ginfo
->statics_not_written
);
521 /* Called when node is removed. */
524 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
526 ipa_reference_optimization_summary_t ginfo
;
527 ginfo
= get_reference_optimization_summary (node
);
530 if (ginfo
->statics_not_read
531 && ginfo
->statics_not_read
!= all_module_statics
)
532 BITMAP_FREE (ginfo
->statics_not_read
);
534 if (ginfo
->statics_not_written
535 && ginfo
->statics_not_written
!= all_module_statics
)
536 BITMAP_FREE (ginfo
->statics_not_written
);
538 set_reference_optimization_summary (node
, NULL
);
542 /* Analyze each function in the cgraph to see which global or statics
543 are read or written. */
546 generate_summary (void)
548 struct cgraph_node
*node
;
554 /* Process all of the functions next. */
555 FOR_EACH_DEFINED_FUNCTION (node
)
556 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
558 struct ipa_ref
*ref
= NULL
;
561 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
563 if (!is_a
<varpool_node
*> (ref
->referred
))
565 var
= ref
->referred
->decl
;
566 if (!is_proper_for_analysis (var
))
568 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
571 FOR_EACH_DEFINED_FUNCTION (node
)
572 analyze_function (node
);
575 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
577 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
578 get_static_name (index
), index
);
582 FOR_EACH_DEFINED_FUNCTION (node
)
583 if (node
->get_availability () >= AVAIL_INTERPOSABLE
584 && opt_for_fn (node
->decl
, flag_ipa_reference
))
586 ipa_reference_local_vars_info_t l
;
590 l
= &get_reference_vars_info (node
)->local
;
592 "\nFunction name:%s/%i:",
593 node
->asm_name (), node
->order
);
594 fprintf (dump_file
, "\n locals read: ");
596 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
599 fprintf (dump_file
, "%s ",
600 get_static_name (index
));
602 fprintf (dump_file
, "\n locals written: ");
603 if (l
->statics_written
)
604 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
607 fprintf (dump_file
, "%s ", get_static_name (index
));
612 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
615 read_write_all_from_decl (struct cgraph_node
*node
,
616 bool &read_all
, bool &write_all
)
618 tree decl
= node
->decl
;
619 int flags
= flags_from_decl_or_type (decl
);
620 if ((flags
& ECF_LEAF
)
621 && node
->get_availability () < AVAIL_INTERPOSABLE
)
623 else if (flags
& ECF_CONST
)
625 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
628 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
629 fprintf (dump_file
, " %s/%i -> read all\n",
630 node
->asm_name (), node
->order
);
634 /* TODO: To be able to produce sane results, we should also handle
635 common builtins, in particular throw. */
638 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
639 fprintf (dump_file
, " %s/%i -> read all, write all\n",
640 node
->asm_name (), node
->order
);
644 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
645 in the cycle of NODE. */
648 get_read_write_all_from_node (struct cgraph_node
*node
,
649 bool &read_all
, bool &write_all
)
651 struct cgraph_edge
*e
, *ie
;
653 /* When function is overwritable, we can not assume anything. */
654 if (node
->get_availability () <= AVAIL_INTERPOSABLE
655 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
656 read_write_all_from_decl (node
, read_all
, write_all
);
658 for (e
= node
->callees
;
659 e
&& !(read_all
&& write_all
);
662 enum availability avail
;
663 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
664 gcc_checking_assert (callee
);
665 if (avail
<= AVAIL_INTERPOSABLE
666 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
667 read_write_all_from_decl (callee
, read_all
, write_all
);
670 for (ie
= node
->indirect_calls
;
671 ie
&& !(read_all
&& write_all
);
672 ie
= ie
->next_callee
)
673 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
676 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
677 fprintf (dump_file
, " indirect call -> read all\n");
678 if (!ie
->cannot_lead_to_return_p ()
679 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
681 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
682 fprintf (dump_file
, " indirect call -> write all\n");
688 /* Skip edges from and to nodes without ipa_reference enables. This leave
689 them out of strongy connected coponents and makes them easyto skip in the
690 propagation loop bellow. */
693 ignore_edge_p (cgraph_edge
*e
)
695 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
696 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
697 flag_ipa_reference
));
700 /* Produce the global information by preforming a transitive closure
701 on the local information that was produced by ipa_analyze_function. */
706 struct cgraph_node
*node
;
707 struct cgraph_node
**order
=
708 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
714 cgraph_node::dump_cgraph (dump_file
);
716 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
719 /* Propagate the local information through the call graph to produce
720 the global information. All the nodes within a cycle will have
721 the same info so we collapse cycles first. Then we can do the
722 propagation in one pass from the leaves to the roots. */
723 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
725 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
727 for (i
= 0; i
< order_pos
; i
++ )
730 struct cgraph_node
*w
;
731 ipa_reference_vars_info_t node_info
;
732 ipa_reference_global_vars_info_t node_g
;
733 ipa_reference_local_vars_info_t node_l
;
734 bool read_all
= false;
735 bool write_all
= false;
738 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
741 node_info
= get_reference_vars_info (node
);
742 gcc_assert (node_info
);
743 node_l
= &node_info
->local
;
744 node_g
= &node_info
->global
;
746 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
747 fprintf (dump_file
, "Starting cycle with %s/%i\n",
748 node
->asm_name (), node
->order
);
750 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
752 /* If any node in a cycle is read_all or write_all, they all are. */
753 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
755 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
756 fprintf (dump_file
, " Visiting %s/%i\n",
757 w
->asm_name (), w
->order
);
758 get_read_write_all_from_node (w
, read_all
, write_all
);
759 if (read_all
&& write_all
)
763 /* Initialized the bitmaps global sets for the reduced node. */
765 node_g
->statics_read
= all_module_statics
;
767 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
769 node_g
->statics_written
= all_module_statics
;
771 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
773 /* Merge the sets of this cycle with all sets of callees reached
775 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
777 if (read_all
&& write_all
)
782 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
783 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
784 int flags
= flags_from_decl_or_type (w
->decl
);
786 if (!(flags
& ECF_CONST
))
787 read_all
= union_static_var_sets (node_g
->statics_read
,
789 if (!(flags
& ECF_PURE
)
790 && !w
->cannot_return_p ())
791 write_all
= union_static_var_sets (node_g
->statics_written
,
792 w_l
->statics_written
);
795 propagate_bits (node_g
, w
);
798 /* All nodes within a cycle have the same global info bitmaps. */
799 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
801 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
802 w_ri
->global
= *node_g
;
805 cycle_nodes
.release ();
810 for (i
= 0; i
< order_pos
; i
++)
813 struct cgraph_node
*w
;
816 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
820 "\nFunction name:%s/%i:",
821 node
->asm_name (), node
->order
);
823 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
824 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
826 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
827 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
829 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
830 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
832 fprintf (dump_file
, "\n next cycle: %s/%i ",
833 w
->asm_name (), w
->order
);
834 fprintf (dump_file
, "\n locals read: ");
835 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
836 fprintf (dump_file
, "\n locals written: ");
837 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
839 cycle_nodes
.release ();
841 fprintf (dump_file
, "\n globals read: ");
842 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
843 fprintf (dump_file
, "\n globals written: ");
844 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
845 fprintf (dump_file
, "\n");
850 FOR_EACH_DEFINED_FUNCTION (node
)
852 ipa_reference_vars_info_t node_info
;
853 ipa_reference_global_vars_info_t node_g
;
854 ipa_reference_optimization_summary_t opt
;
856 node_info
= get_reference_vars_info (node
);
857 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
858 && (node
->get_availability () > AVAIL_INTERPOSABLE
859 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
861 node_g
= &node_info
->global
;
863 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
864 set_reference_optimization_summary (node
, opt
);
866 /* Create the complimentary sets. */
868 if (bitmap_empty_p (node_g
->statics_read
))
869 opt
->statics_not_read
= all_module_statics
;
872 opt
->statics_not_read
873 = BITMAP_ALLOC (&optimization_summary_obstack
);
874 if (node_g
->statics_read
!= all_module_statics
)
875 bitmap_and_compl (opt
->statics_not_read
,
877 node_g
->statics_read
);
880 if (bitmap_empty_p (node_g
->statics_written
))
881 opt
->statics_not_written
= all_module_statics
;
884 opt
->statics_not_written
885 = BITMAP_ALLOC (&optimization_summary_obstack
);
886 if (node_g
->statics_written
!= all_module_statics
)
887 bitmap_and_compl (opt
->statics_not_written
,
889 node_g
->statics_written
);
895 ipa_free_postorder_info ();
898 bitmap_obstack_release (&local_info_obstack
);
899 ipa_reference_vars_vector
.release ();
901 splay_tree_delete (reference_vars_to_consider
);
902 reference_vars_to_consider
= NULL
;
903 return remove_p
? TODO_remove_functions
: 0;
906 /* Return true if we need to write summary of NODE. */
909 write_node_summary_p (struct cgraph_node
*node
,
910 lto_symtab_encoder_t encoder
,
911 bitmap ltrans_statics
)
913 ipa_reference_optimization_summary_t info
;
915 /* See if we have (non-empty) info. */
916 if (!node
->definition
|| node
->global
.inlined_to
)
918 info
= get_reference_optimization_summary (node
);
919 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
920 && bitmap_empty_p (info
->statics_not_written
)))
923 /* See if we want to encode it.
924 Encode also referenced functions since constant folding might turn it into
927 In future we might also want to include summaries of functions references
928 by initializers of constant variables references in current unit. */
929 if (!reachable_from_this_partition_p (node
, encoder
)
930 && !referenced_from_this_partition_p (node
, encoder
))
933 /* See if the info has non-empty intersections with vars we want to encode. */
934 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
935 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
940 /* Stream out BITS<RANS_STATICS as list of decls to OB.
941 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
942 or -1. When it is positive, just output -1 when
943 BITS<RANS_STATICS == BITS<RANS_STATICS. */
946 stream_out_bitmap (struct lto_simple_output_block
*ob
,
947 bitmap bits
, bitmap ltrans_statics
,
948 int ltrans_statics_bitcount
)
953 if (bits
== all_module_statics
)
955 streamer_write_hwi_stream (ob
->main_stream
, -1);
958 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
960 if (count
== ltrans_statics_bitcount
)
962 streamer_write_hwi_stream (ob
->main_stream
, -1);
965 streamer_write_hwi_stream (ob
->main_stream
, count
);
968 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
970 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
971 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
975 /* Serialize the ipa info for lto. */
978 ipa_reference_write_optimization_summary (void)
980 struct lto_simple_output_block
*ob
981 = lto_create_simple_output_block (LTO_section_ipa_reference
);
982 unsigned int count
= 0;
983 int ltrans_statics_bitcount
= 0;
984 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
985 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
988 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
990 /* See what variables we are interested in. */
991 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
993 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
994 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
996 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
997 && referenced_from_this_partition_p (vnode
, encoder
))
999 tree decl
= vnode
->decl
;
1000 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
1001 splay_tree_insert (reference_vars_to_consider
,
1002 DECL_UID (decl
), (splay_tree_value
)decl
);
1003 ltrans_statics_bitcount
++;
1008 if (ltrans_statics_bitcount
)
1009 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1011 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1012 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1013 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1017 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1019 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1022 /* Process all of the functions. */
1023 if (ltrans_statics_bitcount
)
1024 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1026 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1027 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1028 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1030 ipa_reference_optimization_summary_t info
;
1033 info
= get_reference_optimization_summary (cnode
);
1034 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1035 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1037 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1038 ltrans_statics_bitcount
);
1039 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1040 ltrans_statics_bitcount
);
1043 BITMAP_FREE (ltrans_statics
);
1044 lto_destroy_simple_output_block (ob
);
1045 splay_tree_delete (reference_vars_to_consider
);
1048 /* Deserialize the ipa info for lto. */
1051 ipa_reference_read_optimization_summary (void)
1053 struct lto_file_decl_data
** file_data_vec
1054 = lto_get_file_decl_data ();
1055 struct lto_file_decl_data
* file_data
;
1057 bitmap_obstack_initialize (&optimization_summary_obstack
);
1059 node_removal_hook_holder
=
1060 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1061 node_duplication_hook_holder
=
1062 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1063 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1065 while ((file_data
= file_data_vec
[j
++]))
1069 struct lto_input_block
*ib
1070 = lto_create_simple_input_block (file_data
,
1071 LTO_section_ipa_reference
,
1076 unsigned int f_count
= streamer_read_uhwi (ib
);
1080 b_count
= streamer_read_hwi (ib
);
1082 fprintf (dump_file
, "all module statics:");
1083 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1085 unsigned int var_index
= streamer_read_uhwi (ib
);
1086 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1088 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1090 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1093 for (i
= 0; i
< f_count
; i
++)
1095 unsigned int j
, index
;
1096 struct cgraph_node
*node
;
1097 ipa_reference_optimization_summary_t info
;
1099 lto_symtab_encoder_t encoder
;
1101 index
= streamer_read_uhwi (ib
);
1102 encoder
= file_data
->symtab_node_encoder
;
1103 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1105 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1106 set_reference_optimization_summary (node
, info
);
1107 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1108 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1111 "\nFunction name:%s/%i:\n static not read:",
1112 node
->asm_name (), node
->order
);
1114 /* Set the statics not read. */
1115 v_count
= streamer_read_hwi (ib
);
1118 info
->statics_not_read
= all_module_statics
;
1120 fprintf (dump_file
, " all module statics");
1123 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1125 unsigned int var_index
= streamer_read_uhwi (ib
);
1126 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1128 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1130 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1135 "\n static not written:");
1136 /* Set the statics not written. */
1137 v_count
= streamer_read_hwi (ib
);
1140 info
->statics_not_written
= all_module_statics
;
1142 fprintf (dump_file
, " all module statics");
1145 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1147 unsigned int var_index
= streamer_read_uhwi (ib
);
1148 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1150 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1152 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1155 fprintf (dump_file
, "\n");
1158 lto_destroy_simple_input_block (file_data
,
1159 LTO_section_ipa_reference
,
1163 /* Fatal error here. We do not want to support compiling ltrans units with
1164 different version of compiler or different flags than the WPA unit, so
1165 this should never happen. */
1166 fatal_error (input_location
,
1167 "ipa reference summary is missing in ltrans unit");
1173 const pass_data pass_data_ipa_reference
=
1175 IPA_PASS
, /* type */
1176 "static-var", /* name */
1177 OPTGROUP_NONE
, /* optinfo_flags */
1178 TV_IPA_REFERENCE
, /* tv_id */
1179 0, /* properties_required */
1180 0, /* properties_provided */
1181 0, /* properties_destroyed */
1182 0, /* todo_flags_start */
1183 0, /* todo_flags_finish */
1186 class pass_ipa_reference
: public ipa_opt_pass_d
1189 pass_ipa_reference (gcc::context
*ctxt
)
1190 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1191 NULL
, /* generate_summary */
1192 NULL
, /* write_summary */
1193 NULL
, /* read_summary */
1194 ipa_reference_write_optimization_summary
, /*
1195 write_optimization_summary */
1196 ipa_reference_read_optimization_summary
, /*
1197 read_optimization_summary */
1198 NULL
, /* stmt_fixup */
1199 0, /* function_transform_todo_flags_start */
1200 NULL
, /* function_transform */
1201 NULL
) /* variable_transform */
1204 /* opt_pass methods: */
1205 virtual bool gate (function
*)
1207 return ((in_lto_p
|| flag_ipa_reference
)
1208 /* Don't bother doing anything if the program has errors. */
1212 virtual unsigned int execute (function
*) { return propagate (); }
1214 }; // class pass_ipa_reference
1219 make_pass_ipa_reference (gcc::context
*ctxt
)
1221 return new pass_ipa_reference (ctxt
);
1224 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1225 within the same process. For use by toplev::finalize. */
1228 ipa_reference_c_finalize (void)
1232 bitmap_obstack_release (&optimization_summary_obstack
);
1236 if (node_removal_hook_holder
)
1238 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1239 node_removal_hook_holder
= NULL
;
1241 if (node_duplication_hook_holder
)
1243 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1244 node_duplication_hook_holder
= NULL
;