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 The transitive call site specific clobber effects are computed
26 for the variables whose scope is contained within this compilation
29 First each function and static variable initialization is analyzed
30 to determine which local static variables are either read, written,
31 or have their address taken. Any local static that has its address
32 taken is removed from consideration. Once the local read and
33 writes are determined, a transitive closure of this information is
34 performed over the call graph to determine the worst case set of
35 side effects of each call. In later parts of the compiler, these
36 local and global sets are examined to make the call clobbering less
37 traumatic, promote some statics to registers, and improve aliasing
42 #include "coretypes.h"
45 #include "tree-flow.h"
46 #include "tree-inline.h"
47 #include "tree-pass.h"
48 #include "langhooks.h"
49 #include "pointer-set.h"
50 #include "splay-tree.h"
52 #include "ipa-utils.h"
53 #include "ipa-reference.h"
59 #include "diagnostic.h"
60 #include "langhooks.h"
61 #include "lto-streamer.h"
63 static void remove_node_data (struct cgraph_node
*node
,
64 void *data ATTRIBUTE_UNUSED
);
65 static void duplicate_node_data (struct cgraph_node
*src
,
66 struct cgraph_node
*dst
,
67 void *data ATTRIBUTE_UNUSED
);
69 /* The static variables defined within the compilation unit that are
70 loaded or stored directly by function that owns this structure. */
72 struct ipa_reference_local_vars_info_d
75 bitmap statics_written
;
77 /* Set when this function calls another function external to the
78 compilation unit or if the function has a asm clobber of memory.
79 In general, such calls are modeled as reading and writing all
80 variables (both bits on) but sometime there are attributes on the
81 called function so we can do better. */
86 /* Statics that are read and written by some set of functions. The
87 local ones are based on the loads and stores local to the function.
88 The global ones are based on the local info as well as the
89 transitive closure of the functions that are called. The
90 structures are separated to allow the global structures to be
91 shared between several functions since every function within a
92 strongly connected component will have the same information. This
93 sharing saves both time and space in the computation of the vectors
94 as well as their translation from decl_uid form to ann_uid
97 struct ipa_reference_global_vars_info_d
100 bitmap statics_written
;
101 bitmap statics_not_read
;
102 bitmap statics_not_written
;
105 typedef struct ipa_reference_local_vars_info_d
*ipa_reference_local_vars_info_t
;
106 typedef struct ipa_reference_global_vars_info_d
*ipa_reference_global_vars_info_t
;
107 struct ipa_reference_vars_info_d
109 ipa_reference_local_vars_info_t local
;
110 ipa_reference_global_vars_info_t 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. For
117 module_at_a_time compilation, this is the set of static but not
118 public variables. Any variables that either have their address
119 taken or participate in otherwise unsavory operations are deleted
121 static GTY((param1_is(int), param2_is(tree
)))
122 splay_tree reference_vars_to_consider
;
124 /* This bitmap is used to knock out the module static variables whose
125 addresses have been taken and passed around. */
126 static bitmap module_statics_escape
;
128 /* A bit is set for every module static we are considering. This is
129 ored into the local info when asm code is found that clobbers all
131 static bitmap all_module_statics
;
133 /* Obstack holding bitmaps of local analysis (live from analysis to
135 static bitmap_obstack local_info_obstack
;
136 /* Obstack holding global analysis live forever. */
137 static bitmap_obstack global_info_obstack
;
139 /* Holders of ipa cgraph hooks: */
140 static struct cgraph_2node_hook_list
*node_duplication_hook_holder
;
141 static struct cgraph_node_hook_list
*node_removal_hook_holder
;
143 enum initialization_status_t
150 tree memory_identifier_string
;
152 /* Vector where the reference var infos are actually stored. */
153 DEF_VEC_P (ipa_reference_vars_info_t
);
154 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t
, heap
);
155 static VEC (ipa_reference_vars_info_t
, heap
) *ipa_reference_vars_vector
;
157 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
158 static inline ipa_reference_vars_info_t
159 get_reference_vars_info (struct cgraph_node
*node
)
161 if (!ipa_reference_vars_vector
162 || VEC_length (ipa_reference_vars_info_t
, ipa_reference_vars_vector
) <= (unsigned int)node
->uid
)
164 return VEC_index (ipa_reference_vars_info_t
, ipa_reference_vars_vector
, node
->uid
);
167 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
169 set_reference_vars_info (struct cgraph_node
*node
, ipa_reference_vars_info_t info
)
171 if (!ipa_reference_vars_vector
172 || VEC_length (ipa_reference_vars_info_t
, ipa_reference_vars_vector
) <= (unsigned int)node
->uid
)
173 VEC_safe_grow_cleared (ipa_reference_vars_info_t
, heap
, ipa_reference_vars_vector
, node
->uid
+ 1);
174 VEC_replace (ipa_reference_vars_info_t
, ipa_reference_vars_vector
, node
->uid
, info
);
177 /* Get a bitmap that contains all of the globally referenced static
178 variables for function FN. */
180 static ipa_reference_global_vars_info_t
181 get_global_reference_vars_info (struct cgraph_node
*fn
)
183 ipa_reference_vars_info_t info
= get_reference_vars_info (fn
);
188 /* This phase was not run. */
192 /* Return a bitmap indexed by VAR_DECL uid for the static variables
193 that are read during the execution of the function FN. Returns
194 NULL if no data is available. */
197 ipa_reference_get_read_global (struct cgraph_node
*fn
)
199 ipa_reference_global_vars_info_t g
= get_global_reference_vars_info (fn
);
201 return g
->statics_read
;
206 /* Return a bitmap indexed by VAR_DECL uid for the static variables
207 that are 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_written_global (struct cgraph_node
*fn
)
214 ipa_reference_global_vars_info_t g
= get_global_reference_vars_info (fn
);
216 return g
->statics_written
;
221 /* Return a bitmap indexed by_DECL_UID uid for the static variables
222 that are not read during the execution of the function FN. Returns
223 NULL if no data is available. */
226 ipa_reference_get_not_read_global (struct cgraph_node
*fn
)
228 ipa_reference_global_vars_info_t g
= get_global_reference_vars_info (fn
);
230 return g
->statics_not_read
;
235 /* Return a bitmap indexed by DECL_UID uid for the static variables
236 that are not written during the execution of the function FN. Note
237 that variables written may or may not be read during the function
238 call. Returns NULL if no data is available. */
241 ipa_reference_get_not_written_global (struct cgraph_node
*fn
)
243 ipa_reference_global_vars_info_t g
= get_global_reference_vars_info (fn
);
245 return g
->statics_not_written
;
252 /* Add VAR to all_module_statics and the two
253 reference_vars_to_consider* sets. */
256 add_static_var (tree var
)
258 int uid
= DECL_UID (var
);
259 gcc_assert (TREE_CODE (var
) == VAR_DECL
);
260 if (!bitmap_bit_p (all_module_statics
, uid
))
262 splay_tree_insert (reference_vars_to_consider
,
263 uid
, (splay_tree_value
)var
);
264 bitmap_set_bit (all_module_statics
, uid
);
268 /* Return true if the variable T is the right kind of static variable to
269 perform compilation unit scope escape analysis. */
272 is_proper_for_analysis (tree t
)
274 /* If the variable has the "used" attribute, treat it as if it had a
275 been touched by the devil. */
276 if (DECL_PRESERVE_P (t
))
279 /* Do not want to do anything with volatile except mark any
280 function that uses one to be not const or pure. */
281 if (TREE_THIS_VOLATILE (t
))
284 /* We cannot touch decls where the type needs constructing. */
285 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t
)))
288 /* This is a variable we care about. Check if we have seen it
289 before, and if not add it the set of variables we care about. */
290 if (!bitmap_bit_p (all_module_statics
, DECL_UID (t
)))
296 /* Lookup the tree node for the static variable that has UID and
297 convert the name to a string for debugging. */
300 get_static_name (int index
)
302 splay_tree_node stn
=
303 splay_tree_lookup (reference_vars_to_consider
, index
);
305 return lang_hooks
.decl_printable_name ((tree
)(stn
->value
), 2);
309 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
310 bit vector. There are several cases to check to avoid the sparse
314 propagate_bits (ipa_reference_global_vars_info_t x_global
, struct cgraph_node
*x
)
316 struct cgraph_edge
*e
;
317 for (e
= x
->callees
; e
; e
= e
->next_callee
)
319 struct cgraph_node
*y
= e
->callee
;
321 /* Only look into nodes we can propagate something. */
322 if (cgraph_function_body_availability (e
->callee
) > AVAIL_OVERWRITABLE
)
324 if (get_reference_vars_info (y
))
326 ipa_reference_vars_info_t y_info
327 = get_reference_vars_info (y
);
328 ipa_reference_global_vars_info_t y_global
= y_info
->global
;
330 /* Calls in current cycle do not have global computed yet. */
334 if (x_global
->statics_read
335 != all_module_statics
)
337 if (y_global
->statics_read
338 == all_module_statics
)
340 BITMAP_FREE (x_global
->statics_read
);
341 x_global
->statics_read
342 = all_module_statics
;
344 /* Skip bitmaps that are pointer equal to node's bitmap
345 (no reason to spin within the cycle). */
346 else if (x_global
->statics_read
347 != y_global
->statics_read
)
348 bitmap_ior_into (x_global
->statics_read
,
349 y_global
->statics_read
);
352 if (x_global
->statics_written
353 != all_module_statics
)
355 if (y_global
->statics_written
356 == all_module_statics
)
358 BITMAP_FREE (x_global
->statics_written
);
359 x_global
->statics_written
360 = all_module_statics
;
362 /* Skip bitmaps that are pointer equal to node's bitmap
363 (no reason to spin within the cycle). */
364 else if (x_global
->statics_written
365 != y_global
->statics_written
)
366 bitmap_ior_into (x_global
->statics_written
,
367 y_global
->statics_written
);
376 /* The init routine for analyzing global static variable usage. See
377 comments at top for description. */
381 static bool init_p
= false;
388 memory_identifier_string
= build_string(7, "memory");
390 reference_vars_to_consider
=
391 splay_tree_new_ggc (splay_tree_compare_ints
);
393 bitmap_obstack_initialize (&local_info_obstack
);
394 bitmap_obstack_initialize (&global_info_obstack
);
395 module_statics_escape
= BITMAP_ALLOC (&local_info_obstack
);
396 all_module_statics
= BITMAP_ALLOC (&global_info_obstack
);
398 node_removal_hook_holder
=
399 cgraph_add_node_removal_hook (&remove_node_data
, NULL
);
400 node_duplication_hook_holder
=
401 cgraph_add_node_duplication_hook (&duplicate_node_data
, NULL
);
404 /* Check out the rhs of a static or global initialization VNODE to see
405 if any of them contain addressof operations. Note that some of
406 these variables may not even be referenced in the code in this
407 compilation unit but their right hand sides may contain references
408 to variables defined within this unit. */
411 analyze_variable (struct varpool_node
*vnode
)
415 for (i
= 0; ipa_ref_list_reference_iterate (&vnode
->ref_list
, i
, ref
); i
++)
418 if (ref
->refered_type
!= IPA_REF_VARPOOL
)
420 var
= ipa_ref_varpool_node (ref
)->decl
;
421 if (ipa_ref_varpool_node (ref
)->externally_visible
422 || !ipa_ref_varpool_node (ref
)->analyzed
423 || !is_proper_for_analysis (var
))
432 bitmap_set_bit (module_statics_escape
, DECL_UID (var
));
439 /* Set up the persistent info for FN. */
441 static ipa_reference_local_vars_info_t
442 init_function_info (struct cgraph_node
*fn
)
444 ipa_reference_vars_info_t info
445 = XCNEW (struct ipa_reference_vars_info_d
);
446 ipa_reference_local_vars_info_t l
447 = XCNEW (struct ipa_reference_local_vars_info_d
);
449 /* Add the info to the tree's annotation. */
450 set_reference_vars_info (fn
, info
);
453 l
->statics_read
= BITMAP_ALLOC (&local_info_obstack
);
454 l
->statics_written
= BITMAP_ALLOC (&local_info_obstack
);
460 /* This is the main routine for finding the reference patterns for
461 global variables within a function FN. */
464 analyze_function (struct cgraph_node
*fn
)
466 ipa_reference_local_vars_info_t local
;
470 struct cgraph_edge
*ie
;
472 local
= init_function_info (fn
);
473 /* Process indirect calls. All direct calles are handled at propagation
475 for (ie
= fn
->indirect_calls
; ie
; ie
= ie
->next_callee
)
476 if (!(ie
->indirect_info
->ecf_flags
& ECF_CONST
))
478 local
->calls_read_all
= true;
479 if (!(ie
->indirect_info
->ecf_flags
& ECF_PURE
)
480 && ((ie
->indirect_info
->ecf_flags
& (ECF_NOTHROW
| ECF_NORETURN
))
481 != (ECF_NOTHROW
| ECF_NORETURN
)))
482 local
->calls_write_all
= true;
484 for (i
= 0; ipa_ref_list_reference_iterate (&fn
->ref_list
, i
, ref
); i
++)
486 if (ref
->refered_type
!= IPA_REF_VARPOOL
)
488 var
= ipa_ref_varpool_node (ref
)->decl
;
489 if (ipa_ref_varpool_node (ref
)->externally_visible
490 || !ipa_ref_varpool_node (ref
)->analyzed
491 || !is_proper_for_analysis (var
))
496 bitmap_set_bit (local
->statics_read
, DECL_UID (var
));
499 bitmap_set_bit (local
->statics_written
, DECL_UID (var
));
502 bitmap_set_bit (module_statics_escape
, DECL_UID (var
));
507 if ((flags_from_decl_or_type (fn
->decl
) & (ECF_NOTHROW
| ECF_NORETURN
))
508 == (ECF_NOTHROW
| ECF_NORETURN
))
510 local
->calls_write_all
= false;
511 bitmap_clear (local
->statics_written
);
514 /* Free bitmaps of direct references if we can not use them anyway. */
515 if (local
->calls_write_all
)
516 BITMAP_FREE (local
->statics_written
);
517 if (local
->calls_read_all
)
518 BITMAP_FREE (local
->statics_read
);
521 /* Remove local data associated with function FN. */
523 clean_function_local_data (struct cgraph_node
*fn
)
525 ipa_reference_vars_info_t info
= get_reference_vars_info (fn
);
526 ipa_reference_local_vars_info_t l
= info
->local
;
530 && l
->statics_read
!= all_module_statics
)
531 BITMAP_FREE (l
->statics_read
);
532 if (l
->statics_written
533 &&l
->statics_written
!= all_module_statics
)
534 BITMAP_FREE (l
->statics_written
);
540 /* Remove all data associated with function FN. */
543 clean_function (struct cgraph_node
*fn
)
545 ipa_reference_vars_info_t info
= get_reference_vars_info (fn
);
546 ipa_reference_global_vars_info_t g
= info
->global
;
548 clean_function_local_data (fn
);
552 && g
->statics_read
!= all_module_statics
)
553 BITMAP_FREE (g
->statics_read
);
555 if (g
->statics_written
556 && g
->statics_written
!= all_module_statics
)
557 BITMAP_FREE (g
->statics_written
);
559 if (g
->statics_not_read
560 && g
->statics_not_read
!= all_module_statics
)
561 BITMAP_FREE (g
->statics_not_read
);
563 if (g
->statics_not_written
564 && g
->statics_not_written
!= all_module_statics
)
565 BITMAP_FREE (g
->statics_not_written
);
570 free (get_reference_vars_info (fn
));
571 set_reference_vars_info (fn
, NULL
);
575 copy_global_bitmap (bitmap src
)
580 if (src
== all_module_statics
)
581 return all_module_statics
;
582 dst
= BITMAP_ALLOC (&global_info_obstack
);
583 bitmap_copy (dst
, src
);
588 /* Called when new clone is inserted to callgraph late. */
591 duplicate_node_data (struct cgraph_node
*src
, struct cgraph_node
*dst
,
592 void *data ATTRIBUTE_UNUSED
)
594 ipa_reference_global_vars_info_t ginfo
;
595 ipa_reference_global_vars_info_t dst_ginfo
;
597 ginfo
= get_global_reference_vars_info (src
);
600 init_function_info (dst
);
603 get_reference_vars_info (dst
)->global
= XCNEW (struct ipa_reference_global_vars_info_d
);
604 dst_ginfo
= get_global_reference_vars_info (dst
);
605 dst_ginfo
->statics_read
= copy_global_bitmap (ginfo
->statics_read
);
606 dst_ginfo
->statics_written
= copy_global_bitmap (ginfo
->statics_written
);
607 dst_ginfo
->statics_not_read
= copy_global_bitmap (ginfo
->statics_not_read
);
608 dst_ginfo
->statics_not_written
= copy_global_bitmap (ginfo
->statics_not_written
);
612 /* Called when node is removed. */
615 remove_node_data (struct cgraph_node
*node
, void *data ATTRIBUTE_UNUSED
)
617 if (get_reference_vars_info (node
))
618 clean_function (node
);
621 /* Analyze each function in the cgraph to see which global or statics
622 are read or written. */
625 generate_summary (void)
627 struct cgraph_node
*node
;
628 struct varpool_node
*vnode
;
634 bm_temp
= BITMAP_ALLOC (&local_info_obstack
);
636 /* Process all of the variables first. */
637 FOR_EACH_STATIC_INITIALIZER (vnode
)
638 analyze_variable (vnode
);
640 /* Process all of the functions next. */
641 for (node
= cgraph_nodes
; node
; node
= node
->next
)
643 analyze_function (node
);
645 /* Prune out the variables that were found to behave badly
646 (i.e. have their address taken). */
647 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape
, 0, index
, bi
)
649 splay_tree_remove (reference_vars_to_consider
, index
);
652 bitmap_and_compl_into (all_module_statics
,
653 module_statics_escape
);
655 BITMAP_FREE(module_statics_escape
);
656 module_statics_escape
= NULL
;
659 EXECUTE_IF_SET_IN_BITMAP (all_module_statics
, 0, index
, bi
)
661 fprintf (dump_file
, "\nPromotable global:%s",
662 get_static_name (index
));
665 for (node
= cgraph_nodes
; node
; node
= node
->next
)
666 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
668 ipa_reference_local_vars_info_t l
;
669 l
= get_reference_vars_info (node
)->local
;
671 /* Any variables that are not in all_module_statics are
672 removed from the local maps. This will include all of the
673 variables that were found to escape in the function
676 bitmap_and_into (l
->statics_read
,
678 if (l
->statics_written
)
679 bitmap_and_into (l
->statics_written
,
683 BITMAP_FREE(bm_temp
);
686 for (node
= cgraph_nodes
; node
; node
= node
->next
)
687 if (cgraph_function_body_availability (node
) >= AVAIL_OVERWRITABLE
)
689 ipa_reference_local_vars_info_t l
;
693 l
= get_reference_vars_info (node
)->local
;
695 "\nFunction name:%s/%i:",
696 cgraph_node_name (node
), node
->uid
);
697 fprintf (dump_file
, "\n locals read: ");
699 EXECUTE_IF_SET_IN_BITMAP (l
->statics_read
,
702 fprintf (dump_file
, "%s ",
703 get_static_name (index
));
705 fprintf (dump_file
, "\n locals written: ");
706 if (l
->statics_written
)
707 EXECUTE_IF_SET_IN_BITMAP (l
->statics_written
,
710 fprintf(dump_file
, "%s ",
711 get_static_name (index
));
713 if (l
->calls_read_all
)
714 fprintf (dump_file
, "\n calls read all: ");
715 if (l
->calls_write_all
)
716 fprintf (dump_file
, "\n calls read all: ");
720 /* Set READ_ALL/WRITE_ALL based on DECL flags. */
722 read_write_all_from_decl (tree decl
, bool * read_all
, bool * write_all
)
724 int flags
= flags_from_decl_or_type (decl
);
725 if (flags
& ECF_CONST
)
727 else if (flags
& ECF_PURE
)
731 /* TODO: To be able to produce sane results, we should also handle
732 common builtins, in particular throw.
733 Indirect calls hsould be only counted and as inliner is replacing them
734 by direct calls, we can conclude if any indirect calls are left in body */
736 /* When function does not reutrn, it is safe to ignore anythign it writes
737 to, because the effect will never happen. */
738 if ((flags
& (ECF_NOTHROW
| ECF_NORETURN
))
739 != (ECF_NOTHROW
| ECF_NORETURN
))
744 /* Produce the global information by preforming a transitive closure
745 on the local information that was produced by ipa_analyze_function
746 and ipa_analyze_variable. */
751 struct cgraph_node
*node
;
752 struct cgraph_node
*w
;
753 struct cgraph_node
**order
=
754 XCNEWVEC (struct cgraph_node
*, cgraph_n_nodes
);
755 int order_pos
= ipa_utils_reduced_inorder (order
, false, true, NULL
);
759 dump_cgraph (dump_file
);
763 /* Propagate the local information thru the call graph to produce
764 the global information. All the nodes within a cycle will have
765 the same info so we collapse cycles first. Then we can do the
766 propagation in one pass from the leaves to the roots. */
767 order_pos
= ipa_utils_reduced_inorder (order
, true, true, NULL
);
769 ipa_utils_print_order(dump_file
, "reduced", order
, order_pos
);
771 for (i
= 0; i
< order_pos
; i
++ )
773 ipa_reference_vars_info_t node_info
;
774 ipa_reference_global_vars_info_t node_g
=
775 XCNEW (struct ipa_reference_global_vars_info_d
);
776 ipa_reference_local_vars_info_t node_l
;
777 struct cgraph_edge
*e
;
781 struct ipa_dfs_info
* w_info
;
784 node_info
= get_reference_vars_info (node
);
787 dump_cgraph_node (stderr
, node
);
788 dump_cgraph (stderr
);
792 gcc_assert (!node_info
->global
);
793 node_l
= node_info
->local
;
795 read_all
= node_l
->calls_read_all
;
796 write_all
= node_l
->calls_write_all
;
798 /* When function is overwrittable, we can not assume anything. */
799 if (cgraph_function_body_availability (node
) <= AVAIL_OVERWRITABLE
)
800 read_write_all_from_decl (node
->decl
, &read_all
, &write_all
);
802 for (e
= node
->callees
; e
; e
= e
->next_callee
)
803 if (cgraph_function_body_availability (e
->callee
) <= AVAIL_OVERWRITABLE
)
804 read_write_all_from_decl (e
->callee
->decl
, &read_all
, &write_all
);
807 /* If any node in a cycle is calls_read_all or calls_write_all
809 w_info
= (struct ipa_dfs_info
*) node
->aux
;
810 w
= w_info
->next_cycle
;
813 ipa_reference_local_vars_info_t w_l
=
814 get_reference_vars_info (w
)->local
;
816 /* When function is overwrittable, we can not assume anything. */
817 if (cgraph_function_body_availability (w
) <= AVAIL_OVERWRITABLE
)
818 read_write_all_from_decl (w
->decl
, &read_all
, &write_all
);
820 for (e
= w
->callees
; e
; e
= e
->next_callee
)
821 if (cgraph_function_body_availability (e
->callee
) <= AVAIL_OVERWRITABLE
)
822 read_write_all_from_decl (e
->callee
->decl
, &read_all
, &write_all
);
824 read_all
|= w_l
->calls_read_all
;
825 write_all
|= w_l
->calls_write_all
;
827 w_info
= (struct ipa_dfs_info
*) w
->aux
;
828 w
= w_info
->next_cycle
;
832 /* Initialized the bitmaps for the reduced nodes */
834 node_g
->statics_read
= all_module_statics
;
837 node_g
->statics_read
= BITMAP_ALLOC (&global_info_obstack
);
838 bitmap_copy (node_g
->statics_read
,
839 node_l
->statics_read
);
842 node_g
->statics_written
= all_module_statics
;
845 node_g
->statics_written
= BITMAP_ALLOC (&global_info_obstack
);
846 bitmap_copy (node_g
->statics_written
,
847 node_l
->statics_written
);
850 propagate_bits (node_g
, node
);
851 w_info
= (struct ipa_dfs_info
*) node
->aux
;
852 w
= w_info
->next_cycle
;
855 ipa_reference_vars_info_t w_ri
=
856 get_reference_vars_info (w
);
857 ipa_reference_local_vars_info_t w_l
= w_ri
->local
;
859 /* These global bitmaps are initialized from the local info
860 of all of the nodes in the region. However there is no
861 need to do any work if the bitmaps were set to
862 all_module_statics. */
864 bitmap_ior_into (node_g
->statics_read
,
867 bitmap_ior_into (node_g
->statics_written
,
868 w_l
->statics_written
);
869 propagate_bits (node_g
, w
);
870 w_info
= (struct ipa_dfs_info
*) w
->aux
;
871 w
= w_info
->next_cycle
;
874 /* All nodes within a cycle have the same global info bitmaps. */
875 node_info
->global
= node_g
;
876 w_info
= (struct ipa_dfs_info
*) node
->aux
;
877 w
= w_info
->next_cycle
;
880 ipa_reference_vars_info_t w_ri
=
881 get_reference_vars_info (w
);
883 gcc_assert (!w_ri
->global
);
884 w_ri
->global
= XCNEW (struct ipa_reference_global_vars_info_d
);
885 w_ri
->global
->statics_read
= copy_global_bitmap (node_g
->statics_read
);
886 w_ri
->global
->statics_written
= copy_global_bitmap (node_g
->statics_written
);
888 w_info
= (struct ipa_dfs_info
*) w
->aux
;
889 w
= w_info
->next_cycle
;
895 for (i
= 0; i
< order_pos
; i
++ )
897 ipa_reference_vars_info_t node_info
;
898 ipa_reference_global_vars_info_t node_g
;
899 ipa_reference_local_vars_info_t node_l
;
902 struct ipa_dfs_info
* w_info
;
905 node_info
= get_reference_vars_info (node
);
906 node_g
= node_info
->global
;
907 node_l
= node_info
->local
;
909 "\nFunction name:%s/%i:",
910 cgraph_node_name (node
), node
->uid
);
911 fprintf (dump_file
, "\n locals read: ");
912 if (node_l
->statics_read
)
913 EXECUTE_IF_SET_IN_BITMAP (node_l
->statics_read
,
916 fprintf (dump_file
, "%s ",
917 get_static_name (index
));
919 fprintf (dump_file
, "\n locals written: ");
920 if (node_l
->statics_written
)
921 EXECUTE_IF_SET_IN_BITMAP (node_l
->statics_written
,
924 fprintf(dump_file
, "%s ",
925 get_static_name (index
));
928 w_info
= (struct ipa_dfs_info
*) node
->aux
;
929 w
= w_info
->next_cycle
;
932 ipa_reference_vars_info_t w_ri
=
933 get_reference_vars_info (w
);
934 ipa_reference_local_vars_info_t w_l
= w_ri
->local
;
935 fprintf (dump_file
, "\n next cycle: %s/%i ",
936 cgraph_node_name (w
), w
->uid
);
937 fprintf (dump_file
, "\n locals read: ");
938 if (w_l
->statics_read
)
939 EXECUTE_IF_SET_IN_BITMAP (w_l
->statics_read
,
942 fprintf (dump_file
, "%s ",
943 get_static_name (index
));
946 fprintf (dump_file
, "\n locals written: ");
947 if (w_l
->statics_written
)
948 EXECUTE_IF_SET_IN_BITMAP (w_l
->statics_written
,
951 fprintf (dump_file
, "%s ",
952 get_static_name (index
));
955 w_info
= (struct ipa_dfs_info
*) w
->aux
;
956 w
= w_info
->next_cycle
;
958 fprintf (dump_file
, "\n globals read: ");
959 if (node_g
->statics_read
== all_module_statics
)
960 fprintf (dump_file
, "ALL");
962 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_read
,
965 fprintf (dump_file
, "%s ",
966 get_static_name (index
));
968 fprintf (dump_file
, "\n globals written: ");
969 if (node_g
->statics_written
== all_module_statics
)
970 fprintf (dump_file
, "ALL");
972 EXECUTE_IF_SET_IN_BITMAP (node_g
->statics_written
,
975 fprintf (dump_file
, "%s ",
976 get_static_name (index
));
982 for (i
= 0; i
< order_pos
; i
++ )
984 ipa_reference_vars_info_t node_info
;
985 ipa_reference_global_vars_info_t node_g
;
987 node_info
= get_reference_vars_info (node
);
988 node_g
= node_info
->global
;
990 /* Create the complimentary sets. These are more useful for
992 node_g
->statics_not_read
= BITMAP_ALLOC (&global_info_obstack
);
993 node_g
->statics_not_written
= BITMAP_ALLOC (&global_info_obstack
);
995 if (node_g
->statics_read
!= all_module_statics
)
996 bitmap_and_compl (node_g
->statics_not_read
,
998 node_g
->statics_read
);
1000 if (node_g
->statics_written
1001 != all_module_statics
)
1002 bitmap_and_compl (node_g
->statics_not_written
,
1004 node_g
->statics_written
);
1009 for (node
= cgraph_nodes
; node
; node
= node
->next
)
1011 ipa_reference_vars_info_t node_info
;
1012 node_info
= get_reference_vars_info (node
);
1013 /* Get rid of the aux information. */
1021 if (cgraph_function_body_availability (node
) == AVAIL_OVERWRITABLE
)
1022 clean_function (node
);
1024 clean_function_local_data (node
);
1026 bitmap_obstack_release (&local_info_obstack
);
1027 ipa_discover_readonly_nonaddressable_vars ();
1033 gate_reference (void)
1035 return (flag_ipa_reference
1036 /* Don't bother doing anything if the program has errors. */
1037 && !(errorcount
|| sorrycount
));
1040 struct ipa_opt_pass_d pass_ipa_reference
=
1044 "static-var", /* name */
1045 gate_reference
, /* gate */
1046 propagate
, /* execute */
1049 0, /* static_pass_number */
1050 TV_IPA_REFERENCE
, /* tv_id */
1051 0, /* properties_required */
1052 0, /* properties_provided */
1053 0, /* properties_destroyed */
1054 0, /* todo_flags_start */
1055 0 /* todo_flags_finish */
1057 NULL
, /* generate_summary */
1058 NULL
, /* write_summary */
1059 NULL
, /* read_summary */
1060 NULL
, /* write_optimization_summary */
1061 NULL
, /* read_optimization_summary */
1062 NULL
, /* stmt_fixup */
1064 NULL
, /* function_transform */
1065 NULL
/* variable_transform */
1068 #include "gt-ipa-reference.h"