ipa-reference.c: Do not include c-common.h, include splay-tree.h.
[gcc.git] / gcc / ipa-reference.c
1 /* Callgraph based analysis of static variables.
2 Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc.
3 Contributed by Kenneth Zadeck <zadeck@naturalbridge.com>
4
5 This file is part of GCC.
6
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
10 version.
11
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
15 for more details.
16
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/>. */
20
21 /* This file gathers information about how variables whose scope is
22 confined to the compilation unit are used.
23
24 There are two categories of information produced by this pass:
25
26 1) The addressable (TREE_ADDRESSABLE) bit and readonly
27 (TREE_READONLY) bit associated with these variables is properly set
28 based on scanning all of the code withing the compilation unit.
29
30 2) The transitive call site specific clobber effects are computed
31 for the variables whose scope is contained within this compilation
32 unit.
33
34 First each function and static variable initialization is analyzed
35 to determine which local static variables are either read, written,
36 or have their address taken. Any local static that has its address
37 taken is removed from consideration. Once the local read and
38 writes are determined, a transitive closure of this information is
39 performed over the call graph to determine the worst case set of
40 side effects of each call. In later parts of the compiler, these
41 local and global sets are examined to make the call clobbering less
42 traumatic, promote some statics to registers, and improve aliasing
43 information.
44
45 Currently must be run after inlining decisions have been made since
46 otherwise, the local sets will not contain information that is
47 consistent with post inlined state. The global sets are not prone
48 to this problem since they are by definition transitive. */
49
50 #include "config.h"
51 #include "system.h"
52 #include "coretypes.h"
53 #include "tm.h"
54 #include "tree.h"
55 #include "tree-flow.h"
56 #include "tree-inline.h"
57 #include "tree-pass.h"
58 #include "langhooks.h"
59 #include "pointer-set.h"
60 #include "splay-tree.h"
61 #include "ggc.h"
62 #include "ipa-utils.h"
63 #include "ipa-reference.h"
64 #include "gimple.h"
65 #include "cgraph.h"
66 #include "output.h"
67 #include "flags.h"
68 #include "timevar.h"
69 #include "diagnostic.h"
70 #include "langhooks.h"
71
72 /* The static variables defined within the compilation unit that are
73 loaded or stored directly by function that owns this structure. */
74
75 struct ipa_reference_local_vars_info_d
76 {
77 bitmap statics_read;
78 bitmap statics_written;
79
80 /* Set when this function calls another function external to the
81 compilation unit or if the function has a asm clobber of memory.
82 In general, such calls are modeled as reading and writing all
83 variables (both bits on) but sometime there are attributes on the
84 called function so we can do better. */
85 bool calls_read_all;
86 bool calls_write_all;
87 };
88
89 /* Statics that are read and written by some set of functions. The
90 local ones are based on the loads and stores local to the function.
91 The global ones are based on the local info as well as the
92 transitive closure of the functions that are called. The
93 structures are separated to allow the global structures to be
94 shared between several functions since every function within a
95 strongly connected component will have the same information. This
96 sharing saves both time and space in the computation of the vectors
97 as well as their translation from decl_uid form to ann_uid
98 form. */
99
100 struct ipa_reference_global_vars_info_d
101 {
102 bitmap statics_read;
103 bitmap statics_written;
104 bitmap statics_not_read;
105 bitmap statics_not_written;
106 };
107
108 typedef struct ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
109 typedef struct ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
110 struct ipa_reference_vars_info_d
111 {
112 ipa_reference_local_vars_info_t local;
113 ipa_reference_global_vars_info_t global;
114 };
115
116 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
117
118 /* This splay tree contains all of the static variables that are
119 being considered by the compilation level alias analysis. For
120 module_at_a_time compilation, this is the set of static but not
121 public variables. Any variables that either have their address
122 taken or participate in otherwise unsavory operations are deleted
123 from this list. */
124 static GTY((param1_is(int), param2_is(tree)))
125 splay_tree reference_vars_to_consider;
126
127 /* This bitmap is used to knock out the module static variables whose
128 addresses have been taken and passed around. */
129 static bitmap module_statics_escape;
130
131 /* This bitmap is used to knock out the module static variables that
132 are not readonly. */
133 static bitmap module_statics_written;
134
135 /* A bit is set for every module static we are considering. This is
136 ored into the local info when asm code is found that clobbers all
137 memory. */
138 static bitmap all_module_statics;
139
140 static struct pointer_set_t *visited_nodes;
141
142 /* Obstack holding bitmaps of local analysis (live from analysis to
143 propagation) */
144 static bitmap_obstack local_info_obstack;
145 /* Obstack holding global analysis live forever. */
146 static bitmap_obstack global_info_obstack;
147
148 /* Holders of ipa cgraph hooks: */
149 static struct cgraph_node_hook_list *function_insertion_hook_holder;
150 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
151 static struct cgraph_node_hook_list *node_removal_hook_holder;
152
153 enum initialization_status_t
154 {
155 UNINITIALIZED,
156 RUNNING,
157 FINISHED
158 };
159
160 tree memory_identifier_string;
161
162 /* Vector where the reference var infos are actually stored. */
163 DEF_VEC_P (ipa_reference_vars_info_t);
164 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
165 static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
166
167 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
168 static inline ipa_reference_vars_info_t
169 get_reference_vars_info (struct cgraph_node *node)
170 {
171 if (!ipa_reference_vars_vector
172 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
173 return NULL;
174 return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid);
175 }
176
177 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
178 static inline void
179 set_reference_vars_info (struct cgraph_node *node, ipa_reference_vars_info_t info)
180 {
181 if (!ipa_reference_vars_vector
182 || VEC_length (ipa_reference_vars_info_t, ipa_reference_vars_vector) <= (unsigned int)node->uid)
183 VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector, node->uid + 1);
184 VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector, node->uid, info);
185 }
186
187 /* Get a bitmap that contains all of the locally referenced static
188 variables for function FN. */
189 static ipa_reference_local_vars_info_t
190 get_local_reference_vars_info (struct cgraph_node *fn)
191 {
192 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
193
194 if (info)
195 return info->local;
196 else
197 /* This phase was not run. */
198 return NULL;
199 }
200
201 /* Get a bitmap that contains all of the globally referenced static
202 variables for function FN. */
203
204 static ipa_reference_global_vars_info_t
205 get_global_reference_vars_info (struct cgraph_node *fn)
206 {
207 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
208
209 if (info)
210 return info->global;
211 else
212 /* This phase was not run. */
213 return NULL;
214 }
215
216 /* Return a bitmap indexed by VAR_DECL uid for the static variables
217 that are read during the execution of the function FN. Returns
218 NULL if no data is available. */
219
220 bitmap
221 ipa_reference_get_read_global (struct cgraph_node *fn)
222 {
223 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
224 if (g)
225 return g->statics_read;
226 else
227 return NULL;
228 }
229
230 /* Return a bitmap indexed by VAR_DECL uid for the static variables
231 that are written during the execution of the function FN. Note
232 that variables written may or may not be read during the function
233 call. Returns NULL if no data is available. */
234
235 bitmap
236 ipa_reference_get_written_global (struct cgraph_node *fn)
237 {
238 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
239 if (g)
240 return g->statics_written;
241 else
242 return NULL;
243 }
244
245 /* Return a bitmap indexed by_DECL_UID uid for the static variables
246 that are not read during the execution of the function FN. Returns
247 NULL if no data is available. */
248
249 bitmap
250 ipa_reference_get_not_read_global (struct cgraph_node *fn)
251 {
252 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
253 if (g)
254 return g->statics_not_read;
255 else
256 return NULL;
257 }
258
259 /* Return a bitmap indexed by DECL_UID uid for the static variables
260 that are not written during the execution of the function FN. Note
261 that variables written may or may not be read during the function
262 call. Returns NULL if no data is available. */
263
264 bitmap
265 ipa_reference_get_not_written_global (struct cgraph_node *fn)
266 {
267 ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn);
268 if (g)
269 return g->statics_not_written;
270 else
271 return NULL;
272 }
273
274 \f
275
276 /* Add VAR to all_module_statics and the two
277 reference_vars_to_consider* sets. */
278
279 static inline void
280 add_static_var (tree var)
281 {
282 int uid = DECL_UID (var);
283 gcc_assert (TREE_CODE (var) == VAR_DECL);
284 if (!bitmap_bit_p (all_module_statics, uid))
285 {
286 splay_tree_insert (reference_vars_to_consider,
287 uid, (splay_tree_value)var);
288 bitmap_set_bit (all_module_statics, uid);
289 }
290 }
291
292 /* Return true if the variable T is the right kind of static variable to
293 perform compilation unit scope escape analysis. */
294
295 static inline bool
296 has_proper_scope_for_analysis (tree t)
297 {
298 /* If the variable has the "used" attribute, treat it as if it had a
299 been touched by the devil. */
300 if (lookup_attribute ("used", DECL_ATTRIBUTES (t)))
301 return false;
302
303 /* Do not want to do anything with volatile except mark any
304 function that uses one to be not const or pure. */
305 if (TREE_THIS_VOLATILE (t))
306 return false;
307
308 /* Do not care about a local automatic that is not static. */
309 if (!TREE_STATIC (t) && !DECL_EXTERNAL (t))
310 return false;
311
312 if (DECL_EXTERNAL (t) || TREE_PUBLIC (t))
313 return false;
314
315 /* We cannot touch decls where the type needs constructing. */
316 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
317 return false;
318
319 /* This is a variable we care about. Check if we have seen it
320 before, and if not add it the set of variables we care about. */
321 if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
322 add_static_var (t);
323
324 return true;
325 }
326
327 /* Mark tree T as having address taken. */
328
329 static void
330 mark_address_taken (tree x)
331 {
332 if (TREE_CODE (x) == VAR_DECL
333 && module_statics_escape && has_proper_scope_for_analysis (x))
334 bitmap_set_bit (module_statics_escape, DECL_UID (x));
335 }
336
337 /* Wrapper around mark_address_taken for the stmt walker. */
338
339 static bool
340 mark_address (gimple stmt ATTRIBUTE_UNUSED, tree addr,
341 void *data ATTRIBUTE_UNUSED)
342 {
343 while (handled_component_p (addr))
344 addr = TREE_OPERAND (addr, 0);
345 mark_address_taken (addr);
346 return false;
347 }
348
349 /* Mark load of T. */
350
351 static bool
352 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
353 {
354 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
355 if (TREE_CODE (t) == VAR_DECL
356 && has_proper_scope_for_analysis (t))
357 bitmap_set_bit (local->statics_read, DECL_UID (t));
358 return false;
359 }
360
361 /* Mark store of T. */
362
363 static bool
364 mark_store (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
365 {
366 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
367 if (TREE_CODE (t) == VAR_DECL
368 && has_proper_scope_for_analysis (t))
369 {
370 if (local)
371 bitmap_set_bit (local->statics_written, DECL_UID (t));
372 /* Mark the write so we can tell which statics are
373 readonly. */
374 if (module_statics_written)
375 bitmap_set_bit (module_statics_written, DECL_UID (t));
376 }
377 return false;
378 }
379
380 /* Look for memory clobber and set read_all/write_all if present. */
381
382 static void
383 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt)
384 {
385 size_t i;
386 tree op;
387
388 for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
389 {
390 op = gimple_asm_clobber_op (stmt, i);
391 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
392 {
393 /* Abandon all hope, ye who enter here. */
394 local->calls_read_all = true;
395 local->calls_write_all = true;
396 }
397 }
398 }
399
400 /* Look for external calls and set read_all/write_all correspondingly. */
401
402 static void
403 check_call (ipa_reference_local_vars_info_t local, gimple stmt)
404 {
405 int flags = gimple_call_flags (stmt);
406 tree callee_t = gimple_call_fndecl (stmt);
407 enum availability avail = AVAIL_NOT_AVAILABLE;
408
409 if (callee_t)
410 {
411 struct cgraph_node* callee = cgraph_node(callee_t);
412 avail = cgraph_function_body_availability (callee);
413 }
414
415 if (avail <= AVAIL_OVERWRITABLE)
416 if (local)
417 {
418 if (flags & ECF_CONST)
419 ;
420 else if (flags & ECF_PURE)
421 local->calls_read_all = true;
422 else
423 {
424 local->calls_read_all = true;
425 local->calls_write_all = true;
426 }
427 }
428 /* TODO: To be able to produce sane results, we should also handle
429 common builtins, in particular throw.
430 Indirect calls hsould be only counted and as inliner is replacing them
431 by direct calls, we can conclude if any indirect calls are left in body */
432 }
433
434 /* TP is the part of the tree currently under the microscope.
435 WALK_SUBTREES is part of the walk_tree api but is unused here.
436 DATA is cgraph_node of the function being walked. */
437
438 static tree
439 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
440 struct cgraph_node *fn)
441 {
442 gimple stmt = gsi_stmt (*gsip);
443 ipa_reference_local_vars_info_t local = NULL;
444
445 if (fn)
446 local = get_reference_vars_info (fn)->local;
447
448 /* Look for direct loads and stores. */
449 walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store,
450 mark_address);
451
452 if (is_gimple_call (stmt))
453 check_call (local, stmt);
454 else if (gimple_code (stmt) == GIMPLE_ASM)
455 check_asm_memory_clobber (local, stmt);
456
457 return NULL;
458 }
459
460 /* Call-back to scan variable initializers for static references.
461 Called using walk_tree. */
462
463 static tree
464 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees,
465 void *data ATTRIBUTE_UNUSED)
466 {
467 tree t = *tp;
468
469 if (TREE_CODE (t) == ADDR_EXPR)
470 {
471 mark_address_taken (get_base_var (t));
472 *walk_subtrees = 0;
473 }
474 /* Save some cycles by not walking types and declaration as we
475 won't find anything useful there anyway. */
476 else if (IS_TYPE_OR_DECL_P (*tp))
477 *walk_subtrees = 0;
478
479 return NULL;
480 }
481
482 /* Lookup the tree node for the static variable that has UID. */
483 static tree
484 get_static_decl (int index)
485 {
486 splay_tree_node stn =
487 splay_tree_lookup (reference_vars_to_consider, index);
488 if (stn)
489 return (tree)stn->value;
490 return NULL;
491 }
492
493 /* Lookup the tree node for the static variable that has UID and
494 convert the name to a string for debugging. */
495
496 static const char *
497 get_static_name (int index)
498 {
499 splay_tree_node stn =
500 splay_tree_lookup (reference_vars_to_consider, index);
501 if (stn)
502 return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
503 return NULL;
504 }
505
506 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
507 bit vector. There are several cases to check to avoid the sparse
508 bitmap oring. */
509
510 static void
511 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
512 {
513 struct cgraph_edge *e;
514 for (e = x->callees; e; e = e->next_callee)
515 {
516 struct cgraph_node *y = e->callee;
517
518 /* Only look at the master nodes and skip external nodes. */
519 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
520 {
521 if (get_reference_vars_info (y))
522 {
523 ipa_reference_vars_info_t y_info
524 = get_reference_vars_info (y);
525 ipa_reference_global_vars_info_t y_global = y_info->global;
526
527 /* Calls in current cycle do not have global computed yet. */
528 if (!y_info->global)
529 continue;
530
531 if (x_global->statics_read
532 != all_module_statics)
533 {
534 if (y_global->statics_read
535 == all_module_statics)
536 {
537 BITMAP_FREE (x_global->statics_read);
538 x_global->statics_read
539 = all_module_statics;
540 }
541 /* Skip bitmaps that are pointer equal to node's bitmap
542 (no reason to spin within the cycle). */
543 else if (x_global->statics_read
544 != y_global->statics_read)
545 bitmap_ior_into (x_global->statics_read,
546 y_global->statics_read);
547 }
548
549 if (x_global->statics_written
550 != all_module_statics)
551 {
552 if (y_global->statics_written
553 == all_module_statics)
554 {
555 BITMAP_FREE (x_global->statics_written);
556 x_global->statics_written
557 = all_module_statics;
558 }
559 /* Skip bitmaps that are pointer equal to node's bitmap
560 (no reason to spin within the cycle). */
561 else if (x_global->statics_written
562 != y_global->statics_written)
563 bitmap_ior_into (x_global->statics_written,
564 y_global->statics_written);
565 }
566 }
567 else
568 gcc_unreachable ();
569 }
570 }
571 }
572
573 /* The init routine for analyzing global static variable usage. See
574 comments at top for description. */
575 static void
576 ipa_init (void)
577 {
578 memory_identifier_string = build_string(7, "memory");
579
580 reference_vars_to_consider =
581 splay_tree_new_ggc (splay_tree_compare_ints);
582
583 bitmap_obstack_initialize (&local_info_obstack);
584 bitmap_obstack_initialize (&global_info_obstack);
585 module_statics_escape = BITMAP_ALLOC (&local_info_obstack);
586 module_statics_written = BITMAP_ALLOC (&local_info_obstack);
587 all_module_statics = BITMAP_ALLOC (&global_info_obstack);
588
589 /* There are some shared nodes, in particular the initializers on
590 static declarations. We do not need to scan them more than once
591 since all we would be interested in are the addressof
592 operations. */
593 visited_nodes = pointer_set_create ();
594 }
595
596 /* Check out the rhs of a static or global initialization VNODE to see
597 if any of them contain addressof operations. Note that some of
598 these variables may not even be referenced in the code in this
599 compilation unit but their right hand sides may contain references
600 to variables defined within this unit. */
601
602 static void
603 analyze_variable (struct varpool_node *vnode)
604 {
605 struct walk_stmt_info wi;
606 tree global = vnode->decl;
607
608 memset (&wi, 0, sizeof (wi));
609 wi.pset = visited_nodes;
610 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs,
611 &wi, wi.pset);
612 }
613
614 /* Set up the persistent info for FN. */
615
616 static ipa_reference_local_vars_info_t
617 init_function_info (struct cgraph_node *fn)
618 {
619 ipa_reference_vars_info_t info
620 = XCNEW (struct ipa_reference_vars_info_d);
621 ipa_reference_local_vars_info_t l
622 = XCNEW (struct ipa_reference_local_vars_info_d);
623
624 /* Add the info to the tree's annotation. */
625 set_reference_vars_info (fn, info);
626
627 info->local = l;
628 l->statics_read = BITMAP_ALLOC (&local_info_obstack);
629 l->statics_written = BITMAP_ALLOC (&local_info_obstack);
630
631 return l;
632 }
633
634 /* This is the main routine for finding the reference patterns for
635 global variables within a function FN. */
636
637 static void
638 analyze_function (struct cgraph_node *fn)
639 {
640 tree decl = fn->decl;
641 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
642 basic_block this_block;
643 #ifdef ENABLE_CHECKING
644 tree step;
645 #endif
646
647 if (dump_file)
648 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
649
650 push_cfun (DECL_STRUCT_FUNCTION (decl));
651 current_function_decl = decl;
652
653 init_function_info (fn);
654 FOR_EACH_BB_FN (this_block, this_cfun)
655 {
656 gimple_stmt_iterator gsi;
657 gimple phi;
658 tree op;
659 use_operand_p use;
660 ssa_op_iter iter;
661
662 /* Find the addresses taken in phi node arguments. */
663 for (gsi = gsi_start_phis (this_block);
664 !gsi_end_p (gsi);
665 gsi_next (&gsi))
666 {
667 phi = gsi_stmt (gsi);
668 FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
669 {
670 op = USE_FROM_PTR (use);
671 if (TREE_CODE (op) == ADDR_EXPR)
672 mark_address_taken (get_base_var (op));
673 }
674 }
675
676 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
677 scan_stmt_for_static_refs (&gsi, fn);
678 }
679
680 #ifdef ENABLE_CHECKING
681 /* Verify that all local initializers was expanded by gimplifier. */
682 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls;
683 step;
684 step = TREE_CHAIN (step))
685 {
686 tree var = TREE_VALUE (step);
687 if (TREE_CODE (var) == VAR_DECL
688 && DECL_INITIAL (var)
689 && !TREE_STATIC (var))
690 gcc_unreachable ();
691 }
692 #endif
693 pop_cfun ();
694 current_function_decl = NULL;
695 }
696
697 /* Remove local data associated with function FN. */
698 static void
699 clean_function_local_data (struct cgraph_node *fn)
700 {
701 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
702 ipa_reference_local_vars_info_t l = info->local;
703 if (l)
704 {
705 if (l->statics_read
706 && l->statics_read != all_module_statics)
707 BITMAP_FREE (l->statics_read);
708 if (l->statics_written
709 &&l->statics_written != all_module_statics)
710 BITMAP_FREE (l->statics_written);
711 free (l);
712 info->local = NULL;
713 }
714 }
715
716 /* Remove all data associated with function FN. */
717
718 static void
719 clean_function (struct cgraph_node *fn)
720 {
721 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
722 ipa_reference_global_vars_info_t g = info->global;
723
724 clean_function_local_data (fn);
725 if (g)
726 {
727 if (g->statics_read
728 && g->statics_read != all_module_statics)
729 BITMAP_FREE (g->statics_read);
730
731 if (g->statics_written
732 && g->statics_written != all_module_statics)
733 BITMAP_FREE (g->statics_written);
734
735 if (g->statics_not_read
736 && g->statics_not_read != all_module_statics)
737 BITMAP_FREE (g->statics_not_read);
738
739 if (g->statics_not_written
740 && g->statics_not_written != all_module_statics)
741 BITMAP_FREE (g->statics_not_written);
742 free (g);
743 info->global = NULL;
744 }
745
746 free (get_reference_vars_info (fn));
747 set_reference_vars_info (fn, NULL);
748 }
749
750 /* Called when new function is inserted to callgraph late. */
751 static void
752 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
753 {
754 /* There are some shared nodes, in particular the initializers on
755 static declarations. We do not need to scan them more than once
756 since all we would be interested in are the addressof
757 operations. */
758 analyze_function (node);
759 visited_nodes = NULL;
760 }
761
762 static bitmap
763 copy_local_bitmap (bitmap src)
764 {
765 bitmap dst;
766 if (!src)
767 return NULL;
768 if (src == all_module_statics)
769 return all_module_statics;
770 dst = BITMAP_ALLOC (&local_info_obstack);
771 bitmap_copy (dst, src);
772 return dst;
773 }
774
775 static bitmap
776 copy_global_bitmap (bitmap src)
777 {
778 bitmap dst;
779 if (!src)
780 return NULL;
781 if (src == all_module_statics)
782 return all_module_statics;
783 dst = BITMAP_ALLOC (&global_info_obstack);
784 bitmap_copy (dst, src);
785 return dst;
786 }
787
788 /* Called when new clone is inserted to callgraph late. */
789
790 static void
791 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
792 void *data ATTRIBUTE_UNUSED)
793 {
794 ipa_reference_global_vars_info_t ginfo;
795 ipa_reference_local_vars_info_t linfo;
796 ipa_reference_global_vars_info_t dst_ginfo;
797 ipa_reference_local_vars_info_t dst_linfo;
798
799 ginfo = get_global_reference_vars_info (src);
800 linfo = get_local_reference_vars_info (src);
801 if (!linfo && !ginfo)
802 return;
803 init_function_info (dst);
804 if (linfo)
805 {
806 dst_linfo = get_local_reference_vars_info (dst);
807 dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read);
808 dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written);
809 dst_linfo->calls_read_all = linfo->calls_read_all;
810 dst_linfo->calls_write_all = linfo->calls_write_all;
811 }
812 if (ginfo)
813 {
814 get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d);
815 dst_ginfo = get_global_reference_vars_info (dst);
816 dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read);
817 dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written);
818 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
819 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
820 }
821 }
822
823 /* Called when node is removed. */
824
825 static void
826 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
827 {
828 if (get_reference_vars_info (node))
829 clean_function (node);
830 }
831
832 /* Analyze each function in the cgraph to see which global or statics
833 are read or written. */
834
835 static void
836 generate_summary (void)
837 {
838 struct cgraph_node *node;
839 struct varpool_node *vnode;
840 unsigned int index;
841 bitmap_iterator bi;
842 bitmap module_statics_readonly;
843 bitmap bm_temp;
844
845 function_insertion_hook_holder =
846 cgraph_add_function_insertion_hook (&add_new_function, NULL);
847 node_removal_hook_holder =
848 cgraph_add_node_removal_hook (&remove_node_data, NULL);
849 node_duplication_hook_holder =
850 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
851 ipa_init ();
852 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack);
853 bm_temp = BITMAP_ALLOC (&local_info_obstack);
854
855 /* Process all of the variables first. */
856 FOR_EACH_STATIC_INITIALIZER (vnode)
857 analyze_variable (vnode);
858
859 /* Process all of the functions next.
860
861 We do not want to process any of the clones so we check that this
862 is a master clone. However, we do need to process any
863 AVAIL_OVERWRITABLE functions (these are never clones) because
864 they may cause a static variable to escape. The code that can
865 overwrite such a function cannot access the statics because it
866 would not be in the same compilation unit. When the analysis is
867 finished, the computed information of these AVAIL_OVERWRITABLE is
868 replaced with worst case info.
869 */
870 for (node = cgraph_nodes; node; node = node->next)
871 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
872 analyze_function (node);
873
874 pointer_set_destroy (visited_nodes);
875 visited_nodes = NULL;
876
877 /* Prune out the variables that were found to behave badly
878 (i.e. have their address taken). */
879 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
880 {
881 splay_tree_remove (reference_vars_to_consider, index);
882 }
883
884 bitmap_and_compl_into (all_module_statics,
885 module_statics_escape);
886
887 bitmap_and_compl (module_statics_readonly, all_module_statics,
888 module_statics_written);
889
890 /* If the address is not taken, we can unset the addressable bit
891 on this variable. */
892 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
893 {
894 tree var = get_static_decl (index);
895 TREE_ADDRESSABLE (var) = 0;
896 if (dump_file)
897 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
898 get_static_name (index));
899 }
900
901 /* If the variable is never written, we can set the TREE_READONLY
902 flag. Additionally if it has a DECL_INITIAL that is made up of
903 constants we can treat the entire global as a constant. */
904
905 bitmap_and_compl (module_statics_readonly, all_module_statics,
906 module_statics_written);
907 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
908 {
909 tree var = get_static_decl (index);
910
911 /* Ignore variables in named sections - changing TREE_READONLY
912 changes the section flags, potentially causing conflicts with
913 other variables in the same named section. */
914 if (DECL_SECTION_NAME (var) == NULL_TREE)
915 {
916 TREE_READONLY (var) = 1;
917 if (dump_file)
918 fprintf (dump_file, "read-only var %s\n",
919 get_static_name (index));
920 }
921 }
922
923 BITMAP_FREE(module_statics_escape);
924 BITMAP_FREE(module_statics_written);
925 module_statics_escape = NULL;
926 module_statics_written = NULL;
927
928 if (dump_file)
929 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
930 {
931 fprintf (dump_file, "\nPromotable global:%s",
932 get_static_name (index));
933 }
934
935 for (node = cgraph_nodes; node; node = node->next)
936 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
937 {
938 ipa_reference_local_vars_info_t l;
939 l = get_reference_vars_info (node)->local;
940
941 /* Any variables that are not in all_module_statics are
942 removed from the local maps. This will include all of the
943 variables that were found to escape in the function
944 scanning. */
945 bitmap_and_into (l->statics_read,
946 all_module_statics);
947 bitmap_and_into (l->statics_written,
948 all_module_statics);
949 }
950
951 BITMAP_FREE(module_statics_readonly);
952 BITMAP_FREE(bm_temp);
953
954 if (dump_file)
955 for (node = cgraph_nodes; node; node = node->next)
956 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
957 {
958 ipa_reference_local_vars_info_t l;
959 unsigned int index;
960 bitmap_iterator bi;
961
962 l = get_reference_vars_info (node)->local;
963 fprintf (dump_file,
964 "\nFunction name:%s/%i:",
965 cgraph_node_name (node), node->uid);
966 fprintf (dump_file, "\n locals read: ");
967 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
968 0, index, bi)
969 {
970 fprintf (dump_file, "%s ",
971 get_static_name (index));
972 }
973 fprintf (dump_file, "\n locals written: ");
974 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
975 0, index, bi)
976 {
977 fprintf(dump_file, "%s ",
978 get_static_name (index));
979 }
980 if (l->calls_read_all)
981 fprintf (dump_file, "\n calls read all: ");
982 if (l->calls_write_all)
983 fprintf (dump_file, "\n calls read all: ");
984 }
985 }
986 \f
987 /* Produce the global information by preforming a transitive closure
988 on the local information that was produced by ipa_analyze_function
989 and ipa_analyze_variable. */
990
991 static unsigned int
992 propagate (void)
993 {
994 struct cgraph_node *node;
995 struct cgraph_node *w;
996 struct cgraph_node **order =
997 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
998 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
999 int i;
1000
1001 cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
1002 if (dump_file)
1003 dump_cgraph (dump_file);
1004
1005 /* Propagate the local information thru the call graph to produce
1006 the global information. All the nodes within a cycle will have
1007 the same info so we collapse cycles first. Then we can do the
1008 propagation in one pass from the leaves to the roots. */
1009 order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
1010 if (dump_file)
1011 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1012
1013 for (i = 0; i < order_pos; i++ )
1014 {
1015 ipa_reference_vars_info_t node_info;
1016 ipa_reference_global_vars_info_t node_g =
1017 XCNEW (struct ipa_reference_global_vars_info_d);
1018 ipa_reference_local_vars_info_t node_l;
1019
1020 bool read_all;
1021 bool write_all;
1022 struct ipa_dfs_info * w_info;
1023
1024 node = order[i];
1025 node_info = get_reference_vars_info (node);
1026 if (!node_info)
1027 {
1028 dump_cgraph_node (stderr, node);
1029 dump_cgraph (stderr);
1030 gcc_unreachable ();
1031 }
1032
1033 gcc_assert (!node_info->global);
1034 node_l = node_info->local;
1035
1036 read_all = node_l->calls_read_all;
1037 write_all = node_l->calls_write_all;
1038
1039 /* If any node in a cycle is calls_read_all or calls_write_all
1040 they all are. */
1041 w_info = (struct ipa_dfs_info *) node->aux;
1042 w = w_info->next_cycle;
1043 while (w)
1044 {
1045 ipa_reference_local_vars_info_t w_l =
1046 get_reference_vars_info (w)->local;
1047 read_all |= w_l->calls_read_all;
1048 write_all |= w_l->calls_write_all;
1049
1050 w_info = (struct ipa_dfs_info *) w->aux;
1051 w = w_info->next_cycle;
1052 }
1053
1054 /* Initialized the bitmaps for the reduced nodes */
1055 if (read_all)
1056 node_g->statics_read = all_module_statics;
1057 else
1058 {
1059 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack);
1060 bitmap_copy (node_g->statics_read,
1061 node_l->statics_read);
1062 }
1063
1064 if (write_all)
1065 node_g->statics_written = all_module_statics;
1066 else
1067 {
1068 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack);
1069 bitmap_copy (node_g->statics_written,
1070 node_l->statics_written);
1071 }
1072
1073 propagate_bits (node_g, node);
1074 w_info = (struct ipa_dfs_info *) node->aux;
1075 w = w_info->next_cycle;
1076 while (w)
1077 {
1078 ipa_reference_vars_info_t w_ri =
1079 get_reference_vars_info (w);
1080 ipa_reference_local_vars_info_t w_l = w_ri->local;
1081
1082 /* These global bitmaps are initialized from the local info
1083 of all of the nodes in the region. However there is no
1084 need to do any work if the bitmaps were set to
1085 all_module_statics. */
1086 if (!read_all)
1087 bitmap_ior_into (node_g->statics_read,
1088 w_l->statics_read);
1089 if (!write_all)
1090 bitmap_ior_into (node_g->statics_written,
1091 w_l->statics_written);
1092 propagate_bits (node_g, w);
1093 w_info = (struct ipa_dfs_info *) w->aux;
1094 w = w_info->next_cycle;
1095 }
1096
1097 /* All nodes within a cycle have the same global info bitmaps. */
1098 node_info->global = node_g;
1099 w_info = (struct ipa_dfs_info *) node->aux;
1100 w = w_info->next_cycle;
1101 while (w)
1102 {
1103 ipa_reference_vars_info_t w_ri =
1104 get_reference_vars_info (w);
1105
1106 gcc_assert (!w_ri->global);
1107 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d);
1108 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read);
1109 w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written);
1110
1111 w_info = (struct ipa_dfs_info *) w->aux;
1112 w = w_info->next_cycle;
1113 }
1114 }
1115
1116 if (dump_file)
1117 {
1118 for (i = 0; i < order_pos; i++ )
1119 {
1120 ipa_reference_vars_info_t node_info;
1121 ipa_reference_global_vars_info_t node_g;
1122 ipa_reference_local_vars_info_t node_l;
1123 unsigned int index;
1124 bitmap_iterator bi;
1125 struct ipa_dfs_info * w_info;
1126
1127 node = order[i];
1128 node_info = get_reference_vars_info (node);
1129 node_g = node_info->global;
1130 node_l = node_info->local;
1131 fprintf (dump_file,
1132 "\nFunction name:%s/%i:",
1133 cgraph_node_name (node), node->uid);
1134 fprintf (dump_file, "\n locals read: ");
1135 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1136 0, index, bi)
1137 {
1138 fprintf (dump_file, "%s ",
1139 get_static_name (index));
1140 }
1141 fprintf (dump_file, "\n locals written: ");
1142 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1143 0, index, bi)
1144 {
1145 fprintf(dump_file, "%s ",
1146 get_static_name (index));
1147 }
1148
1149 w_info = (struct ipa_dfs_info *) node->aux;
1150 w = w_info->next_cycle;
1151 while (w)
1152 {
1153 ipa_reference_vars_info_t w_ri =
1154 get_reference_vars_info (w);
1155 ipa_reference_local_vars_info_t w_l = w_ri->local;
1156 fprintf (dump_file, "\n next cycle: %s/%i ",
1157 cgraph_node_name (w), w->uid);
1158 fprintf (dump_file, "\n locals read: ");
1159 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1160 0, index, bi)
1161 {
1162 fprintf (dump_file, "%s ",
1163 get_static_name (index));
1164 }
1165
1166 fprintf (dump_file, "\n locals written: ");
1167 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1168 0, index, bi)
1169 {
1170 fprintf(dump_file, "%s ",
1171 get_static_name (index));
1172 }
1173
1174
1175 w_info = (struct ipa_dfs_info *) w->aux;
1176 w = w_info->next_cycle;
1177 }
1178 fprintf (dump_file, "\n globals read: ");
1179 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1180 0, index, bi)
1181 {
1182 fprintf (dump_file, "%s ",
1183 get_static_name (index));
1184 }
1185 fprintf (dump_file, "\n globals written: ");
1186 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1187 0, index, bi)
1188 {
1189 fprintf (dump_file, "%s ",
1190 get_static_name (index));
1191 }
1192 }
1193 }
1194
1195 /* Cleanup. */
1196 for (i = 0; i < order_pos; i++ )
1197 {
1198 ipa_reference_vars_info_t node_info;
1199 ipa_reference_global_vars_info_t node_g;
1200 node = order[i];
1201 node_info = get_reference_vars_info (node);
1202 node_g = node_info->global;
1203
1204 /* Create the complimentary sets. These are more useful for
1205 certain apis. */
1206 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack);
1207 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack);
1208
1209 if (node_g->statics_read != all_module_statics)
1210 bitmap_and_compl (node_g->statics_not_read,
1211 all_module_statics,
1212 node_g->statics_read);
1213
1214 if (node_g->statics_written
1215 != all_module_statics)
1216 bitmap_and_compl (node_g->statics_not_written,
1217 all_module_statics,
1218 node_g->statics_written);
1219 }
1220
1221 free (order);
1222
1223 for (node = cgraph_nodes; node; node = node->next)
1224 {
1225 ipa_reference_vars_info_t node_info;
1226 node_info = get_reference_vars_info (node);
1227 /* Get rid of the aux information. */
1228
1229 if (node->aux)
1230 {
1231 free (node->aux);
1232 node->aux = NULL;
1233 }
1234
1235 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)
1236 clean_function (node);
1237 else if (node_info)
1238 clean_function_local_data (node);
1239 }
1240 bitmap_obstack_release (&local_info_obstack);
1241 return 0;
1242 }
1243
1244
1245 static bool
1246 gate_reference (void)
1247 {
1248 return (flag_ipa_reference
1249 /* Don't bother doing anything if the program has errors. */
1250 && !(errorcount || sorrycount));
1251 }
1252
1253 struct ipa_opt_pass pass_ipa_reference =
1254 {
1255 {
1256 IPA_PASS,
1257 "static-var", /* name */
1258 gate_reference, /* gate */
1259 propagate, /* execute */
1260 NULL, /* sub */
1261 NULL, /* next */
1262 0, /* static_pass_number */
1263 TV_IPA_REFERENCE, /* tv_id */
1264 0, /* properties_required */
1265 0, /* properties_provided */
1266 0, /* properties_destroyed */
1267 0, /* todo_flags_start */
1268 0 /* todo_flags_finish */
1269 },
1270 generate_summary, /* generate_summary */
1271 NULL, /* write_summary */
1272 NULL, /* read_summary */
1273 NULL, /* function_read_summary */
1274 0, /* TODOs */
1275 NULL, /* function_transform */
1276 NULL /* variable_transform */
1277 };
1278
1279 #include "gt-ipa-reference.h"