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"
45 #include "hard-reg-set.h"
48 #include "fold-const.h"
50 #include "internal-fn.h"
51 #include "tree-inline.h"
52 #include "tree-pass.h"
53 #include "splay-tree.h"
55 #include "ipa-utils.h"
56 #include "ipa-reference.h"
58 #include "diagnostic.h"
59 #include "data-streamer.h"
60 #include "lto-streamer.h"
62 static void remove_node_data (struct cgraph_node
*node
,
63 void *data ATTRIBUTE_UNUSED
);
64 static void duplicate_node_data (struct cgraph_node
*src
,
65 struct cgraph_node
*dst
,
66 void *data ATTRIBUTE_UNUSED
);
68 /* The static variables defined within the compilation unit that are
69 loaded or stored directly by function that owns this structure. */
71 struct ipa_reference_local_vars_info_d
74 bitmap statics_written
;
77 /* Statics that are read and written by some set of functions. The
78 local ones are based on the loads and stores local to the function.
79 The global ones are based on the local info as well as the
80 transitive closure of the functions that are called. */
82 struct ipa_reference_global_vars_info_d
85 bitmap statics_written
;
88 /* Information we save about every function after ipa-reference is completed. */
90 struct ipa_reference_optimization_summary_d
92 bitmap statics_not_read
;
93 bitmap statics_not_written
;
96 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
97 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
98 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
100 struct ipa_reference_vars_info_d
102 struct ipa_reference_local_vars_info_d local
;
103 struct ipa_reference_global_vars_info_d global
;
106 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
108 /* This splay tree contains all of the static variables that are
109 being considered by the compilation level alias analysis. */
110 static splay_tree reference_vars_to_consider
;
112 /* Set of all interesting module statics. A bit is set for every module
113 static we are considering. This is added to the local info when asm
114 code is found that clobbers all memory. */
115 static bitmap all_module_statics
;
116 /* Set of all statics that should be ignored becuase they are touched by
117 -fno-ipa-reference code. */
118 static bitmap ignore_module_statics
;
120 /* Obstack holding bitmaps of local analysis (live from analysis to
122 static bitmap_obstack local_info_obstack
;
123 /* Obstack holding global analysis live forever. */
124 static bitmap_obstack optimization_summary_obstack
;
126 /* Holders of ipa cgraph hooks: */
127 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
128 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
130 /* Vector where the reference var infos are actually stored.
131 Indexed by UID of call graph nodes. */
132 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
134 /* TODO: find a place where we should release the vector. */
135 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
137 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
138 static inline ipa_reference_vars_info_t
139 get_reference_vars_info (struct cgraph_node
*node
)
141 if (!ipa_reference_vars_vector
.exists ()
142 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
144 return ipa_reference_vars_vector
[node
->uid
];
147 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
148 static inline ipa_reference_optimization_summary_t
149 get_reference_optimization_summary (struct cgraph_node
*node
)
151 if (!ipa_reference_opt_sum_vector
.exists ()
152 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
154 return ipa_reference_opt_sum_vector
[node
->uid
];
157 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
159 set_reference_vars_info (struct cgraph_node
*node
,
160 ipa_reference_vars_info_t info
)
162 if (!ipa_reference_vars_vector
.exists ()
163 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
164 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
165 ipa_reference_vars_vector
[node
->uid
] = info
;
168 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
170 set_reference_optimization_summary (struct cgraph_node
*node
,
171 ipa_reference_optimization_summary_t info
)
173 if (!ipa_reference_opt_sum_vector
.exists ()
174 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
175 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
176 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
179 /* Return a bitmap indexed by DECL_UID for the static variables that
180 are *not* read during the execution of the function FN. Returns
181 NULL if no data is available. */
184 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
186 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
187 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
189 ipa_reference_optimization_summary_t info
=
190 get_reference_optimization_summary (fn
->function_symbol (NULL
));
192 return info
->statics_not_read
;
193 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
194 return all_module_statics
;
199 /* Return a bitmap indexed by DECL_UID for the static variables that
200 are *not* written during the execution of the function FN. Note
201 that variables written may or may not be read during the function
202 call. Returns NULL if no data is available. */
205 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
207 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
208 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
210 ipa_reference_optimization_summary_t info
=
211 get_reference_optimization_summary (fn
);
213 return info
->statics_not_written
;
214 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
215 return all_module_statics
;
221 /* Return true if the variable T is the right kind of static variable to
222 perform compilation unit scope escape analysis. */
225 is_proper_for_analysis (tree t
)
227 /* If the variable has the "used" attribute, treat it as if it had a
228 been touched by the devil. */
229 if (DECL_PRESERVE_P (t
))
232 /* Do not want to do anything with volatile except mark any
233 function that uses one to be not const or pure. */
234 if (TREE_THIS_VOLATILE (t
))
237 /* We do not need to analyze readonly vars, we already know they do not
239 if (TREE_READONLY (t
))
242 /* We can not track variables with address taken. */
243 if (TREE_ADDRESSABLE (t
))
246 /* TODO: We could track public variables that are not addressable, but currently
247 frontends don't give us those. */
251 /* TODO: Check aliases. */
252 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
258 /* Lookup the tree node for the static variable that has UID and
259 convert the name to a string for debugging. */
262 get_static_name (int index
)
264 splay_tree_node stn
=
265 splay_tree_lookup (reference_vars_to_consider
, index
);
266 return fndecl_name ((tree
)(stn
->value
));
269 /* Dump a set of static vars to FILE. */
271 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
277 else if (set
== all_module_statics
)
280 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
282 fprintf (f
, "%s ", get_static_name (index
));
286 /* Compute X |= Y, taking into account the possibility that
287 either X or Y is already the maximum set.
288 Return true if X is the maximum set after taking the union with Y. */
291 union_static_var_sets (bitmap
&x
, bitmap y
)
293 if (x
!= all_module_statics
)
295 if (y
== all_module_statics
)
298 x
= all_module_statics
;
300 else if (bitmap_ior_into (x
, y
))
302 /* The union may have reduced X to the maximum set.
303 In that case, we want to make that visible explicitly.
304 Even though bitmap_equal_p can be very expensive, it
305 turns out to be an overall win to check this here for
306 an LTO bootstrap of GCC itself. Liberally extrapoliate
307 that result to be applicable to all cases. */
308 if (bitmap_equal_p (x
, all_module_statics
))
311 x
= all_module_statics
;
315 return x
== all_module_statics
;
318 /* Return a copy of SET on the bitmap obstack containing SET.
319 But if SET is NULL or the maximum set, return that instead. */
322 copy_static_var_set (bitmap set
)
324 if (set
== NULL
|| set
== all_module_statics
)
326 bitmap_obstack
*o
= set
->obstack
;
327 gcc_checking_assert (o
);
328 bitmap copy
= BITMAP_ALLOC (o
);
329 bitmap_copy (copy
, set
);
333 /* Compute the union all of the statics read and written by every callee of X
334 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
335 actually the set representing the cycle containing X. If the read and
336 written sets of X_GLOBAL has been reduced to the maximum set, we don't
337 have to look at the remaining callees. */
340 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
342 struct cgraph_edge
*e
;
343 bool read_all
= x_global
->statics_read
== all_module_statics
;
344 bool write_all
= x_global
->statics_written
== all_module_statics
;
346 e
&& !(read_all
&& write_all
);
349 enum availability avail
;
350 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
354 /* Only look into nodes we can propagate something. */
355 int flags
= flags_from_decl_or_type (y
->decl
);
356 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
357 && (avail
> AVAIL_INTERPOSABLE
358 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
360 if (get_reference_vars_info (y
))
362 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
363 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
365 /* Calls in the current cycle do not have their global set
366 computed yet (but everything else does because we're
367 visiting nodes in topological order). */
368 if (!y_global
->statics_read
)
371 /* If the function is const, it reads no memory even if it
372 seems so to local analysis. */
373 if (flags
& ECF_CONST
)
376 union_static_var_sets (x_global
->statics_read
,
377 y_global
->statics_read
);
379 /* If the function is pure, it has no stores even if it
380 seems so to local analysis. If we cannot return from
381 the function, we can safely ignore the call. */
382 if ((flags
& ECF_PURE
)
383 || e
->cannot_lead_to_return_p ())
386 union_static_var_sets (x_global
->statics_written
,
387 y_global
->statics_written
);
395 static bool ipa_init_p
= false;
397 /* The init routine for analyzing global static variable usage. See
398 comments at top for description. */
408 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
410 bitmap_obstack_initialize (&local_info_obstack
);
411 bitmap_obstack_initialize (&optimization_summary_obstack
);
412 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
413 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
415 node_removal_hook_holder
=
416 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
417 node_duplication_hook_holder
=
418 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
422 /* Set up the persistent info for FN. */
424 static ipa_reference_local_vars_info_t
425 init_function_info (struct cgraph_node
*fn
)
427 ipa_reference_vars_info_t info
428 = XCNEW (struct ipa_reference_vars_info_d
);
430 /* Add the info to the tree's annotation. */
431 set_reference_vars_info (fn
, info
);
433 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
434 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
440 /* This is the main routine for finding the reference patterns for
441 global variables within a function FN. */
444 analyze_function (struct cgraph_node
*fn
)
446 ipa_reference_local_vars_info_t local
;
447 struct ipa_ref
*ref
= NULL
;
451 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
453 local
= init_function_info (fn
);
454 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
456 if (!is_a
<varpool_node
*> (ref
->referred
))
458 var
= ref
->referred
->decl
;
459 if (!is_proper_for_analysis (var
))
461 /* This is a variable we care about. Check if we have seen it
462 before, and if not add it the set of variables we care about. */
463 if (all_module_statics
464 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
467 splay_tree_insert (reference_vars_to_consider
,
468 DECL_UID (var
), (splay_tree_value
)var
);
473 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
476 if (ref
->cannot_lead_to_return ())
478 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
487 if (fn
->cannot_return_p ())
488 bitmap_clear (local
->statics_written
);
492 /* Called when new clone is inserted to callgraph late. */
495 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
496 void *data ATTRIBUTE_UNUSED
)
498 ipa_reference_optimization_summary_t ginfo
;
499 ipa_reference_optimization_summary_t dst_ginfo
;
501 ginfo
= get_reference_optimization_summary (src
);
504 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
505 set_reference_optimization_summary (dst
, dst_ginfo
);
506 dst_ginfo
->statics_not_read
=
507 copy_static_var_set (ginfo
->statics_not_read
);
508 dst_ginfo
->statics_not_written
=
509 copy_static_var_set (ginfo
->statics_not_written
);
512 /* Called when node is removed. */
515 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
517 ipa_reference_optimization_summary_t ginfo
;
518 ginfo
= get_reference_optimization_summary (node
);
521 if (ginfo
->statics_not_read
522 && ginfo
->statics_not_read
!= all_module_statics
)
523 BITMAP_FREE (ginfo
->statics_not_read
);
525 if (ginfo
->statics_not_written
526 && ginfo
->statics_not_written
!= all_module_statics
)
527 BITMAP_FREE (ginfo
->statics_not_written
);
529 set_reference_optimization_summary (node
, NULL
);
533 /* Analyze each function in the cgraph to see which global or statics
534 are read or written. */
537 generate_summary (void)
539 struct cgraph_node
*node
;
545 /* Process all of the functions next. */
546 FOR_EACH_DEFINED_FUNCTION (node
)
547 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
549 struct ipa_ref
*ref
= NULL
;
552 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
554 if (!is_a
<varpool_node
*> (ref
->referred
))
556 var
= ref
->referred
->decl
;
557 if (!is_proper_for_analysis (var
))
559 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
562 FOR_EACH_DEFINED_FUNCTION (node
)
563 analyze_function (node
);
566 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
568 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
569 get_static_name (index
), index
);
573 FOR_EACH_DEFINED_FUNCTION (node
)
574 if (node
->get_availability () >= AVAIL_INTERPOSABLE
575 && opt_for_fn (node
->decl
, flag_ipa_reference
))
577 ipa_reference_local_vars_info_t l
;
581 l
= &get_reference_vars_info (node
)->local
;
583 "\nFunction name:%s/%i:",
584 node
->asm_name (), node
->order
);
585 fprintf (dump_file
, "\n locals read: ");
587 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
590 fprintf (dump_file
, "%s ",
591 get_static_name (index
));
593 fprintf (dump_file
, "\n locals written: ");
594 if (l
->statics_written
)
595 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
598 fprintf (dump_file
, "%s ", get_static_name (index
));
603 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
606 read_write_all_from_decl (struct cgraph_node
*node
,
607 bool &read_all
, bool &write_all
)
609 tree decl
= node
->decl
;
610 int flags
= flags_from_decl_or_type (decl
);
611 if ((flags
& ECF_LEAF
)
612 && node
->get_availability () < AVAIL_INTERPOSABLE
)
614 else if (flags
& ECF_CONST
)
616 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
619 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
620 fprintf (dump_file
, " %s/%i -> read all\n",
621 node
->asm_name (), node
->order
);
625 /* TODO: To be able to produce sane results, we should also handle
626 common builtins, in particular throw. */
629 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
630 fprintf (dump_file
, " %s/%i -> read all, write all\n",
631 node
->asm_name (), node
->order
);
635 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
636 in the cycle of NODE. */
639 get_read_write_all_from_node (struct cgraph_node
*node
,
640 bool &read_all
, bool &write_all
)
642 struct cgraph_edge
*e
, *ie
;
644 /* When function is overwritable, we can not assume anything. */
645 if (node
->get_availability () <= AVAIL_INTERPOSABLE
646 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
647 read_write_all_from_decl (node
, read_all
, write_all
);
649 for (e
= node
->callees
;
650 e
&& !(read_all
&& write_all
);
653 enum availability avail
;
654 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
655 gcc_checking_assert (callee
);
656 if (avail
<= AVAIL_INTERPOSABLE
657 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
658 read_write_all_from_decl (callee
, read_all
, write_all
);
661 for (ie
= node
->indirect_calls
;
662 ie
&& !(read_all
&& write_all
);
663 ie
= ie
->next_callee
)
664 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
667 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
668 fprintf (dump_file
, " indirect call -> read all\n");
669 if (!ie
->cannot_lead_to_return_p ()
670 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
672 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
673 fprintf (dump_file
, " indirect call -> write all\n");
679 /* Skip edges from and to nodes without ipa_reference enables. This leave
680 them out of strongy connected coponents and makes them easyto skip in the
681 propagation loop bellow. */
684 ignore_edge_p (cgraph_edge
*e
)
686 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
687 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
688 flag_ipa_reference
));
691 /* Produce the global information by preforming a transitive closure
692 on the local information that was produced by ipa_analyze_function. */
697 struct cgraph_node
*node
;
698 struct cgraph_node
**order
=
699 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
705 cgraph_node::dump_cgraph (dump_file
);
707 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
710 /* Propagate the local information through the call graph to produce
711 the global information. All the nodes within a cycle will have
712 the same info so we collapse cycles first. Then we can do the
713 propagation in one pass from the leaves to the roots. */
714 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
716 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
718 for (i
= 0; i
< order_pos
; i
++ )
721 struct cgraph_node
*w
;
722 ipa_reference_vars_info_t node_info
;
723 ipa_reference_global_vars_info_t node_g
;
724 ipa_reference_local_vars_info_t node_l
;
725 bool read_all
= false;
726 bool write_all
= false;
729 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
732 node_info
= get_reference_vars_info (node
);
733 gcc_assert (node_info
);
734 node_l
= &node_info
->local
;
735 node_g
= &node_info
->global
;
737 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
738 fprintf (dump_file
, "Starting cycle with %s/%i\n",
739 node
->asm_name (), node
->order
);
741 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
743 /* If any node in a cycle is read_all or write_all, they all are. */
744 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
746 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
747 fprintf (dump_file
, " Visiting %s/%i\n",
748 w
->asm_name (), w
->order
);
749 get_read_write_all_from_node (w
, read_all
, write_all
);
750 if (read_all
&& write_all
)
754 /* Initialized the bitmaps global sets for the reduced node. */
756 node_g
->statics_read
= all_module_statics
;
758 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
760 node_g
->statics_written
= all_module_statics
;
762 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
764 /* Merge the sets of this cycle with all sets of callees reached
766 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
768 if (read_all
&& write_all
)
773 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
774 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
775 int flags
= flags_from_decl_or_type (w
->decl
);
777 if (!(flags
& ECF_CONST
))
778 read_all
= union_static_var_sets (node_g
->statics_read
,
780 if (!(flags
& ECF_PURE
)
781 && !w
->cannot_return_p ())
782 write_all
= union_static_var_sets (node_g
->statics_written
,
783 w_l
->statics_written
);
786 propagate_bits (node_g
, w
);
789 /* All nodes within a cycle have the same global info bitmaps. */
790 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
792 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
793 w_ri
->global
= *node_g
;
796 cycle_nodes
.release ();
801 for (i
= 0; i
< order_pos
; i
++)
804 struct cgraph_node
*w
;
807 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
811 "\nFunction name:%s/%i:",
812 node
->asm_name (), node
->order
);
814 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
815 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
817 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
818 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
820 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
821 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
823 fprintf (dump_file
, "\n next cycle: %s/%i ",
824 w
->asm_name (), w
->order
);
825 fprintf (dump_file
, "\n locals read: ");
826 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
827 fprintf (dump_file
, "\n locals written: ");
828 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
830 cycle_nodes
.release ();
832 fprintf (dump_file
, "\n globals read: ");
833 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
834 fprintf (dump_file
, "\n globals written: ");
835 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
836 fprintf (dump_file
, "\n");
841 FOR_EACH_DEFINED_FUNCTION (node
)
843 ipa_reference_vars_info_t node_info
;
844 ipa_reference_global_vars_info_t node_g
;
845 ipa_reference_optimization_summary_t opt
;
847 node_info
= get_reference_vars_info (node
);
848 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
849 && (node
->get_availability () > AVAIL_INTERPOSABLE
850 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
852 node_g
= &node_info
->global
;
854 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
855 set_reference_optimization_summary (node
, opt
);
857 /* Create the complimentary sets. */
859 if (bitmap_empty_p (node_g
->statics_read
))
860 opt
->statics_not_read
= all_module_statics
;
863 opt
->statics_not_read
864 = BITMAP_ALLOC (&optimization_summary_obstack
);
865 if (node_g
->statics_read
!= all_module_statics
)
866 bitmap_and_compl (opt
->statics_not_read
,
868 node_g
->statics_read
);
871 if (bitmap_empty_p (node_g
->statics_written
))
872 opt
->statics_not_written
= all_module_statics
;
875 opt
->statics_not_written
876 = BITMAP_ALLOC (&optimization_summary_obstack
);
877 if (node_g
->statics_written
!= all_module_statics
)
878 bitmap_and_compl (opt
->statics_not_written
,
880 node_g
->statics_written
);
886 ipa_free_postorder_info ();
889 bitmap_obstack_release (&local_info_obstack
);
890 ipa_reference_vars_vector
.release ();
892 splay_tree_delete (reference_vars_to_consider
);
893 reference_vars_to_consider
= NULL
;
894 return remove_p
? TODO_remove_functions
: 0;
897 /* Return true if we need to write summary of NODE. */
900 write_node_summary_p (struct cgraph_node
*node
,
901 lto_symtab_encoder_t encoder
,
902 bitmap ltrans_statics
)
904 ipa_reference_optimization_summary_t info
;
906 /* See if we have (non-empty) info. */
907 if (!node
->definition
|| node
->global
.inlined_to
)
909 info
= get_reference_optimization_summary (node
);
910 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
911 && bitmap_empty_p (info
->statics_not_written
)))
914 /* See if we want to encode it.
915 Encode also referenced functions since constant folding might turn it into
918 In future we might also want to include summaries of functions references
919 by initializers of constant variables references in current unit. */
920 if (!reachable_from_this_partition_p (node
, encoder
)
921 && !referenced_from_this_partition_p (node
, encoder
))
924 /* See if the info has non-empty intersections with vars we want to encode. */
925 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
926 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
931 /* Stream out BITS<RANS_STATICS as list of decls to OB.
932 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
933 or -1. When it is positive, just output -1 when
934 BITS<RANS_STATICS == BITS<RANS_STATICS. */
937 stream_out_bitmap (struct lto_simple_output_block
*ob
,
938 bitmap bits
, bitmap ltrans_statics
,
939 int ltrans_statics_bitcount
)
944 if (bits
== all_module_statics
)
946 streamer_write_hwi_stream (ob
->main_stream
, -1);
949 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
951 if (count
== ltrans_statics_bitcount
)
953 streamer_write_hwi_stream (ob
->main_stream
, -1);
956 streamer_write_hwi_stream (ob
->main_stream
, count
);
959 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
961 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
962 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
966 /* Serialize the ipa info for lto. */
969 ipa_reference_write_optimization_summary (void)
971 struct lto_simple_output_block
*ob
972 = lto_create_simple_output_block (LTO_section_ipa_reference
);
973 unsigned int count
= 0;
974 int ltrans_statics_bitcount
= 0;
975 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
976 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
979 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
981 /* See what variables we are interested in. */
982 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
984 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
985 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
987 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
988 && referenced_from_this_partition_p (vnode
, encoder
))
990 tree decl
= vnode
->decl
;
991 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
992 splay_tree_insert (reference_vars_to_consider
,
993 DECL_UID (decl
), (splay_tree_value
)decl
);
994 ltrans_statics_bitcount
++;
999 if (ltrans_statics_bitcount
)
1000 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1002 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1003 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1004 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1008 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1010 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1013 /* Process all of the functions. */
1014 if (ltrans_statics_bitcount
)
1015 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1017 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1018 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1019 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1021 ipa_reference_optimization_summary_t info
;
1024 info
= get_reference_optimization_summary (cnode
);
1025 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1026 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1028 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1029 ltrans_statics_bitcount
);
1030 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1031 ltrans_statics_bitcount
);
1034 BITMAP_FREE (ltrans_statics
);
1035 lto_destroy_simple_output_block (ob
);
1036 splay_tree_delete (reference_vars_to_consider
);
1039 /* Deserialize the ipa info for lto. */
1042 ipa_reference_read_optimization_summary (void)
1044 struct lto_file_decl_data
** file_data_vec
1045 = lto_get_file_decl_data ();
1046 struct lto_file_decl_data
* file_data
;
1048 bitmap_obstack_initialize (&optimization_summary_obstack
);
1050 node_removal_hook_holder
=
1051 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1052 node_duplication_hook_holder
=
1053 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1054 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1056 while ((file_data
= file_data_vec
[j
++]))
1060 struct lto_input_block
*ib
1061 = lto_create_simple_input_block (file_data
,
1062 LTO_section_ipa_reference
,
1067 unsigned int f_count
= streamer_read_uhwi (ib
);
1071 b_count
= streamer_read_hwi (ib
);
1073 fprintf (dump_file
, "all module statics:");
1074 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1076 unsigned int var_index
= streamer_read_uhwi (ib
);
1077 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1079 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1081 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1084 for (i
= 0; i
< f_count
; i
++)
1086 unsigned int j
, index
;
1087 struct cgraph_node
*node
;
1088 ipa_reference_optimization_summary_t info
;
1090 lto_symtab_encoder_t encoder
;
1092 index
= streamer_read_uhwi (ib
);
1093 encoder
= file_data
->symtab_node_encoder
;
1094 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1096 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1097 set_reference_optimization_summary (node
, info
);
1098 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1099 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1102 "\nFunction name:%s/%i:\n static not read:",
1103 node
->asm_name (), node
->order
);
1105 /* Set the statics not read. */
1106 v_count
= streamer_read_hwi (ib
);
1109 info
->statics_not_read
= all_module_statics
;
1111 fprintf (dump_file
, " all module statics");
1114 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1116 unsigned int var_index
= streamer_read_uhwi (ib
);
1117 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1119 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1121 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1126 "\n static not written:");
1127 /* Set the statics not written. */
1128 v_count
= streamer_read_hwi (ib
);
1131 info
->statics_not_written
= all_module_statics
;
1133 fprintf (dump_file
, " all module statics");
1136 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1138 unsigned int var_index
= streamer_read_uhwi (ib
);
1139 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1141 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1143 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1146 fprintf (dump_file
, "\n");
1149 lto_destroy_simple_input_block (file_data
,
1150 LTO_section_ipa_reference
,
1154 /* Fatal error here. We do not want to support compiling ltrans units with
1155 different version of compiler or different flags than the WPA unit, so
1156 this should never happen. */
1157 fatal_error (input_location
,
1158 "ipa reference summary is missing in ltrans unit");
1164 const pass_data pass_data_ipa_reference
=
1166 IPA_PASS
, /* type */
1167 "static-var", /* name */
1168 OPTGROUP_NONE
, /* optinfo_flags */
1169 TV_IPA_REFERENCE
, /* tv_id */
1170 0, /* properties_required */
1171 0, /* properties_provided */
1172 0, /* properties_destroyed */
1173 0, /* todo_flags_start */
1174 0, /* todo_flags_finish */
1177 class pass_ipa_reference
: public ipa_opt_pass_d
1180 pass_ipa_reference (gcc::context
*ctxt
)
1181 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1182 NULL
, /* generate_summary */
1183 NULL
, /* write_summary */
1184 NULL
, /* read_summary */
1185 ipa_reference_write_optimization_summary
, /*
1186 write_optimization_summary */
1187 ipa_reference_read_optimization_summary
, /*
1188 read_optimization_summary */
1189 NULL
, /* stmt_fixup */
1190 0, /* function_transform_todo_flags_start */
1191 NULL
, /* function_transform */
1192 NULL
) /* variable_transform */
1195 /* opt_pass methods: */
1196 virtual bool gate (function
*)
1198 return ((in_lto_p
|| flag_ipa_reference
)
1199 /* Don't bother doing anything if the program has errors. */
1203 virtual unsigned int execute (function
*) { return propagate (); }
1205 }; // class pass_ipa_reference
1210 make_pass_ipa_reference (gcc::context
*ctxt
)
1212 return new pass_ipa_reference (ctxt
);
1215 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1216 within the same process. For use by toplev::finalize. */
1219 ipa_reference_c_finalize (void)
1223 bitmap_obstack_release (&optimization_summary_obstack
);
1227 if (node_removal_hook_holder
)
1229 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1230 node_removal_hook_holder
= NULL
;
1232 if (node_duplication_hook_holder
)
1234 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1235 node_duplication_hook_holder
= NULL
;