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"
51 #include "fold-const.h"
54 #include "hard-reg-set.h"
57 #include "basic-block.h"
58 #include "tree-ssa-alias.h"
59 #include "internal-fn.h"
60 #include "gimple-expr.h"
63 #include "tree-inline.h"
64 #include "tree-pass.h"
65 #include "splay-tree.h"
67 #include "plugin-api.h"
70 #include "ipa-utils.h"
72 #include "ipa-reference.h"
74 #include "diagnostic.h"
75 #include "data-streamer.h"
76 #include "lto-streamer.h"
78 static void remove_node_data (struct cgraph_node
*node
,
79 void *data ATTRIBUTE_UNUSED
);
80 static void duplicate_node_data (struct cgraph_node
*src
,
81 struct cgraph_node
*dst
,
82 void *data ATTRIBUTE_UNUSED
);
84 /* The static variables defined within the compilation unit that are
85 loaded or stored directly by function that owns this structure. */
87 struct ipa_reference_local_vars_info_d
90 bitmap statics_written
;
93 /* Statics that are read and written by some set of functions. The
94 local ones are based on the loads and stores local to the function.
95 The global ones are based on the local info as well as the
96 transitive closure of the functions that are called. */
98 struct ipa_reference_global_vars_info_d
101 bitmap statics_written
;
104 /* Information we save about every function after ipa-reference is completed. */
106 struct ipa_reference_optimization_summary_d
108 bitmap statics_not_read
;
109 bitmap statics_not_written
;
112 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
113 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
114 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
116 struct ipa_reference_vars_info_d
118 struct ipa_reference_local_vars_info_d local
;
119 struct ipa_reference_global_vars_info_d global
;
122 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
124 /* This splay tree contains all of the static variables that are
125 being considered by the compilation level alias analysis. */
126 static splay_tree reference_vars_to_consider
;
128 /* Set of all interesting module statics. A bit is set for every module
129 static we are considering. This is added to the local info when asm
130 code is found that clobbers all memory. */
131 static bitmap all_module_statics
;
132 /* Set of all statics that should be ignored becuase they are touched by
133 -fno-ipa-reference code. */
134 static bitmap ignore_module_statics
;
136 /* Obstack holding bitmaps of local analysis (live from analysis to
138 static bitmap_obstack local_info_obstack
;
139 /* Obstack holding global analysis live forever. */
140 static bitmap_obstack optimization_summary_obstack
;
142 /* Holders of ipa cgraph hooks: */
143 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
144 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
146 /* Vector where the reference var infos are actually stored.
147 Indexed by UID of call graph nodes. */
148 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
150 /* TODO: find a place where we should release the vector. */
151 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
153 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
154 static inline ipa_reference_vars_info_t
155 get_reference_vars_info (struct cgraph_node
*node
)
157 if (!ipa_reference_vars_vector
.exists ()
158 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
160 return ipa_reference_vars_vector
[node
->uid
];
163 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
164 static inline ipa_reference_optimization_summary_t
165 get_reference_optimization_summary (struct cgraph_node
*node
)
167 if (!ipa_reference_opt_sum_vector
.exists ()
168 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
170 return ipa_reference_opt_sum_vector
[node
->uid
];
173 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
175 set_reference_vars_info (struct cgraph_node
*node
,
176 ipa_reference_vars_info_t info
)
178 if (!ipa_reference_vars_vector
.exists ()
179 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
180 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
181 ipa_reference_vars_vector
[node
->uid
] = info
;
184 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
186 set_reference_optimization_summary (struct cgraph_node
*node
,
187 ipa_reference_optimization_summary_t info
)
189 if (!ipa_reference_opt_sum_vector
.exists ()
190 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
191 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
192 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
195 /* Return a bitmap indexed by DECL_UID for the static variables that
196 are *not* read during the execution of the function FN. Returns
197 NULL if no data is available. */
200 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
202 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
203 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
205 ipa_reference_optimization_summary_t info
=
206 get_reference_optimization_summary (fn
->function_symbol (NULL
));
208 return info
->statics_not_read
;
209 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
210 return all_module_statics
;
215 /* Return a bitmap indexed by DECL_UID for the static variables that
216 are *not* written during the execution of the function FN. Note
217 that variables written may or may not be read during the function
218 call. Returns NULL if no data is available. */
221 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
223 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
224 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
226 ipa_reference_optimization_summary_t info
=
227 get_reference_optimization_summary (fn
);
229 return info
->statics_not_written
;
230 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
231 return all_module_statics
;
237 /* Return true if the variable T is the right kind of static variable to
238 perform compilation unit scope escape analysis. */
241 is_proper_for_analysis (tree t
)
243 /* If the variable has the "used" attribute, treat it as if it had a
244 been touched by the devil. */
245 if (DECL_PRESERVE_P (t
))
248 /* Do not want to do anything with volatile except mark any
249 function that uses one to be not const or pure. */
250 if (TREE_THIS_VOLATILE (t
))
253 /* We do not need to analyze readonly vars, we already know they do not
255 if (TREE_READONLY (t
))
258 /* We can not track variables with address taken. */
259 if (TREE_ADDRESSABLE (t
))
262 /* TODO: We could track public variables that are not addressable, but currently
263 frontends don't give us those. */
267 /* TODO: Check aliases. */
268 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
274 /* Lookup the tree node for the static variable that has UID and
275 convert the name to a string for debugging. */
278 get_static_name (int index
)
280 splay_tree_node stn
=
281 splay_tree_lookup (reference_vars_to_consider
, index
);
282 return fndecl_name ((tree
)(stn
->value
));
285 /* Dump a set of static vars to FILE. */
287 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
293 else if (set
== all_module_statics
)
296 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
298 fprintf (f
, "%s ", get_static_name (index
));
302 /* Compute X |= Y, taking into account the possibility that
303 either X or Y is already the maximum set.
304 Return true if X is the maximum set after taking the union with Y. */
307 union_static_var_sets (bitmap
&x
, bitmap y
)
309 if (x
!= all_module_statics
)
311 if (y
== all_module_statics
)
314 x
= all_module_statics
;
316 else if (bitmap_ior_into (x
, y
))
318 /* The union may have reduced X to the maximum set.
319 In that case, we want to make that visible explicitly.
320 Even though bitmap_equal_p can be very expensive, it
321 turns out to be an overall win to check this here for
322 an LTO bootstrap of GCC itself. Liberally extrapoliate
323 that result to be applicable to all cases. */
324 if (bitmap_equal_p (x
, all_module_statics
))
327 x
= all_module_statics
;
331 return x
== all_module_statics
;
334 /* Return a copy of SET on the bitmap obstack containing SET.
335 But if SET is NULL or the maximum set, return that instead. */
338 copy_static_var_set (bitmap set
)
340 if (set
== NULL
|| set
== all_module_statics
)
342 bitmap_obstack
*o
= set
->obstack
;
343 gcc_checking_assert (o
);
344 bitmap copy
= BITMAP_ALLOC (o
);
345 bitmap_copy (copy
, set
);
349 /* Compute the union all of the statics read and written by every callee of X
350 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
351 actually the set representing the cycle containing X. If the read and
352 written sets of X_GLOBAL has been reduced to the maximum set, we don't
353 have to look at the remaining callees. */
356 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
358 struct cgraph_edge
*e
;
359 bool read_all
= x_global
->statics_read
== all_module_statics
;
360 bool write_all
= x_global
->statics_written
== all_module_statics
;
362 e
&& !(read_all
&& write_all
);
365 enum availability avail
;
366 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
370 /* Only look into nodes we can propagate something. */
371 int flags
= flags_from_decl_or_type (y
->decl
);
372 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
373 && (avail
> AVAIL_INTERPOSABLE
374 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
376 if (get_reference_vars_info (y
))
378 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
379 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
381 /* Calls in the current cycle do not have their global set
382 computed yet (but everything else does because we're
383 visiting nodes in topological order). */
384 if (!y_global
->statics_read
)
387 /* If the function is const, it reads no memory even if it
388 seems so to local analysis. */
389 if (flags
& ECF_CONST
)
392 union_static_var_sets (x_global
->statics_read
,
393 y_global
->statics_read
);
395 /* If the function is pure, it has no stores even if it
396 seems so to local analysis. If we cannot return from
397 the function, we can safely ignore the call. */
398 if ((flags
& ECF_PURE
)
399 || e
->cannot_lead_to_return_p ())
402 union_static_var_sets (x_global
->statics_written
,
403 y_global
->statics_written
);
411 static bool ipa_init_p
= false;
413 /* The init routine for analyzing global static variable usage. See
414 comments at top for description. */
424 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
426 bitmap_obstack_initialize (&local_info_obstack
);
427 bitmap_obstack_initialize (&optimization_summary_obstack
);
428 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
429 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
431 node_removal_hook_holder
=
432 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
433 node_duplication_hook_holder
=
434 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
438 /* Set up the persistent info for FN. */
440 static ipa_reference_local_vars_info_t
441 init_function_info (struct cgraph_node
*fn
)
443 ipa_reference_vars_info_t info
444 = XCNEW (struct ipa_reference_vars_info_d
);
446 /* Add the info to the tree's annotation. */
447 set_reference_vars_info (fn
, info
);
449 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
450 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
456 /* This is the main routine for finding the reference patterns for
457 global variables within a function FN. */
460 analyze_function (struct cgraph_node
*fn
)
462 ipa_reference_local_vars_info_t local
;
463 struct ipa_ref
*ref
= NULL
;
467 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
469 local
= init_function_info (fn
);
470 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
472 if (!is_a
<varpool_node
*> (ref
->referred
))
474 var
= ref
->referred
->decl
;
475 if (!is_proper_for_analysis (var
))
477 /* This is a variable we care about. Check if we have seen it
478 before, and if not add it the set of variables we care about. */
479 if (all_module_statics
480 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
483 splay_tree_insert (reference_vars_to_consider
,
484 DECL_UID (var
), (splay_tree_value
)var
);
489 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
492 if (ref
->cannot_lead_to_return ())
494 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
503 if (fn
->cannot_return_p ())
504 bitmap_clear (local
->statics_written
);
508 /* Called when new clone is inserted to callgraph late. */
511 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
512 void *data ATTRIBUTE_UNUSED
)
514 ipa_reference_optimization_summary_t ginfo
;
515 ipa_reference_optimization_summary_t dst_ginfo
;
517 ginfo
= get_reference_optimization_summary (src
);
520 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
521 set_reference_optimization_summary (dst
, dst_ginfo
);
522 dst_ginfo
->statics_not_read
=
523 copy_static_var_set (ginfo
->statics_not_read
);
524 dst_ginfo
->statics_not_written
=
525 copy_static_var_set (ginfo
->statics_not_written
);
528 /* Called when node is removed. */
531 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
533 ipa_reference_optimization_summary_t ginfo
;
534 ginfo
= get_reference_optimization_summary (node
);
537 if (ginfo
->statics_not_read
538 && ginfo
->statics_not_read
!= all_module_statics
)
539 BITMAP_FREE (ginfo
->statics_not_read
);
541 if (ginfo
->statics_not_written
542 && ginfo
->statics_not_written
!= all_module_statics
)
543 BITMAP_FREE (ginfo
->statics_not_written
);
545 set_reference_optimization_summary (node
, NULL
);
549 /* Analyze each function in the cgraph to see which global or statics
550 are read or written. */
553 generate_summary (void)
555 struct cgraph_node
*node
;
561 /* Process all of the functions next. */
562 FOR_EACH_DEFINED_FUNCTION (node
)
563 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
565 struct ipa_ref
*ref
= NULL
;
568 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
570 if (!is_a
<varpool_node
*> (ref
->referred
))
572 var
= ref
->referred
->decl
;
573 if (!is_proper_for_analysis (var
))
575 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
578 FOR_EACH_DEFINED_FUNCTION (node
)
579 analyze_function (node
);
582 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
584 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
585 get_static_name (index
), index
);
589 FOR_EACH_DEFINED_FUNCTION (node
)
590 if (node
->get_availability () >= AVAIL_INTERPOSABLE
591 && opt_for_fn (node
->decl
, flag_ipa_reference
))
593 ipa_reference_local_vars_info_t l
;
597 l
= &get_reference_vars_info (node
)->local
;
599 "\nFunction name:%s/%i:",
600 node
->asm_name (), node
->order
);
601 fprintf (dump_file
, "\n locals read: ");
603 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
606 fprintf (dump_file
, "%s ",
607 get_static_name (index
));
609 fprintf (dump_file
, "\n locals written: ");
610 if (l
->statics_written
)
611 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
614 fprintf (dump_file
, "%s ", get_static_name (index
));
619 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
622 read_write_all_from_decl (struct cgraph_node
*node
,
623 bool &read_all
, bool &write_all
)
625 tree decl
= node
->decl
;
626 int flags
= flags_from_decl_or_type (decl
);
627 if ((flags
& ECF_LEAF
)
628 && node
->get_availability () < AVAIL_INTERPOSABLE
)
630 else if (flags
& ECF_CONST
)
632 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
635 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
636 fprintf (dump_file
, " %s/%i -> read all\n",
637 node
->asm_name (), node
->order
);
641 /* TODO: To be able to produce sane results, we should also handle
642 common builtins, in particular throw. */
645 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
646 fprintf (dump_file
, " %s/%i -> read all, write all\n",
647 node
->asm_name (), node
->order
);
651 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
652 in the cycle of NODE. */
655 get_read_write_all_from_node (struct cgraph_node
*node
,
656 bool &read_all
, bool &write_all
)
658 struct cgraph_edge
*e
, *ie
;
660 /* When function is overwritable, we can not assume anything. */
661 if (node
->get_availability () <= AVAIL_INTERPOSABLE
662 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
663 read_write_all_from_decl (node
, read_all
, write_all
);
665 for (e
= node
->callees
;
666 e
&& !(read_all
&& write_all
);
669 enum availability avail
;
670 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
671 gcc_checking_assert (callee
);
672 if (avail
<= AVAIL_INTERPOSABLE
673 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
674 read_write_all_from_decl (callee
, read_all
, write_all
);
677 for (ie
= node
->indirect_calls
;
678 ie
&& !(read_all
&& write_all
);
679 ie
= ie
->next_callee
)
680 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
683 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
684 fprintf (dump_file
, " indirect call -> read all\n");
685 if (!ie
->cannot_lead_to_return_p ()
686 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
688 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
689 fprintf (dump_file
, " indirect call -> write all\n");
695 /* Skip edges from and to nodes without ipa_reference enables. This leave
696 them out of strongy connected coponents and makes them easyto skip in the
697 propagation loop bellow. */
700 ignore_edge_p (cgraph_edge
*e
)
702 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
703 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
704 flag_ipa_reference
));
707 /* Produce the global information by preforming a transitive closure
708 on the local information that was produced by ipa_analyze_function. */
713 struct cgraph_node
*node
;
714 struct cgraph_node
**order
=
715 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
721 cgraph_node::dump_cgraph (dump_file
);
723 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
726 /* Propagate the local information through the call graph to produce
727 the global information. All the nodes within a cycle will have
728 the same info so we collapse cycles first. Then we can do the
729 propagation in one pass from the leaves to the roots. */
730 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
732 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
734 for (i
= 0; i
< order_pos
; i
++ )
737 struct cgraph_node
*w
;
738 ipa_reference_vars_info_t node_info
;
739 ipa_reference_global_vars_info_t node_g
;
740 ipa_reference_local_vars_info_t node_l
;
741 bool read_all
= false;
742 bool write_all
= false;
745 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
748 node_info
= get_reference_vars_info (node
);
749 gcc_assert (node_info
);
750 node_l
= &node_info
->local
;
751 node_g
= &node_info
->global
;
753 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
754 fprintf (dump_file
, "Starting cycle with %s/%i\n",
755 node
->asm_name (), node
->order
);
757 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
759 /* If any node in a cycle is read_all or write_all, they all are. */
760 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
762 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
763 fprintf (dump_file
, " Visiting %s/%i\n",
764 w
->asm_name (), w
->order
);
765 get_read_write_all_from_node (w
, read_all
, write_all
);
766 if (read_all
&& write_all
)
770 /* Initialized the bitmaps global sets for the reduced node. */
772 node_g
->statics_read
= all_module_statics
;
774 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
776 node_g
->statics_written
= all_module_statics
;
778 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
780 /* Merge the sets of this cycle with all sets of callees reached
782 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
784 if (read_all
&& write_all
)
789 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
790 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
791 int flags
= flags_from_decl_or_type (w
->decl
);
793 if (!(flags
& ECF_CONST
))
794 read_all
= union_static_var_sets (node_g
->statics_read
,
796 if (!(flags
& ECF_PURE
)
797 && !w
->cannot_return_p ())
798 write_all
= union_static_var_sets (node_g
->statics_written
,
799 w_l
->statics_written
);
802 propagate_bits (node_g
, w
);
805 /* All nodes within a cycle have the same global info bitmaps. */
806 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
808 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
809 w_ri
->global
= *node_g
;
812 cycle_nodes
.release ();
817 for (i
= 0; i
< order_pos
; i
++)
820 struct cgraph_node
*w
;
823 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
827 "\nFunction name:%s/%i:",
828 node
->asm_name (), node
->order
);
830 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
831 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
833 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
834 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
836 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
837 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
839 fprintf (dump_file
, "\n next cycle: %s/%i ",
840 w
->asm_name (), w
->order
);
841 fprintf (dump_file
, "\n locals read: ");
842 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
843 fprintf (dump_file
, "\n locals written: ");
844 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
846 cycle_nodes
.release ();
848 fprintf (dump_file
, "\n globals read: ");
849 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
850 fprintf (dump_file
, "\n globals written: ");
851 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
852 fprintf (dump_file
, "\n");
857 FOR_EACH_DEFINED_FUNCTION (node
)
859 ipa_reference_vars_info_t node_info
;
860 ipa_reference_global_vars_info_t node_g
;
861 ipa_reference_optimization_summary_t opt
;
863 node_info
= get_reference_vars_info (node
);
864 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
865 && (node
->get_availability () > AVAIL_INTERPOSABLE
866 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
868 node_g
= &node_info
->global
;
870 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
871 set_reference_optimization_summary (node
, opt
);
873 /* Create the complimentary sets. */
875 if (bitmap_empty_p (node_g
->statics_read
))
876 opt
->statics_not_read
= all_module_statics
;
879 opt
->statics_not_read
880 = BITMAP_ALLOC (&optimization_summary_obstack
);
881 if (node_g
->statics_read
!= all_module_statics
)
882 bitmap_and_compl (opt
->statics_not_read
,
884 node_g
->statics_read
);
887 if (bitmap_empty_p (node_g
->statics_written
))
888 opt
->statics_not_written
= all_module_statics
;
891 opt
->statics_not_written
892 = BITMAP_ALLOC (&optimization_summary_obstack
);
893 if (node_g
->statics_written
!= all_module_statics
)
894 bitmap_and_compl (opt
->statics_not_written
,
896 node_g
->statics_written
);
902 ipa_free_postorder_info ();
905 bitmap_obstack_release (&local_info_obstack
);
906 ipa_reference_vars_vector
.release ();
908 splay_tree_delete (reference_vars_to_consider
);
909 reference_vars_to_consider
= NULL
;
910 return remove_p
? TODO_remove_functions
: 0;
913 /* Return true if we need to write summary of NODE. */
916 write_node_summary_p (struct cgraph_node
*node
,
917 lto_symtab_encoder_t encoder
,
918 bitmap ltrans_statics
)
920 ipa_reference_optimization_summary_t info
;
922 /* See if we have (non-empty) info. */
923 if (!node
->definition
|| node
->global
.inlined_to
)
925 info
= get_reference_optimization_summary (node
);
926 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
927 && bitmap_empty_p (info
->statics_not_written
)))
930 /* See if we want to encode it.
931 Encode also referenced functions since constant folding might turn it into
934 In future we might also want to include summaries of functions references
935 by initializers of constant variables references in current unit. */
936 if (!reachable_from_this_partition_p (node
, encoder
)
937 && !referenced_from_this_partition_p (node
, encoder
))
940 /* See if the info has non-empty intersections with vars we want to encode. */
941 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
942 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
947 /* Stream out BITS<RANS_STATICS as list of decls to OB.
948 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
949 or -1. When it is positive, just output -1 when
950 BITS<RANS_STATICS == BITS<RANS_STATICS. */
953 stream_out_bitmap (struct lto_simple_output_block
*ob
,
954 bitmap bits
, bitmap ltrans_statics
,
955 int ltrans_statics_bitcount
)
960 if (bits
== all_module_statics
)
962 streamer_write_hwi_stream (ob
->main_stream
, -1);
965 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
967 if (count
== ltrans_statics_bitcount
)
969 streamer_write_hwi_stream (ob
->main_stream
, -1);
972 streamer_write_hwi_stream (ob
->main_stream
, count
);
975 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
977 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
978 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
982 /* Serialize the ipa info for lto. */
985 ipa_reference_write_optimization_summary (void)
987 struct lto_simple_output_block
*ob
988 = lto_create_simple_output_block (LTO_section_ipa_reference
);
989 unsigned int count
= 0;
990 int ltrans_statics_bitcount
= 0;
991 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
992 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
995 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
997 /* See what variables we are interested in. */
998 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1000 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1001 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
1003 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
1004 && referenced_from_this_partition_p (vnode
, encoder
))
1006 tree decl
= vnode
->decl
;
1007 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
1008 splay_tree_insert (reference_vars_to_consider
,
1009 DECL_UID (decl
), (splay_tree_value
)decl
);
1010 ltrans_statics_bitcount
++;
1015 if (ltrans_statics_bitcount
)
1016 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1018 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1019 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1020 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1024 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1026 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1029 /* Process all of the functions. */
1030 if (ltrans_statics_bitcount
)
1031 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1033 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1034 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1035 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1037 ipa_reference_optimization_summary_t info
;
1040 info
= get_reference_optimization_summary (cnode
);
1041 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1042 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1044 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1045 ltrans_statics_bitcount
);
1046 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1047 ltrans_statics_bitcount
);
1050 BITMAP_FREE (ltrans_statics
);
1051 lto_destroy_simple_output_block (ob
);
1052 splay_tree_delete (reference_vars_to_consider
);
1055 /* Deserialize the ipa info for lto. */
1058 ipa_reference_read_optimization_summary (void)
1060 struct lto_file_decl_data
** file_data_vec
1061 = lto_get_file_decl_data ();
1062 struct lto_file_decl_data
* file_data
;
1064 bitmap_obstack_initialize (&optimization_summary_obstack
);
1066 node_removal_hook_holder
=
1067 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1068 node_duplication_hook_holder
=
1069 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1070 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1072 while ((file_data
= file_data_vec
[j
++]))
1076 struct lto_input_block
*ib
1077 = lto_create_simple_input_block (file_data
,
1078 LTO_section_ipa_reference
,
1083 unsigned int f_count
= streamer_read_uhwi (ib
);
1087 b_count
= streamer_read_hwi (ib
);
1089 fprintf (dump_file
, "all module statics:");
1090 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1092 unsigned int var_index
= streamer_read_uhwi (ib
);
1093 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1095 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1097 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1100 for (i
= 0; i
< f_count
; i
++)
1102 unsigned int j
, index
;
1103 struct cgraph_node
*node
;
1104 ipa_reference_optimization_summary_t info
;
1106 lto_symtab_encoder_t encoder
;
1108 index
= streamer_read_uhwi (ib
);
1109 encoder
= file_data
->symtab_node_encoder
;
1110 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1112 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1113 set_reference_optimization_summary (node
, info
);
1114 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1115 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1118 "\nFunction name:%s/%i:\n static not read:",
1119 node
->asm_name (), node
->order
);
1121 /* Set the statics not read. */
1122 v_count
= streamer_read_hwi (ib
);
1125 info
->statics_not_read
= all_module_statics
;
1127 fprintf (dump_file
, " all module statics");
1130 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1132 unsigned int var_index
= streamer_read_uhwi (ib
);
1133 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1135 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1137 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1142 "\n static not written:");
1143 /* Set the statics not written. */
1144 v_count
= streamer_read_hwi (ib
);
1147 info
->statics_not_written
= all_module_statics
;
1149 fprintf (dump_file
, " all module statics");
1152 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1154 unsigned int var_index
= streamer_read_uhwi (ib
);
1155 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1157 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1159 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1162 fprintf (dump_file
, "\n");
1165 lto_destroy_simple_input_block (file_data
,
1166 LTO_section_ipa_reference
,
1170 /* Fatal error here. We do not want to support compiling ltrans units with
1171 different version of compiler or different flags than the WPA unit, so
1172 this should never happen. */
1173 fatal_error (input_location
,
1174 "ipa reference summary is missing in ltrans unit");
1180 const pass_data pass_data_ipa_reference
=
1182 IPA_PASS
, /* type */
1183 "static-var", /* name */
1184 OPTGROUP_NONE
, /* optinfo_flags */
1185 TV_IPA_REFERENCE
, /* tv_id */
1186 0, /* properties_required */
1187 0, /* properties_provided */
1188 0, /* properties_destroyed */
1189 0, /* todo_flags_start */
1190 0, /* todo_flags_finish */
1193 class pass_ipa_reference
: public ipa_opt_pass_d
1196 pass_ipa_reference (gcc::context
*ctxt
)
1197 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1198 NULL
, /* generate_summary */
1199 NULL
, /* write_summary */
1200 NULL
, /* read_summary */
1201 ipa_reference_write_optimization_summary
, /*
1202 write_optimization_summary */
1203 ipa_reference_read_optimization_summary
, /*
1204 read_optimization_summary */
1205 NULL
, /* stmt_fixup */
1206 0, /* function_transform_todo_flags_start */
1207 NULL
, /* function_transform */
1208 NULL
) /* variable_transform */
1211 /* opt_pass methods: */
1212 virtual bool gate (function
*)
1214 return ((in_lto_p
|| flag_ipa_reference
)
1215 /* Don't bother doing anything if the program has errors. */
1219 virtual unsigned int execute (function
*) { return propagate (); }
1221 }; // class pass_ipa_reference
1226 make_pass_ipa_reference (gcc::context
*ctxt
)
1228 return new pass_ipa_reference (ctxt
);
1231 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1232 within the same process. For use by toplev::finalize. */
1235 ipa_reference_c_finalize (void)
1239 bitmap_obstack_release (&optimization_summary_obstack
);
1243 if (node_removal_hook_holder
)
1245 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1246 node_removal_hook_holder
= NULL
;
1248 if (node_duplication_hook_holder
)
1250 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1251 node_duplication_hook_holder
= NULL
;