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"
48 #include "fold-const.h"
51 #include "hard-reg-set.h"
54 #include "basic-block.h"
55 #include "tree-ssa-alias.h"
56 #include "internal-fn.h"
57 #include "gimple-expr.h"
60 #include "tree-inline.h"
61 #include "tree-pass.h"
62 #include "splay-tree.h"
63 #include "plugin-api.h"
66 #include "ipa-utils.h"
68 #include "ipa-reference.h"
70 #include "diagnostic.h"
71 #include "data-streamer.h"
72 #include "lto-streamer.h"
74 static void remove_node_data (struct cgraph_node
*node
,
75 void *data ATTRIBUTE_UNUSED
);
76 static void duplicate_node_data (struct cgraph_node
*src
,
77 struct cgraph_node
*dst
,
78 void *data ATTRIBUTE_UNUSED
);
80 /* The static variables defined within the compilation unit that are
81 loaded or stored directly by function that owns this structure. */
83 struct ipa_reference_local_vars_info_d
86 bitmap statics_written
;
89 /* Statics that are read and written by some set of functions. The
90 local ones are based on the loads and stores local to the function.
91 The global ones are based on the local info as well as the
92 transitive closure of the functions that are called. */
94 struct ipa_reference_global_vars_info_d
97 bitmap statics_written
;
100 /* Information we save about every function after ipa-reference is completed. */
102 struct ipa_reference_optimization_summary_d
104 bitmap statics_not_read
;
105 bitmap statics_not_written
;
108 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
109 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
110 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
112 struct ipa_reference_vars_info_d
114 struct ipa_reference_local_vars_info_d local
;
115 struct ipa_reference_global_vars_info_d global
;
118 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
120 /* This splay tree contains all of the static variables that are
121 being considered by the compilation level alias analysis. */
122 static splay_tree reference_vars_to_consider
;
124 /* Set of all interesting module statics. A bit is set for every module
125 static we are considering. This is added to the local info when asm
126 code is found that clobbers all memory. */
127 static bitmap all_module_statics
;
128 /* Set of all statics that should be ignored becuase they are touched by
129 -fno-ipa-reference code. */
130 static bitmap ignore_module_statics
;
132 /* Obstack holding bitmaps of local analysis (live from analysis to
134 static bitmap_obstack local_info_obstack
;
135 /* Obstack holding global analysis live forever. */
136 static bitmap_obstack optimization_summary_obstack
;
138 /* Holders of ipa cgraph hooks: */
139 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
140 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
142 /* Vector where the reference var infos are actually stored.
143 Indexed by UID of call graph nodes. */
144 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
146 /* TODO: find a place where we should release the vector. */
147 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
149 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
150 static inline ipa_reference_vars_info_t
151 get_reference_vars_info (struct cgraph_node
*node
)
153 if (!ipa_reference_vars_vector
.exists ()
154 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
156 return ipa_reference_vars_vector
[node
->uid
];
159 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
160 static inline ipa_reference_optimization_summary_t
161 get_reference_optimization_summary (struct cgraph_node
*node
)
163 if (!ipa_reference_opt_sum_vector
.exists ()
164 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
166 return ipa_reference_opt_sum_vector
[node
->uid
];
169 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
171 set_reference_vars_info (struct cgraph_node
*node
,
172 ipa_reference_vars_info_t info
)
174 if (!ipa_reference_vars_vector
.exists ()
175 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
176 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
177 ipa_reference_vars_vector
[node
->uid
] = info
;
180 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
182 set_reference_optimization_summary (struct cgraph_node
*node
,
183 ipa_reference_optimization_summary_t info
)
185 if (!ipa_reference_opt_sum_vector
.exists ()
186 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
187 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
188 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
191 /* Return a bitmap indexed by DECL_UID for the static variables that
192 are *not* read during the execution of the function FN. Returns
193 NULL if no data is available. */
196 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
198 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
199 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
201 ipa_reference_optimization_summary_t info
=
202 get_reference_optimization_summary (fn
->function_symbol (NULL
));
204 return info
->statics_not_read
;
205 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
206 return all_module_statics
;
211 /* Return a bitmap indexed by DECL_UID for the static variables that
212 are *not* written during the execution of the function FN. Note
213 that variables written may or may not be read during the function
214 call. Returns NULL if no data is available. */
217 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
219 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
220 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
222 ipa_reference_optimization_summary_t info
=
223 get_reference_optimization_summary (fn
);
225 return info
->statics_not_written
;
226 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
227 return all_module_statics
;
233 /* Return true if the variable T is the right kind of static variable to
234 perform compilation unit scope escape analysis. */
237 is_proper_for_analysis (tree t
)
239 /* If the variable has the "used" attribute, treat it as if it had a
240 been touched by the devil. */
241 if (DECL_PRESERVE_P (t
))
244 /* Do not want to do anything with volatile except mark any
245 function that uses one to be not const or pure. */
246 if (TREE_THIS_VOLATILE (t
))
249 /* We do not need to analyze readonly vars, we already know they do not
251 if (TREE_READONLY (t
))
254 /* We can not track variables with address taken. */
255 if (TREE_ADDRESSABLE (t
))
258 /* TODO: We could track public variables that are not addressable, but currently
259 frontends don't give us those. */
263 /* TODO: Check aliases. */
264 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
270 /* Lookup the tree node for the static variable that has UID and
271 convert the name to a string for debugging. */
274 get_static_name (int index
)
276 splay_tree_node stn
=
277 splay_tree_lookup (reference_vars_to_consider
, index
);
278 return fndecl_name ((tree
)(stn
->value
));
281 /* Dump a set of static vars to FILE. */
283 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
289 else if (set
== all_module_statics
)
292 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
294 fprintf (f
, "%s ", get_static_name (index
));
298 /* Compute X |= Y, taking into account the possibility that
299 either X or Y is already the maximum set.
300 Return true if X is the maximum set after taking the union with Y. */
303 union_static_var_sets (bitmap
&x
, bitmap y
)
305 if (x
!= all_module_statics
)
307 if (y
== all_module_statics
)
310 x
= all_module_statics
;
312 else if (bitmap_ior_into (x
, y
))
314 /* The union may have reduced X to the maximum set.
315 In that case, we want to make that visible explicitly.
316 Even though bitmap_equal_p can be very expensive, it
317 turns out to be an overall win to check this here for
318 an LTO bootstrap of GCC itself. Liberally extrapoliate
319 that result to be applicable to all cases. */
320 if (bitmap_equal_p (x
, all_module_statics
))
323 x
= all_module_statics
;
327 return x
== all_module_statics
;
330 /* Return a copy of SET on the bitmap obstack containing SET.
331 But if SET is NULL or the maximum set, return that instead. */
334 copy_static_var_set (bitmap set
)
336 if (set
== NULL
|| set
== all_module_statics
)
338 bitmap_obstack
*o
= set
->obstack
;
339 gcc_checking_assert (o
);
340 bitmap copy
= BITMAP_ALLOC (o
);
341 bitmap_copy (copy
, set
);
345 /* Compute the union all of the statics read and written by every callee of X
346 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
347 actually the set representing the cycle containing X. If the read and
348 written sets of X_GLOBAL has been reduced to the maximum set, we don't
349 have to look at the remaining callees. */
352 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
354 struct cgraph_edge
*e
;
355 bool read_all
= x_global
->statics_read
== all_module_statics
;
356 bool write_all
= x_global
->statics_written
== all_module_statics
;
358 e
&& !(read_all
&& write_all
);
361 enum availability avail
;
362 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
366 /* Only look into nodes we can propagate something. */
367 int flags
= flags_from_decl_or_type (y
->decl
);
368 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
369 && (avail
> AVAIL_INTERPOSABLE
370 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
372 if (get_reference_vars_info (y
))
374 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
375 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
377 /* Calls in the current cycle do not have their global set
378 computed yet (but everything else does because we're
379 visiting nodes in topological order). */
380 if (!y_global
->statics_read
)
383 /* If the function is const, it reads no memory even if it
384 seems so to local analysis. */
385 if (flags
& ECF_CONST
)
388 union_static_var_sets (x_global
->statics_read
,
389 y_global
->statics_read
);
391 /* If the function is pure, it has no stores even if it
392 seems so to local analysis. If we cannot return from
393 the function, we can safely ignore the call. */
394 if ((flags
& ECF_PURE
)
395 || e
->cannot_lead_to_return_p ())
398 union_static_var_sets (x_global
->statics_written
,
399 y_global
->statics_written
);
407 static bool ipa_init_p
= false;
409 /* The init routine for analyzing global static variable usage. See
410 comments at top for description. */
420 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
422 bitmap_obstack_initialize (&local_info_obstack
);
423 bitmap_obstack_initialize (&optimization_summary_obstack
);
424 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
425 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
427 node_removal_hook_holder
=
428 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
429 node_duplication_hook_holder
=
430 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
434 /* Set up the persistent info for FN. */
436 static ipa_reference_local_vars_info_t
437 init_function_info (struct cgraph_node
*fn
)
439 ipa_reference_vars_info_t info
440 = XCNEW (struct ipa_reference_vars_info_d
);
442 /* Add the info to the tree's annotation. */
443 set_reference_vars_info (fn
, info
);
445 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
446 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
452 /* This is the main routine for finding the reference patterns for
453 global variables within a function FN. */
456 analyze_function (struct cgraph_node
*fn
)
458 ipa_reference_local_vars_info_t local
;
459 struct ipa_ref
*ref
= NULL
;
463 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
465 local
= init_function_info (fn
);
466 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
468 if (!is_a
<varpool_node
*> (ref
->referred
))
470 var
= ref
->referred
->decl
;
471 if (!is_proper_for_analysis (var
))
473 /* This is a variable we care about. Check if we have seen it
474 before, and if not add it the set of variables we care about. */
475 if (all_module_statics
476 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
479 splay_tree_insert (reference_vars_to_consider
,
480 DECL_UID (var
), (splay_tree_value
)var
);
485 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
488 if (ref
->cannot_lead_to_return ())
490 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
499 if (fn
->cannot_return_p ())
500 bitmap_clear (local
->statics_written
);
504 /* Called when new clone is inserted to callgraph late. */
507 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
508 void *data ATTRIBUTE_UNUSED
)
510 ipa_reference_optimization_summary_t ginfo
;
511 ipa_reference_optimization_summary_t dst_ginfo
;
513 ginfo
= get_reference_optimization_summary (src
);
516 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
517 set_reference_optimization_summary (dst
, dst_ginfo
);
518 dst_ginfo
->statics_not_read
=
519 copy_static_var_set (ginfo
->statics_not_read
);
520 dst_ginfo
->statics_not_written
=
521 copy_static_var_set (ginfo
->statics_not_written
);
524 /* Called when node is removed. */
527 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
529 ipa_reference_optimization_summary_t ginfo
;
530 ginfo
= get_reference_optimization_summary (node
);
533 if (ginfo
->statics_not_read
534 && ginfo
->statics_not_read
!= all_module_statics
)
535 BITMAP_FREE (ginfo
->statics_not_read
);
537 if (ginfo
->statics_not_written
538 && ginfo
->statics_not_written
!= all_module_statics
)
539 BITMAP_FREE (ginfo
->statics_not_written
);
541 set_reference_optimization_summary (node
, NULL
);
545 /* Analyze each function in the cgraph to see which global or statics
546 are read or written. */
549 generate_summary (void)
551 struct cgraph_node
*node
;
557 /* Process all of the functions next. */
558 FOR_EACH_DEFINED_FUNCTION (node
)
559 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
561 struct ipa_ref
*ref
= NULL
;
564 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
566 if (!is_a
<varpool_node
*> (ref
->referred
))
568 var
= ref
->referred
->decl
;
569 if (!is_proper_for_analysis (var
))
571 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
574 FOR_EACH_DEFINED_FUNCTION (node
)
575 analyze_function (node
);
578 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
580 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
581 get_static_name (index
), index
);
585 FOR_EACH_DEFINED_FUNCTION (node
)
586 if (node
->get_availability () >= AVAIL_INTERPOSABLE
587 && opt_for_fn (node
->decl
, flag_ipa_reference
))
589 ipa_reference_local_vars_info_t l
;
593 l
= &get_reference_vars_info (node
)->local
;
595 "\nFunction name:%s/%i:",
596 node
->asm_name (), node
->order
);
597 fprintf (dump_file
, "\n locals read: ");
599 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
602 fprintf (dump_file
, "%s ",
603 get_static_name (index
));
605 fprintf (dump_file
, "\n locals written: ");
606 if (l
->statics_written
)
607 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
610 fprintf (dump_file
, "%s ", get_static_name (index
));
615 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
618 read_write_all_from_decl (struct cgraph_node
*node
,
619 bool &read_all
, bool &write_all
)
621 tree decl
= node
->decl
;
622 int flags
= flags_from_decl_or_type (decl
);
623 if ((flags
& ECF_LEAF
)
624 && node
->get_availability () < AVAIL_INTERPOSABLE
)
626 else if (flags
& ECF_CONST
)
628 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
631 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
632 fprintf (dump_file
, " %s/%i -> read all\n",
633 node
->asm_name (), node
->order
);
637 /* TODO: To be able to produce sane results, we should also handle
638 common builtins, in particular throw. */
641 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
642 fprintf (dump_file
, " %s/%i -> read all, write all\n",
643 node
->asm_name (), node
->order
);
647 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
648 in the cycle of NODE. */
651 get_read_write_all_from_node (struct cgraph_node
*node
,
652 bool &read_all
, bool &write_all
)
654 struct cgraph_edge
*e
, *ie
;
656 /* When function is overwritable, we can not assume anything. */
657 if (node
->get_availability () <= AVAIL_INTERPOSABLE
658 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
659 read_write_all_from_decl (node
, read_all
, write_all
);
661 for (e
= node
->callees
;
662 e
&& !(read_all
&& write_all
);
665 enum availability avail
;
666 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
667 gcc_checking_assert (callee
);
668 if (avail
<= AVAIL_INTERPOSABLE
669 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
670 read_write_all_from_decl (callee
, read_all
, write_all
);
673 for (ie
= node
->indirect_calls
;
674 ie
&& !(read_all
&& write_all
);
675 ie
= ie
->next_callee
)
676 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
679 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
680 fprintf (dump_file
, " indirect call -> read all\n");
681 if (!ie
->cannot_lead_to_return_p ()
682 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
684 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
685 fprintf (dump_file
, " indirect call -> write all\n");
691 /* Skip edges from and to nodes without ipa_reference enables. This leave
692 them out of strongy connected coponents and makes them easyto skip in the
693 propagation loop bellow. */
696 ignore_edge_p (cgraph_edge
*e
)
698 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
699 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
700 flag_ipa_reference
));
703 /* Produce the global information by preforming a transitive closure
704 on the local information that was produced by ipa_analyze_function. */
709 struct cgraph_node
*node
;
710 struct cgraph_node
**order
=
711 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
717 cgraph_node::dump_cgraph (dump_file
);
719 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
722 /* Propagate the local information through the call graph to produce
723 the global information. All the nodes within a cycle will have
724 the same info so we collapse cycles first. Then we can do the
725 propagation in one pass from the leaves to the roots. */
726 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
728 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
730 for (i
= 0; i
< order_pos
; i
++ )
733 struct cgraph_node
*w
;
734 ipa_reference_vars_info_t node_info
;
735 ipa_reference_global_vars_info_t node_g
;
736 ipa_reference_local_vars_info_t node_l
;
737 bool read_all
= false;
738 bool write_all
= false;
741 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
744 node_info
= get_reference_vars_info (node
);
745 gcc_assert (node_info
);
746 node_l
= &node_info
->local
;
747 node_g
= &node_info
->global
;
749 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
750 fprintf (dump_file
, "Starting cycle with %s/%i\n",
751 node
->asm_name (), node
->order
);
753 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
755 /* If any node in a cycle is read_all or write_all, they all are. */
756 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
758 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
759 fprintf (dump_file
, " Visiting %s/%i\n",
760 w
->asm_name (), w
->order
);
761 get_read_write_all_from_node (w
, read_all
, write_all
);
762 if (read_all
&& write_all
)
766 /* Initialized the bitmaps global sets for the reduced node. */
768 node_g
->statics_read
= all_module_statics
;
770 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
772 node_g
->statics_written
= all_module_statics
;
774 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
776 /* Merge the sets of this cycle with all sets of callees reached
778 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
780 if (read_all
&& write_all
)
785 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
786 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
787 int flags
= flags_from_decl_or_type (w
->decl
);
789 if (!(flags
& ECF_CONST
))
790 read_all
= union_static_var_sets (node_g
->statics_read
,
792 if (!(flags
& ECF_PURE
)
793 && !w
->cannot_return_p ())
794 write_all
= union_static_var_sets (node_g
->statics_written
,
795 w_l
->statics_written
);
798 propagate_bits (node_g
, w
);
801 /* All nodes within a cycle have the same global info bitmaps. */
802 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
804 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
805 w_ri
->global
= *node_g
;
808 cycle_nodes
.release ();
813 for (i
= 0; i
< order_pos
; i
++)
816 struct cgraph_node
*w
;
819 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
823 "\nFunction name:%s/%i:",
824 node
->asm_name (), node
->order
);
826 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
827 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
829 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
830 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
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
;
835 fprintf (dump_file
, "\n next cycle: %s/%i ",
836 w
->asm_name (), w
->order
);
837 fprintf (dump_file
, "\n locals read: ");
838 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
839 fprintf (dump_file
, "\n locals written: ");
840 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
842 cycle_nodes
.release ();
844 fprintf (dump_file
, "\n globals read: ");
845 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
846 fprintf (dump_file
, "\n globals written: ");
847 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
848 fprintf (dump_file
, "\n");
853 FOR_EACH_DEFINED_FUNCTION (node
)
855 ipa_reference_vars_info_t node_info
;
856 ipa_reference_global_vars_info_t node_g
;
857 ipa_reference_optimization_summary_t opt
;
859 node_info
= get_reference_vars_info (node
);
860 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
861 && (node
->get_availability () > AVAIL_INTERPOSABLE
862 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
864 node_g
= &node_info
->global
;
866 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
867 set_reference_optimization_summary (node
, opt
);
869 /* Create the complimentary sets. */
871 if (bitmap_empty_p (node_g
->statics_read
))
872 opt
->statics_not_read
= all_module_statics
;
875 opt
->statics_not_read
876 = BITMAP_ALLOC (&optimization_summary_obstack
);
877 if (node_g
->statics_read
!= all_module_statics
)
878 bitmap_and_compl (opt
->statics_not_read
,
880 node_g
->statics_read
);
883 if (bitmap_empty_p (node_g
->statics_written
))
884 opt
->statics_not_written
= all_module_statics
;
887 opt
->statics_not_written
888 = BITMAP_ALLOC (&optimization_summary_obstack
);
889 if (node_g
->statics_written
!= all_module_statics
)
890 bitmap_and_compl (opt
->statics_not_written
,
892 node_g
->statics_written
);
898 ipa_free_postorder_info ();
901 bitmap_obstack_release (&local_info_obstack
);
902 ipa_reference_vars_vector
.release ();
904 splay_tree_delete (reference_vars_to_consider
);
905 reference_vars_to_consider
= NULL
;
906 return remove_p
? TODO_remove_functions
: 0;
909 /* Return true if we need to write summary of NODE. */
912 write_node_summary_p (struct cgraph_node
*node
,
913 lto_symtab_encoder_t encoder
,
914 bitmap ltrans_statics
)
916 ipa_reference_optimization_summary_t info
;
918 /* See if we have (non-empty) info. */
919 if (!node
->definition
|| node
->global
.inlined_to
)
921 info
= get_reference_optimization_summary (node
);
922 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
923 && bitmap_empty_p (info
->statics_not_written
)))
926 /* See if we want to encode it.
927 Encode also referenced functions since constant folding might turn it into
930 In future we might also want to include summaries of functions references
931 by initializers of constant variables references in current unit. */
932 if (!reachable_from_this_partition_p (node
, encoder
)
933 && !referenced_from_this_partition_p (node
, encoder
))
936 /* See if the info has non-empty intersections with vars we want to encode. */
937 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
938 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
943 /* Stream out BITS<RANS_STATICS as list of decls to OB.
944 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
945 or -1. When it is positive, just output -1 when
946 BITS<RANS_STATICS == BITS<RANS_STATICS. */
949 stream_out_bitmap (struct lto_simple_output_block
*ob
,
950 bitmap bits
, bitmap ltrans_statics
,
951 int ltrans_statics_bitcount
)
956 if (bits
== all_module_statics
)
958 streamer_write_hwi_stream (ob
->main_stream
, -1);
961 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
963 if (count
== ltrans_statics_bitcount
)
965 streamer_write_hwi_stream (ob
->main_stream
, -1);
968 streamer_write_hwi_stream (ob
->main_stream
, count
);
971 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
973 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
974 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
978 /* Serialize the ipa info for lto. */
981 ipa_reference_write_optimization_summary (void)
983 struct lto_simple_output_block
*ob
984 = lto_create_simple_output_block (LTO_section_ipa_reference
);
985 unsigned int count
= 0;
986 int ltrans_statics_bitcount
= 0;
987 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
988 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
991 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
993 /* See what variables we are interested in. */
994 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
996 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
997 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
999 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
1000 && referenced_from_this_partition_p (vnode
, encoder
))
1002 tree decl
= vnode
->decl
;
1003 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
1004 splay_tree_insert (reference_vars_to_consider
,
1005 DECL_UID (decl
), (splay_tree_value
)decl
);
1006 ltrans_statics_bitcount
++;
1011 if (ltrans_statics_bitcount
)
1012 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1014 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1015 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1016 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1020 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1022 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1025 /* Process all of the functions. */
1026 if (ltrans_statics_bitcount
)
1027 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1029 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1030 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1031 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1033 ipa_reference_optimization_summary_t info
;
1036 info
= get_reference_optimization_summary (cnode
);
1037 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1038 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1040 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1041 ltrans_statics_bitcount
);
1042 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1043 ltrans_statics_bitcount
);
1046 BITMAP_FREE (ltrans_statics
);
1047 lto_destroy_simple_output_block (ob
);
1048 splay_tree_delete (reference_vars_to_consider
);
1051 /* Deserialize the ipa info for lto. */
1054 ipa_reference_read_optimization_summary (void)
1056 struct lto_file_decl_data
** file_data_vec
1057 = lto_get_file_decl_data ();
1058 struct lto_file_decl_data
* file_data
;
1060 bitmap_obstack_initialize (&optimization_summary_obstack
);
1062 node_removal_hook_holder
=
1063 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1064 node_duplication_hook_holder
=
1065 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1066 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1068 while ((file_data
= file_data_vec
[j
++]))
1072 struct lto_input_block
*ib
1073 = lto_create_simple_input_block (file_data
,
1074 LTO_section_ipa_reference
,
1079 unsigned int f_count
= streamer_read_uhwi (ib
);
1083 b_count
= streamer_read_hwi (ib
);
1085 fprintf (dump_file
, "all module statics:");
1086 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1088 unsigned int var_index
= streamer_read_uhwi (ib
);
1089 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1091 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1093 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1096 for (i
= 0; i
< f_count
; i
++)
1098 unsigned int j
, index
;
1099 struct cgraph_node
*node
;
1100 ipa_reference_optimization_summary_t info
;
1102 lto_symtab_encoder_t encoder
;
1104 index
= streamer_read_uhwi (ib
);
1105 encoder
= file_data
->symtab_node_encoder
;
1106 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1108 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1109 set_reference_optimization_summary (node
, info
);
1110 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1111 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1114 "\nFunction name:%s/%i:\n static not read:",
1115 node
->asm_name (), node
->order
);
1117 /* Set the statics not read. */
1118 v_count
= streamer_read_hwi (ib
);
1121 info
->statics_not_read
= all_module_statics
;
1123 fprintf (dump_file
, " all module statics");
1126 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1128 unsigned int var_index
= streamer_read_uhwi (ib
);
1129 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1131 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1133 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1138 "\n static not written:");
1139 /* Set the statics not written. */
1140 v_count
= streamer_read_hwi (ib
);
1143 info
->statics_not_written
= all_module_statics
;
1145 fprintf (dump_file
, " all module statics");
1148 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1150 unsigned int var_index
= streamer_read_uhwi (ib
);
1151 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1153 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1155 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1158 fprintf (dump_file
, "\n");
1161 lto_destroy_simple_input_block (file_data
,
1162 LTO_section_ipa_reference
,
1166 /* Fatal error here. We do not want to support compiling ltrans units with
1167 different version of compiler or different flags than the WPA unit, so
1168 this should never happen. */
1169 fatal_error (input_location
,
1170 "ipa reference summary is missing in ltrans unit");
1176 const pass_data pass_data_ipa_reference
=
1178 IPA_PASS
, /* type */
1179 "static-var", /* name */
1180 OPTGROUP_NONE
, /* optinfo_flags */
1181 TV_IPA_REFERENCE
, /* tv_id */
1182 0, /* properties_required */
1183 0, /* properties_provided */
1184 0, /* properties_destroyed */
1185 0, /* todo_flags_start */
1186 0, /* todo_flags_finish */
1189 class pass_ipa_reference
: public ipa_opt_pass_d
1192 pass_ipa_reference (gcc::context
*ctxt
)
1193 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1194 NULL
, /* generate_summary */
1195 NULL
, /* write_summary */
1196 NULL
, /* read_summary */
1197 ipa_reference_write_optimization_summary
, /*
1198 write_optimization_summary */
1199 ipa_reference_read_optimization_summary
, /*
1200 read_optimization_summary */
1201 NULL
, /* stmt_fixup */
1202 0, /* function_transform_todo_flags_start */
1203 NULL
, /* function_transform */
1204 NULL
) /* variable_transform */
1207 /* opt_pass methods: */
1208 virtual bool gate (function
*)
1210 return ((in_lto_p
|| flag_ipa_reference
)
1211 /* Don't bother doing anything if the program has errors. */
1215 virtual unsigned int execute (function
*) { return propagate (); }
1217 }; // class pass_ipa_reference
1222 make_pass_ipa_reference (gcc::context
*ctxt
)
1224 return new pass_ipa_reference (ctxt
);
1227 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1228 within the same process. For use by toplev::finalize. */
1231 ipa_reference_c_finalize (void)
1235 bitmap_obstack_release (&optimization_summary_obstack
);
1239 if (node_removal_hook_holder
)
1241 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1242 node_removal_hook_holder
= NULL
;
1244 if (node_duplication_hook_holder
)
1246 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1247 node_duplication_hook_holder
= NULL
;