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"
43 #include "hard-reg-set.h"
46 #include "tree-pass.h"
48 #include "data-streamer.h"
49 #include "diagnostic.h"
51 #include "fold-const.h"
53 #include "internal-fn.h"
54 #include "tree-inline.h"
55 #include "splay-tree.h"
56 #include "ipa-utils.h"
57 #include "ipa-reference.h"
60 static void remove_node_data (struct cgraph_node
*node
,
61 void *data ATTRIBUTE_UNUSED
);
62 static void duplicate_node_data (struct cgraph_node
*src
,
63 struct cgraph_node
*dst
,
64 void *data ATTRIBUTE_UNUSED
);
66 /* The static variables defined within the compilation unit that are
67 loaded or stored directly by function that owns this structure. */
69 struct ipa_reference_local_vars_info_d
72 bitmap statics_written
;
75 /* Statics that are read and written by some set of functions. The
76 local ones are based on the loads and stores local to the function.
77 The global ones are based on the local info as well as the
78 transitive closure of the functions that are called. */
80 struct ipa_reference_global_vars_info_d
83 bitmap statics_written
;
86 /* Information we save about every function after ipa-reference is completed. */
88 struct ipa_reference_optimization_summary_d
90 bitmap statics_not_read
;
91 bitmap statics_not_written
;
94 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
95 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
96 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
98 struct ipa_reference_vars_info_d
100 struct ipa_reference_local_vars_info_d local
;
101 struct ipa_reference_global_vars_info_d global
;
104 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
106 /* This splay tree contains all of the static variables that are
107 being considered by the compilation level alias analysis. */
108 static splay_tree reference_vars_to_consider
;
110 /* Set of all interesting module statics. A bit is set for every module
111 static we are considering. This is added to the local info when asm
112 code is found that clobbers all memory. */
113 static bitmap all_module_statics
;
114 /* Set of all statics that should be ignored becuase they are touched by
115 -fno-ipa-reference code. */
116 static bitmap ignore_module_statics
;
118 /* Obstack holding bitmaps of local analysis (live from analysis to
120 static bitmap_obstack local_info_obstack
;
121 /* Obstack holding global analysis live forever. */
122 static bitmap_obstack optimization_summary_obstack
;
124 /* Holders of ipa cgraph hooks: */
125 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
126 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
128 /* Vector where the reference var infos are actually stored.
129 Indexed by UID of call graph nodes. */
130 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
132 /* TODO: find a place where we should release the vector. */
133 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
135 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
136 static inline ipa_reference_vars_info_t
137 get_reference_vars_info (struct cgraph_node
*node
)
139 if (!ipa_reference_vars_vector
.exists ()
140 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
142 return ipa_reference_vars_vector
[node
->uid
];
145 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
146 static inline ipa_reference_optimization_summary_t
147 get_reference_optimization_summary (struct cgraph_node
*node
)
149 if (!ipa_reference_opt_sum_vector
.exists ()
150 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
152 return ipa_reference_opt_sum_vector
[node
->uid
];
155 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
157 set_reference_vars_info (struct cgraph_node
*node
,
158 ipa_reference_vars_info_t info
)
160 if (!ipa_reference_vars_vector
.exists ()
161 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
162 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
163 ipa_reference_vars_vector
[node
->uid
] = info
;
166 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
168 set_reference_optimization_summary (struct cgraph_node
*node
,
169 ipa_reference_optimization_summary_t info
)
171 if (!ipa_reference_opt_sum_vector
.exists ()
172 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
173 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
174 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
177 /* Return a bitmap indexed by DECL_UID for the static variables that
178 are *not* read during the execution of the function FN. Returns
179 NULL if no data is available. */
182 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
184 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
185 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
187 ipa_reference_optimization_summary_t info
=
188 get_reference_optimization_summary (fn
->function_symbol (NULL
));
190 return info
->statics_not_read
;
191 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
192 return all_module_statics
;
197 /* Return a bitmap indexed by DECL_UID for the static variables that
198 are *not* written during the execution of the function FN. Note
199 that variables written may or may not be read during the function
200 call. Returns NULL if no data is available. */
203 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
205 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
206 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
208 ipa_reference_optimization_summary_t info
=
209 get_reference_optimization_summary (fn
);
211 return info
->statics_not_written
;
212 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
213 return all_module_statics
;
219 /* Return true if the variable T is the right kind of static variable to
220 perform compilation unit scope escape analysis. */
223 is_proper_for_analysis (tree t
)
225 /* If the variable has the "used" attribute, treat it as if it had a
226 been touched by the devil. */
227 if (DECL_PRESERVE_P (t
))
230 /* Do not want to do anything with volatile except mark any
231 function that uses one to be not const or pure. */
232 if (TREE_THIS_VOLATILE (t
))
235 /* We do not need to analyze readonly vars, we already know they do not
237 if (TREE_READONLY (t
))
240 /* We can not track variables with address taken. */
241 if (TREE_ADDRESSABLE (t
))
244 /* TODO: We could track public variables that are not addressable, but currently
245 frontends don't give us those. */
249 /* TODO: Check aliases. */
250 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
256 /* Lookup the tree node for the static variable that has UID and
257 convert the name to a string for debugging. */
260 get_static_name (int index
)
262 splay_tree_node stn
=
263 splay_tree_lookup (reference_vars_to_consider
, index
);
264 return fndecl_name ((tree
)(stn
->value
));
267 /* Dump a set of static vars to FILE. */
269 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
275 else if (set
== all_module_statics
)
278 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
280 fprintf (f
, "%s ", get_static_name (index
));
284 /* Compute X |= Y, taking into account the possibility that
285 either X or Y is already the maximum set.
286 Return true if X is the maximum set after taking the union with Y. */
289 union_static_var_sets (bitmap
&x
, bitmap y
)
291 if (x
!= all_module_statics
)
293 if (y
== all_module_statics
)
296 x
= all_module_statics
;
298 else if (bitmap_ior_into (x
, y
))
300 /* The union may have reduced X to the maximum set.
301 In that case, we want to make that visible explicitly.
302 Even though bitmap_equal_p can be very expensive, it
303 turns out to be an overall win to check this here for
304 an LTO bootstrap of GCC itself. Liberally extrapoliate
305 that result to be applicable to all cases. */
306 if (bitmap_equal_p (x
, all_module_statics
))
309 x
= all_module_statics
;
313 return x
== all_module_statics
;
316 /* Return a copy of SET on the bitmap obstack containing SET.
317 But if SET is NULL or the maximum set, return that instead. */
320 copy_static_var_set (bitmap set
)
322 if (set
== NULL
|| set
== all_module_statics
)
324 bitmap_obstack
*o
= set
->obstack
;
325 gcc_checking_assert (o
);
326 bitmap copy
= BITMAP_ALLOC (o
);
327 bitmap_copy (copy
, set
);
331 /* Compute the union all of the statics read and written by every callee of X
332 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
333 actually the set representing the cycle containing X. If the read and
334 written sets of X_GLOBAL has been reduced to the maximum set, we don't
335 have to look at the remaining callees. */
338 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
340 struct cgraph_edge
*e
;
341 bool read_all
= x_global
->statics_read
== all_module_statics
;
342 bool write_all
= x_global
->statics_written
== all_module_statics
;
344 e
&& !(read_all
&& write_all
);
347 enum availability avail
;
348 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
352 /* Only look into nodes we can propagate something. */
353 int flags
= flags_from_decl_or_type (y
->decl
);
354 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
355 && (avail
> AVAIL_INTERPOSABLE
356 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
358 if (get_reference_vars_info (y
))
360 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
361 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
363 /* Calls in the current cycle do not have their global set
364 computed yet (but everything else does because we're
365 visiting nodes in topological order). */
366 if (!y_global
->statics_read
)
369 /* If the function is const, it reads no memory even if it
370 seems so to local analysis. */
371 if (flags
& ECF_CONST
)
374 union_static_var_sets (x_global
->statics_read
,
375 y_global
->statics_read
);
377 /* If the function is pure, it has no stores even if it
378 seems so to local analysis. If we cannot return from
379 the function, we can safely ignore the call. */
380 if ((flags
& ECF_PURE
)
381 || e
->cannot_lead_to_return_p ())
384 union_static_var_sets (x_global
->statics_written
,
385 y_global
->statics_written
);
393 static bool ipa_init_p
= false;
395 /* The init routine for analyzing global static variable usage. See
396 comments at top for description. */
406 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
408 bitmap_obstack_initialize (&local_info_obstack
);
409 bitmap_obstack_initialize (&optimization_summary_obstack
);
410 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
411 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
413 node_removal_hook_holder
=
414 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
415 node_duplication_hook_holder
=
416 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
420 /* Set up the persistent info for FN. */
422 static ipa_reference_local_vars_info_t
423 init_function_info (struct cgraph_node
*fn
)
425 ipa_reference_vars_info_t info
426 = XCNEW (struct ipa_reference_vars_info_d
);
428 /* Add the info to the tree's annotation. */
429 set_reference_vars_info (fn
, info
);
431 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
432 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
438 /* This is the main routine for finding the reference patterns for
439 global variables within a function FN. */
442 analyze_function (struct cgraph_node
*fn
)
444 ipa_reference_local_vars_info_t local
;
445 struct ipa_ref
*ref
= NULL
;
449 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
451 local
= init_function_info (fn
);
452 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
454 if (!is_a
<varpool_node
*> (ref
->referred
))
456 var
= ref
->referred
->decl
;
457 if (!is_proper_for_analysis (var
))
459 /* This is a variable we care about. Check if we have seen it
460 before, and if not add it the set of variables we care about. */
461 if (all_module_statics
462 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
465 splay_tree_insert (reference_vars_to_consider
,
466 DECL_UID (var
), (splay_tree_value
)var
);
471 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
474 if (ref
->cannot_lead_to_return ())
476 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
485 if (fn
->cannot_return_p ())
486 bitmap_clear (local
->statics_written
);
490 /* Called when new clone is inserted to callgraph late. */
493 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
494 void *data ATTRIBUTE_UNUSED
)
496 ipa_reference_optimization_summary_t ginfo
;
497 ipa_reference_optimization_summary_t dst_ginfo
;
499 ginfo
= get_reference_optimization_summary (src
);
502 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
503 set_reference_optimization_summary (dst
, dst_ginfo
);
504 dst_ginfo
->statics_not_read
=
505 copy_static_var_set (ginfo
->statics_not_read
);
506 dst_ginfo
->statics_not_written
=
507 copy_static_var_set (ginfo
->statics_not_written
);
510 /* Called when node is removed. */
513 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
515 ipa_reference_optimization_summary_t ginfo
;
516 ginfo
= get_reference_optimization_summary (node
);
519 if (ginfo
->statics_not_read
520 && ginfo
->statics_not_read
!= all_module_statics
)
521 BITMAP_FREE (ginfo
->statics_not_read
);
523 if (ginfo
->statics_not_written
524 && ginfo
->statics_not_written
!= all_module_statics
)
525 BITMAP_FREE (ginfo
->statics_not_written
);
527 set_reference_optimization_summary (node
, NULL
);
531 /* Analyze each function in the cgraph to see which global or statics
532 are read or written. */
535 generate_summary (void)
537 struct cgraph_node
*node
;
543 /* Process all of the functions next. */
544 FOR_EACH_DEFINED_FUNCTION (node
)
545 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
547 struct ipa_ref
*ref
= NULL
;
550 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
552 if (!is_a
<varpool_node
*> (ref
->referred
))
554 var
= ref
->referred
->decl
;
555 if (!is_proper_for_analysis (var
))
557 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
560 FOR_EACH_DEFINED_FUNCTION (node
)
561 analyze_function (node
);
564 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
566 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
567 get_static_name (index
), index
);
571 FOR_EACH_DEFINED_FUNCTION (node
)
572 if (node
->get_availability () >= AVAIL_INTERPOSABLE
573 && opt_for_fn (node
->decl
, flag_ipa_reference
))
575 ipa_reference_local_vars_info_t l
;
579 l
= &get_reference_vars_info (node
)->local
;
581 "\nFunction name:%s/%i:",
582 node
->asm_name (), node
->order
);
583 fprintf (dump_file
, "\n locals read: ");
585 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
588 fprintf (dump_file
, "%s ",
589 get_static_name (index
));
591 fprintf (dump_file
, "\n locals written: ");
592 if (l
->statics_written
)
593 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
596 fprintf (dump_file
, "%s ", get_static_name (index
));
601 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
604 read_write_all_from_decl (struct cgraph_node
*node
,
605 bool &read_all
, bool &write_all
)
607 tree decl
= node
->decl
;
608 int flags
= flags_from_decl_or_type (decl
);
609 if ((flags
& ECF_LEAF
)
610 && node
->get_availability () < AVAIL_INTERPOSABLE
)
612 else if (flags
& ECF_CONST
)
614 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
617 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
618 fprintf (dump_file
, " %s/%i -> read all\n",
619 node
->asm_name (), node
->order
);
623 /* TODO: To be able to produce sane results, we should also handle
624 common builtins, in particular throw. */
627 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
628 fprintf (dump_file
, " %s/%i -> read all, write all\n",
629 node
->asm_name (), node
->order
);
633 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
634 in the cycle of NODE. */
637 get_read_write_all_from_node (struct cgraph_node
*node
,
638 bool &read_all
, bool &write_all
)
640 struct cgraph_edge
*e
, *ie
;
642 /* When function is overwritable, we can not assume anything. */
643 if (node
->get_availability () <= AVAIL_INTERPOSABLE
644 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
645 read_write_all_from_decl (node
, read_all
, write_all
);
647 for (e
= node
->callees
;
648 e
&& !(read_all
&& write_all
);
651 enum availability avail
;
652 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
653 gcc_checking_assert (callee
);
654 if (avail
<= AVAIL_INTERPOSABLE
655 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
656 read_write_all_from_decl (callee
, read_all
, write_all
);
659 for (ie
= node
->indirect_calls
;
660 ie
&& !(read_all
&& write_all
);
661 ie
= ie
->next_callee
)
662 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
665 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
666 fprintf (dump_file
, " indirect call -> read all\n");
667 if (!ie
->cannot_lead_to_return_p ()
668 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
670 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
671 fprintf (dump_file
, " indirect call -> write all\n");
677 /* Skip edges from and to nodes without ipa_reference enables. This leave
678 them out of strongy connected coponents and makes them easyto skip in the
679 propagation loop bellow. */
682 ignore_edge_p (cgraph_edge
*e
)
684 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
685 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
686 flag_ipa_reference
));
689 /* Produce the global information by preforming a transitive closure
690 on the local information that was produced by ipa_analyze_function. */
695 struct cgraph_node
*node
;
696 struct cgraph_node
**order
=
697 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
703 cgraph_node::dump_cgraph (dump_file
);
705 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
708 /* Propagate the local information through the call graph to produce
709 the global information. All the nodes within a cycle will have
710 the same info so we collapse cycles first. Then we can do the
711 propagation in one pass from the leaves to the roots. */
712 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
714 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
716 for (i
= 0; i
< order_pos
; i
++ )
719 struct cgraph_node
*w
;
720 ipa_reference_vars_info_t node_info
;
721 ipa_reference_global_vars_info_t node_g
;
722 ipa_reference_local_vars_info_t node_l
;
723 bool read_all
= false;
724 bool write_all
= false;
727 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
730 node_info
= get_reference_vars_info (node
);
731 gcc_assert (node_info
);
732 node_l
= &node_info
->local
;
733 node_g
= &node_info
->global
;
735 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
736 fprintf (dump_file
, "Starting cycle with %s/%i\n",
737 node
->asm_name (), node
->order
);
739 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
741 /* If any node in a cycle is read_all or write_all, they all are. */
742 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
744 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
745 fprintf (dump_file
, " Visiting %s/%i\n",
746 w
->asm_name (), w
->order
);
747 get_read_write_all_from_node (w
, read_all
, write_all
);
748 if (read_all
&& write_all
)
752 /* Initialized the bitmaps global sets for the reduced node. */
754 node_g
->statics_read
= all_module_statics
;
756 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
758 node_g
->statics_written
= all_module_statics
;
760 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
762 /* Merge the sets of this cycle with all sets of callees reached
764 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
766 if (read_all
&& write_all
)
771 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
772 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
773 int flags
= flags_from_decl_or_type (w
->decl
);
775 if (!(flags
& ECF_CONST
))
776 read_all
= union_static_var_sets (node_g
->statics_read
,
778 if (!(flags
& ECF_PURE
)
779 && !w
->cannot_return_p ())
780 write_all
= union_static_var_sets (node_g
->statics_written
,
781 w_l
->statics_written
);
784 propagate_bits (node_g
, w
);
787 /* All nodes within a cycle have the same global info bitmaps. */
788 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
790 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
791 w_ri
->global
= *node_g
;
794 cycle_nodes
.release ();
799 for (i
= 0; i
< order_pos
; i
++)
802 struct cgraph_node
*w
;
805 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
809 "\nFunction name:%s/%i:",
810 node
->asm_name (), node
->order
);
812 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
813 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
815 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
816 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
818 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
819 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
821 fprintf (dump_file
, "\n next cycle: %s/%i ",
822 w
->asm_name (), w
->order
);
823 fprintf (dump_file
, "\n locals read: ");
824 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
825 fprintf (dump_file
, "\n locals written: ");
826 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
828 cycle_nodes
.release ();
830 fprintf (dump_file
, "\n globals read: ");
831 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
832 fprintf (dump_file
, "\n globals written: ");
833 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
834 fprintf (dump_file
, "\n");
839 FOR_EACH_DEFINED_FUNCTION (node
)
841 ipa_reference_vars_info_t node_info
;
842 ipa_reference_global_vars_info_t node_g
;
843 ipa_reference_optimization_summary_t opt
;
845 node_info
= get_reference_vars_info (node
);
846 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
847 && (node
->get_availability () > AVAIL_INTERPOSABLE
848 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
850 node_g
= &node_info
->global
;
852 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
853 set_reference_optimization_summary (node
, opt
);
855 /* Create the complimentary sets. */
857 if (bitmap_empty_p (node_g
->statics_read
))
858 opt
->statics_not_read
= all_module_statics
;
861 opt
->statics_not_read
862 = BITMAP_ALLOC (&optimization_summary_obstack
);
863 if (node_g
->statics_read
!= all_module_statics
)
864 bitmap_and_compl (opt
->statics_not_read
,
866 node_g
->statics_read
);
869 if (bitmap_empty_p (node_g
->statics_written
))
870 opt
->statics_not_written
= all_module_statics
;
873 opt
->statics_not_written
874 = BITMAP_ALLOC (&optimization_summary_obstack
);
875 if (node_g
->statics_written
!= all_module_statics
)
876 bitmap_and_compl (opt
->statics_not_written
,
878 node_g
->statics_written
);
884 ipa_free_postorder_info ();
887 bitmap_obstack_release (&local_info_obstack
);
888 ipa_reference_vars_vector
.release ();
890 splay_tree_delete (reference_vars_to_consider
);
891 reference_vars_to_consider
= NULL
;
892 return remove_p
? TODO_remove_functions
: 0;
895 /* Return true if we need to write summary of NODE. */
898 write_node_summary_p (struct cgraph_node
*node
,
899 lto_symtab_encoder_t encoder
,
900 bitmap ltrans_statics
)
902 ipa_reference_optimization_summary_t info
;
904 /* See if we have (non-empty) info. */
905 if (!node
->definition
|| node
->global
.inlined_to
)
907 info
= get_reference_optimization_summary (node
);
908 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
909 && bitmap_empty_p (info
->statics_not_written
)))
912 /* See if we want to encode it.
913 Encode also referenced functions since constant folding might turn it into
916 In future we might also want to include summaries of functions references
917 by initializers of constant variables references in current unit. */
918 if (!reachable_from_this_partition_p (node
, encoder
)
919 && !referenced_from_this_partition_p (node
, encoder
))
922 /* See if the info has non-empty intersections with vars we want to encode. */
923 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
924 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
929 /* Stream out BITS<RANS_STATICS as list of decls to OB.
930 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
931 or -1. When it is positive, just output -1 when
932 BITS<RANS_STATICS == BITS<RANS_STATICS. */
935 stream_out_bitmap (struct lto_simple_output_block
*ob
,
936 bitmap bits
, bitmap ltrans_statics
,
937 int ltrans_statics_bitcount
)
942 if (bits
== all_module_statics
)
944 streamer_write_hwi_stream (ob
->main_stream
, -1);
947 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
949 if (count
== ltrans_statics_bitcount
)
951 streamer_write_hwi_stream (ob
->main_stream
, -1);
954 streamer_write_hwi_stream (ob
->main_stream
, count
);
957 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
959 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
960 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
964 /* Serialize the ipa info for lto. */
967 ipa_reference_write_optimization_summary (void)
969 struct lto_simple_output_block
*ob
970 = lto_create_simple_output_block (LTO_section_ipa_reference
);
971 unsigned int count
= 0;
972 int ltrans_statics_bitcount
= 0;
973 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
974 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
977 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
979 /* See what variables we are interested in. */
980 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
982 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
983 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
985 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
986 && referenced_from_this_partition_p (vnode
, encoder
))
988 tree decl
= vnode
->decl
;
989 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
990 splay_tree_insert (reference_vars_to_consider
,
991 DECL_UID (decl
), (splay_tree_value
)decl
);
992 ltrans_statics_bitcount
++;
997 if (ltrans_statics_bitcount
)
998 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1000 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1001 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1002 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1006 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1008 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1011 /* Process all of the functions. */
1012 if (ltrans_statics_bitcount
)
1013 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1015 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1016 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1017 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1019 ipa_reference_optimization_summary_t info
;
1022 info
= get_reference_optimization_summary (cnode
);
1023 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1024 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1026 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1027 ltrans_statics_bitcount
);
1028 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1029 ltrans_statics_bitcount
);
1032 BITMAP_FREE (ltrans_statics
);
1033 lto_destroy_simple_output_block (ob
);
1034 splay_tree_delete (reference_vars_to_consider
);
1037 /* Deserialize the ipa info for lto. */
1040 ipa_reference_read_optimization_summary (void)
1042 struct lto_file_decl_data
** file_data_vec
1043 = lto_get_file_decl_data ();
1044 struct lto_file_decl_data
* file_data
;
1046 bitmap_obstack_initialize (&optimization_summary_obstack
);
1048 node_removal_hook_holder
=
1049 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1050 node_duplication_hook_holder
=
1051 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1052 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1054 while ((file_data
= file_data_vec
[j
++]))
1058 struct lto_input_block
*ib
1059 = lto_create_simple_input_block (file_data
,
1060 LTO_section_ipa_reference
,
1065 unsigned int f_count
= streamer_read_uhwi (ib
);
1069 b_count
= streamer_read_hwi (ib
);
1071 fprintf (dump_file
, "all module statics:");
1072 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1074 unsigned int var_index
= streamer_read_uhwi (ib
);
1075 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1077 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1079 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1082 for (i
= 0; i
< f_count
; i
++)
1084 unsigned int j
, index
;
1085 struct cgraph_node
*node
;
1086 ipa_reference_optimization_summary_t info
;
1088 lto_symtab_encoder_t encoder
;
1090 index
= streamer_read_uhwi (ib
);
1091 encoder
= file_data
->symtab_node_encoder
;
1092 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1094 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1095 set_reference_optimization_summary (node
, info
);
1096 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1097 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1100 "\nFunction name:%s/%i:\n static not read:",
1101 node
->asm_name (), node
->order
);
1103 /* Set the statics not read. */
1104 v_count
= streamer_read_hwi (ib
);
1107 info
->statics_not_read
= all_module_statics
;
1109 fprintf (dump_file
, " all module statics");
1112 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1114 unsigned int var_index
= streamer_read_uhwi (ib
);
1115 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1117 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1119 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1124 "\n static not written:");
1125 /* Set the statics not written. */
1126 v_count
= streamer_read_hwi (ib
);
1129 info
->statics_not_written
= all_module_statics
;
1131 fprintf (dump_file
, " all module statics");
1134 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1136 unsigned int var_index
= streamer_read_uhwi (ib
);
1137 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1139 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1141 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1144 fprintf (dump_file
, "\n");
1147 lto_destroy_simple_input_block (file_data
,
1148 LTO_section_ipa_reference
,
1152 /* Fatal error here. We do not want to support compiling ltrans units with
1153 different version of compiler or different flags than the WPA unit, so
1154 this should never happen. */
1155 fatal_error (input_location
,
1156 "ipa reference summary is missing in ltrans unit");
1162 const pass_data pass_data_ipa_reference
=
1164 IPA_PASS
, /* type */
1165 "static-var", /* name */
1166 OPTGROUP_NONE
, /* optinfo_flags */
1167 TV_IPA_REFERENCE
, /* tv_id */
1168 0, /* properties_required */
1169 0, /* properties_provided */
1170 0, /* properties_destroyed */
1171 0, /* todo_flags_start */
1172 0, /* todo_flags_finish */
1175 class pass_ipa_reference
: public ipa_opt_pass_d
1178 pass_ipa_reference (gcc::context
*ctxt
)
1179 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1180 NULL
, /* generate_summary */
1181 NULL
, /* write_summary */
1182 NULL
, /* read_summary */
1183 ipa_reference_write_optimization_summary
, /*
1184 write_optimization_summary */
1185 ipa_reference_read_optimization_summary
, /*
1186 read_optimization_summary */
1187 NULL
, /* stmt_fixup */
1188 0, /* function_transform_todo_flags_start */
1189 NULL
, /* function_transform */
1190 NULL
) /* variable_transform */
1193 /* opt_pass methods: */
1194 virtual bool gate (function
*)
1196 return ((in_lto_p
|| flag_ipa_reference
)
1197 /* Don't bother doing anything if the program has errors. */
1201 virtual unsigned int execute (function
*) { return propagate (); }
1203 }; // class pass_ipa_reference
1208 make_pass_ipa_reference (gcc::context
*ctxt
)
1210 return new pass_ipa_reference (ctxt
);
1213 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1214 within the same process. For use by toplev::finalize. */
1217 ipa_reference_c_finalize (void)
1221 bitmap_obstack_release (&optimization_summary_obstack
);
1225 if (node_removal_hook_holder
)
1227 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1228 node_removal_hook_holder
= NULL
;
1230 if (node_duplication_hook_holder
)
1232 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1233 node_duplication_hook_holder
= NULL
;