1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004-2014 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 "basic-block.h"
46 #include "tree-ssa-alias.h"
47 #include "internal-fn.h"
48 #include "gimple-expr.h"
51 #include "tree-inline.h"
52 #include "tree-pass.h"
53 #include "splay-tree.h"
54 #include "ipa-utils.h"
55 #include "ipa-reference.h"
57 #include "diagnostic.h"
58 #include "data-streamer.h"
59 #include "lto-streamer.h"
61 static void remove_node_data (struct cgraph_node
*node
,
62 void *data ATTRIBUTE_UNUSED
);
63 static void duplicate_node_data (struct cgraph_node
*src
,
64 struct cgraph_node
*dst
,
65 void *data ATTRIBUTE_UNUSED
);
67 /* The static variables defined within the compilation unit that are
68 loaded or stored directly by function that owns this structure. */
70 struct ipa_reference_local_vars_info_d
73 bitmap statics_written
;
76 /* Statics that are read and written by some set of functions. The
77 local ones are based on the loads and stores local to the function.
78 The global ones are based on the local info as well as the
79 transitive closure of the functions that are called. */
81 struct ipa_reference_global_vars_info_d
84 bitmap statics_written
;
87 /* Information we save about every function after ipa-reference is completed. */
89 struct ipa_reference_optimization_summary_d
91 bitmap statics_not_read
;
92 bitmap statics_not_written
;
95 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
96 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
97 typedef struct ipa_reference_optimization_summary_d
*ipa_reference_optimization_summary_t
;
99 struct ipa_reference_vars_info_d
101 struct ipa_reference_local_vars_info_d local
;
102 struct ipa_reference_global_vars_info_d global
;
105 typedef struct ipa_reference_vars_info_d
*ipa_reference_vars_info_t
;
107 /* This splay tree contains all of the static variables that are
108 being considered by the compilation level alias analysis. */
109 static splay_tree reference_vars_to_consider
;
111 /* Set of all interesting module statics. A bit is set for every module
112 static we are considering. This is added to the local info when asm
113 code is found that clobbers all memory. */
114 static bitmap all_module_statics
;
116 /* Obstack holding bitmaps of local analysis (live from analysis to
118 static bitmap_obstack local_info_obstack
;
119 /* Obstack holding global analysis live forever. */
120 static bitmap_obstack optimization_summary_obstack
;
122 /* Holders of ipa cgraph hooks: */
123 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
124 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
126 /* Vector where the reference var infos are actually stored.
127 Indexed by UID of call graph nodes. */
128 static vec
<ipa_reference_vars_info_t
> ipa_reference_vars_vector
;
130 static vec
<ipa_reference_optimization_summary_t
> ipa_reference_opt_sum_vector
;
132 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
133 static inline ipa_reference_vars_info_t
134 get_reference_vars_info (struct cgraph_node
*node
)
136 if (!ipa_reference_vars_vector
.exists ()
137 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
139 return ipa_reference_vars_vector
[node
->uid
];
142 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
143 static inline ipa_reference_optimization_summary_t
144 get_reference_optimization_summary (struct cgraph_node
*node
)
146 if (!ipa_reference_opt_sum_vector
.exists ()
147 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
149 return ipa_reference_opt_sum_vector
[node
->uid
];
152 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
154 set_reference_vars_info (struct cgraph_node
*node
,
155 ipa_reference_vars_info_t info
)
157 if (!ipa_reference_vars_vector
.exists ()
158 || ipa_reference_vars_vector
.length () <= (unsigned int) node
->uid
)
159 ipa_reference_vars_vector
.safe_grow_cleared (node
->uid
+ 1);
160 ipa_reference_vars_vector
[node
->uid
] = info
;
163 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
165 set_reference_optimization_summary (struct cgraph_node
*node
,
166 ipa_reference_optimization_summary_t info
)
168 if (!ipa_reference_opt_sum_vector
.exists ()
169 || (ipa_reference_opt_sum_vector
.length () <= (unsigned int) node
->uid
))
170 ipa_reference_opt_sum_vector
.safe_grow_cleared (node
->uid
+ 1);
171 ipa_reference_opt_sum_vector
[node
->uid
] = info
;
174 /* Return a bitmap indexed by DECL_UID for the static variables that
175 are *not* read during the execution of the function FN. Returns
176 NULL if no data is available. */
179 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
181 ipa_reference_optimization_summary_t info
=
182 get_reference_optimization_summary (cgraph_function_node (fn
, NULL
));
184 return info
->statics_not_read
;
185 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
186 return all_module_statics
;
191 /* Return a bitmap indexed by DECL_UID for the static variables that
192 are *not* written during the execution of the function FN. Note
193 that variables written may or may not be read during the function
194 call. Returns NULL if no data is available. */
197 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
199 ipa_reference_optimization_summary_t info
=
200 get_reference_optimization_summary (fn
);
202 return info
->statics_not_written
;
203 else if (flags_from_decl_or_type (fn
->decl
) & ECF_LEAF
)
204 return all_module_statics
;
211 /* Add VAR to all_module_statics and the two
212 reference_vars_to_consider* sets. */
215 add_static_var (tree var
)
217 int uid
= DECL_UID (var
);
218 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
220 splay_tree_insert (reference_vars_to_consider
,
221 uid
, (splay_tree_value
)var
);
222 bitmap_set_bit (all_module_statics
, uid
);
225 /* Return true if the variable T is the right kind of static variable to
226 perform compilation unit scope escape analysis. */
229 is_proper_for_analysis (tree t
)
231 /* If the variable has the "used" attribute, treat it as if it had a
232 been touched by the devil. */
233 if (DECL_PRESERVE_P (t
))
236 /* Do not want to do anything with volatile except mark any
237 function that uses one to be not const or pure. */
238 if (TREE_THIS_VOLATILE (t
))
241 /* We do not need to analyze readonly vars, we already know they do not
243 if (TREE_READONLY (t
))
246 /* We can not track variables with address taken. */
247 if (TREE_ADDRESSABLE (t
))
250 /* TODO: We could track public variables that are not addressable, but currently
251 frontends don't give us those. */
255 /* TODO: Check aliases. */
257 /* This is a variable we care about. Check if we have seen it
258 before, and if not add it the set of variables we care about. */
259 if (all_module_statics
260 && !bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
266 /* Lookup the tree node for the static variable that has UID and
267 convert the name to a string for debugging. */
270 get_static_name (int index
)
272 splay_tree_node stn
=
273 splay_tree_lookup (reference_vars_to_consider
, index
);
274 return fndecl_name ((tree
)(stn
->value
));
277 /* Dump a set of static vars to FILE. */
279 dump_static_vars_set_to_file (FILE *f
, bitmap set
)
285 else if (set
== all_module_statics
)
288 EXECUTE_IF_SET_IN_BITMAP (set
, 0, index
, bi
)
290 fprintf (f
, "%s ", get_static_name (index
));
294 /* Compute X |= Y, taking into account the possibility that
295 either X or Y is already the maximum set.
296 Return true if X is the maximum set after taking the union with Y. */
299 union_static_var_sets (bitmap
&x
, bitmap y
)
301 if (x
!= all_module_statics
)
303 if (y
== all_module_statics
)
306 x
= all_module_statics
;
308 else if (bitmap_ior_into (x
, y
))
310 /* The union may have reduced X to the maximum set.
311 In that case, we want to make that visible explicitly.
312 Even though bitmap_equal_p can be very expensive, it
313 turns out to be an overall win to check this here for
314 an LTO bootstrap of GCC itself. Liberally extrapoliate
315 that result to be applicable to all cases. */
316 if (bitmap_equal_p (x
, all_module_statics
))
319 x
= all_module_statics
;
323 return x
== all_module_statics
;
326 /* Return a copy of SET on the bitmap obstack containing SET.
327 But if SET is NULL or the maximum set, return that instead. */
330 copy_static_var_set (bitmap set
)
332 if (set
== NULL
|| set
== all_module_statics
)
334 bitmap_obstack
*o
= set
->obstack
;
335 gcc_checking_assert (o
);
336 bitmap copy
= BITMAP_ALLOC (o
);
337 bitmap_copy (copy
, set
);
341 /* Compute the union all of the statics read and written by every callee of X
342 into X_GLOBAL->statics_read and X_GLOBAL->statics_written. X_GLOBAL is
343 actually the set representing the cycle containing X. If the read and
344 written sets of X_GLOBAL has been reduced to the maximum set, we don't
345 have to look at the remaining callees. */
348 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
350 struct cgraph_edge
*e
;
351 bool read_all
= x_global
->statics_read
== all_module_statics
;
352 bool write_all
= x_global
->statics_written
== all_module_statics
;
354 e
&& !(read_all
&& write_all
);
357 enum availability avail
;
358 struct cgraph_node
*y
= cgraph_function_node (e
->callee
, &avail
);
362 /* Only look into nodes we can propagate something. */
363 int flags
= flags_from_decl_or_type (y
->decl
);
364 if (avail
> AVAIL_OVERWRITABLE
365 || (avail
== AVAIL_OVERWRITABLE
&& (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 || cgraph_edge_cannot_lead_to_return (e
))
393 union_static_var_sets (x_global
->statics_written
,
394 y_global
->statics_written
);
402 /* The init routine for analyzing global static variable usage. See
403 comments at top for description. */
407 static bool init_p
= false;
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
);
421 node_removal_hook_holder
=
422 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
423 node_duplication_hook_holder
=
424 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
428 /* Set up the persistent info for FN. */
430 static ipa_reference_local_vars_info_t
431 init_function_info (struct cgraph_node
*fn
)
433 ipa_reference_vars_info_t info
434 = XCNEW (struct ipa_reference_vars_info_d
);
436 /* Add the info to the tree's annotation. */
437 set_reference_vars_info (fn
, info
);
439 info
->local
.statics_read
= BITMAP_ALLOC (&local_info_obstack
);
440 info
->local
.statics_written
= BITMAP_ALLOC (&local_info_obstack
);
446 /* This is the main routine for finding the reference patterns for
447 global variables within a function FN. */
450 analyze_function (struct cgraph_node
*fn
)
452 ipa_reference_local_vars_info_t local
;
453 struct ipa_ref
*ref
= NULL
;
457 local
= init_function_info (fn
);
458 for (i
= 0; fn
->iterate_reference (i
, ref
); i
++)
460 if (!is_a
<varpool_node
*> (ref
->referred
))
462 var
= ref
->referred
->decl
;
463 if (!is_proper_for_analysis (var
))
468 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
471 if (ref
->cannot_lead_to_return ())
473 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
482 if (cgraph_node_cannot_return (fn
))
483 bitmap_clear (local
->statics_written
);
487 /* Called when new clone is inserted to callgraph late. */
490 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
491 void *data ATTRIBUTE_UNUSED
)
493 ipa_reference_optimization_summary_t ginfo
;
494 ipa_reference_optimization_summary_t dst_ginfo
;
496 ginfo
= get_reference_optimization_summary (src
);
499 dst_ginfo
= XCNEW (struct ipa_reference_optimization_summary_d
);
500 set_reference_optimization_summary (dst
, dst_ginfo
);
501 dst_ginfo
->statics_not_read
=
502 copy_static_var_set (ginfo
->statics_not_read
);
503 dst_ginfo
->statics_not_written
=
504 copy_static_var_set (ginfo
->statics_not_written
);
507 /* Called when node is removed. */
510 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
512 ipa_reference_optimization_summary_t ginfo
;
513 ginfo
= get_reference_optimization_summary (node
);
516 if (ginfo
->statics_not_read
517 && ginfo
->statics_not_read
!= all_module_statics
)
518 BITMAP_FREE (ginfo
->statics_not_read
);
520 if (ginfo
->statics_not_written
521 && ginfo
->statics_not_written
!= all_module_statics
)
522 BITMAP_FREE (ginfo
->statics_not_written
);
524 set_reference_optimization_summary (node
, NULL
);
528 /* Analyze each function in the cgraph to see which global or statics
529 are read or written. */
532 generate_summary (void)
534 struct cgraph_node
*node
;
540 /* Process all of the functions next. */
541 FOR_EACH_DEFINED_FUNCTION (node
)
542 analyze_function (node
);
545 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
547 fprintf (dump_file
, "\nPromotable global:%s (uid=%u)\n",
548 get_static_name (index
), index
);
552 FOR_EACH_DEFINED_FUNCTION (node
)
553 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
555 ipa_reference_local_vars_info_t l
;
559 l
= &get_reference_vars_info (node
)->local
;
561 "\nFunction name:%s/%i:",
562 node
->asm_name (), node
->order
);
563 fprintf (dump_file
, "\n locals read: ");
565 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
568 fprintf (dump_file
, "%s ",
569 get_static_name (index
));
571 fprintf (dump_file
, "\n locals written: ");
572 if (l
->statics_written
)
573 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
576 fprintf (dump_file
, "%s ", get_static_name (index
));
581 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE. */
584 read_write_all_from_decl (struct cgraph_node
*node
,
585 bool &read_all
, bool &write_all
)
587 tree decl
= node
->decl
;
588 int flags
= flags_from_decl_or_type (decl
);
589 if ((flags
& ECF_LEAF
)
590 && cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
592 else if (flags
& ECF_CONST
)
594 else if ((flags
& ECF_PURE
)
595 || cgraph_node_cannot_return (node
))
598 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
599 fprintf (dump_file
, " %s/%i -> read all\n",
600 node
->asm_name (), node
->order
);
604 /* TODO: To be able to produce sane results, we should also handle
605 common builtins, in particular throw. */
608 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
609 fprintf (dump_file
, " %s/%i -> read all, write all\n",
610 node
->asm_name (), node
->order
);
614 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
615 in the cycle of NODE. */
618 get_read_write_all_from_node (struct cgraph_node
*node
,
619 bool &read_all
, bool &write_all
)
621 struct cgraph_edge
*e
, *ie
;
623 /* When function is overwritable, we can not assume anything. */
624 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
625 read_write_all_from_decl (node
, read_all
, write_all
);
627 for (e
= node
->callees
;
628 e
&& !(read_all
&& write_all
);
631 enum availability avail
;
632 struct cgraph_node
*callee
= cgraph_function_node (e
->callee
, &avail
);
633 gcc_checking_assert (callee
);
634 if (avail
<= AVAIL_OVERWRITABLE
)
635 read_write_all_from_decl (callee
, read_all
, write_all
);
638 for (ie
= node
->indirect_calls
;
639 ie
&& !(read_all
&& write_all
);
640 ie
= ie
->next_callee
)
641 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
644 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
645 fprintf (dump_file
, " indirect call -> read all\n");
646 if (!cgraph_edge_cannot_lead_to_return (ie
)
647 && !(ie
->indirect_info
->ecf_flags
& ECF_PURE
))
649 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
650 fprintf (dump_file
, " indirect call -> write all\n");
656 /* Produce the global information by preforming a transitive closure
657 on the local information that was produced by ipa_analyze_function. */
662 struct cgraph_node
*node
;
663 struct cgraph_node
**order
=
664 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
669 dump_cgraph (dump_file
);
671 ipa_discover_readonly_nonaddressable_vars ();
674 /* Propagate the local information through the call graph to produce
675 the global information. All the nodes within a cycle will have
676 the same info so we collapse cycles first. Then we can do the
677 propagation in one pass from the leaves to the roots. */
678 order_pos
= ipa_reduced_postorder (order
, true, true, NULL
);
680 ipa_print_order (dump_file
, "reduced", order
, order_pos
);
682 for (i
= 0; i
< order_pos
; i
++ )
685 struct cgraph_node
*w
;
686 ipa_reference_vars_info_t node_info
;
687 ipa_reference_global_vars_info_t node_g
;
688 ipa_reference_local_vars_info_t node_l
;
689 bool read_all
= false;
690 bool write_all
= false;
696 node_info
= get_reference_vars_info (node
);
697 gcc_assert (node_info
);
698 node_l
= &node_info
->local
;
699 node_g
= &node_info
->global
;
701 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
702 fprintf (dump_file
, "Starting cycle with %s/%i\n",
703 node
->asm_name (), node
->order
);
705 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
707 /* If any node in a cycle is read_all or write_all, they all are. */
708 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
710 if (dump_file
&& (dump_flags
& TDF_DETAILS
))
711 fprintf (dump_file
, " Visiting %s/%i\n",
712 w
->asm_name (), w
->order
);
713 get_read_write_all_from_node (w
, read_all
, write_all
);
714 if (read_all
&& write_all
)
718 /* Initialized the bitmaps global sets for the reduced node. */
720 node_g
->statics_read
= all_module_statics
;
722 node_g
->statics_read
= copy_static_var_set (node_l
->statics_read
);
724 node_g
->statics_written
= all_module_statics
;
726 node_g
->statics_written
= copy_static_var_set (node_l
->statics_written
);
728 /* Merge the sets of this cycle with all sets of callees reached
730 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
732 if (read_all
&& write_all
)
737 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
738 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
739 int flags
= flags_from_decl_or_type (w
->decl
);
741 if (!(flags
& ECF_CONST
))
742 read_all
= union_static_var_sets (node_g
->statics_read
,
744 if (!(flags
& ECF_PURE
)
745 && !cgraph_node_cannot_return (w
))
746 write_all
= union_static_var_sets (node_g
->statics_written
,
747 w_l
->statics_written
);
750 propagate_bits (node_g
, w
);
753 /* All nodes within a cycle have the same global info bitmaps. */
754 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
756 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
757 w_ri
->global
= *node_g
;
760 cycle_nodes
.release ();
765 for (i
= 0; i
< order_pos
; i
++)
768 struct cgraph_node
*w
;
775 "\nFunction name:%s/%i:",
776 node
->asm_name (), node
->order
);
778 ipa_reference_vars_info_t node_info
= get_reference_vars_info (node
);
779 ipa_reference_global_vars_info_t node_g
= &node_info
->global
;
781 vec
<cgraph_node_ptr
> cycle_nodes
= ipa_get_nodes_in_cycle (node
);
782 FOR_EACH_VEC_ELT (cycle_nodes
, x
, w
)
784 ipa_reference_vars_info_t w_ri
= get_reference_vars_info (w
);
785 ipa_reference_local_vars_info_t w_l
= &w_ri
->local
;
787 fprintf (dump_file
, "\n next cycle: %s/%i ",
788 w
->asm_name (), w
->order
);
789 fprintf (dump_file
, "\n locals read: ");
790 dump_static_vars_set_to_file (dump_file
, w_l
->statics_read
);
791 fprintf (dump_file
, "\n locals written: ");
792 dump_static_vars_set_to_file (dump_file
, w_l
->statics_written
);
794 cycle_nodes
.release ();
796 fprintf (dump_file
, "\n globals read: ");
797 dump_static_vars_set_to_file (dump_file
, node_g
->statics_read
);
798 fprintf (dump_file
, "\n globals written: ");
799 dump_static_vars_set_to_file (dump_file
, node_g
->statics_written
);
800 fprintf (dump_file
, "\n");
805 FOR_EACH_DEFINED_FUNCTION (node
)
807 ipa_reference_vars_info_t node_info
;
808 ipa_reference_global_vars_info_t node_g
;
809 ipa_reference_optimization_summary_t opt
;
811 node_info
= get_reference_vars_info (node
);
813 && (cgraph_function_body_availability (node
) > AVAIL_OVERWRITABLE
814 || (flags_from_decl_or_type (node
->decl
) & ECF_LEAF
)))
816 node_g
= &node_info
->global
;
818 opt
= XCNEW (struct ipa_reference_optimization_summary_d
);
819 set_reference_optimization_summary (node
, opt
);
821 /* Create the complimentary sets. */
823 if (bitmap_empty_p (node_g
->statics_read
))
824 opt
->statics_not_read
= all_module_statics
;
827 opt
->statics_not_read
828 = BITMAP_ALLOC (&optimization_summary_obstack
);
829 if (node_g
->statics_read
!= all_module_statics
)
830 bitmap_and_compl (opt
->statics_not_read
,
832 node_g
->statics_read
);
835 if (bitmap_empty_p (node_g
->statics_written
))
836 opt
->statics_not_written
= all_module_statics
;
839 opt
->statics_not_written
840 = BITMAP_ALLOC (&optimization_summary_obstack
);
841 if (node_g
->statics_written
!= all_module_statics
)
842 bitmap_and_compl (opt
->statics_not_written
,
844 node_g
->statics_written
);
850 ipa_free_postorder_info ();
853 bitmap_obstack_release (&local_info_obstack
);
854 ipa_reference_vars_vector
.release ();
856 splay_tree_delete (reference_vars_to_consider
);
857 reference_vars_to_consider
= NULL
;
861 /* Return true if we need to write summary of NODE. */
864 write_node_summary_p (struct cgraph_node
*node
,
865 lto_symtab_encoder_t encoder
,
866 bitmap ltrans_statics
)
868 ipa_reference_optimization_summary_t info
;
870 /* See if we have (non-empty) info. */
871 if (!node
->definition
|| node
->global
.inlined_to
)
873 info
= get_reference_optimization_summary (node
);
874 if (!info
|| (bitmap_empty_p (info
->statics_not_read
)
875 && bitmap_empty_p (info
->statics_not_written
)))
878 /* See if we want to encode it.
879 Encode also referenced functions since constant folding might turn it into
882 In future we might also want to include summaries of functions references
883 by initializers of constant variables references in current unit. */
884 if (!reachable_from_this_partition_p (node
, encoder
)
885 && !referenced_from_this_partition_p (node
, encoder
))
888 /* See if the info has non-empty intersections with vars we want to encode. */
889 if (!bitmap_intersect_p (info
->statics_not_read
, ltrans_statics
)
890 && !bitmap_intersect_p (info
->statics_not_written
, ltrans_statics
))
895 /* Stream out BITS<RANS_STATICS as list of decls to OB.
896 LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
897 or -1. When it is positive, just output -1 when
898 BITS<RANS_STATICS == BITS<RANS_STATICS. */
901 stream_out_bitmap (struct lto_simple_output_block
*ob
,
902 bitmap bits
, bitmap ltrans_statics
,
903 int ltrans_statics_bitcount
)
908 if (bits
== all_module_statics
)
910 streamer_write_hwi_stream (ob
->main_stream
, -1);
913 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
915 if (count
== ltrans_statics_bitcount
)
917 streamer_write_hwi_stream (ob
->main_stream
, -1);
920 streamer_write_hwi_stream (ob
->main_stream
, count
);
923 EXECUTE_IF_AND_IN_BITMAP (bits
, ltrans_statics
, 0, index
, bi
)
925 tree decl
= (tree
)splay_tree_lookup (reference_vars_to_consider
, index
)->value
;
926 lto_output_var_decl_index (ob
->decl_state
, ob
->main_stream
, decl
);
930 /* Serialize the ipa info for lto. */
933 ipa_reference_write_optimization_summary (void)
935 struct lto_simple_output_block
*ob
936 = lto_create_simple_output_block (LTO_section_ipa_reference
);
937 unsigned int count
= 0;
938 int ltrans_statics_bitcount
= 0;
939 lto_symtab_encoder_t encoder
= ob
->decl_state
->symtab_node_encoder
;
940 bitmap ltrans_statics
= BITMAP_ALLOC (NULL
);
943 reference_vars_to_consider
= splay_tree_new (splay_tree_compare_ints
, 0, 0);
945 /* See what variables we are interested in. */
946 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
948 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
949 varpool_node
*vnode
= dyn_cast
<varpool_node
*> (snode
);
951 && bitmap_bit_p (all_module_statics
, DECL_UID (vnode
->decl
))
952 && referenced_from_this_partition_p (vnode
, encoder
))
954 tree decl
= vnode
->decl
;
955 bitmap_set_bit (ltrans_statics
, DECL_UID (decl
));
956 splay_tree_insert (reference_vars_to_consider
,
957 DECL_UID (decl
), (splay_tree_value
)decl
);
958 ltrans_statics_bitcount
++;
963 if (ltrans_statics_bitcount
)
964 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
966 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
967 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
968 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
972 streamer_write_uhwi_stream (ob
->main_stream
, count
);
974 stream_out_bitmap (ob
, ltrans_statics
, ltrans_statics
,
977 /* Process all of the functions. */
978 if (ltrans_statics_bitcount
)
979 for (i
= 0; i
< lto_symtab_encoder_size (encoder
); i
++)
981 symtab_node
*snode
= lto_symtab_encoder_deref (encoder
, i
);
982 cgraph_node
*cnode
= dyn_cast
<cgraph_node
*> (snode
);
983 if (cnode
&& write_node_summary_p (cnode
, encoder
, ltrans_statics
))
985 ipa_reference_optimization_summary_t info
;
988 info
= get_reference_optimization_summary (cnode
);
989 node_ref
= lto_symtab_encoder_encode (encoder
, snode
);
990 streamer_write_uhwi_stream (ob
->main_stream
, node_ref
);
992 stream_out_bitmap (ob
, info
->statics_not_read
, ltrans_statics
,
993 ltrans_statics_bitcount
);
994 stream_out_bitmap (ob
, info
->statics_not_written
, ltrans_statics
,
995 ltrans_statics_bitcount
);
998 BITMAP_FREE (ltrans_statics
);
999 lto_destroy_simple_output_block (ob
);
1000 splay_tree_delete (reference_vars_to_consider
);
1003 /* Deserialize the ipa info for lto. */
1006 ipa_reference_read_optimization_summary (void)
1008 struct lto_file_decl_data
** file_data_vec
1009 = lto_get_file_decl_data ();
1010 struct lto_file_decl_data
* file_data
;
1012 bitmap_obstack_initialize (&optimization_summary_obstack
);
1014 node_removal_hook_holder
=
1015 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
1016 node_duplication_hook_holder
=
1017 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
1018 all_module_statics
= BITMAP_ALLOC (&optimization_summary_obstack
);
1020 while ((file_data
= file_data_vec
[j
++]))
1024 struct lto_input_block
*ib
1025 = lto_create_simple_input_block (file_data
,
1026 LTO_section_ipa_reference
,
1031 unsigned int f_count
= streamer_read_uhwi (ib
);
1035 b_count
= streamer_read_hwi (ib
);
1037 fprintf (dump_file
, "all module statics:");
1038 for (i
= 0; i
< (unsigned int)b_count
; i
++)
1040 unsigned int var_index
= streamer_read_uhwi (ib
);
1041 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1043 bitmap_set_bit (all_module_statics
, DECL_UID (v_decl
));
1045 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1048 for (i
= 0; i
< f_count
; i
++)
1050 unsigned int j
, index
;
1051 struct cgraph_node
*node
;
1052 ipa_reference_optimization_summary_t info
;
1054 lto_symtab_encoder_t encoder
;
1056 index
= streamer_read_uhwi (ib
);
1057 encoder
= file_data
->symtab_node_encoder
;
1058 node
= cgraph (lto_symtab_encoder_deref (encoder
, index
));
1059 info
= XCNEW (struct ipa_reference_optimization_summary_d
);
1060 set_reference_optimization_summary (node
, info
);
1061 info
->statics_not_read
= BITMAP_ALLOC (&optimization_summary_obstack
);
1062 info
->statics_not_written
= BITMAP_ALLOC (&optimization_summary_obstack
);
1065 "\nFunction name:%s/%i:\n static not read:",
1066 node
->asm_name (), node
->order
);
1068 /* Set the statics not read. */
1069 v_count
= streamer_read_hwi (ib
);
1072 info
->statics_not_read
= all_module_statics
;
1074 fprintf (dump_file
, " all module statics");
1077 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1079 unsigned int var_index
= streamer_read_uhwi (ib
);
1080 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1082 bitmap_set_bit (info
->statics_not_read
, DECL_UID (v_decl
));
1084 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1089 "\n static not written:");
1090 /* Set the statics not written. */
1091 v_count
= streamer_read_hwi (ib
);
1094 info
->statics_not_written
= all_module_statics
;
1096 fprintf (dump_file
, " all module statics");
1099 for (j
= 0; j
< (unsigned int)v_count
; j
++)
1101 unsigned int var_index
= streamer_read_uhwi (ib
);
1102 tree v_decl
= lto_file_decl_data_get_var_decl (file_data
,
1104 bitmap_set_bit (info
->statics_not_written
, DECL_UID (v_decl
));
1106 fprintf (dump_file
, " %s", fndecl_name (v_decl
));
1109 fprintf (dump_file
, "\n");
1112 lto_destroy_simple_input_block (file_data
,
1113 LTO_section_ipa_reference
,
1117 /* Fatal error here. We do not want to support compiling ltrans units with
1118 different version of compiler or different flags than the WPA unit, so
1119 this should never happen. */
1120 fatal_error ("ipa reference summary is missing in ltrans unit");
1126 const pass_data pass_data_ipa_reference
=
1128 IPA_PASS
, /* type */
1129 "static-var", /* name */
1130 OPTGROUP_NONE
, /* optinfo_flags */
1131 TV_IPA_REFERENCE
, /* tv_id */
1132 0, /* properties_required */
1133 0, /* properties_provided */
1134 0, /* properties_destroyed */
1135 0, /* todo_flags_start */
1136 0, /* todo_flags_finish */
1139 class pass_ipa_reference
: public ipa_opt_pass_d
1142 pass_ipa_reference (gcc::context
*ctxt
)
1143 : ipa_opt_pass_d (pass_data_ipa_reference
, ctxt
,
1144 NULL
, /* generate_summary */
1145 NULL
, /* write_summary */
1146 NULL
, /* read_summary */
1147 ipa_reference_write_optimization_summary
, /*
1148 write_optimization_summary */
1149 ipa_reference_read_optimization_summary
, /*
1150 read_optimization_summary */
1151 NULL
, /* stmt_fixup */
1152 0, /* function_transform_todo_flags_start */
1153 NULL
, /* function_transform */
1154 NULL
) /* variable_transform */
1157 /* opt_pass methods: */
1158 virtual bool gate (function
*)
1160 return (flag_ipa_reference
1161 /* Don't bother doing anything if the program has errors. */
1165 virtual unsigned int execute (function
*) { return propagate (); }
1167 }; // class pass_ipa_reference
1172 make_pass_ipa_reference (gcc::context
*ctxt
)
1174 return new pass_ipa_reference (ctxt
);