1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2019 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-pass.h"
47 #include "data-streamer.h"
49 #include "ipa-utils.h"
50 #include "ipa-reference.h"
51 #include "symbol-summary.h"
53 /* The static variables defined within the compilation unit that are
54 loaded or stored directly by function that owns this structure. */
56 struct ipa_reference_local_vars_info_d
59 bitmap statics_written
;
62 /* Statics that are read and written by some set of functions. The
63 local ones are based on the loads and stores local to the function.
64 The global ones are based on the local info as well as the
65 transitive closure of the functions that are called. */
67 struct ipa_reference_global_vars_info_d
70 bitmap statics_written
;
73 /* Information we save about every function after ipa-reference is completed. */
75 struct ipa_reference_optimization_summary_d
78 bitmap statics_written
;
81 typedef ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
82 typedef ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
83 typedef ipa_reference_optimization_summary_d
*
84 ipa_reference_optimization_summary_t
;
86 struct ipa_reference_vars_info_d
88 struct ipa_reference_local_vars_info_d local
;
89 struct ipa_reference_global_vars_info_d global
;
92 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
94 /* This map contains all of the static variables that are
95 being considered by the compilation level alias analysis. */
96 typedef hash_map
<tree
, int> reference_vars_map_t
;
97 static reference_vars_map_t
*ipa_reference_vars_map
;
98 static int ipa_reference_vars_uids
;
99 static vec
<tree
> *reference_vars_to_consider
;
100 varpool_node_hook_list
*varpool_node_hooks
;
102 /* Set of all interesting module statics. A bit is set for every module
103 static we are considering. This is added to the local info when asm
104 code is found that clobbers all memory. */
105 static bitmap all_module_statics
;
107 static bitmap no_module_statics
;
108 /* Set of all statics that should be ignored because they are touched by
109 -fno-ipa-reference code. */
110 static bitmap ignore_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 class ipa_ref_var_info_summary_t
: public fast_function_summary
119 <ipa_reference_vars_info_d
*, va_heap
>
122 ipa_ref_var_info_summary_t (symbol_table
*symtab
):
123 fast_function_summary
<ipa_reference_vars_info_d
*, va_heap
> (symtab
) {}
126 static ipa_ref_var_info_summary_t
*ipa_ref_var_info_summaries
= NULL
;
128 class ipa_ref_opt_summary_t
: public fast_function_summary
129 <ipa_reference_optimization_summary_d
*, va_heap
>
132 ipa_ref_opt_summary_t (symbol_table
*symtab
):
133 fast_function_summary
<ipa_reference_optimization_summary_d
*, va_heap
> (symtab
) {}
135 virtual void remove (cgraph_node
*src_node
,
136 ipa_reference_optimization_summary_d
*data
);
137 virtual void duplicate (cgraph_node
*src_node
, cgraph_node
*dst_node
,
138 ipa_reference_optimization_summary_d
*src_data
,
139 ipa_reference_optimization_summary_d
*dst_data
);
142 static ipa_ref_opt_summary_t
*ipa_ref_opt_sum_summaries
= NULL
;
144 /* Return ID used by ipa-reference bitmaps. -1 if failed. */
146 ipa_reference_var_uid (tree t
)
148 if (!ipa_reference_vars_map
)
150 int *id
= ipa_reference_vars_map
->get
151 (symtab_node::get (t
)->ultimate_alias_target (NULL
)->decl
);
157 /* Return ID used by ipa-reference bitmaps. Create new entry if
158 T is not in map. Set EXISTED accordinly */
160 ipa_reference_var_get_or_insert_uid (tree t
, bool *existed
)
162 int &id
= ipa_reference_vars_map
->get_or_insert
163 (symtab_node::get (t
)->ultimate_alias_target (NULL
)->decl
, existed
);
165 id
= ipa_reference_vars_uids
++;
169 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
170 static inline ipa_reference_vars_info_t
171 get_reference_vars_info (struct cgraph_node
*node
)
173 if (ipa_ref_var_info_summaries
== NULL
)
176 ipa_reference_vars_info_t v
= ipa_ref_var_info_summaries
->get (node
);
177 return v
== NULL
? NULL
: v
;
180 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
181 static inline ipa_reference_optimization_summary_t
182 get_reference_optimization_summary (struct cgraph_node
*node
)
184 if (ipa_ref_opt_sum_summaries
== NULL
)
187 ipa_reference_optimization_summary_t v
188 = ipa_ref_opt_sum_summaries
->get (node
);
190 return v
== NULL
? NULL
: v
;
193 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
194 that are *not* read during the execution of the function FN. Returns
195 NULL if no data is available. */
198 ipa_reference_get_read_global (struct cgraph_node
*fn
)
200 if (!opt_for_fn (current_function_decl
, flag_ipa_reference
))
203 enum availability avail
;
204 struct cgraph_node
*fn2
= fn
->function_symbol (&avail
);
205 ipa_reference_optimization_summary_t info
=
206 get_reference_optimization_summary (fn2
);
209 && (avail
>= AVAIL_AVAILABLE
210 || (avail
== AVAIL_INTERPOSABLE
211 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
))
212 && opt_for_fn (fn2
->decl
, flag_ipa_reference
))
213 return info
->statics_read
;
214 else if (avail
== AVAIL_NOT_AVAILABLE
215 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
216 return no_module_statics
;
221 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
222 that are *not* written during the execution of the function FN. Note
223 that variables written may or may not be read during the function
224 call. Returns NULL if no data is available. */
227 ipa_reference_get_written_global (struct cgraph_node
*fn
)
229 if (!opt_for_fn (current_function_decl
, flag_ipa_reference
))
232 enum availability avail
;
233 struct cgraph_node
*fn2
= fn
->function_symbol (&avail
);
234 ipa_reference_optimization_summary_t info
=
235 get_reference_optimization_summary (fn2
);
238 && (avail
>= AVAIL_AVAILABLE
239 || (avail
== AVAIL_INTERPOSABLE
240 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
))
241 && opt_for_fn (fn2
->decl
, flag_ipa_reference
))
242 return info
->statics_written
;
243 else if (avail
== AVAIL_NOT_AVAILABLE
244 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
245 return no_module_statics
;
251 /* Hepler for is_proper_for_analysis. */
253 is_improper (symtab_node
*n
, void *v ATTRIBUTE_UNUSED
)
256 /* If the variable has the "used" attribute, treat it as if it had a
257 been touched by the devil. */
258 if (DECL_PRESERVE_P (t
))
261 /* Do not want to do anything with volatile except mark any
262 function that uses one to be not const or pure. */
263 if (TREE_THIS_VOLATILE (t
))
266 /* We do not need to analyze readonly vars, we already know they do not
268 if (TREE_READONLY (t
))
271 /* We cannot track variables with address taken. */
272 if (TREE_ADDRESSABLE (t
))
275 /* TODO: We could track public variables that are not addressable, but
276 currently frontends don't give us those. */
283 /* Return true if the variable T is the right kind of static variable to
284 perform compilation unit scope escape analysis. */
287 is_proper_for_analysis (tree t
)
289 int id
= ipa_reference_var_uid (t
);
291 if (id
!= -1 && bitmap_bit_p (ignore_module_statics
, id
))
294 if (symtab_node::get (t
)
295 ->call_for_symbol_and_aliases (is_improper
, NULL
, true))
301 /* Lookup the tree node for the static variable that has UID and
302 convert the name to a string for debugging. */
305 get_static_name (int index
)
307 return fndecl_name ((*reference_vars_to_consider
)[index
]);
310 /* Dump a set of static vars to FILE. */
312 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
318 else if (set
== all_module_statics
)
320 else if (set
== no_module_statics
)
323 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
325 fprintf (f
, "%s ", get_static_name (index
));
329 /* Compute X |= Y, taking into account the possibility that
330 either X or Y is already the maximum set.
331 Return true if X is the maximum set after taking the union with Y. */
334 union_static_var_sets (bitmap
&x
, bitmap y
)
336 if (x
!= all_module_statics
)
338 if (y
== all_module_statics
)
341 x
= all_module_statics
;
343 else if (bitmap_ior_into (x
, y
))
345 /* The union may have reduced X to the maximum set.
346 In that case, we want to make that visible explicitly.
347 Even though bitmap_equal_p can be very expensive, it
348 turns out to be an overall win to check this here for
349 an LTO bootstrap of GCC itself. Liberally extrapoliate
350 that result to be applicable to all cases. */
351 if (bitmap_equal_p (x
, all_module_statics
))
354 x
= all_module_statics
;
358 return x
== all_module_statics
;
361 /* Return a copy of SET on the bitmap obstack containing SET.
362 But if SET is NULL or the maximum set, return that instead. */
365 copy_static_var_set (bitmap set
, bool for_propagation
)
367 if (set
== NULL
|| set
== all_module_statics
)
369 if (!for_propagation
&& set
== no_module_statics
)
371 bitmap_obstack
*o
= set
->obstack
;
372 gcc_checking_assert (o
);
373 bitmap copy
= BITMAP_ALLOC (o
);
374 bitmap_copy (copy
, set
);
378 /* Compute the union all of the statics read and written by every callee of X
379 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
380 actually the set representing the cycle containing X. If the read and
381 written sets of X_GLOBAL has been reduced to the maximum set, we don't
382 have to look at the remaining callees. */
385 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
387 struct cgraph_edge
*e
;
388 bool read_all
= x_global
->statics_read
== all_module_statics
;
389 bool write_all
= x_global
->statics_written
== all_module_statics
;
391 e
&& !(read_all
&& write_all
);
394 enum availability avail
;
395 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
399 /* Only look into nodes we can propagate something. */
400 int flags
= flags_from_decl_or_type (y
->decl
);
401 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
402 && (avail
> AVAIL_INTERPOSABLE
403 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
405 if (get_reference_vars_info (y
))
407 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
408 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
410 /* Calls in the current cycle do not have their global set
411 computed yet (but everything else does because we're
412 visiting nodes in topological order). */
413 if (!y_global
->statics_read
)
416 /* If the function is const, it reads no memory even if it
417 seems so to local analysis. */
418 if (flags
& ECF_CONST
)
421 union_static_var_sets (x_global
->statics_read
,
422 y_global
->statics_read
);
424 /* If the function is pure, it has no stores even if it
425 seems so to local analysis. If we cannot return from
426 the function, we can safely ignore the call. */
427 if ((flags
& ECF_PURE
)
428 || e
->cannot_lead_to_return_p ())
431 union_static_var_sets (x_global
->statics_written
,
432 y_global
->statics_written
);
440 /* Delete NODE from map. */
443 varpool_removal_hook (varpool_node
*node
, void *)
445 ipa_reference_vars_map
->remove (node
->decl
);
448 static bool ipa_init_p
= false;
450 /* The init routine for analyzing global static variable usage. See
451 comments at top for description. */
460 vec_alloc (reference_vars_to_consider
, 10);
463 if (ipa_ref_opt_sum_summaries
!= NULL
)
465 delete ipa_ref_opt_sum_summaries
;
466 ipa_ref_opt_sum_summaries
= NULL
;
467 delete ipa_reference_vars_map
;
469 ipa_reference_vars_map
= new reference_vars_map_t(257);
471 = symtab
->add_varpool_removal_hook (varpool_removal_hook
, NULL
);
472 ipa_reference_vars_uids
= 0;
474 bitmap_obstack_initialize (&local_info_obstack
);
475 bitmap_obstack_initialize (&optimization_summary_obstack
);
476 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
477 no_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
478 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
480 if (ipa_ref_var_info_summaries
== NULL
)
481 ipa_ref_var_info_summaries
= new ipa_ref_var_info_summary_t (symtab
);
485 /* Set up the persistent info for FN. */
487 static ipa_reference_local_vars_info_t
488 init_function_info (struct cgraph_node
*fn
)
490 ipa_reference_vars_info_t info
491 = ipa_ref_var_info_summaries
->get_create (fn
);
493 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
494 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
500 /* This is the main routine for finding the reference patterns for
501 global variables within a function FN. */
504 analyze_function (struct cgraph_node
*fn
)
506 ipa_reference_local_vars_info_t local
;
507 struct ipa_ref
*ref
= NULL
;
511 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
513 local
= init_function_info (fn
);
514 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
518 if (!is_a
<varpool_node
*> (ref
->referred
))
520 var
= ref
->referred
->decl
;
521 if (!is_proper_for_analysis (var
))
523 /* This is a variable we care about. Check if we have seen it
524 before, and if not add it the set of variables we care about. */
525 id
= ipa_reference_var_get_or_insert_uid (var
, &existed
);
528 bitmap_set_bit (all_module_statics
, id
);
530 reference_vars_to_consider
->safe_push (var
);
535 bitmap_set_bit (local
->statics_read
, id
);
538 if (ref
->cannot_lead_to_return ())
540 bitmap_set_bit (local
->statics_written
, id
);
549 if (fn
->cannot_return_p ())
550 bitmap_clear (local
->statics_written
);
554 /* Called when new clone is inserted to callgraph late. */
557 ipa_ref_opt_summary_t::duplicate (cgraph_node
*, cgraph_node
*,
558 ipa_reference_optimization_summary_d
*ginfo
,
559 ipa_reference_optimization_summary_d
562 dst_ginfo
->statics_read
=
563 copy_static_var_set (ginfo
->statics_read
, false);
564 dst_ginfo
->statics_written
=
565 copy_static_var_set (ginfo
->statics_written
, false);
568 /* Called when node is removed. */
571 ipa_ref_opt_summary_t::remove (cgraph_node
*,
572 ipa_reference_optimization_summary_d
*ginfo
)
574 if (ginfo
->statics_read
575 && ginfo
->statics_read
!= all_module_statics
576 && ginfo
->statics_read
!= no_module_statics
)
577 BITMAP_FREE (ginfo
->statics_read
);
579 if (ginfo
->statics_written
580 && ginfo
->statics_written
!= all_module_statics
581 && ginfo
->statics_written
!= no_module_statics
)
582 BITMAP_FREE (ginfo
->statics_written
);
585 /* Analyze each function in the cgraph to see which global or statics
586 are read or written. */
589 generate_summary (void)
591 struct cgraph_node
*node
;
597 /* Process all of the functions next. */
598 FOR_EACH_DEFINED_FUNCTION (node
)
599 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
601 struct ipa_ref
*ref
= NULL
;
604 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
606 if (!is_a
<varpool_node
*> (ref
->referred
))
608 var
= ref
->referred
->decl
;
609 if (!is_proper_for_analysis (var
))
611 bitmap_set_bit (ignore_module_statics
, ipa_reference_var_uid (var
));
614 FOR_EACH_DEFINED_FUNCTION (node
)
615 analyze_function (node
);
618 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
620 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
621 get_static_name (index
), index
);
625 FOR_EACH_DEFINED_FUNCTION (node
)
626 if (node
->get_availability () >= AVAIL_INTERPOSABLE
627 && opt_for_fn (node
->decl
, flag_ipa_reference
))
629 ipa_reference_local_vars_info_t l
;
633 l
= &get_reference_vars_info (node
)->local
;
635 "\nFunction name:%s:", node
->dump_name ());
636 fprintf (dump_file
, "\n locals read: ");
638 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
641 fprintf (dump_file
, "%s ",
642 get_static_name (index
));
644 fprintf (dump_file
, "\n locals written: ");
645 if (l
->statics_written
)
646 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
649 fprintf (dump_file
, "%s ", get_static_name (index
));
654 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
657 read_write_all_from_decl (struct cgraph_node
*node
,
658 bool &read_all
, bool &write_all
)
660 tree decl
= node
->decl
;
661 int flags
= flags_from_decl_or_type (decl
);
662 if ((flags
& ECF_LEAF
)
663 && node
->get_availability () < AVAIL_INTERPOSABLE
)
665 else if (flags
& ECF_CONST
)
667 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
670 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
671 fprintf (dump_file
, " %s -> read all\n", node
->dump_name ());
675 /* TODO: To be able to produce sane results, we should also handle
676 common builtins, in particular throw. */
679 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
680 fprintf (dump_file
, " %s -> read all, write all\n",
685 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
686 in the cycle of NODE. */
689 get_read_write_all_from_node (struct cgraph_node
*node
,
690 bool &read_all
, bool &write_all
)
692 struct cgraph_edge
*e
, *ie
;
694 /* When function is overwritable, we cannot assume anything. */
695 if (node
->get_availability () <= AVAIL_INTERPOSABLE
696 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
697 read_write_all_from_decl (node
, read_all
, write_all
);
699 for (e
= node
->callees
;
700 e
&& !(read_all
&& write_all
);
703 enum availability avail
;
704 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
705 gcc_checking_assert (callee
);
706 if (avail
<= AVAIL_INTERPOSABLE
707 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
,
708 flag_ipa_reference
)))
709 read_write_all_from_decl (callee
, read_all
, write_all
);
712 for (ie
= node
->indirect_calls
;
713 ie
&& !(read_all
&& write_all
);
714 ie
= ie
->next_callee
)
715 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
718 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
719 fprintf (dump_file
, " indirect call -> read all\n");
720 if (!ie
->cannot_lead_to_return_p ()
721 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
723 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
724 fprintf (dump_file
, " indirect call -> write all\n");
730 /* Skip edges from and to nodes without ipa_reference enabled.
731 Ignore not available symbols. This leave
732 them out of strongly connected components and makes them easy to skip in the
733 propagation loop bellow. */
736 ignore_edge_p (cgraph_edge
*e
)
738 enum availability avail
;
739 cgraph_node
*ultimate_target
740 = e
->callee
->function_or_virtual_thunk_symbol (&avail
, e
->caller
);
742 return (avail
< AVAIL_INTERPOSABLE
743 || (avail
== AVAIL_INTERPOSABLE
744 && !(flags_from_decl_or_type (e
->callee
->decl
) & ECF_LEAF
))
745 || !opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
746 || !opt_for_fn (ultimate_target
->decl
, flag_ipa_reference
));
749 /* Produce the global information by preforming a transitive closure
750 on the local information that was produced by ipa_analyze_function. */
755 struct cgraph_node
*node
;
756 struct cgraph_node
**order
=
757 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
763 cgraph_node::dump_cgraph (dump_file
);
765 remove_p
= ipa_discover_variable_flags ();
768 /* Propagate the local information through the call graph to produce
769 the global information. All the nodes within a cycle will have
770 the same info so we collapse cycles first. Then we can do the
771 propagation in one pass from the leaves to the roots. */
772 order_pos
= ipa_reduced_postorder (order
, true, ignore_edge_p
);
774 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
776 for (i
= 0; i
< order_pos
; i
++ )
779 struct cgraph_node
*w
;
780 ipa_reference_vars_info_t node_info
;
781 ipa_reference_global_vars_info_t node_g
;
782 ipa_reference_local_vars_info_t node_l
;
783 bool read_all
= false;
784 bool write_all
= false;
787 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
790 node_info
= get_reference_vars_info (node
);
791 gcc_assert (node_info
);
792 node_l
= &node_info
->local
;
793 node_g
= &node_info
->global
;
795 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
796 fprintf (dump_file
, "Starting cycle with %s\n", node
->dump_name ());
798 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
800 /* If any node in a cycle is read_all or write_all, they all are. */
801 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
803 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
804 fprintf (dump_file
, " Visiting %s\n", w
->dump_asm_name ());
805 get_read_write_all_from_node (w
, read_all
, write_all
);
806 if (read_all
&& write_all
)
810 /* Initialized the bitmaps global sets for the reduced node. */
812 node_g
->statics_read
= all_module_statics
;
814 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
, true);
816 node_g
->statics_written
= all_module_statics
;
818 node_g
->statics_written
819 = copy_static_var_set (node_l
->statics_written
, true);
821 /* Merge the sets of this cycle with all sets of callees reached
823 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
825 if (read_all
&& write_all
)
830 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
831 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
832 int flags
= flags_from_decl_or_type (w
->decl
);
834 if (!(flags
& ECF_CONST
))
835 read_all
= union_static_var_sets (node_g
->statics_read
,
837 if (!(flags
& ECF_PURE
)
838 && !w
->cannot_return_p ())
839 write_all
= union_static_var_sets (node_g
->statics_written
,
840 w_l
->statics_written
);
843 propagate_bits (node_g
, w
);
846 /* All nodes within a cycle have the same global info bitmaps. */
847 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
849 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
850 w_ri
->global
= *node_g
;
853 cycle_nodes
.release ();
858 for (i
= 0; i
< order_pos
; i
++)
861 struct cgraph_node
*w
;
864 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
867 fprintf (dump_file
, "\nFunction name:%s:", node
->dump_asm_name ());
869 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
870 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
872 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
873 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
875 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
876 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
878 fprintf (dump_file
, "\n next cycle: %s ", w
->dump_asm_name ());
879 fprintf (dump_file
, "\n locals read: ");
880 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
881 fprintf (dump_file
, "\n locals written: ");
882 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
884 cycle_nodes
.release ();
886 fprintf (dump_file
, "\n globals read: ");
887 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
888 fprintf (dump_file
, "\n globals written: ");
889 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
890 fprintf (dump_file
, "\n");
894 if (ipa_ref_opt_sum_summaries
== NULL
)
895 ipa_ref_opt_sum_summaries
= new ipa_ref_opt_summary_t (symtab
);
898 FOR_EACH_DEFINED_FUNCTION (node
)
900 ipa_reference_vars_info_t node_info
;
901 ipa_reference_global_vars_info_t node_g
;
903 /* No need to produce summaries for inline clones. */
904 if (node
->inlined_to
)
907 node_info
= get_reference_vars_info (node
);
908 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
))
910 node_g
= &node_info
->global
;
912 (node_g
->statics_read
== all_module_statics
913 || bitmap_equal_p (node_g
->statics_read
, all_module_statics
));
915 (node_g
->statics_written
== all_module_statics
916 || bitmap_equal_p (node_g
->statics_written
,
917 all_module_statics
));
919 /* There is no need to produce summary if we collected nothing
921 if (read_all
&& written_all
)
924 ipa_reference_optimization_summary_d
*opt
925 = ipa_ref_opt_sum_summaries
->get_create (node
);
927 /* Create the complimentary sets. */
929 if (bitmap_empty_p (node_g
->statics_read
))
930 opt
->statics_read
= no_module_statics
;
932 opt
->statics_read
= all_module_statics
;
936 = BITMAP_ALLOC (&optimization_summary_obstack
);
937 bitmap_copy (opt
->statics_read
, node_g
->statics_read
);
940 if (bitmap_empty_p (node_g
->statics_written
))
941 opt
->statics_written
= no_module_statics
;
942 else if (written_all
)
943 opt
->statics_written
= all_module_statics
;
947 = BITMAP_ALLOC (&optimization_summary_obstack
);
948 bitmap_copy (opt
->statics_written
, node_g
->statics_written
);
953 ipa_free_postorder_info ();
956 bitmap_obstack_release (&local_info_obstack
);
958 if (ipa_ref_var_info_summaries
!= NULL
)
960 delete ipa_ref_var_info_summaries
;
961 ipa_ref_var_info_summaries
= NULL
;
965 vec_free (reference_vars_to_consider
);
966 reference_vars_to_consider
= NULL
;
967 return remove_p
? TODO_remove_functions
: 0;
970 /* Return true if we need to write summary of NODE. */
973 write_node_summary_p (struct cgraph_node
*node
,
974 lto_symtab_encoder_t encoder
,
975 bitmap ltrans_statics
)
977 ipa_reference_optimization_summary_t info
;
979 /* See if we have (non-empty) info. */
980 if (!node
->definition
|| node
->inlined_to
)
982 info
= get_reference_optimization_summary (node
);
986 /* See if we want to encode it.
987 Encode also referenced functions since constant folding might turn it into
990 In future we might also want to include summaries of functions references
991 by initializers of constant variables references in current unit. */
992 if (!reachable_from_this_partition_p (node
, encoder
)
993 && !referenced_from_this_partition_p (node
, encoder
))
996 /* See if the info has non-empty intersections with vars we want to
1000 EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics
, info
->statics_read
, 0,
1003 EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics
, info
->statics_written
, 0,
1009 /* Stream out BITS<RANS_STATICS as list of decls to OB.
1010 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
1011 or -1. When it is positive, just output -1 when
1012 BITS<RANS_STATICS == BITS<RANS_STATICS. */
1015 stream_out_bitmap (struct lto_simple_output_block
*ob
,
1016 bitmap bits
, bitmap ltrans_statics
,
1017 int ltrans_statics_bitcount
)
1022 if (bits
== all_module_statics
)
1024 streamer_write_hwi_stream (ob
->main_stream
, -1);
1027 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1029 if (count
== ltrans_statics_bitcount
)
1031 streamer_write_hwi_stream (ob
->main_stream
, -1);
1034 streamer_write_hwi_stream (ob
->main_stream
, count
);
1037 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1039 tree decl
= (*reference_vars_to_consider
) [index
];
1040 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
1044 /* Serialize the ipa info for lto. */
1047 ipa_reference_write_optimization_summary (void)
1049 struct lto_simple_output_block
*ob
1050 = lto_create_simple_output_block (LTO_section_ipa_reference
);
1051 unsigned int count
= 0;
1052 int ltrans_statics_bitcount
= 0;
1053 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
1054 auto_bitmap ltrans_statics
;
1057 vec_alloc (reference_vars_to_consider
, ipa_reference_vars_uids
);
1058 reference_vars_to_consider
->safe_grow (ipa_reference_vars_uids
);
1060 /* See what variables we are interested in. */
1061 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1063 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1064 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
1068 && (id
= ipa_reference_var_uid (vnode
->decl
)) != -1
1069 && referenced_from_this_partition_p (vnode
, encoder
))
1071 tree decl
= vnode
->decl
;
1072 bitmap_set_bit (ltrans_statics
, id
);
1073 (*reference_vars_to_consider
)[id
] = decl
;
1074 ltrans_statics_bitcount
++;
1079 if (ltrans_statics_bitcount
)
1080 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1082 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1083 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1084 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1088 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1090 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1093 /* Process all of the functions. */
1094 if (ltrans_statics_bitcount
)
1095 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1097 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1098 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1099 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1101 ipa_reference_optimization_summary_t info
;
1104 info
= get_reference_optimization_summary (cnode
);
1105 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1106 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1108 stream_out_bitmap (ob
, info
->statics_read
, ltrans_statics
,
1109 ltrans_statics_bitcount
);
1110 stream_out_bitmap (ob
, info
->statics_written
, ltrans_statics
,
1111 ltrans_statics_bitcount
);
1114 lto_destroy_simple_output_block (ob
);
1115 delete reference_vars_to_consider
;
1118 /* Deserialize the ipa info for lto. */
1121 ipa_reference_read_optimization_summary (void)
1123 struct lto_file_decl_data
** file_data_vec
1124 = lto_get_file_decl_data ();
1125 struct lto_file_decl_data
* file_data
;
1127 bitmap_obstack_initialize (&optimization_summary_obstack
);
1129 gcc_checking_assert (ipa_ref_opt_sum_summaries
== NULL
);
1130 ipa_ref_opt_sum_summaries
= new ipa_ref_opt_summary_t (symtab
);
1131 ipa_reference_vars_map
= new reference_vars_map_t(257);
1133 = symtab
->add_varpool_removal_hook (varpool_removal_hook
, NULL
);
1134 ipa_reference_vars_uids
= 0;
1136 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1137 no_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1139 while ((file_data
= file_data_vec
[j
++]))
1143 class lto_input_block
*ib
1144 = lto_create_simple_input_block (file_data
,
1145 LTO_section_ipa_reference
,
1150 unsigned int f_count
= streamer_read_uhwi (ib
);
1154 b_count
= streamer_read_hwi (ib
);
1156 fprintf (dump_file
, "all module statics:");
1157 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1159 unsigned int var_index
= streamer_read_uhwi (ib
);
1160 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1163 bitmap_set_bit (all_module_statics
,
1164 ipa_reference_var_get_or_insert_uid
1165 (v_decl
, &existed
));
1166 gcc_checking_assert (!existed
);
1168 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1171 for (i
= 0; i
< f_count
; i
++)
1173 unsigned int j
, index
;
1174 struct cgraph_node
*node
;
1176 lto_symtab_encoder_t encoder
;
1178 index
= streamer_read_uhwi (ib
);
1179 encoder
= file_data
->symtab_node_encoder
;
1180 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1183 ipa_reference_optimization_summary_d
*info
1184 = ipa_ref_opt_sum_summaries
->get_create (node
);
1188 "\nFunction name:%s:\n static read:",
1189 node
->dump_asm_name ());
1191 /* Set the statics read. */
1192 v_count
= streamer_read_hwi (ib
);
1195 info
->statics_read
= all_module_statics
;
1197 fprintf (dump_file
, " all module statics");
1199 else if (v_count
== 0)
1200 info
->statics_read
= no_module_statics
;
1203 info
->statics_read
= BITMAP_ALLOC
1204 (&optimization_summary_obstack
);
1205 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1207 unsigned int var_index
= streamer_read_uhwi (ib
);
1208 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1210 bitmap_set_bit (info
->statics_read
,
1211 ipa_reference_var_uid (v_decl
));
1213 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1219 "\n static written:");
1220 /* Set the statics written. */
1221 v_count
= streamer_read_hwi (ib
);
1224 info
->statics_written
= all_module_statics
;
1226 fprintf (dump_file
, " all module statics");
1228 else if (v_count
== 0)
1229 info
->statics_written
= no_module_statics
;
1232 info
->statics_written
= BITMAP_ALLOC
1233 (&optimization_summary_obstack
);
1234 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1236 unsigned int var_index
= streamer_read_uhwi (ib
);
1237 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1239 bitmap_set_bit (info
->statics_written
,
1240 ipa_reference_var_uid (v_decl
));
1242 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1246 fprintf (dump_file
, "\n");
1249 lto_destroy_simple_input_block (file_data
,
1250 LTO_section_ipa_reference
,
1254 /* Fatal error here. We do not want to support compiling ltrans units
1255 with different version of compiler or different flags than
1256 the WPA unit, so this should never happen. */
1257 fatal_error (input_location
,
1258 "ipa reference summary is missing in ltrans unit");
1264 const pass_data pass_data_ipa_reference
=
1266 IPA_PASS
, /* type */
1267 "static-var", /* name */
1268 OPTGROUP_NONE
, /* optinfo_flags */
1269 TV_IPA_REFERENCE
, /* tv_id */
1270 0, /* properties_required */
1271 0, /* properties_provided */
1272 0, /* properties_destroyed */
1273 0, /* todo_flags_start */
1274 0, /* todo_flags_finish */
1277 class pass_ipa_reference
: public ipa_opt_pass_d
1280 pass_ipa_reference (gcc::context
*ctxt
)
1281 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1282 NULL
, /* generate_summary */
1283 NULL
, /* write_summary */
1284 NULL
, /* read_summary */
1285 ipa_reference_write_optimization_summary
, /*
1286 write_optimization_summary */
1287 ipa_reference_read_optimization_summary
, /*
1288 read_optimization_summary */
1289 NULL
, /* stmt_fixup */
1290 0, /* function_transform_todo_flags_start */
1291 NULL
, /* function_transform */
1292 NULL
) /* variable_transform */
1295 /* opt_pass methods: */
1296 virtual bool gate (function
*)
1298 return ((in_lto_p
|| flag_ipa_reference
)
1299 /* Don't bother doing anything if the program has errors. */
1303 virtual unsigned int execute (function
*) { return propagate (); }
1305 }; // class pass_ipa_reference
1310 make_pass_ipa_reference (gcc::context
*ctxt
)
1312 return new pass_ipa_reference (ctxt
);
1315 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1316 within the same process. For use by toplev::finalize. */
1319 ipa_reference_c_finalize (void)
1321 if (ipa_ref_opt_sum_summaries
!= NULL
)
1323 delete ipa_ref_opt_sum_summaries
;
1324 ipa_ref_opt_sum_summaries
= NULL
;
1325 delete ipa_reference_vars_map
;
1326 ipa_reference_vars_map
= NULL
;
1327 symtab
->remove_varpool_removal_hook (varpool_node_hooks
);
1332 bitmap_obstack_release (&optimization_summary_obstack
);