1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010
3 Free Software Foundation, Inc.
4 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This file gathers information about how variables whose scope is
23 confined to the compilation unit are used.
25 There are two categories of information produced by this pass:
27 1) The addressable (TREE_ADDRESSABLE) bit and readonly
28 (TREE_READONLY) bit associated with these variables is properly set
29 based on scanning all of the code withing the compilation unit.
31 2) The transitive call site specific clobber effects are computed
32 for the variables whose scope is contained within this compilation
35 First each function and static variable initialization is analyzed
36 to determine which local static variables are either read, written,
37 or have their address taken. Any local static that has its address
38 taken is removed from consideration. Once the local read and
39 writes are determined, a transitive closure of this information is
40 performed over the call graph to determine the worst case set of
41 side effects of each call. In later parts of the compiler, these
42 local and global sets are examined to make the call clobbering less
43 traumatic, promote some statics to registers, and improve aliasing
46 Currently must be run after inlining decisions have been made since
47 otherwise, the local sets will not contain information that is
48 consistent with post inlined state. The global sets are not prone
49 to this problem since they are by definition transitive. */
53 #include "coretypes.h"
56 #include "tree-flow.h"
57 #include "tree-inline.h"
58 #include "tree-pass.h"
59 #include "langhooks.h"
60 #include "pointer-set.h"
61 #include "splay-tree.h"
63 #include "ipa-utils.h"
64 #include "ipa-reference.h"
70 #include "diagnostic.h"
71 #include "langhooks.h"
72 #include "lto-streamer.h"
74 static void add_new_function (struct cgraph_node *node,
75 void *data ATTRIBUTE_UNUSED);
76 static void remove_node_data (struct cgraph_node *node,
77 void *data ATTRIBUTE_UNUSED);
78 static void duplicate_node_data (struct cgraph_node *src,
79 struct cgraph_node *dst,
80 void *data ATTRIBUTE_UNUSED);
82 /* The static variables defined within the compilation unit that are
83 loaded or stored directly by function that owns this structure. */
85 struct ipa_reference_local_vars_info_d
88 bitmap statics_written;
90 /* Set when this function calls another function external to the
91 compilation unit or if the function has a asm clobber of memory.
92 In general, such calls are modeled as reading and writing all
93 variables (both bits on) but sometime there are attributes on the
94 called function so we can do better. */
99 /* Statics that are read and written by some set of functions. The
100 local ones are based on the loads and stores local to the function.
101 The global ones are based on the local info as well as the
102 transitive closure of the functions that are called. The
103 structures are separated to allow the global structures to be
104 shared between several functions since every function within a
105 strongly connected component will have the same information. This
106 sharing saves both time and space in the computation of the vectors
107 as well as their translation from decl_uid form to ann_uid
110 struct ipa_reference_global_vars_info_d
113 bitmap statics_written;
114 bitmap statics_not_read;
115 bitmap statics_not_written;
118 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
119 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
120 struct ipa_reference_vars_info_d
122 ipa_reference_local_vars_info_t local;
123 ipa_reference_global_vars_info_t global;
126 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
128 /* This splay tree contains all of the static variables that are
129 being considered by the compilation level alias analysis. For
130 module_at_a_time compilation, this is the set of static but not
131 public variables. Any variables that either have their address
132 taken or participate in otherwise unsavory operations are deleted
134 static GTY((param1_is(int), param2_is(tree)))
135 splay_tree reference_vars_to_consider;
137 /* This bitmap is used to knock out the module static variables whose
138 addresses have been taken and passed around. */
139 static bitmap module_statics_escape;
141 /* This bitmap is used to knock out the module static variables that
143 static bitmap module_statics_written;
145 /* A bit is set for every module static we are considering. This is
146 ored into the local info when asm code is found that clobbers all
148 static bitmap all_module_statics;
150 static struct pointer_set_t *visited_nodes;
152 /* Obstack holding bitmaps of local analysis (live from analysis to
154 static bitmap_obstack local_info_obstack;
155 /* Obstack holding global analysis live forever. */
156 static bitmap_obstack global_info_obstack;
158 /* Holders of ipa cgraph hooks: */
159 static struct cgraph_node_hook_list *function_insertion_hook_holder;
160 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
161 static struct cgraph_node_hook_list *node_removal_hook_holder;
163 enum initialization_status_t
170 tree memory_identifier_string;
172 /* Vector where the reference var infos are actually stored. */
173 DEF_VEC_P (ipa_reference_vars_info_t);
174 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
175 static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
177 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
178 static inline ipa_reference_vars_info_t
179 get_reference_vars_info (struct cgraph_node *node)
181 if (!ipa_reference_vars_vector
182 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
184 return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid);
187 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
189 set_reference_vars_info (struct cgraph_node *node, ipa_reference_vars_info_t info)
191 if (!ipa_reference_vars_vector
192 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
193 VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector, node->uid + 1);
194 VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid, info);
197 /* Get a bitmap that contains all of the locally referenced static
198 variables for function FN. */
199 static ipa_reference_local_vars_info_t
200 get_local_reference_vars_info (struct cgraph_node *fn)
202 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
207 /* This phase was not run. */
211 /* Get a bitmap that contains all of the globally referenced static
212 variables for function FN. */
214 static ipa_reference_global_vars_info_t
215 get_global_reference_vars_info (struct cgraph_node *fn)
217 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
222 /* This phase was not run. */
226 /* Return a bitmap indexed by VAR_DECL uid for the static variables
227 that are read during the execution of the function FN. Returns
228 NULL if no data is available. */
231 ipa_reference_get_read_global (struct cgraph_node *fn)
233 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
235 return g->statics_read;
240 /* Return a bitmap indexed by VAR_DECL uid for the static variables
241 that are written during the execution of the function FN. Note
242 that variables written may or may not be read during the function
243 call. Returns NULL if no data is available. */
246 ipa_reference_get_written_global (struct cgraph_node *fn)
248 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
250 return g->statics_written;
255 /* Return a bitmap indexed by_DECL_UID uid for the static variables
256 that are not read during the execution of the function FN. Returns
257 NULL if no data is available. */
260 ipa_reference_get_not_read_global (struct cgraph_node *fn)
262 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
264 return g->statics_not_read;
269 /* Return a bitmap indexed by DECL_UID uid for the static variables
270 that are not written during the execution of the function FN. Note
271 that variables written may or may not be read during the function
272 call. Returns NULL if no data is available. */
275 ipa_reference_get_not_written_global (struct cgraph_node *fn)
277 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
279 return g->statics_not_written;
286 /* Add VAR to all_module_statics and the two
287 reference_vars_to_consider* sets. */
290 add_static_var (tree var)
292 int uid = DECL_UID (var);
293 gcc_assert (TREE_CODE (var) == VAR_DECL);
294 if (!bitmap_bit_p (all_module_statics, uid))
296 splay_tree_insert (reference_vars_to_consider,
297 uid, (splay_tree_value)var);
298 bitmap_set_bit (all_module_statics, uid);
302 /* Return true if the variable T is the right kind of static variable to
303 perform compilation unit scope escape analysis. */
306 has_proper_scope_for_analysis (tree t)
308 /* If the variable has the "used" attribute, treat it as if it had a
309 been touched by the devil. */
310 if (DECL_PRESERVE_P (t))
313 /* Do not want to do anything with volatile except mark any
314 function that uses one to be not const or pure. */
315 if (TREE_THIS_VOLATILE (t))
318 /* Do not care about a local automatic that is not static. */
319 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
322 /* FIXME: for LTO we should include PUBLIC vars too. This is bit difficult
323 as summarie would need unsharing. */
324 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
327 /* We cannot touch decls where the type needs constructing. */
328 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
331 /* This is a variable we care about. Check if we have seen it
332 before, and if not add it the set of variables we care about. */
333 if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
339 /* Mark tree T as having address taken. */
342 mark_address_taken (tree x)
344 if (TREE_CODE (x) == VAR_DECL
345 && module_statics_escape && has_proper_scope_for_analysis (x))
346 bitmap_set_bit (module_statics_escape, DECL_UID (x));
349 /* Wrapper around mark_address_taken for the stmt walker. */
352 mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
353 void *data ATTRIBUTE_UNUSED)
355 addr = get_base_address (addr);
357 mark_address_taken (addr);
361 /* Mark load of T. */
364 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
366 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
367 t = get_base_address (t);
368 if (t && TREE_CODE (t) == VAR_DECL
369 && has_proper_scope_for_analysis (t))
370 bitmap_set_bit (local->statics_read, DECL_UID (t));
374 /* Mark store of T. */
377 mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
379 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
380 t = get_base_address (t);
381 if (t && TREE_CODE (t) == VAR_DECL
382 && has_proper_scope_for_analysis (t))
385 bitmap_set_bit (local->statics_written, DECL_UID (t));
386 /* Mark the write so we can tell which statics are
388 if (module_statics_written)
389 bitmap_set_bit (module_statics_written, DECL_UID (t));
394 /* Look for memory clobber and set read_all/write_all if present. */
397 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt)
402 for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
404 op = gimple_asm_clobber_op (stmt, i);
405 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
407 /* Abandon all hope, ye who enter here. */
408 local->calls_read_all = true;
409 local->calls_write_all = true;
414 /* Look for external calls and set read_all/write_all correspondingly. */
417 check_call (ipa_reference_local_vars_info_t local, gimple stmt)
419 int flags = gimple_call_flags (stmt);
420 tree callee_t = gimple_call_fndecl (stmt);
422 /* Process indirect calls. All direct calles are handled at propagation
426 if (flags & ECF_CONST)
428 else if (flags & ECF_PURE)
429 local->calls_read_all = true;
432 local->calls_read_all = true;
433 /* When function does not reutrn, it is safe to ignore anythign it writes
434 to, because the effect will never happen. */
435 if ((flags & (ECF_NOTHROW | ECF_NORETURN))
436 != (ECF_NOTHROW | ECF_NORETURN))
437 local->calls_write_all = true;
442 /* TP is the part of the tree currently under the microscope.
443 WALK_SUBTREES is part of the walk_tree api but is unused here.
444 DATA is cgraph_node of the function being walked. */
447 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
448 struct cgraph_node *fn)
450 gimple stmt = gsi_stmt (*gsip);
451 ipa_reference_local_vars_info_t local = NULL;
453 if (is_gimple_debug (stmt))
457 local = get_reference_vars_info (fn)->local;
459 /* Look for direct loads and stores. */
460 walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store,
463 if (is_gimple_call (stmt))
464 check_call (local, stmt);
465 else if (gimple_code (stmt) == GIMPLE_ASM)
466 check_asm_memory_clobber (local, stmt);
471 /* Call-back to scan variable initializers for static references.
472 Called using walk_tree. */
475 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees,
476 void *data ATTRIBUTE_UNUSED)
480 if (TREE_CODE (t) == ADDR_EXPR)
482 mark_address_taken (get_base_var (t));
485 /* Save some cycles by not walking types and declaration as we
486 won't find anything useful there anyway. */
487 else if (IS_TYPE_OR_DECL_P (*tp))
493 /* Lookup the tree node for the static variable that has UID. */
495 get_static_decl (int index)
497 splay_tree_node stn =
498 splay_tree_lookup (reference_vars_to_consider, index);
500 return (tree)stn->value;
504 /* Lookup the tree node for the static variable that has UID and
505 convert the name to a string for debugging. */
508 get_static_name (int index)
510 splay_tree_node stn =
511 splay_tree_lookup (reference_vars_to_consider, index);
513 return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
517 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
518 bit vector. There are several cases to check to avoid the sparse
522 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
524 struct cgraph_edge *e;
525 for (e = x->callees; e; e = e->next_callee)
527 struct cgraph_node *y = e->callee;
529 /* Only look into nodes we can propagate something. */
530 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
532 if (get_reference_vars_info (y))
534 ipa_reference_vars_info_t y_info
535 = get_reference_vars_info (y);
536 ipa_reference_global_vars_info_t y_global = y_info->global;
538 /* Calls in current cycle do not have global computed yet. */
542 if (x_global->statics_read
543 != all_module_statics)
545 if (y_global->statics_read
546 == all_module_statics)
548 BITMAP_FREE (x_global->statics_read);
549 x_global->statics_read
550 = all_module_statics;
552 /* Skip bitmaps that are pointer equal to node's bitmap
553 (no reason to spin within the cycle). */
554 else if (x_global->statics_read
555 != y_global->statics_read)
556 bitmap_ior_into (x_global->statics_read,
557 y_global->statics_read);
560 if (x_global->statics_written
561 != all_module_statics)
563 if (y_global->statics_written
564 == all_module_statics)
566 BITMAP_FREE (x_global->statics_written);
567 x_global->statics_written
568 = all_module_statics;
570 /* Skip bitmaps that are pointer equal to node's bitmap
571 (no reason to spin within the cycle). */
572 else if (x_global->statics_written
573 != y_global->statics_written)
574 bitmap_ior_into (x_global->statics_written,
575 y_global->statics_written);
584 /* The init routine for analyzing global static variable usage. See
585 comments at top for description. */
589 static bool init_p = false;
596 memory_identifier_string = build_string(7, "memory");
598 reference_vars_to_consider =
599 splay_tree_new_ggc (splay_tree_compare_ints);
601 bitmap_obstack_initialize (&local_info_obstack);
602 bitmap_obstack_initialize (&global_info_obstack);
603 module_statics_escape = BITMAP_ALLOC (&local_info_obstack);
604 module_statics_written = BITMAP_ALLOC (&local_info_obstack);
605 all_module_statics = BITMAP_ALLOC (&global_info_obstack);
607 /* There are some shared nodes, in particular the initializers on
608 static declarations. We do not need to scan them more than once
609 since all we would be interested in are the addressof
611 visited_nodes = pointer_set_create ();
613 function_insertion_hook_holder =
614 cgraph_add_function_insertion_hook (&add_new_function, NULL);
615 node_removal_hook_holder =
616 cgraph_add_node_removal_hook (&remove_node_data, NULL);
617 node_duplication_hook_holder =
618 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
621 /* Check out the rhs of a static or global initialization VNODE to see
622 if any of them contain addressof operations. Note that some of
623 these variables may not even be referenced in the code in this
624 compilation unit but their right hand sides may contain references
625 to variables defined within this unit. */
628 analyze_variable (struct varpool_node *vnode)
630 struct walk_stmt_info wi;
631 tree global = vnode->decl;
633 memset (&wi, 0, sizeof (wi));
634 wi.pset = visited_nodes;
635 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs,
640 /* Set up the persistent info for FN. */
642 static ipa_reference_local_vars_info_t
643 init_function_info (struct cgraph_node *fn)
645 ipa_reference_vars_info_t info
646 = XCNEW (struct ipa_reference_vars_info_d);
647 ipa_reference_local_vars_info_t l
648 = XCNEW (struct ipa_reference_local_vars_info_d);
650 /* Add the info to the tree's annotation. */
651 set_reference_vars_info (fn, info);
654 l->statics_read = BITMAP_ALLOC (&local_info_obstack);
655 l->statics_written = BITMAP_ALLOC (&local_info_obstack);
661 /* This is the main routine for finding the reference patterns for
662 global variables within a function FN. */
665 analyze_function (struct cgraph_node *fn)
667 tree decl = fn->decl;
668 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
669 basic_block this_block;
670 #ifdef ENABLE_CHECKING
673 ipa_reference_local_vars_info_t local;
676 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
678 push_cfun (DECL_STRUCT_FUNCTION (decl));
679 current_function_decl = decl;
681 init_function_info (fn);
682 FOR_EACH_BB_FN (this_block, this_cfun)
684 gimple_stmt_iterator gsi;
690 /* Find the addresses taken in phi node arguments. */
691 for (gsi = gsi_start_phis (this_block);
695 phi = gsi_stmt (gsi);
696 FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
698 op = USE_FROM_PTR (use);
699 if (TREE_CODE (op) == ADDR_EXPR)
700 mark_address_taken (get_base_var (op));
704 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
705 scan_stmt_for_static_refs (&gsi, fn);
708 local = get_reference_vars_info (fn)->local;
709 if ((flags_from_decl_or_type (decl) & (ECF_NOTHROW | ECF_NORETURN))
710 == (ECF_NOTHROW | ECF_NORETURN))
712 local->calls_write_all = false;
713 bitmap_clear (local->statics_written);
716 /* Free bitmaps of direct references if we can not use them anyway. */
717 if (local->calls_write_all)
718 BITMAP_FREE (local->statics_written);
719 if (local->calls_read_all)
720 BITMAP_FREE (local->statics_read);
723 #ifdef ENABLE_CHECKING
724 /* Verify that all local initializers was expanded by gimplifier. */
725 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls;
727 step = TREE_CHAIN (step))
729 tree var = TREE_VALUE (step);
730 if (TREE_CODE (var) == VAR_DECL
731 && DECL_INITIAL (var)
732 && !TREE_STATIC (var))
737 current_function_decl = NULL;
740 /* Remove local data associated with function FN. */
742 clean_function_local_data (struct cgraph_node *fn)
744 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
745 ipa_reference_local_vars_info_t l = info->local;
749 && l->statics_read != all_module_statics)
750 BITMAP_FREE (l->statics_read);
751 if (l->statics_written
752 &&l->statics_written != all_module_statics)
753 BITMAP_FREE (l->statics_written);
759 /* Remove all data associated with function FN. */
762 clean_function (struct cgraph_node *fn)
764 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
765 ipa_reference_global_vars_info_t g = info->global;
767 clean_function_local_data (fn);
771 && g->statics_read != all_module_statics)
772 BITMAP_FREE (g->statics_read);
774 if (g->statics_written
775 && g->statics_written != all_module_statics)
776 BITMAP_FREE (g->statics_written);
778 if (g->statics_not_read
779 && g->statics_not_read != all_module_statics)
780 BITMAP_FREE (g->statics_not_read);
782 if (g->statics_not_written
783 && g->statics_not_written != all_module_statics)
784 BITMAP_FREE (g->statics_not_written);
789 free (get_reference_vars_info (fn));
790 set_reference_vars_info (fn, NULL);
793 /* Called when new function is inserted to callgraph late. */
795 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
797 /* There are some shared nodes, in particular the initializers on
798 static declarations. We do not need to scan them more than once
799 since all we would be interested in are the addressof
801 analyze_function (node);
802 visited_nodes = NULL;
806 copy_local_bitmap (bitmap src)
811 if (src == all_module_statics)
812 return all_module_statics;
813 dst = BITMAP_ALLOC (&local_info_obstack);
814 bitmap_copy (dst, src);
819 copy_global_bitmap (bitmap src)
824 if (src == all_module_statics)
825 return all_module_statics;
826 dst = BITMAP_ALLOC (&global_info_obstack);
827 bitmap_copy (dst, src);
831 /* Called when new clone is inserted to callgraph late. */
834 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
835 void *data ATTRIBUTE_UNUSED)
837 ipa_reference_global_vars_info_t ginfo;
838 ipa_reference_local_vars_info_t linfo;
839 ipa_reference_global_vars_info_t dst_ginfo;
840 ipa_reference_local_vars_info_t dst_linfo;
842 ginfo = get_global_reference_vars_info (src);
843 linfo = get_local_reference_vars_info (src);
844 if (!linfo && !ginfo)
846 init_function_info (dst);
849 dst_linfo = get_local_reference_vars_info (dst);
850 dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read);
851 dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written);
852 dst_linfo->calls_read_all = linfo->calls_read_all;
853 dst_linfo->calls_write_all = linfo->calls_write_all;
857 get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d);
858 dst_ginfo = get_global_reference_vars_info (dst);
859 dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read);
860 dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written);
861 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
862 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
866 /* Called when node is removed. */
869 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
871 if (get_reference_vars_info (node))
872 clean_function (node);
875 /* Analyze each function in the cgraph to see which global or statics
876 are read or written. */
879 generate_summary (void)
881 struct cgraph_node *node;
882 struct varpool_node *vnode;
885 bitmap module_statics_readonly;
889 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack);
890 bm_temp = BITMAP_ALLOC (&local_info_obstack);
892 /* Process all of the variables first. */
893 FOR_EACH_STATIC_INITIALIZER (vnode)
894 analyze_variable (vnode);
896 /* Process all of the functions next.
898 We do not want to process any of the clones so we check that this
899 is a master clone. However, we do need to process any
900 AVAIL_OVERWRITABLE functions (these are never clones) because
901 they may cause a static variable to escape. The code that can
902 overwrite such a function cannot access the statics because it
903 would not be in the same compilation unit. When the analysis is
904 finished, the computed information of these AVAIL_OVERWRITABLE is
905 replaced with worst case info.
907 for (node = cgraph_nodes; node; node = node->next)
908 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
909 analyze_function (node);
911 pointer_set_destroy (visited_nodes);
912 visited_nodes = NULL;
914 /* Prune out the variables that were found to behave badly
915 (i.e. have their address taken). */
916 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
918 splay_tree_remove (reference_vars_to_consider, index);
921 bitmap_and_compl_into (all_module_statics,
922 module_statics_escape);
924 bitmap_and_compl (module_statics_readonly, all_module_statics,
925 module_statics_written);
927 /* If the address is not taken, we can unset the addressable bit
929 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
931 tree var = get_static_decl (index);
932 TREE_ADDRESSABLE (var) = 0;
934 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
935 get_static_name (index));
938 /* If the variable is never written, we can set the TREE_READONLY
939 flag. Additionally if it has a DECL_INITIAL that is made up of
940 constants we can treat the entire global as a constant. */
942 bitmap_and_compl (module_statics_readonly, all_module_statics,
943 module_statics_written);
944 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
946 tree var = get_static_decl (index);
948 /* Ignore variables in named sections - changing TREE_READONLY
949 changes the section flags, potentially causing conflicts with
950 other variables in the same named section. */
951 if (DECL_SECTION_NAME (var) == NULL_TREE)
953 TREE_READONLY (var) = 1;
955 fprintf (dump_file, "read-only var %s\n",
956 get_static_name (index));
960 BITMAP_FREE(module_statics_escape);
961 BITMAP_FREE(module_statics_written);
962 module_statics_escape = NULL;
963 module_statics_written = NULL;
966 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
968 fprintf (dump_file, "\nPromotable global:%s",
969 get_static_name (index));
972 for (node = cgraph_nodes; node; node = node->next)
973 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
975 ipa_reference_local_vars_info_t l;
976 l = get_reference_vars_info (node)->local;
978 /* Any variables that are not in all_module_statics are
979 removed from the local maps. This will include all of the
980 variables that were found to escape in the function
983 bitmap_and_into (l->statics_read,
985 if (l->statics_written)
986 bitmap_and_into (l->statics_written,
990 BITMAP_FREE(module_statics_readonly);
991 BITMAP_FREE(bm_temp);
994 for (node = cgraph_nodes; node; node = node->next)
995 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
997 ipa_reference_local_vars_info_t l;
1001 l = get_reference_vars_info (node)->local;
1003 "\nFunction name:%s/%i:",
1004 cgraph_node_name (node), node->uid);
1005 fprintf (dump_file, "\n locals read: ");
1006 if (l->statics_read)
1007 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
1010 fprintf (dump_file, "%s ",
1011 get_static_name (index));
1013 fprintf (dump_file, "\n locals written: ");
1014 if (l->statics_written)
1015 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
1018 fprintf(dump_file, "%s ",
1019 get_static_name (index));
1021 if (l->calls_read_all)
1022 fprintf (dump_file, "\n calls read all: ");
1023 if (l->calls_write_all)
1024 fprintf (dump_file, "\n calls read all: ");
1029 /* Return true if we need to write summary of NODE. */
1032 write_node_summary_p (struct cgraph_node *node)
1034 gcc_assert (node->global.inlined_to == NULL);
1035 return (node->analyzed
1036 && cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE
1037 && get_reference_vars_info (node) != NULL);
1040 /* Serialize the ipa info for lto. */
1043 ipa_reference_write_summary (cgraph_node_set set,
1044 varpool_node_set vset ATTRIBUTE_UNUSED)
1046 struct cgraph_node *node;
1047 struct lto_simple_output_block *ob
1048 = lto_create_simple_output_block (LTO_section_ipa_reference);
1049 unsigned int count = 0;
1050 cgraph_node_set_iterator csi;
1052 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
1053 if (write_node_summary_p (csi_node (csi)))
1056 lto_output_uleb128_stream (ob->main_stream, count);
1058 /* Process all of the functions. */
1059 for (csi = csi_start (set); !csi_end_p (csi); csi_next (&csi))
1061 node = csi_node (csi);
1062 if (write_node_summary_p (node))
1064 ipa_reference_local_vars_info_t l
1065 = get_reference_vars_info (node)->local;
1068 lto_cgraph_encoder_t encoder;
1071 encoder = ob->decl_state->cgraph_node_encoder;
1072 node_ref = lto_cgraph_encoder_encode (encoder, node);
1073 lto_output_uleb128_stream (ob->main_stream, node_ref);
1075 /* Stream out the statics read. */
1076 if (l->calls_read_all)
1077 lto_output_sleb128_stream (ob->main_stream, -1);
1080 lto_output_sleb128_stream (ob->main_stream,
1081 bitmap_count_bits (l->statics_read));
1082 EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 0, index, bi)
1083 lto_output_var_decl_index(ob->decl_state, ob->main_stream,
1084 get_static_decl (index));
1087 /* Stream out the statics written. */
1088 if (l->calls_write_all)
1089 lto_output_sleb128_stream (ob->main_stream, -1);
1092 lto_output_sleb128_stream (ob->main_stream,
1093 bitmap_count_bits (l->statics_written));
1094 EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 0, index, bi)
1095 lto_output_var_decl_index(ob->decl_state, ob->main_stream,
1096 get_static_decl (index));
1100 lto_destroy_simple_output_block (ob);
1104 /* Deserialize the ipa info for lto. */
1107 ipa_reference_read_summary (void)
1109 struct lto_file_decl_data ** file_data_vec
1110 = lto_get_file_decl_data ();
1111 struct lto_file_decl_data * file_data;
1116 while ((file_data = file_data_vec[j++]))
1120 struct lto_input_block *ib
1121 = lto_create_simple_input_block (file_data,
1122 LTO_section_ipa_reference,
1127 unsigned int f_count = lto_input_uleb128 (ib);
1129 for (i = 0; i < f_count; i++)
1131 unsigned int j, index;
1132 struct cgraph_node *node;
1133 ipa_reference_local_vars_info_t l;
1135 lto_cgraph_encoder_t encoder;
1137 index = lto_input_uleb128 (ib);
1138 encoder = file_data->cgraph_node_encoder;
1139 node = lto_cgraph_encoder_deref (encoder, index);
1140 l = init_function_info (node);
1142 /* Set the statics read. */
1143 v_count = lto_input_sleb128 (ib);
1145 l->calls_read_all = true;
1147 for (j = 0; j < (unsigned int)v_count; j++)
1149 unsigned int var_index = lto_input_uleb128 (ib);
1150 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1152 add_static_var (v_decl);
1153 bitmap_set_bit (l->statics_read, DECL_UID (v_decl));
1156 /* Set the statics written. */
1157 v_count = lto_input_sleb128 (ib);
1159 l->calls_write_all = true;
1161 for (j = 0; j < (unsigned int)v_count; j++)
1163 unsigned int var_index = lto_input_uleb128 (ib);
1164 tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1166 add_static_var (v_decl);
1167 bitmap_set_bit (l->statics_written, DECL_UID (v_decl));
1171 lto_destroy_simple_input_block (file_data,
1172 LTO_section_ipa_reference,
1180 /* Set READ_ALL/WRITE_ALL based on DECL flags. */
1182 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all)
1184 int flags = flags_from_decl_or_type (decl);
1185 if (flags & ECF_CONST)
1187 else if (flags & ECF_PURE)
1191 /* TODO: To be able to produce sane results, we should also handle
1192 common builtins, in particular throw.
1193 Indirect calls hsould be only counted and as inliner is replacing them
1194 by direct calls, we can conclude if any indirect calls are left in body */
1196 /* When function does not reutrn, it is safe to ignore anythign it writes
1197 to, because the effect will never happen. */
1198 if ((flags & (ECF_NOTHROW | ECF_NORETURN))
1199 != (ECF_NOTHROW | ECF_NORETURN))
1204 /* Produce the global information by preforming a transitive closure
1205 on the local information that was produced by ipa_analyze_function
1206 and ipa_analyze_variable. */
1211 struct cgraph_node *node;
1212 struct cgraph_node *w;
1213 struct cgraph_node **order =
1214 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
1215 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
1218 cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
1220 dump_cgraph (dump_file);
1222 /* Propagate the local information thru the call graph to produce
1223 the global information. All the nodes within a cycle will have
1224 the same info so we collapse cycles first. Then we can do the
1225 propagation in one pass from the leaves to the roots. */
1226 order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
1228 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1230 for (i = 0; i < order_pos; i++ )
1232 ipa_reference_vars_info_t node_info;
1233 ipa_reference_global_vars_info_t node_g =
1234 XCNEW (struct ipa_reference_global_vars_info_d);
1235 ipa_reference_local_vars_info_t node_l;
1236 struct cgraph_edge *e;
1240 struct ipa_dfs_info * w_info;
1243 node_info = get_reference_vars_info (node);
1246 dump_cgraph_node (stderr, node);
1247 dump_cgraph (stderr);
1251 gcc_assert (!node_info->global);
1252 node_l = node_info->local;
1254 read_all = node_l->calls_read_all;
1255 write_all = node_l->calls_write_all;
1257 /* When function is overwrittable, we can not assume anything. */
1258 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
1259 read_write_all_from_decl (node->decl, &read_all, &write_all);
1261 for (e = node->callees; e; e = e->next_callee)
1262 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
1263 read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
1266 /* If any node in a cycle is calls_read_all or calls_write_all
1268 w_info = (struct ipa_dfs_info *) node->aux;
1269 w = w_info->next_cycle;
1272 ipa_reference_local_vars_info_t w_l =
1273 get_reference_vars_info (w)->local;
1275 /* When function is overwrittable, we can not assume anything. */
1276 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
1277 read_write_all_from_decl (w->decl, &read_all, &write_all);
1279 for (e = w->callees; e; e = e->next_callee)
1280 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
1281 read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
1283 read_all |= w_l->calls_read_all;
1284 write_all |= w_l->calls_write_all;
1286 w_info = (struct ipa_dfs_info *) w->aux;
1287 w = w_info->next_cycle;
1291 /* Initialized the bitmaps for the reduced nodes */
1293 node_g->statics_read = all_module_statics;
1296 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack);
1297 bitmap_copy (node_g->statics_read,
1298 node_l->statics_read);
1301 node_g->statics_written = all_module_statics;
1304 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack);
1305 bitmap_copy (node_g->statics_written,
1306 node_l->statics_written);
1309 propagate_bits (node_g, node);
1310 w_info = (struct ipa_dfs_info *) node->aux;
1311 w = w_info->next_cycle;
1314 ipa_reference_vars_info_t w_ri =
1315 get_reference_vars_info (w);
1316 ipa_reference_local_vars_info_t w_l = w_ri->local;
1318 /* These global bitmaps are initialized from the local info
1319 of all of the nodes in the region. However there is no
1320 need to do any work if the bitmaps were set to
1321 all_module_statics. */
1323 bitmap_ior_into (node_g->statics_read,
1326 bitmap_ior_into (node_g->statics_written,
1327 w_l->statics_written);
1328 propagate_bits (node_g, w);
1329 w_info = (struct ipa_dfs_info *) w->aux;
1330 w = w_info->next_cycle;
1333 /* All nodes within a cycle have the same global info bitmaps. */
1334 node_info->global = node_g;
1335 w_info = (struct ipa_dfs_info *) node->aux;
1336 w = w_info->next_cycle;
1339 ipa_reference_vars_info_t w_ri =
1340 get_reference_vars_info (w);
1342 gcc_assert (!w_ri->global);
1343 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d);
1344 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read);
1345 w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written);
1347 w_info = (struct ipa_dfs_info *) w->aux;
1348 w = w_info->next_cycle;
1354 for (i = 0; i < order_pos; i++ )
1356 ipa_reference_vars_info_t node_info;
1357 ipa_reference_global_vars_info_t node_g;
1358 ipa_reference_local_vars_info_t node_l;
1361 struct ipa_dfs_info * w_info;
1364 node_info = get_reference_vars_info (node);
1365 node_g = node_info->global;
1366 node_l = node_info->local;
1368 "\nFunction name:%s/%i:",
1369 cgraph_node_name (node), node->uid);
1370 fprintf (dump_file, "\n locals read: ");
1371 if (node_l->statics_read)
1372 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1375 fprintf (dump_file, "%s ",
1376 get_static_name (index));
1378 fprintf (dump_file, "\n locals written: ");
1379 if (node_l->statics_written)
1380 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1383 fprintf(dump_file, "%s ",
1384 get_static_name (index));
1387 w_info = (struct ipa_dfs_info *) node->aux;
1388 w = w_info->next_cycle;
1391 ipa_reference_vars_info_t w_ri =
1392 get_reference_vars_info (w);
1393 ipa_reference_local_vars_info_t w_l = w_ri->local;
1394 fprintf (dump_file, "\n next cycle: %s/%i ",
1395 cgraph_node_name (w), w->uid);
1396 fprintf (dump_file, "\n locals read: ");
1397 if (w_l->statics_read)
1398 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1401 fprintf (dump_file, "%s ",
1402 get_static_name (index));
1405 fprintf (dump_file, "\n locals written: ");
1406 if (w_l->statics_written)
1407 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1410 fprintf (dump_file, "%s ",
1411 get_static_name (index));
1414 w_info = (struct ipa_dfs_info *) w->aux;
1415 w = w_info->next_cycle;
1417 fprintf (dump_file, "\n globals read: ");
1418 if (node_g->statics_read == all_module_statics)
1419 fprintf (dump_file, "ALL");
1421 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1424 fprintf (dump_file, "%s ",
1425 get_static_name (index));
1427 fprintf (dump_file, "\n globals written: ");
1428 if (node_g->statics_written == all_module_statics)
1429 fprintf (dump_file, "ALL");
1431 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1434 fprintf (dump_file, "%s ",
1435 get_static_name (index));
1441 for (i = 0; i < order_pos; i++ )
1443 ipa_reference_vars_info_t node_info;
1444 ipa_reference_global_vars_info_t node_g;
1446 node_info = get_reference_vars_info (node);
1447 node_g = node_info->global;
1449 /* Create the complimentary sets. These are more useful for
1451 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack);
1452 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack);
1454 if (node_g->statics_read != all_module_statics)
1455 bitmap_and_compl (node_g->statics_not_read,
1457 node_g->statics_read);
1459 if (node_g->statics_written
1460 != all_module_statics)
1461 bitmap_and_compl (node_g->statics_not_written,
1463 node_g->statics_written);
1468 for (node = cgraph_nodes; node; node = node->next)
1470 ipa_reference_vars_info_t node_info;
1471 node_info = get_reference_vars_info (node);
1472 /* Get rid of the aux information. */
1480 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)
1481 clean_function (node);
1483 clean_function_local_data (node);
1485 bitmap_obstack_release (&local_info_obstack);
1491 gate_reference (void)
1493 return (flag_ipa_reference
1494 /* Don't bother doing anything if the program has errors. */
1495 && !(errorcount || sorrycount));
1498 struct ipa_opt_pass_d pass_ipa_reference =
1502 "static-var", /* name */
1503 gate_reference, /* gate */
1504 propagate, /* execute */
1507 0, /* static_pass_number */
1508 TV_IPA_REFERENCE, /* tv_id */
1509 0, /* properties_required */
1510 0, /* properties_provided */
1511 0, /* properties_destroyed */
1512 0, /* todo_flags_start */
1513 0 /* todo_flags_finish */
1515 generate_summary, /* generate_summary */
1516 ipa_reference_write_summary, /* write_summary */
1517 ipa_reference_read_summary, /* read_summary */
1518 NULL, /* write_optimization_summary */
1519 NULL, /* read_optimization_summary */
1520 NULL, /* stmt_fixup */
1522 NULL, /* function_transform */
1523 NULL /* variable_transform */
1526 #include "gt-ipa-reference.h"