1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2021 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 "alloc-pool.h"
52 #include "symbol-summary.h"
54 /* The static variables defined within the compilation unit that are
55 loaded or stored directly by function that owns this structure. */
57 struct ipa_reference_local_vars_info_d
60 bitmap statics_written
;
63 /* Statics that are read and written by some set of functions. The
64 local ones are based on the loads and stores local to the function.
65 The global ones are based on the local info as well as the
66 transitive closure of the functions that are called. */
68 struct ipa_reference_global_vars_info_d
71 bitmap statics_written
;
74 /* Information we save about every function after ipa-reference is completed. */
76 struct ipa_reference_optimization_summary_d
79 bitmap statics_written
;
82 typedef ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
83 typedef ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
84 typedef ipa_reference_optimization_summary_d
*
85 ipa_reference_optimization_summary_t
;
87 struct ipa_reference_vars_info_d
89 struct ipa_reference_local_vars_info_d local
;
90 struct ipa_reference_global_vars_info_d global
;
93 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
95 /* This map contains all of the static variables that are
96 being considered by the compilation level alias analysis. */
97 typedef hash_map
<tree
, int> reference_vars_map_t
;
98 static reference_vars_map_t
*ipa_reference_vars_map
;
99 static int ipa_reference_vars_uids
;
100 static vec
<tree
> *reference_vars_to_consider
;
101 varpool_node_hook_list
*varpool_node_hooks
;
103 /* Set of all interesting module statics. A bit is set for every module
104 static we are considering. This is added to the local info when asm
105 code is found that clobbers all memory. */
106 static bitmap all_module_statics
;
108 static bitmap no_module_statics
;
109 /* Set of all statics that should be ignored because they are touched by
110 -fno-ipa-reference code. */
111 static bitmap ignore_module_statics
;
113 /* Obstack holding bitmaps of local analysis (live from analysis to
115 static bitmap_obstack local_info_obstack
;
116 /* Obstack holding global analysis live forever. */
117 static bitmap_obstack optimization_summary_obstack
;
119 class ipa_ref_var_info_summary_t
: public fast_function_summary
120 <ipa_reference_vars_info_d
*, va_heap
>
123 ipa_ref_var_info_summary_t (symbol_table
*symtab
):
124 fast_function_summary
<ipa_reference_vars_info_d
*, va_heap
> (symtab
) {}
127 static ipa_ref_var_info_summary_t
*ipa_ref_var_info_summaries
= NULL
;
129 class ipa_ref_opt_summary_t
: public fast_function_summary
130 <ipa_reference_optimization_summary_d
*, va_heap
>
133 ipa_ref_opt_summary_t (symbol_table
*symtab
):
134 fast_function_summary
<ipa_reference_optimization_summary_d
*, va_heap
> (symtab
) {}
136 virtual void remove (cgraph_node
*src_node
,
137 ipa_reference_optimization_summary_d
*data
);
138 virtual void duplicate (cgraph_node
*src_node
, cgraph_node
*dst_node
,
139 ipa_reference_optimization_summary_d
*src_data
,
140 ipa_reference_optimization_summary_d
*dst_data
);
143 static ipa_ref_opt_summary_t
*ipa_ref_opt_sum_summaries
= NULL
;
145 /* Return ID used by ipa-reference bitmaps. -1 if failed. */
147 ipa_reference_var_uid (tree t
)
149 if (!ipa_reference_vars_map
)
151 int *id
= ipa_reference_vars_map
->get
152 (symtab_node::get (t
)->ultimate_alias_target (NULL
)->decl
);
158 /* Return ID used by ipa-reference bitmaps. Create new entry if
159 T is not in map. Set EXISTED accordinly */
161 ipa_reference_var_get_or_insert_uid (tree t
, bool *existed
)
163 int &id
= ipa_reference_vars_map
->get_or_insert
164 (symtab_node::get (t
)->ultimate_alias_target (NULL
)->decl
, existed
);
166 id
= ipa_reference_vars_uids
++;
170 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
171 static inline ipa_reference_vars_info_t
172 get_reference_vars_info (struct cgraph_node
*node
)
174 if (ipa_ref_var_info_summaries
== NULL
)
177 ipa_reference_vars_info_t v
= ipa_ref_var_info_summaries
->get (node
);
178 return v
== NULL
? NULL
: v
;
181 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
182 static inline ipa_reference_optimization_summary_t
183 get_reference_optimization_summary (struct cgraph_node
*node
)
185 if (ipa_ref_opt_sum_summaries
== NULL
)
188 ipa_reference_optimization_summary_t v
189 = ipa_ref_opt_sum_summaries
->get (node
);
191 return v
== NULL
? NULL
: v
;
194 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
195 that are *not* read during the execution of the function FN. Returns
196 NULL if no data is available. */
199 ipa_reference_get_read_global (struct cgraph_node
*fn
)
201 if (!opt_for_fn (current_function_decl
, flag_ipa_reference
))
204 enum availability avail
;
205 struct cgraph_node
*fn2
= fn
->function_symbol (&avail
);
206 ipa_reference_optimization_summary_t info
=
207 get_reference_optimization_summary (fn2
);
210 && (avail
>= AVAIL_AVAILABLE
211 || (avail
== AVAIL_INTERPOSABLE
212 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
))
213 && opt_for_fn (fn2
->decl
, flag_ipa_reference
))
214 return info
->statics_read
;
215 else if (avail
== AVAIL_NOT_AVAILABLE
216 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
217 return no_module_statics
;
222 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
223 that are *not* written during the execution of the function FN. Note
224 that variables written may or may not be read during the function
225 call. Returns NULL if no data is available. */
228 ipa_reference_get_written_global (struct cgraph_node
*fn
)
230 if (!opt_for_fn (current_function_decl
, flag_ipa_reference
))
233 enum availability avail
;
234 struct cgraph_node
*fn2
= fn
->function_symbol (&avail
);
235 ipa_reference_optimization_summary_t info
=
236 get_reference_optimization_summary (fn2
);
239 && (avail
>= AVAIL_AVAILABLE
240 || (avail
== AVAIL_INTERPOSABLE
241 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
))
242 && opt_for_fn (fn2
->decl
, flag_ipa_reference
))
243 return info
->statics_written
;
244 else if (avail
== AVAIL_NOT_AVAILABLE
245 && flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
246 return no_module_statics
;
252 /* Hepler for is_proper_for_analysis. */
254 is_improper (symtab_node
*n
, void *v ATTRIBUTE_UNUSED
)
257 /* If the variable has the "used" attribute, treat it as if it had a
258 been touched by the devil. */
259 if (DECL_PRESERVE_P (t
))
262 /* Do not want to do anything with volatile except mark any
263 function that uses one to be not const or pure. */
264 if (TREE_THIS_VOLATILE (t
))
267 /* We do not need to analyze readonly vars, we already know they do not
269 if (TREE_READONLY (t
))
272 /* We cannot track variables with address taken. */
273 if (TREE_ADDRESSABLE (t
))
276 /* TODO: We could track public variables that are not addressable, but
277 currently frontends don't give us those. */
284 /* Return true if the variable T is the right kind of static variable to
285 perform compilation unit scope escape analysis. */
288 is_proper_for_analysis (tree t
)
290 int id
= ipa_reference_var_uid (t
);
292 if (id
!= -1 && bitmap_bit_p (ignore_module_statics
, id
))
295 if (symtab_node::get (t
)
296 ->call_for_symbol_and_aliases (is_improper
, NULL
, true))
302 /* Lookup the tree node for the static variable that has UID and
303 convert the name to a string for debugging. */
306 get_static_name (int index
)
308 return fndecl_name ((*reference_vars_to_consider
)[index
]);
311 /* Dump a set of static vars to FILE. */
313 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
319 else if (set
== all_module_statics
)
321 else if (set
== no_module_statics
)
324 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
326 fprintf (f
, "%s ", get_static_name (index
));
330 /* Compute X |= Y, taking into account the possibility that
331 either X or Y is already the maximum set.
332 Return true if X is the maximum set after taking the union with Y. */
335 union_static_var_sets (bitmap
&x
, bitmap y
)
337 if (x
!= all_module_statics
)
339 if (y
== all_module_statics
)
342 x
= all_module_statics
;
344 else if (bitmap_ior_into (x
, y
))
346 /* The union may have reduced X to the maximum set.
347 In that case, we want to make that visible explicitly.
348 Even though bitmap_equal_p can be very expensive, it
349 turns out to be an overall win to check this here for
350 an LTO bootstrap of GCC itself. Liberally extrapoliate
351 that result to be applicable to all cases. */
352 if (bitmap_equal_p (x
, all_module_statics
))
355 x
= all_module_statics
;
359 return x
== all_module_statics
;
362 /* Return a copy of SET on the bitmap obstack containing SET.
363 But if SET is NULL or the maximum set, return that instead. */
366 copy_static_var_set (bitmap set
, bool for_propagation
)
368 if (set
== NULL
|| set
== all_module_statics
)
370 if (!for_propagation
&& set
== no_module_statics
)
372 bitmap_obstack
*o
= set
->obstack
;
373 gcc_checking_assert (o
);
374 bitmap copy
= BITMAP_ALLOC (o
);
375 bitmap_copy (copy
, set
);
379 /* Compute the union all of the statics read and written by every callee of X
380 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
381 actually the set representing the cycle containing X. If the read and
382 written sets of X_GLOBAL has been reduced to the maximum set, we don't
383 have to look at the remaining callees. */
386 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
388 struct cgraph_edge
*e
;
389 bool read_all
= x_global
->statics_read
== all_module_statics
;
390 bool write_all
= x_global
->statics_written
== all_module_statics
;
392 e
&& !(read_all
&& write_all
);
395 enum availability avail
;
396 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
400 /* Only look into nodes we can propagate something. */
401 int flags
= flags_from_decl_or_type (y
->decl
);
402 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
403 && (avail
> AVAIL_INTERPOSABLE
404 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
406 if (get_reference_vars_info (y
))
408 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
409 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
411 /* Calls in the current cycle do not have their global set
412 computed yet (but everything else does because we're
413 visiting nodes in topological order). */
414 if (!y_global
->statics_read
)
417 /* If the function is const, it reads no memory even if it
418 seems so to local analysis. */
419 if (flags
& ECF_CONST
)
422 union_static_var_sets (x_global
->statics_read
,
423 y_global
->statics_read
);
425 /* If the function is pure, it has no stores even if it
426 seems so to local analysis. If we cannot return from
427 the function, we can safely ignore the call. */
428 if ((flags
& ECF_PURE
)
429 || e
->cannot_lead_to_return_p ())
432 union_static_var_sets (x_global
->statics_written
,
433 y_global
->statics_written
);
441 /* Delete NODE from map. */
444 varpool_removal_hook (varpool_node
*node
, void *)
446 ipa_reference_vars_map
->remove (node
->decl
);
449 static bool ipa_init_p
= false;
451 /* The init routine for analyzing global static variable usage. See
452 comments at top for description. */
461 vec_alloc (reference_vars_to_consider
, 10);
464 if (ipa_ref_opt_sum_summaries
!= NULL
)
466 delete ipa_ref_opt_sum_summaries
;
467 ipa_ref_opt_sum_summaries
= NULL
;
468 delete ipa_reference_vars_map
;
470 ipa_reference_vars_map
= new reference_vars_map_t(257);
472 = symtab
->add_varpool_removal_hook (varpool_removal_hook
, NULL
);
473 ipa_reference_vars_uids
= 0;
475 bitmap_obstack_initialize (&local_info_obstack
);
476 bitmap_obstack_initialize (&optimization_summary_obstack
);
477 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
478 no_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
479 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
481 if (ipa_ref_var_info_summaries
== NULL
)
482 ipa_ref_var_info_summaries
= new ipa_ref_var_info_summary_t (symtab
);
486 /* Set up the persistent info for FN. */
488 static ipa_reference_local_vars_info_t
489 init_function_info (struct cgraph_node
*fn
)
491 ipa_reference_vars_info_t info
492 = ipa_ref_var_info_summaries
->get_create (fn
);
494 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
495 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
496 info
->global
.statics_read
= NULL
;
502 /* This is the main routine for finding the reference patterns for
503 global variables within a function FN. */
506 analyze_function (struct cgraph_node
*fn
)
508 ipa_reference_local_vars_info_t local
;
509 struct ipa_ref
*ref
= NULL
;
513 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
515 local
= init_function_info (fn
);
516 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
520 if (!is_a
<varpool_node
*> (ref
->referred
))
522 var
= ref
->referred
->decl
;
523 if (!is_proper_for_analysis (var
))
525 /* This is a variable we care about. Check if we have seen it
526 before, and if not add it the set of variables we care about. */
527 id
= ipa_reference_var_get_or_insert_uid (var
, &existed
);
530 bitmap_set_bit (all_module_statics
, id
);
532 reference_vars_to_consider
->safe_push (var
);
537 bitmap_set_bit (local
->statics_read
, id
);
540 if (ref
->cannot_lead_to_return ())
542 bitmap_set_bit (local
->statics_written
, id
);
551 if (fn
->cannot_return_p ())
552 bitmap_clear (local
->statics_written
);
556 /* Called when new clone is inserted to callgraph late. */
559 ipa_ref_opt_summary_t::duplicate (cgraph_node
*, cgraph_node
*,
560 ipa_reference_optimization_summary_d
*ginfo
,
561 ipa_reference_optimization_summary_d
564 dst_ginfo
->statics_read
=
565 copy_static_var_set (ginfo
->statics_read
, false);
566 dst_ginfo
->statics_written
=
567 copy_static_var_set (ginfo
->statics_written
, false);
570 /* Called when node is removed. */
573 ipa_ref_opt_summary_t::remove (cgraph_node
*,
574 ipa_reference_optimization_summary_d
*ginfo
)
576 if (ginfo
->statics_read
577 && ginfo
->statics_read
!= all_module_statics
578 && ginfo
->statics_read
!= no_module_statics
)
579 BITMAP_FREE (ginfo
->statics_read
);
581 if (ginfo
->statics_written
582 && ginfo
->statics_written
!= all_module_statics
583 && ginfo
->statics_written
!= no_module_statics
)
584 BITMAP_FREE (ginfo
->statics_written
);
587 /* Analyze each function in the cgraph to see which global or statics
588 are read or written. */
591 generate_summary (void)
593 struct cgraph_node
*node
;
599 /* Process all of the functions next. */
600 FOR_EACH_DEFINED_FUNCTION (node
)
601 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
603 struct ipa_ref
*ref
= NULL
;
606 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
608 if (!is_a
<varpool_node
*> (ref
->referred
))
610 var
= ref
->referred
->decl
;
611 if (!is_proper_for_analysis (var
))
613 bitmap_set_bit (ignore_module_statics
, ipa_reference_var_uid (var
));
616 FOR_EACH_DEFINED_FUNCTION (node
)
617 analyze_function (node
);
620 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
622 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
623 get_static_name (index
), index
);
627 FOR_EACH_DEFINED_FUNCTION (node
)
628 if (node
->get_availability () >= AVAIL_INTERPOSABLE
629 && opt_for_fn (node
->decl
, flag_ipa_reference
))
631 ipa_reference_local_vars_info_t l
;
635 l
= &get_reference_vars_info (node
)->local
;
637 "\nFunction name:%s:", node
->dump_name ());
638 fprintf (dump_file
, "\n locals read: ");
640 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
643 fprintf (dump_file
, "%s ",
644 get_static_name (index
));
646 fprintf (dump_file
, "\n locals written: ");
647 if (l
->statics_written
)
648 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
651 fprintf (dump_file
, "%s ", get_static_name (index
));
656 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
659 read_write_all_from_decl (struct cgraph_node
*node
,
660 bool &read_all
, bool &write_all
)
662 tree decl
= node
->decl
;
663 int flags
= flags_from_decl_or_type (decl
);
664 if ((flags
& ECF_LEAF
)
665 && node
->get_availability () < AVAIL_INTERPOSABLE
)
667 else if (flags
& ECF_CONST
)
669 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
672 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
673 fprintf (dump_file
, " %s -> read all\n", node
->dump_name ());
677 /* TODO: To be able to produce sane results, we should also handle
678 common builtins, in particular throw. */
681 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
682 fprintf (dump_file
, " %s -> read all, write all\n",
687 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
688 in the cycle of NODE. */
691 get_read_write_all_from_node (struct cgraph_node
*node
,
692 bool &read_all
, bool &write_all
)
694 struct cgraph_edge
*e
, *ie
;
696 /* When function is overwritable, we cannot assume anything. */
697 if (node
->get_availability () <= AVAIL_INTERPOSABLE
698 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
699 read_write_all_from_decl (node
, read_all
, write_all
);
701 for (e
= node
->callees
;
702 e
&& !(read_all
&& write_all
);
705 enum availability avail
;
706 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
707 gcc_checking_assert (callee
);
708 if (avail
<= AVAIL_INTERPOSABLE
709 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
,
710 flag_ipa_reference
)))
711 read_write_all_from_decl (callee
, read_all
, write_all
);
714 for (ie
= node
->indirect_calls
;
715 ie
&& !(read_all
&& write_all
);
716 ie
= ie
->next_callee
)
717 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
720 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
721 fprintf (dump_file
, " indirect call -> read all\n");
722 if (!ie
->cannot_lead_to_return_p ()
723 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
725 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
726 fprintf (dump_file
, " indirect call -> write all\n");
732 /* Skip edges from and to nodes without ipa_reference enabled.
733 Ignore not available symbols. This leave
734 them out of strongly connected components and makes them easy to skip in the
735 propagation loop bellow. */
738 ignore_edge_p (cgraph_edge
*e
)
740 enum availability avail
;
741 cgraph_node
*ultimate_target
742 = e
->callee
->function_or_virtual_thunk_symbol (&avail
, e
->caller
);
744 return (avail
< AVAIL_INTERPOSABLE
745 || (avail
== AVAIL_INTERPOSABLE
746 && !(flags_from_decl_or_type (e
->callee
->decl
) & ECF_LEAF
))
747 || !opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
748 || !opt_for_fn (ultimate_target
->decl
, flag_ipa_reference
));
751 /* Produce the global information by preforming a transitive closure
752 on the local information that was produced by ipa_analyze_function. */
757 struct cgraph_node
*node
;
758 struct cgraph_node
**order
=
759 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
765 cgraph_node::dump_cgraph (dump_file
);
767 remove_p
= ipa_discover_variable_flags ();
770 /* Propagate the local information through the call graph to produce
771 the global information. All the nodes within a cycle will have
772 the same info so we collapse cycles first. Then we can do the
773 propagation in one pass from the leaves to the roots. */
774 order_pos
= ipa_reduced_postorder (order
, true, ignore_edge_p
);
776 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
778 for (i
= 0; i
< order_pos
; i
++ )
781 struct cgraph_node
*w
;
782 ipa_reference_vars_info_t node_info
;
783 ipa_reference_global_vars_info_t node_g
;
784 ipa_reference_local_vars_info_t node_l
;
785 bool read_all
= false;
786 bool write_all
= false;
789 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
792 node_info
= get_reference_vars_info (node
);
793 gcc_assert (node_info
);
794 node_l
= &node_info
->local
;
795 node_g
= &node_info
->global
;
797 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
798 fprintf (dump_file
, "Starting cycle with %s\n", node
->dump_name ());
800 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
802 /* If any node in a cycle is read_all or write_all, they all are. */
803 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
805 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
806 fprintf (dump_file
, " Visiting %s\n", w
->dump_asm_name ());
807 get_read_write_all_from_node (w
, read_all
, write_all
);
808 if (read_all
&& write_all
)
812 /* Initialized the bitmaps global sets for the reduced node. */
814 node_g
->statics_read
= all_module_statics
;
816 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
, true);
818 node_g
->statics_written
= all_module_statics
;
820 node_g
->statics_written
821 = copy_static_var_set (node_l
->statics_written
, true);
823 /* Merge the sets of this cycle with all sets of callees reached
825 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
827 if (read_all
&& write_all
)
832 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
833 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
834 int flags
= flags_from_decl_or_type (w
->decl
);
836 if (!(flags
& ECF_CONST
))
837 read_all
= union_static_var_sets (node_g
->statics_read
,
839 if (!(flags
& ECF_PURE
)
840 && !w
->cannot_return_p ())
841 write_all
= union_static_var_sets (node_g
->statics_written
,
842 w_l
->statics_written
);
845 propagate_bits (node_g
, w
);
848 /* All nodes within a cycle have the same global info bitmaps. */
849 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
851 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
852 w_ri
->global
= *node_g
;
855 cycle_nodes
.release ();
860 for (i
= 0; i
< order_pos
; i
++)
863 struct cgraph_node
*w
;
866 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
869 fprintf (dump_file
, "\nFunction name:%s:", node
->dump_asm_name ());
871 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
872 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
874 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
875 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
877 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
878 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
880 fprintf (dump_file
, "\n next cycle: %s ", w
->dump_asm_name ());
881 fprintf (dump_file
, "\n locals read: ");
882 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
883 fprintf (dump_file
, "\n locals written: ");
884 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
886 cycle_nodes
.release ();
888 fprintf (dump_file
, "\n globals read: ");
889 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
890 fprintf (dump_file
, "\n globals written: ");
891 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
892 fprintf (dump_file
, "\n");
896 if (ipa_ref_opt_sum_summaries
== NULL
)
898 ipa_ref_opt_sum_summaries
= new ipa_ref_opt_summary_t (symtab
);
899 ipa_ref_opt_sum_summaries
->disable_insertion_hook ();
903 FOR_EACH_DEFINED_FUNCTION (node
)
905 ipa_reference_vars_info_t node_info
;
906 ipa_reference_global_vars_info_t node_g
;
908 /* No need to produce summaries for inline clones. */
909 if (node
->inlined_to
)
912 node_info
= get_reference_vars_info (node
);
913 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
))
915 node_g
= &node_info
->global
;
917 (node_g
->statics_read
== all_module_statics
918 || bitmap_equal_p (node_g
->statics_read
, all_module_statics
));
920 (node_g
->statics_written
== all_module_statics
921 || bitmap_equal_p (node_g
->statics_written
,
922 all_module_statics
));
924 /* There is no need to produce summary if we collected nothing
926 if (read_all
&& written_all
)
929 ipa_reference_optimization_summary_d
*opt
930 = ipa_ref_opt_sum_summaries
->get_create (node
);
932 /* Create the complimentary sets. */
934 if (bitmap_empty_p (node_g
->statics_read
))
935 opt
->statics_read
= no_module_statics
;
937 opt
->statics_read
= all_module_statics
;
941 = BITMAP_ALLOC (&optimization_summary_obstack
);
942 bitmap_copy (opt
->statics_read
, node_g
->statics_read
);
945 if (bitmap_empty_p (node_g
->statics_written
))
946 opt
->statics_written
= no_module_statics
;
947 else if (written_all
)
948 opt
->statics_written
= all_module_statics
;
952 = BITMAP_ALLOC (&optimization_summary_obstack
);
953 bitmap_copy (opt
->statics_written
, node_g
->statics_written
);
958 ipa_free_postorder_info ();
961 bitmap_obstack_release (&local_info_obstack
);
963 if (ipa_ref_var_info_summaries
!= NULL
)
965 delete ipa_ref_var_info_summaries
;
966 ipa_ref_var_info_summaries
= NULL
;
970 vec_free (reference_vars_to_consider
);
971 reference_vars_to_consider
= NULL
;
972 return remove_p
? TODO_remove_functions
: 0;
975 /* Return true if we need to write summary of NODE. */
978 write_node_summary_p (struct cgraph_node
*node
,
979 lto_symtab_encoder_t encoder
,
980 bitmap ltrans_statics
)
982 ipa_reference_optimization_summary_t info
;
984 /* See if we have (non-empty) info. */
985 if (!node
->definition
|| node
->inlined_to
)
987 info
= get_reference_optimization_summary (node
);
991 /* See if we want to encode it.
992 Encode also referenced functions since constant folding might turn it into
995 In future we might also want to include summaries of functions references
996 by initializers of constant variables references in current unit. */
997 if (!reachable_from_this_partition_p (node
, encoder
)
998 && !referenced_from_this_partition_p (node
, encoder
))
1001 /* See if the info has non-empty intersections with vars we want to
1005 EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics
, info
->statics_read
, 0,
1008 EXECUTE_IF_AND_COMPL_IN_BITMAP (ltrans_statics
, info
->statics_written
, 0,
1014 /* Stream out BITS<RANS_STATICS as list of decls to OB.
1015 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
1016 or -1. When it is positive, just output -1 when
1017 BITS<RANS_STATICS == BITS<RANS_STATICS. */
1020 stream_out_bitmap (struct lto_simple_output_block
*ob
,
1021 bitmap bits
, bitmap ltrans_statics
,
1022 int ltrans_statics_bitcount
)
1027 if (bits
== all_module_statics
)
1029 streamer_write_hwi_stream (ob
->main_stream
, -1);
1032 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1034 if (count
== ltrans_statics_bitcount
)
1036 streamer_write_hwi_stream (ob
->main_stream
, -1);
1039 streamer_write_hwi_stream (ob
->main_stream
, count
);
1042 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
1044 tree decl
= (*reference_vars_to_consider
) [index
];
1045 lto_output_var_decl_ref (ob
->decl_state
, ob
->main_stream
, decl
);
1049 /* Serialize the ipa info for lto. */
1052 ipa_reference_write_optimization_summary (void)
1054 struct lto_simple_output_block
*ob
1055 = lto_create_simple_output_block (LTO_section_ipa_reference
);
1056 unsigned int count
= 0;
1057 int ltrans_statics_bitcount
= 0;
1058 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
1059 auto_bitmap ltrans_statics
;
1062 vec_alloc (reference_vars_to_consider
, ipa_reference_vars_uids
);
1063 reference_vars_to_consider
->safe_grow (ipa_reference_vars_uids
, true);
1065 /* See what variables we are interested in. */
1066 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1068 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1069 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
1073 && (id
= ipa_reference_var_uid (vnode
->decl
)) != -1
1074 && referenced_from_this_partition_p (vnode
, encoder
))
1076 tree decl
= vnode
->decl
;
1077 bitmap_set_bit (ltrans_statics
, id
);
1078 (*reference_vars_to_consider
)[id
] = decl
;
1079 ltrans_statics_bitcount
++;
1084 if (ltrans_statics_bitcount
)
1085 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1087 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1088 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1089 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1093 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1095 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1098 /* Process all of the functions. */
1099 if (ltrans_statics_bitcount
)
1100 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1102 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1103 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1104 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1106 ipa_reference_optimization_summary_t info
;
1109 info
= get_reference_optimization_summary (cnode
);
1110 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1111 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1113 stream_out_bitmap (ob
, info
->statics_read
, ltrans_statics
,
1114 ltrans_statics_bitcount
);
1115 stream_out_bitmap (ob
, info
->statics_written
, ltrans_statics
,
1116 ltrans_statics_bitcount
);
1119 lto_destroy_simple_output_block (ob
);
1120 delete reference_vars_to_consider
;
1123 /* Deserialize the ipa info for lto. */
1126 ipa_reference_read_optimization_summary (void)
1128 struct lto_file_decl_data
** file_data_vec
1129 = lto_get_file_decl_data ();
1130 struct lto_file_decl_data
* file_data
;
1132 bitmap_obstack_initialize (&optimization_summary_obstack
);
1134 gcc_checking_assert (ipa_ref_opt_sum_summaries
== NULL
);
1135 ipa_ref_opt_sum_summaries
= new ipa_ref_opt_summary_t (symtab
);
1136 ipa_ref_opt_sum_summaries
->disable_insertion_hook ();
1137 ipa_reference_vars_map
= new reference_vars_map_t(257);
1139 = symtab
->add_varpool_removal_hook (varpool_removal_hook
, NULL
);
1140 ipa_reference_vars_uids
= 0;
1142 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1143 no_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1145 while ((file_data
= file_data_vec
[j
++]))
1149 class lto_input_block
*ib
1150 = lto_create_simple_input_block (file_data
,
1151 LTO_section_ipa_reference
,
1156 unsigned int f_count
= streamer_read_uhwi (ib
);
1160 b_count
= streamer_read_hwi (ib
);
1162 fprintf (dump_file
, "all module statics:");
1163 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1165 tree v_decl
= lto_input_var_decl_ref (ib
, file_data
);
1167 bitmap_set_bit (all_module_statics
,
1168 ipa_reference_var_get_or_insert_uid
1169 (v_decl
, &existed
));
1170 gcc_checking_assert (!existed
);
1172 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1175 for (i
= 0; i
< f_count
; i
++)
1177 unsigned int j
, index
;
1178 struct cgraph_node
*node
;
1180 lto_symtab_encoder_t encoder
;
1182 index
= streamer_read_uhwi (ib
);
1183 encoder
= file_data
->symtab_node_encoder
;
1184 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1187 ipa_reference_optimization_summary_d
*info
1188 = ipa_ref_opt_sum_summaries
->get_create (node
);
1192 "\nFunction name:%s:\n static read:",
1193 node
->dump_asm_name ());
1195 /* Set the statics read. */
1196 v_count
= streamer_read_hwi (ib
);
1199 info
->statics_read
= all_module_statics
;
1201 fprintf (dump_file
, " all module statics");
1203 else if (v_count
== 0)
1204 info
->statics_read
= no_module_statics
;
1207 info
->statics_read
= BITMAP_ALLOC
1208 (&optimization_summary_obstack
);
1209 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1211 tree v_decl
= lto_input_var_decl_ref (ib
, file_data
);
1212 bitmap_set_bit (info
->statics_read
,
1213 ipa_reference_var_uid (v_decl
));
1215 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1221 "\n static written:");
1222 /* Set the statics written. */
1223 v_count
= streamer_read_hwi (ib
);
1226 info
->statics_written
= all_module_statics
;
1228 fprintf (dump_file
, " all module statics");
1230 else if (v_count
== 0)
1231 info
->statics_written
= no_module_statics
;
1234 info
->statics_written
= BITMAP_ALLOC
1235 (&optimization_summary_obstack
);
1236 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1238 tree v_decl
= lto_input_var_decl_ref (ib
, 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
);