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"
47 #include "fold-const.h"
50 #include "hard-reg-set.h"
52 #include "basic-block.h"
53 #include "tree-ssa-alias.h"
54 #include "internal-fn.h"
55 #include "gimple-expr.h"
57 #include "tree-inline.h"
58 #include "tree-pass.h"
59 #include "splay-tree.h"
61 #include "ipa-utils.h"
63 #include "ipa-reference.h"
65 #include "diagnostic.h"
66 #include "data-streamer.h"
67 #include "lto-streamer.h"
69 static void remove_node_data (struct cgraph_node
*node
,
70 void *data ATTRIBUTE_UNUSED
);
71 static void duplicate_node_data (struct cgraph_node
*src
,
72 struct cgraph_node
*dst
,
73 void *data ATTRIBUTE_UNUSED
);
75 /* The static variables defined within the compilation unit that are
76 loaded or stored directly by function that owns this structure. */
78 struct ipa_reference_local_vars_info_d
81 bitmap statics_written
;
84 /* Statics that are read and written by some set of functions. The
85 local ones are based on the loads and stores local to the function.
86 The global ones are based on the local info as well as the
87 transitive closure of the functions that are called. */
89 struct ipa_reference_global_vars_info_d
92 bitmap statics_written
;
95 /* Information we save about every function after ipa-reference is completed. */
97 struct ipa_reference_optimization_summary_d
99 bitmap statics_not_read
;
100 bitmap statics_not_written
;
103 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
104 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
105 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
107 struct ipa_reference_vars_info_d
109 struct ipa_reference_local_vars_info_d local
;
110 struct ipa_reference_global_vars_info_d global
;
113 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
115 /* This splay tree contains all of the static variables that are
116 being considered by the compilation level alias analysis. */
117 static splay_tree reference_vars_to_consider
;
119 /* Set of all interesting module statics. A bit is set for every module
120 static we are considering. This is added to the local info when asm
121 code is found that clobbers all memory. */
122 static bitmap all_module_statics
;
123 /* Set of all statics that should be ignored becuase they are touched by
124 -fno-ipa-reference code. */
125 static bitmap ignore_module_statics
;
127 /* Obstack holding bitmaps of local analysis (live from analysis to
129 static bitmap_obstack local_info_obstack
;
130 /* Obstack holding global analysis live forever. */
131 static bitmap_obstack optimization_summary_obstack
;
133 /* Holders of ipa cgraph hooks: */
134 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
135 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
137 /* Vector where the reference var infos are actually stored.
138 Indexed by UID of call graph nodes. */
139 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
141 /* TODO: find a place where we should release the vector. */
142 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
144 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
145 static inline ipa_reference_vars_info_t
146 get_reference_vars_info (struct cgraph_node
*node
)
148 if (!ipa_reference_vars_vector
.exists ()
149 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
151 return ipa_reference_vars_vector
[node
->uid
];
154 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
155 static inline ipa_reference_optimization_summary_t
156 get_reference_optimization_summary (struct cgraph_node
*node
)
158 if (!ipa_reference_opt_sum_vector
.exists ()
159 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
161 return ipa_reference_opt_sum_vector
[node
->uid
];
164 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
166 set_reference_vars_info (struct cgraph_node
*node
,
167 ipa_reference_vars_info_t info
)
169 if (!ipa_reference_vars_vector
.exists ()
170 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
171 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
172 ipa_reference_vars_vector
[node
->uid
] = info
;
175 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
177 set_reference_optimization_summary (struct cgraph_node
*node
,
178 ipa_reference_optimization_summary_t info
)
180 if (!ipa_reference_opt_sum_vector
.exists ()
181 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
182 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
183 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
186 /* Return a bitmap indexed by DECL_UID for the static variables that
187 are *not* read during the execution of the function FN. Returns
188 NULL if no data is available. */
191 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
193 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
194 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
196 ipa_reference_optimization_summary_t info
=
197 get_reference_optimization_summary (fn
->function_symbol (NULL
));
199 return info
->statics_not_read
;
200 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
201 return all_module_statics
;
206 /* Return a bitmap indexed by DECL_UID for the static variables that
207 are *not* written during the execution of the function FN. Note
208 that variables written may or may not be read during the function
209 call. Returns NULL if no data is available. */
212 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
214 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
)
215 || !opt_for_fn (current_function_decl
, flag_ipa_reference
))
217 ipa_reference_optimization_summary_t info
=
218 get_reference_optimization_summary (fn
);
220 return info
->statics_not_written
;
221 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
222 return all_module_statics
;
228 /* Return true if the variable T is the right kind of static variable to
229 perform compilation unit scope escape analysis. */
232 is_proper_for_analysis (tree t
)
234 /* If the variable has the "used" attribute, treat it as if it had a
235 been touched by the devil. */
236 if (DECL_PRESERVE_P (t
))
239 /* Do not want to do anything with volatile except mark any
240 function that uses one to be not const or pure. */
241 if (TREE_THIS_VOLATILE (t
))
244 /* We do not need to analyze readonly vars, we already know they do not
246 if (TREE_READONLY (t
))
249 /* We can not track variables with address taken. */
250 if (TREE_ADDRESSABLE (t
))
253 /* TODO: We could track public variables that are not addressable, but currently
254 frontends don't give us those. */
258 /* TODO: Check aliases. */
259 if (bitmap_bit_p (ignore_module_statics
, DECL_UID (t
)))
265 /* Lookup the tree node for the static variable that has UID and
266 convert the name to a string for debugging. */
269 get_static_name (int index
)
271 splay_tree_node stn
=
272 splay_tree_lookup (reference_vars_to_consider
, index
);
273 return fndecl_name ((tree
)(stn
->value
));
276 /* Dump a set of static vars to FILE. */
278 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
284 else if (set
== all_module_statics
)
287 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
289 fprintf (f
, "%s ", get_static_name (index
));
293 /* Compute X |= Y, taking into account the possibility that
294 either X or Y is already the maximum set.
295 Return true if X is the maximum set after taking the union with Y. */
298 union_static_var_sets (bitmap
&x
, bitmap y
)
300 if (x
!= all_module_statics
)
302 if (y
== all_module_statics
)
305 x
= all_module_statics
;
307 else if (bitmap_ior_into (x
, y
))
309 /* The union may have reduced X to the maximum set.
310 In that case, we want to make that visible explicitly.
311 Even though bitmap_equal_p can be very expensive, it
312 turns out to be an overall win to check this here for
313 an LTO bootstrap of GCC itself. Liberally extrapoliate
314 that result to be applicable to all cases. */
315 if (bitmap_equal_p (x
, all_module_statics
))
318 x
= all_module_statics
;
322 return x
== all_module_statics
;
325 /* Return a copy of SET on the bitmap obstack containing SET.
326 But if SET is NULL or the maximum set, return that instead. */
329 copy_static_var_set (bitmap set
)
331 if (set
== NULL
|| set
== all_module_statics
)
333 bitmap_obstack
*o
= set
->obstack
;
334 gcc_checking_assert (o
);
335 bitmap copy
= BITMAP_ALLOC (o
);
336 bitmap_copy (copy
, set
);
340 /* Compute the union all of the statics read and written by every callee of X
341 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
342 actually the set representing the cycle containing X. If the read and
343 written sets of X_GLOBAL has been reduced to the maximum set, we don't
344 have to look at the remaining callees. */
347 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
349 struct cgraph_edge
*e
;
350 bool read_all
= x_global
->statics_read
== all_module_statics
;
351 bool write_all
= x_global
->statics_written
== all_module_statics
;
353 e
&& !(read_all
&& write_all
);
356 enum availability avail
;
357 struct cgraph_node
*y
= e
->callee
->function_symbol (&avail
);
361 /* Only look into nodes we can propagate something. */
362 int flags
= flags_from_decl_or_type (y
->decl
);
363 if (opt_for_fn (y
->decl
, flag_ipa_reference
)
364 && (avail
> AVAIL_INTERPOSABLE
365 || (avail
== AVAIL_INTERPOSABLE
&& (flags
& ECF_LEAF
))))
367 if (get_reference_vars_info (y
))
369 ipa_reference_vars_info_t y_info
= get_reference_vars_info (y
);
370 ipa_reference_global_vars_info_t y_global
= &y_info
->global
;
372 /* Calls in the current cycle do not have their global set
373 computed yet (but everything else does because we're
374 visiting nodes in topological order). */
375 if (!y_global
->statics_read
)
378 /* If the function is const, it reads no memory even if it
379 seems so to local analysis. */
380 if (flags
& ECF_CONST
)
383 union_static_var_sets (x_global
->statics_read
,
384 y_global
->statics_read
);
386 /* If the function is pure, it has no stores even if it
387 seems so to local analysis. If we cannot return from
388 the function, we can safely ignore the call. */
389 if ((flags
& ECF_PURE
)
390 || e
->cannot_lead_to_return_p ())
393 union_static_var_sets (x_global
->statics_written
,
394 y_global
->statics_written
);
402 static bool ipa_init_p
= false;
404 /* The init routine for analyzing global static variable usage. See
405 comments at top for description. */
415 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
417 bitmap_obstack_initialize (&local_info_obstack
);
418 bitmap_obstack_initialize (&optimization_summary_obstack
);
419 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
420 ignore_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
422 node_removal_hook_holder
=
423 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
424 node_duplication_hook_holder
=
425 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
429 /* Set up the persistent info for FN. */
431 static ipa_reference_local_vars_info_t
432 init_function_info (struct cgraph_node
*fn
)
434 ipa_reference_vars_info_t info
435 = XCNEW (struct ipa_reference_vars_info_d
);
437 /* Add the info to the tree's annotation. */
438 set_reference_vars_info (fn
, info
);
440 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
441 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
447 /* This is the main routine for finding the reference patterns for
448 global variables within a function FN. */
451 analyze_function (struct cgraph_node
*fn
)
453 ipa_reference_local_vars_info_t local
;
454 struct ipa_ref
*ref
= NULL
;
458 if (!opt_for_fn (fn
->decl
, flag_ipa_reference
))
460 local
= init_function_info (fn
);
461 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
463 if (!is_a
<varpool_node
*> (ref
->referred
))
465 var
= ref
->referred
->decl
;
466 if (!is_proper_for_analysis (var
))
468 /* This is a variable we care about. Check if we have seen it
469 before, and if not add it the set of variables we care about. */
470 if (all_module_statics
471 && bitmap_set_bit (all_module_statics
, DECL_UID (var
)))
474 splay_tree_insert (reference_vars_to_consider
,
475 DECL_UID (var
), (splay_tree_value
)var
);
480 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
483 if (ref
->cannot_lead_to_return ())
485 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
494 if (fn
->cannot_return_p ())
495 bitmap_clear (local
->statics_written
);
499 /* Called when new clone is inserted to callgraph late. */
502 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
503 void *data ATTRIBUTE_UNUSED
)
505 ipa_reference_optimization_summary_t ginfo
;
506 ipa_reference_optimization_summary_t dst_ginfo
;
508 ginfo
= get_reference_optimization_summary (src
);
511 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
512 set_reference_optimization_summary (dst
, dst_ginfo
);
513 dst_ginfo
->statics_not_read
=
514 copy_static_var_set (ginfo
->statics_not_read
);
515 dst_ginfo
->statics_not_written
=
516 copy_static_var_set (ginfo
->statics_not_written
);
519 /* Called when node is removed. */
522 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
524 ipa_reference_optimization_summary_t ginfo
;
525 ginfo
= get_reference_optimization_summary (node
);
528 if (ginfo
->statics_not_read
529 && ginfo
->statics_not_read
!= all_module_statics
)
530 BITMAP_FREE (ginfo
->statics_not_read
);
532 if (ginfo
->statics_not_written
533 && ginfo
->statics_not_written
!= all_module_statics
)
534 BITMAP_FREE (ginfo
->statics_not_written
);
536 set_reference_optimization_summary (node
, NULL
);
540 /* Analyze each function in the cgraph to see which global or statics
541 are read or written. */
544 generate_summary (void)
546 struct cgraph_node
*node
;
552 /* Process all of the functions next. */
553 FOR_EACH_DEFINED_FUNCTION (node
)
554 if (!node
->alias
&& !opt_for_fn (node
->decl
, flag_ipa_reference
))
556 struct ipa_ref
*ref
= NULL
;
559 for (i
= 0; node
->iterate_reference (i
, ref
); i
++)
561 if (!is_a
<varpool_node
*> (ref
->referred
))
563 var
= ref
->referred
->decl
;
564 if (!is_proper_for_analysis (var
))
566 bitmap_set_bit (ignore_module_statics
, DECL_UID (var
));
569 FOR_EACH_DEFINED_FUNCTION (node
)
570 analyze_function (node
);
573 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
575 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
576 get_static_name (index
), index
);
580 FOR_EACH_DEFINED_FUNCTION (node
)
581 if (node
->get_availability () >= AVAIL_INTERPOSABLE
582 && opt_for_fn (node
->decl
, flag_ipa_reference
))
584 ipa_reference_local_vars_info_t l
;
588 l
= &get_reference_vars_info (node
)->local
;
590 "\nFunction name:%s/%i:",
591 node
->asm_name (), node
->order
);
592 fprintf (dump_file
, "\n locals read: ");
594 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
597 fprintf (dump_file
, "%s ",
598 get_static_name (index
));
600 fprintf (dump_file
, "\n locals written: ");
601 if (l
->statics_written
)
602 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
605 fprintf (dump_file
, "%s ", get_static_name (index
));
610 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
613 read_write_all_from_decl (struct cgraph_node
*node
,
614 bool &read_all
, bool &write_all
)
616 tree decl
= node
->decl
;
617 int flags
= flags_from_decl_or_type (decl
);
618 if ((flags
& ECF_LEAF
)
619 && node
->get_availability () < AVAIL_INTERPOSABLE
)
621 else if (flags
& ECF_CONST
)
623 else if ((flags
& ECF_PURE
) || node
->cannot_return_p ())
626 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
627 fprintf (dump_file
, " %s/%i -> read all\n",
628 node
->asm_name (), node
->order
);
632 /* TODO: To be able to produce sane results, we should also handle
633 common builtins, in particular throw. */
636 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
637 fprintf (dump_file
, " %s/%i -> read all, write all\n",
638 node
->asm_name (), node
->order
);
642 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
643 in the cycle of NODE. */
646 get_read_write_all_from_node (struct cgraph_node
*node
,
647 bool &read_all
, bool &write_all
)
649 struct cgraph_edge
*e
, *ie
;
651 /* When function is overwritable, we can not assume anything. */
652 if (node
->get_availability () <= AVAIL_INTERPOSABLE
653 || (node
->analyzed
&& !opt_for_fn (node
->decl
, flag_ipa_reference
)))
654 read_write_all_from_decl (node
, read_all
, write_all
);
656 for (e
= node
->callees
;
657 e
&& !(read_all
&& write_all
);
660 enum availability avail
;
661 struct cgraph_node
*callee
= e
->callee
->function_symbol (&avail
);
662 gcc_checking_assert (callee
);
663 if (avail
<= AVAIL_INTERPOSABLE
664 || (callee
->analyzed
&& !opt_for_fn (callee
->decl
, flag_ipa_reference
)))
665 read_write_all_from_decl (callee
, read_all
, write_all
);
668 for (ie
= node
->indirect_calls
;
669 ie
&& !(read_all
&& write_all
);
670 ie
= ie
->next_callee
)
671 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
674 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
675 fprintf (dump_file
, " indirect call -> read all\n");
676 if (!ie
->cannot_lead_to_return_p ()
677 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
679 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
680 fprintf (dump_file
, " indirect call -> write all\n");
686 /* Skip edges from and to nodes without ipa_reference enables. This leave
687 them out of strongy connected coponents and makes them easyto skip in the
688 propagation loop bellow. */
691 ignore_edge_p (cgraph_edge
*e
)
693 return (!opt_for_fn (e
->caller
->decl
, flag_ipa_reference
)
694 || !opt_for_fn (e
->callee
->function_symbol ()->decl
,
695 flag_ipa_reference
));
698 /* Produce the global information by preforming a transitive closure
699 on the local information that was produced by ipa_analyze_function. */
704 struct cgraph_node
*node
;
705 struct cgraph_node
**order
=
706 XCNEWVEC (struct cgraph_node
*, symtab
->cgraph_count
);
712 cgraph_node::dump_cgraph (dump_file
);
714 remove_p
= ipa_discover_readonly_nonaddressable_vars ();
717 /* Propagate the local information through the call graph to produce
718 the global information. All the nodes within a cycle will have
719 the same info so we collapse cycles first. Then we can do the
720 propagation in one pass from the leaves to the roots. */
721 order_pos
= ipa_reduced_postorder (order
, true, true, ignore_edge_p
);
723 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
725 for (i
= 0; i
< order_pos
; i
++ )
728 struct cgraph_node
*w
;
729 ipa_reference_vars_info_t node_info
;
730 ipa_reference_global_vars_info_t node_g
;
731 ipa_reference_local_vars_info_t node_l
;
732 bool read_all
= false;
733 bool write_all
= false;
736 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
739 node_info
= get_reference_vars_info (node
);
740 gcc_assert (node_info
);
741 node_l
= &node_info
->local
;
742 node_g
= &node_info
->global
;
744 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
745 fprintf (dump_file
, "Starting cycle with %s/%i\n",
746 node
->asm_name (), node
->order
);
748 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
750 /* If any node in a cycle is read_all or write_all, they all are. */
751 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
753 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
754 fprintf (dump_file
, " Visiting %s/%i\n",
755 w
->asm_name (), w
->order
);
756 get_read_write_all_from_node (w
, read_all
, write_all
);
757 if (read_all
&& write_all
)
761 /* Initialized the bitmaps global sets for the reduced node. */
763 node_g
->statics_read
= all_module_statics
;
765 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
767 node_g
->statics_written
= all_module_statics
;
769 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
771 /* Merge the sets of this cycle with all sets of callees reached
773 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
775 if (read_all
&& write_all
)
780 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
781 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
782 int flags
= flags_from_decl_or_type (w
->decl
);
784 if (!(flags
& ECF_CONST
))
785 read_all
= union_static_var_sets (node_g
->statics_read
,
787 if (!(flags
& ECF_PURE
)
788 && !w
->cannot_return_p ())
789 write_all
= union_static_var_sets (node_g
->statics_written
,
790 w_l
->statics_written
);
793 propagate_bits (node_g
, w
);
796 /* All nodes within a cycle have the same global info bitmaps. */
797 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
799 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
800 w_ri
->global
= *node_g
;
803 cycle_nodes
.release ();
808 for (i
= 0; i
< order_pos
; i
++)
811 struct cgraph_node
*w
;
814 if (node
->alias
|| !opt_for_fn (node
->decl
, flag_ipa_reference
))
818 "\nFunction name:%s/%i:",
819 node
->asm_name (), node
->order
);
821 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
822 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
824 vec
<cgraph_node
*> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
825 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
827 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
828 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
830 fprintf (dump_file
, "\n next cycle: %s/%i ",
831 w
->asm_name (), w
->order
);
832 fprintf (dump_file
, "\n locals read: ");
833 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
834 fprintf (dump_file
, "\n locals written: ");
835 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
837 cycle_nodes
.release ();
839 fprintf (dump_file
, "\n globals read: ");
840 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
841 fprintf (dump_file
, "\n globals written: ");
842 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
843 fprintf (dump_file
, "\n");
848 FOR_EACH_DEFINED_FUNCTION (node
)
850 ipa_reference_vars_info_t node_info
;
851 ipa_reference_global_vars_info_t node_g
;
852 ipa_reference_optimization_summary_t opt
;
854 node_info
= get_reference_vars_info (node
);
855 if (!node
->alias
&& opt_for_fn (node
->decl
, flag_ipa_reference
)
856 && (node
->get_availability () > AVAIL_INTERPOSABLE
857 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
859 node_g
= &node_info
->global
;
861 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
862 set_reference_optimization_summary (node
, opt
);
864 /* Create the complimentary sets. */
866 if (bitmap_empty_p (node_g
->statics_read
))
867 opt
->statics_not_read
= all_module_statics
;
870 opt
->statics_not_read
871 = BITMAP_ALLOC (&optimization_summary_obstack
);
872 if (node_g
->statics_read
!= all_module_statics
)
873 bitmap_and_compl (opt
->statics_not_read
,
875 node_g
->statics_read
);
878 if (bitmap_empty_p (node_g
->statics_written
))
879 opt
->statics_not_written
= all_module_statics
;
882 opt
->statics_not_written
883 = BITMAP_ALLOC (&optimization_summary_obstack
);
884 if (node_g
->statics_written
!= all_module_statics
)
885 bitmap_and_compl (opt
->statics_not_written
,
887 node_g
->statics_written
);
893 ipa_free_postorder_info ();
896 bitmap_obstack_release (&local_info_obstack
);
897 ipa_reference_vars_vector
.release ();
899 splay_tree_delete (reference_vars_to_consider
);
900 reference_vars_to_consider
= NULL
;
901 return remove_p
? TODO_remove_functions
: 0;
904 /* Return true if we need to write summary of NODE. */
907 write_node_summary_p (struct cgraph_node
*node
,
908 lto_symtab_encoder_t encoder
,
909 bitmap ltrans_statics
)
911 ipa_reference_optimization_summary_t info
;
913 /* See if we have (non-empty) info. */
914 if (!node
->definition
|| node
->global
.inlined_to
)
916 info
= get_reference_optimization_summary (node
);
917 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
918 && bitmap_empty_p (info
->statics_not_written
)))
921 /* See if we want to encode it.
922 Encode also referenced functions since constant folding might turn it into
925 In future we might also want to include summaries of functions references
926 by initializers of constant variables references in current unit. */
927 if (!reachable_from_this_partition_p (node
, encoder
)
928 && !referenced_from_this_partition_p (node
, encoder
))
931 /* See if the info has non-empty intersections with vars we want to encode. */
932 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
933 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
938 /* Stream out BITS<RANS_STATICS as list of decls to OB.
939 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
940 or -1. When it is positive, just output -1 when
941 BITS<RANS_STATICS == BITS<RANS_STATICS. */
944 stream_out_bitmap (struct lto_simple_output_block
*ob
,
945 bitmap bits
, bitmap ltrans_statics
,
946 int ltrans_statics_bitcount
)
951 if (bits
== all_module_statics
)
953 streamer_write_hwi_stream (ob
->main_stream
, -1);
956 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
958 if (count
== ltrans_statics_bitcount
)
960 streamer_write_hwi_stream (ob
->main_stream
, -1);
963 streamer_write_hwi_stream (ob
->main_stream
, count
);
966 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
968 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
969 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
973 /* Serialize the ipa info for lto. */
976 ipa_reference_write_optimization_summary (void)
978 struct lto_simple_output_block
*ob
979 = lto_create_simple_output_block (LTO_section_ipa_reference
);
980 unsigned int count
= 0;
981 int ltrans_statics_bitcount
= 0;
982 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
983 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
986 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
988 /* See what variables we are interested in. */
989 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
991 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
992 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
994 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
995 && referenced_from_this_partition_p (vnode
, encoder
))
997 tree decl
= vnode
->decl
;
998 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
999 splay_tree_insert (reference_vars_to_consider
,
1000 DECL_UID (decl
), (splay_tree_value
)decl
);
1001 ltrans_statics_bitcount
++;
1006 if (ltrans_statics_bitcount
)
1007 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1009 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1010 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1011 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1015 streamer_write_uhwi_stream (ob
->main_stream
, count
);
1017 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
1020 /* Process all of the functions. */
1021 if (ltrans_statics_bitcount
)
1022 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
1024 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
1025 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
1026 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
1028 ipa_reference_optimization_summary_t info
;
1031 info
= get_reference_optimization_summary (cnode
);
1032 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
1033 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
1035 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
1036 ltrans_statics_bitcount
);
1037 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
1038 ltrans_statics_bitcount
);
1041 BITMAP_FREE (ltrans_statics
);
1042 lto_destroy_simple_output_block (ob
);
1043 splay_tree_delete (reference_vars_to_consider
);
1046 /* Deserialize the ipa info for lto. */
1049 ipa_reference_read_optimization_summary (void)
1051 struct lto_file_decl_data
** file_data_vec
1052 = lto_get_file_decl_data ();
1053 struct lto_file_decl_data
* file_data
;
1055 bitmap_obstack_initialize (&optimization_summary_obstack
);
1057 node_removal_hook_holder
=
1058 symtab
->add_cgraph_removal_hook (&remove_node_data
, NULL
);
1059 node_duplication_hook_holder
=
1060 symtab
->add_cgraph_duplication_hook (&duplicate_node_data
, NULL
);
1061 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1063 while ((file_data
= file_data_vec
[j
++]))
1067 struct lto_input_block
*ib
1068 = lto_create_simple_input_block (file_data
,
1069 LTO_section_ipa_reference
,
1074 unsigned int f_count
= streamer_read_uhwi (ib
);
1078 b_count
= streamer_read_hwi (ib
);
1080 fprintf (dump_file
, "all module statics:");
1081 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1083 unsigned int var_index
= streamer_read_uhwi (ib
);
1084 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1086 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1088 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1091 for (i
= 0; i
< f_count
; i
++)
1093 unsigned int j
, index
;
1094 struct cgraph_node
*node
;
1095 ipa_reference_optimization_summary_t info
;
1097 lto_symtab_encoder_t encoder
;
1099 index
= streamer_read_uhwi (ib
);
1100 encoder
= file_data
->symtab_node_encoder
;
1101 node
= dyn_cast
<cgraph_node
*> (lto_symtab_encoder_deref
1103 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1104 set_reference_optimization_summary (node
, info
);
1105 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1106 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1109 "\nFunction name:%s/%i:\n static not read:",
1110 node
->asm_name (), node
->order
);
1112 /* Set the statics not read. */
1113 v_count
= streamer_read_hwi (ib
);
1116 info
->statics_not_read
= all_module_statics
;
1118 fprintf (dump_file
, " all module statics");
1121 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1123 unsigned int var_index
= streamer_read_uhwi (ib
);
1124 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1126 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1128 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1133 "\n static not written:");
1134 /* Set the statics not written. */
1135 v_count
= streamer_read_hwi (ib
);
1138 info
->statics_not_written
= all_module_statics
;
1140 fprintf (dump_file
, " all module statics");
1143 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1145 unsigned int var_index
= streamer_read_uhwi (ib
);
1146 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1148 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1150 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1153 fprintf (dump_file
, "\n");
1156 lto_destroy_simple_input_block (file_data
,
1157 LTO_section_ipa_reference
,
1161 /* Fatal error here. We do not want to support compiling ltrans units with
1162 different version of compiler or different flags than the WPA unit, so
1163 this should never happen. */
1164 fatal_error (input_location
,
1165 "ipa reference summary is missing in ltrans unit");
1171 const pass_data pass_data_ipa_reference
=
1173 IPA_PASS
, /* type */
1174 "static-var", /* name */
1175 OPTGROUP_NONE
, /* optinfo_flags */
1176 TV_IPA_REFERENCE
, /* tv_id */
1177 0, /* properties_required */
1178 0, /* properties_provided */
1179 0, /* properties_destroyed */
1180 0, /* todo_flags_start */
1181 0, /* todo_flags_finish */
1184 class pass_ipa_reference
: public ipa_opt_pass_d
1187 pass_ipa_reference (gcc::context
*ctxt
)
1188 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1189 NULL
, /* generate_summary */
1190 NULL
, /* write_summary */
1191 NULL
, /* read_summary */
1192 ipa_reference_write_optimization_summary
, /*
1193 write_optimization_summary */
1194 ipa_reference_read_optimization_summary
, /*
1195 read_optimization_summary */
1196 NULL
, /* stmt_fixup */
1197 0, /* function_transform_todo_flags_start */
1198 NULL
, /* function_transform */
1199 NULL
) /* variable_transform */
1202 /* opt_pass methods: */
1203 virtual bool gate (function
*)
1205 return ((in_lto_p
|| flag_ipa_reference
)
1206 /* Don't bother doing anything if the program has errors. */
1210 virtual unsigned int execute (function
*) { return propagate (); }
1212 }; // class pass_ipa_reference
1217 make_pass_ipa_reference (gcc::context
*ctxt
)
1219 return new pass_ipa_reference (ctxt
);
1222 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1223 within the same process. For use by toplev::finalize. */
1226 ipa_reference_c_finalize (void)
1230 bitmap_obstack_release (&optimization_summary_obstack
);
1234 if (node_removal_hook_holder
)
1236 symtab
->remove_cgraph_removal_hook (node_removal_hook_holder
);
1237 node_removal_hook_holder
= NULL
;
1239 if (node_duplication_hook_holder
)
1241 symtab
->remove_cgraph_duplication_hook (node_duplication_hook_holder
);
1242 node_duplication_hook_holder
= NULL
;