gimple.h (walk_stmt_load_store_addr_ops): Declare.
[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 "ggc.h"
61 #include "ipa-utils.h"
62 #include "ipa-reference.h"
63 #include "c-common.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 /* Mark load of T. */
338
339 static bool
340 mark_load (gimple stmt ATTRIBUTE_UNUSED, tree t, void *data)
341 {
342 ipa_reference_local_vars_info_t local = (ipa_reference_local_vars_info_t)data;
343 if (TREE_CODE (t) == VAR_DECL
344 && has_proper_scope_for_analysis (t))
345 bitmap_set_bit (local->statics_read, DECL_UID (t));
346 return false;
347 }
348
349 /* Mark store of T. */
350
351 static bool
352 mark_store (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 {
358 if (local)
359 bitmap_set_bit (local->statics_written, DECL_UID (t));
360 /* Mark the write so we can tell which statics are
361 readonly. */
362 if (module_statics_written)
363 bitmap_set_bit (module_statics_written, DECL_UID (t));
364 }
365 return false;
366 }
367
368 /* Look for memory clobber and set read_all/write_all if present. */
369
370 static void
371 check_asm_memory_clobber (ipa_reference_local_vars_info_t local, gimple stmt)
372 {
373 size_t i;
374 tree op;
375
376 for (i = 0; i < gimple_asm_nclobbers (stmt); i++)
377 {
378 op = gimple_asm_clobber_op (stmt, i);
379 if (simple_cst_equal(TREE_VALUE (op), memory_identifier_string) == 1)
380 {
381 /* Abandon all hope, ye who enter here. */
382 local->calls_read_all = true;
383 local->calls_write_all = true;
384 }
385 }
386 }
387
388 /* Look for external calls and set read_all/write_all correspondingly. */
389
390 static void
391 check_call (ipa_reference_local_vars_info_t local, gimple stmt)
392 {
393 int flags = gimple_call_flags (stmt);
394 tree callee_t = gimple_call_fndecl (stmt);
395 enum availability avail = AVAIL_NOT_AVAILABLE;
396
397 if (callee_t)
398 {
399 struct cgraph_node* callee = cgraph_node(callee_t);
400 avail = cgraph_function_body_availability (callee);
401 }
402
403 if (avail <= AVAIL_OVERWRITABLE)
404 if (local)
405 {
406 if (flags & ECF_CONST)
407 ;
408 else if (flags & ECF_PURE)
409 local->calls_read_all = true;
410 else
411 {
412 local->calls_read_all = true;
413 local->calls_write_all = true;
414 }
415 }
416 /* TODO: To be able to produce sane results, we should also handle
417 common builtins, in particular throw.
418 Indirect calls hsould be only counted and as inliner is replacing them
419 by direct calls, we can conclude if any indirect calls are left in body */
420 }
421
422 /* TP is the part of the tree currently under the microscope.
423 WALK_SUBTREES is part of the walk_tree api but is unused here.
424 DATA is cgraph_node of the function being walked. */
425
426 static tree
427 scan_stmt_for_static_refs (gimple_stmt_iterator *gsip,
428 struct cgraph_node *fn)
429 {
430 gimple stmt = gsi_stmt (*gsip);
431 ipa_reference_local_vars_info_t local = NULL;
432 unsigned int i;
433 bitmap_iterator bi;
434
435 if (fn)
436 local = get_reference_vars_info (fn)->local;
437
438 /* Look for direct loads and stores. */
439 walk_stmt_load_store_addr_ops (stmt, local, mark_load, mark_store, NULL);
440
441 if (is_gimple_call (stmt))
442 check_call (local, stmt);
443 else if (gimple_code (stmt) == GIMPLE_ASM)
444 check_asm_memory_clobber (local, stmt);
445
446 if (gimple_addresses_taken (stmt))
447 EXECUTE_IF_SET_IN_BITMAP (gimple_addresses_taken (stmt), 0, i, bi)
448 mark_address_taken (referenced_var_lookup (i));
449
450 return NULL;
451 }
452
453 /* Call-back to scan variable initializers for static references.
454 Called using walk_tree. */
455
456 static tree
457 scan_initializer_for_static_refs (tree *tp, int *walk_subtrees,
458 void *data ATTRIBUTE_UNUSED)
459 {
460 tree t = *tp;
461
462 if (TREE_CODE (t) == ADDR_EXPR)
463 {
464 mark_address_taken (get_base_var (t));
465 *walk_subtrees = 0;
466 }
467 /* Save some cycles by not walking types and declaration as we
468 won't find anything useful there anyway. */
469 else if (IS_TYPE_OR_DECL_P (*tp))
470 *walk_subtrees = 0;
471
472 return NULL;
473 }
474
475 /* Lookup the tree node for the static variable that has UID. */
476 static tree
477 get_static_decl (int index)
478 {
479 splay_tree_node stn =
480 splay_tree_lookup (reference_vars_to_consider, index);
481 if (stn)
482 return (tree)stn->value;
483 return NULL;
484 }
485
486 /* Lookup the tree node for the static variable that has UID and
487 convert the name to a string for debugging. */
488
489 static const char *
490 get_static_name (int index)
491 {
492 splay_tree_node stn =
493 splay_tree_lookup (reference_vars_to_consider, index);
494 if (stn)
495 return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
496 return NULL;
497 }
498
499 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
500 bit vector. There are several cases to check to avoid the sparse
501 bitmap oring. */
502
503 static void
504 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
505 {
506 struct cgraph_edge *e;
507 for (e = x->callees; e; e = e->next_callee)
508 {
509 struct cgraph_node *y = e->callee;
510
511 /* Only look at the master nodes and skip external nodes. */
512 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
513 {
514 if (get_reference_vars_info (y))
515 {
516 ipa_reference_vars_info_t y_info
517 = get_reference_vars_info (y);
518 ipa_reference_global_vars_info_t y_global = y_info->global;
519
520 /* Calls in current cycle do not have global computed yet. */
521 if (!y_info->global)
522 continue;
523
524 if (x_global->statics_read
525 != all_module_statics)
526 {
527 if (y_global->statics_read
528 == all_module_statics)
529 {
530 BITMAP_FREE (x_global->statics_read);
531 x_global->statics_read
532 = all_module_statics;
533 }
534 /* Skip bitmaps that are pointer equal to node's bitmap
535 (no reason to spin within the cycle). */
536 else if (x_global->statics_read
537 != y_global->statics_read)
538 bitmap_ior_into (x_global->statics_read,
539 y_global->statics_read);
540 }
541
542 if (x_global->statics_written
543 != all_module_statics)
544 {
545 if (y_global->statics_written
546 == all_module_statics)
547 {
548 BITMAP_FREE (x_global->statics_written);
549 x_global->statics_written
550 = all_module_statics;
551 }
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_written
555 != y_global->statics_written)
556 bitmap_ior_into (x_global->statics_written,
557 y_global->statics_written);
558 }
559 }
560 else
561 gcc_unreachable ();
562 }
563 }
564 }
565
566 /* The init routine for analyzing global static variable usage. See
567 comments at top for description. */
568 static void
569 ipa_init (void)
570 {
571 memory_identifier_string = build_string(7, "memory");
572
573 reference_vars_to_consider =
574 splay_tree_new_ggc (splay_tree_compare_ints);
575
576 bitmap_obstack_initialize (&local_info_obstack);
577 bitmap_obstack_initialize (&global_info_obstack);
578 module_statics_escape = BITMAP_ALLOC (&local_info_obstack);
579 module_statics_written = BITMAP_ALLOC (&local_info_obstack);
580 all_module_statics = BITMAP_ALLOC (&global_info_obstack);
581
582 /* There are some shared nodes, in particular the initializers on
583 static declarations. We do not need to scan them more than once
584 since all we would be interested in are the addressof
585 operations. */
586 visited_nodes = pointer_set_create ();
587 }
588
589 /* Check out the rhs of a static or global initialization VNODE to see
590 if any of them contain addressof operations. Note that some of
591 these variables may not even be referenced in the code in this
592 compilation unit but their right hand sides may contain references
593 to variables defined within this unit. */
594
595 static void
596 analyze_variable (struct varpool_node *vnode)
597 {
598 struct walk_stmt_info wi;
599 tree global = vnode->decl;
600
601 memset (&wi, 0, sizeof (wi));
602 wi.pset = visited_nodes;
603 walk_tree (&DECL_INITIAL (global), scan_initializer_for_static_refs,
604 &wi, wi.pset);
605 }
606
607 /* Set up the persistent info for FN. */
608
609 static ipa_reference_local_vars_info_t
610 init_function_info (struct cgraph_node *fn)
611 {
612 ipa_reference_vars_info_t info
613 = XCNEW (struct ipa_reference_vars_info_d);
614 ipa_reference_local_vars_info_t l
615 = XCNEW (struct ipa_reference_local_vars_info_d);
616
617 /* Add the info to the tree's annotation. */
618 set_reference_vars_info (fn, info);
619
620 info->local = l;
621 l->statics_read = BITMAP_ALLOC (&local_info_obstack);
622 l->statics_written = BITMAP_ALLOC (&local_info_obstack);
623
624 return l;
625 }
626
627 /* This is the main routine for finding the reference patterns for
628 global variables within a function FN. */
629
630 static void
631 analyze_function (struct cgraph_node *fn)
632 {
633 tree decl = fn->decl;
634 struct function *this_cfun = DECL_STRUCT_FUNCTION (decl);
635 basic_block this_block;
636 #ifdef ENABLE_CHECKING
637 tree step;
638 #endif
639
640 if (dump_file)
641 fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn));
642
643 push_cfun (DECL_STRUCT_FUNCTION (decl));
644 current_function_decl = decl;
645
646 init_function_info (fn);
647 FOR_EACH_BB_FN (this_block, this_cfun)
648 {
649 gimple_stmt_iterator gsi;
650 gimple phi;
651 tree op;
652 use_operand_p use;
653 ssa_op_iter iter;
654
655 /* Find the addresses taken in phi node arguments. */
656 for (gsi = gsi_start_phis (this_block);
657 !gsi_end_p (gsi);
658 gsi_next (&gsi))
659 {
660 phi = gsi_stmt (gsi);
661 FOR_EACH_PHI_ARG (use, phi, iter, SSA_OP_USE)
662 {
663 op = USE_FROM_PTR (use);
664 if (TREE_CODE (op) == ADDR_EXPR)
665 mark_address_taken (get_base_var (op));
666 }
667 }
668
669 for (gsi = gsi_start_bb (this_block); !gsi_end_p (gsi); gsi_next (&gsi))
670 scan_stmt_for_static_refs (&gsi, fn);
671 }
672
673 #ifdef ENABLE_CHECKING
674 /* Verify that all local initializers was expanded by gimplifier. */
675 for (step = DECL_STRUCT_FUNCTION (decl)->local_decls;
676 step;
677 step = TREE_CHAIN (step))
678 {
679 tree var = TREE_VALUE (step);
680 if (TREE_CODE (var) == VAR_DECL
681 && DECL_INITIAL (var)
682 && !TREE_STATIC (var))
683 gcc_unreachable ();
684 }
685 #endif
686 pop_cfun ();
687 current_function_decl = NULL;
688 }
689
690 /* Remove local data associated with function FN. */
691 static void
692 clean_function_local_data (struct cgraph_node *fn)
693 {
694 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
695 ipa_reference_local_vars_info_t l = info->local;
696 if (l)
697 {
698 if (l->statics_read
699 && l->statics_read != all_module_statics)
700 BITMAP_FREE (l->statics_read);
701 if (l->statics_written
702 &&l->statics_written != all_module_statics)
703 BITMAP_FREE (l->statics_written);
704 free (l);
705 info->local = NULL;
706 }
707 }
708
709 /* Remove all data associated with function FN. */
710
711 static void
712 clean_function (struct cgraph_node *fn)
713 {
714 ipa_reference_vars_info_t info = get_reference_vars_info (fn);
715 ipa_reference_global_vars_info_t g = info->global;
716
717 clean_function_local_data (fn);
718 if (g)
719 {
720 if (g->statics_read
721 && g->statics_read != all_module_statics)
722 BITMAP_FREE (g->statics_read);
723
724 if (g->statics_written
725 && g->statics_written != all_module_statics)
726 BITMAP_FREE (g->statics_written);
727
728 if (g->statics_not_read
729 && g->statics_not_read != all_module_statics)
730 BITMAP_FREE (g->statics_not_read);
731
732 if (g->statics_not_written
733 && g->statics_not_written != all_module_statics)
734 BITMAP_FREE (g->statics_not_written);
735 free (g);
736 info->global = NULL;
737 }
738
739 free (get_reference_vars_info (fn));
740 set_reference_vars_info (fn, NULL);
741 }
742
743 /* Called when new function is inserted to callgraph late. */
744 static void
745 add_new_function (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
746 {
747 /* There are some shared nodes, in particular the initializers on
748 static declarations. We do not need to scan them more than once
749 since all we would be interested in are the addressof
750 operations. */
751 analyze_function (node);
752 visited_nodes = NULL;
753 }
754
755 static bitmap
756 copy_local_bitmap (bitmap src)
757 {
758 bitmap dst;
759 if (!src)
760 return NULL;
761 if (src == all_module_statics)
762 return all_module_statics;
763 dst = BITMAP_ALLOC (&local_info_obstack);
764 bitmap_copy (dst, src);
765 return dst;
766 }
767
768 static bitmap
769 copy_global_bitmap (bitmap src)
770 {
771 bitmap dst;
772 if (!src)
773 return NULL;
774 if (src == all_module_statics)
775 return all_module_statics;
776 dst = BITMAP_ALLOC (&global_info_obstack);
777 bitmap_copy (dst, src);
778 return dst;
779 }
780
781 /* Called when new clone is inserted to callgraph late. */
782
783 static void
784 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
785 void *data ATTRIBUTE_UNUSED)
786 {
787 ipa_reference_global_vars_info_t ginfo;
788 ipa_reference_local_vars_info_t linfo;
789 ipa_reference_global_vars_info_t dst_ginfo;
790 ipa_reference_local_vars_info_t dst_linfo;
791
792 ginfo = get_global_reference_vars_info (src);
793 linfo = get_local_reference_vars_info (src);
794 if (!linfo && !ginfo)
795 return;
796 init_function_info (dst);
797 if (linfo)
798 {
799 dst_linfo = get_local_reference_vars_info (dst);
800 dst_linfo->statics_read = copy_local_bitmap (linfo->statics_read);
801 dst_linfo->statics_written = copy_local_bitmap (linfo->statics_written);
802 dst_linfo->calls_read_all = linfo->calls_read_all;
803 dst_linfo->calls_write_all = linfo->calls_write_all;
804 }
805 if (ginfo)
806 {
807 get_reference_vars_info (dst)->global = XCNEW (struct ipa_reference_global_vars_info_d);
808 dst_ginfo = get_global_reference_vars_info (dst);
809 dst_ginfo->statics_read = copy_global_bitmap (ginfo->statics_read);
810 dst_ginfo->statics_written = copy_global_bitmap (ginfo->statics_written);
811 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
812 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
813 }
814 }
815
816 /* Called when node is removed. */
817
818 static void
819 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
820 {
821 if (get_reference_vars_info (node))
822 clean_function (node);
823 }
824
825 /* Analyze each function in the cgraph to see which global or statics
826 are read or written. */
827
828 static void
829 generate_summary (void)
830 {
831 struct cgraph_node *node;
832 struct varpool_node *vnode;
833 unsigned int index;
834 bitmap_iterator bi;
835 bitmap module_statics_readonly;
836 bitmap bm_temp;
837
838 function_insertion_hook_holder =
839 cgraph_add_function_insertion_hook (&add_new_function, NULL);
840 node_removal_hook_holder =
841 cgraph_add_node_removal_hook (&remove_node_data, NULL);
842 node_duplication_hook_holder =
843 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
844 ipa_init ();
845 module_statics_readonly = BITMAP_ALLOC (&local_info_obstack);
846 bm_temp = BITMAP_ALLOC (&local_info_obstack);
847
848 /* Process all of the variables first. */
849 FOR_EACH_STATIC_INITIALIZER (vnode)
850 analyze_variable (vnode);
851
852 /* Process all of the functions next.
853
854 We do not want to process any of the clones so we check that this
855 is a master clone. However, we do need to process any
856 AVAIL_OVERWRITABLE functions (these are never clones) because
857 they may cause a static variable to escape. The code that can
858 overwrite such a function cannot access the statics because it
859 would not be in the same compilation unit. When the analysis is
860 finished, the computed information of these AVAIL_OVERWRITABLE is
861 replaced with worst case info.
862 */
863 for (node = cgraph_nodes; node; node = node->next)
864 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
865 analyze_function (node);
866
867 pointer_set_destroy (visited_nodes);
868 visited_nodes = NULL;
869
870 /* Prune out the variables that were found to behave badly
871 (i.e. have their address taken). */
872 EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi)
873 {
874 splay_tree_remove (reference_vars_to_consider, index);
875 }
876
877 bitmap_and_compl_into (all_module_statics,
878 module_statics_escape);
879
880 bitmap_and_compl (module_statics_readonly, all_module_statics,
881 module_statics_written);
882
883 /* If the address is not taken, we can unset the addressable bit
884 on this variable. */
885 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
886 {
887 tree var = get_static_decl (index);
888 TREE_ADDRESSABLE (var) = 0;
889 if (dump_file)
890 fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n",
891 get_static_name (index));
892 }
893
894 /* If the variable is never written, we can set the TREE_READONLY
895 flag. Additionally if it has a DECL_INITIAL that is made up of
896 constants we can treat the entire global as a constant. */
897
898 bitmap_and_compl (module_statics_readonly, all_module_statics,
899 module_statics_written);
900 EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi)
901 {
902 tree var = get_static_decl (index);
903
904 /* Ignore variables in named sections - changing TREE_READONLY
905 changes the section flags, potentially causing conflicts with
906 other variables in the same named section. */
907 if (DECL_SECTION_NAME (var) == NULL_TREE)
908 {
909 TREE_READONLY (var) = 1;
910 if (dump_file)
911 fprintf (dump_file, "read-only var %s\n",
912 get_static_name (index));
913 }
914 }
915
916 BITMAP_FREE(module_statics_escape);
917 BITMAP_FREE(module_statics_written);
918 module_statics_escape = NULL;
919 module_statics_written = NULL;
920
921 if (dump_file)
922 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
923 {
924 fprintf (dump_file, "\nPromotable global:%s",
925 get_static_name (index));
926 }
927
928 for (node = cgraph_nodes; node; node = node->next)
929 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
930 {
931 ipa_reference_local_vars_info_t l;
932 l = get_reference_vars_info (node)->local;
933
934 /* Any variables that are not in all_module_statics are
935 removed from the local maps. This will include all of the
936 variables that were found to escape in the function
937 scanning. */
938 bitmap_and_into (l->statics_read,
939 all_module_statics);
940 bitmap_and_into (l->statics_written,
941 all_module_statics);
942 }
943
944 BITMAP_FREE(module_statics_readonly);
945 BITMAP_FREE(bm_temp);
946
947 if (dump_file)
948 for (node = cgraph_nodes; node; node = node->next)
949 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
950 {
951 ipa_reference_local_vars_info_t l;
952 unsigned int index;
953 bitmap_iterator bi;
954
955 l = get_reference_vars_info (node)->local;
956 fprintf (dump_file,
957 "\nFunction name:%s/%i:",
958 cgraph_node_name (node), node->uid);
959 fprintf (dump_file, "\n locals read: ");
960 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
961 0, index, bi)
962 {
963 fprintf (dump_file, "%s ",
964 get_static_name (index));
965 }
966 fprintf (dump_file, "\n locals written: ");
967 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
968 0, index, bi)
969 {
970 fprintf(dump_file, "%s ",
971 get_static_name (index));
972 }
973 if (l->calls_read_all)
974 fprintf (dump_file, "\n calls read all: ");
975 if (l->calls_write_all)
976 fprintf (dump_file, "\n calls read all: ");
977 }
978 }
979 \f
980 /* Produce the global information by preforming a transitive closure
981 on the local information that was produced by ipa_analyze_function
982 and ipa_analyze_variable. */
983
984 static unsigned int
985 propagate (void)
986 {
987 struct cgraph_node *node;
988 struct cgraph_node *w;
989 struct cgraph_node **order =
990 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
991 int order_pos = ipa_utils_reduced_inorder (order, false, true);
992 int i;
993
994 cgraph_remove_function_insertion_hook (function_insertion_hook_holder);
995 if (dump_file)
996 dump_cgraph (dump_file);
997
998 /* Propagate the local information thru the call graph to produce
999 the global information. All the nodes within a cycle will have
1000 the same info so we collapse cycles first. Then we can do the
1001 propagation in one pass from the leaves to the roots. */
1002 order_pos = ipa_utils_reduced_inorder (order, true, true);
1003 if (dump_file)
1004 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
1005
1006 for (i = 0; i < order_pos; i++ )
1007 {
1008 ipa_reference_vars_info_t node_info;
1009 ipa_reference_global_vars_info_t node_g =
1010 XCNEW (struct ipa_reference_global_vars_info_d);
1011 ipa_reference_local_vars_info_t node_l;
1012
1013 bool read_all;
1014 bool write_all;
1015 struct ipa_dfs_info * w_info;
1016
1017 node = order[i];
1018 node_info = get_reference_vars_info (node);
1019 if (!node_info)
1020 {
1021 dump_cgraph_node (stderr, node);
1022 dump_cgraph (stderr);
1023 gcc_unreachable ();
1024 }
1025
1026 gcc_assert (!node_info->global);
1027 node_l = node_info->local;
1028
1029 read_all = node_l->calls_read_all;
1030 write_all = node_l->calls_write_all;
1031
1032 /* If any node in a cycle is calls_read_all or calls_write_all
1033 they all are. */
1034 w_info = (struct ipa_dfs_info *) node->aux;
1035 w = w_info->next_cycle;
1036 while (w)
1037 {
1038 ipa_reference_local_vars_info_t w_l =
1039 get_reference_vars_info (w)->local;
1040 read_all |= w_l->calls_read_all;
1041 write_all |= w_l->calls_write_all;
1042
1043 w_info = (struct ipa_dfs_info *) w->aux;
1044 w = w_info->next_cycle;
1045 }
1046
1047 /* Initialized the bitmaps for the reduced nodes */
1048 if (read_all)
1049 node_g->statics_read = all_module_statics;
1050 else
1051 {
1052 node_g->statics_read = BITMAP_ALLOC (&global_info_obstack);
1053 bitmap_copy (node_g->statics_read,
1054 node_l->statics_read);
1055 }
1056
1057 if (write_all)
1058 node_g->statics_written = all_module_statics;
1059 else
1060 {
1061 node_g->statics_written = BITMAP_ALLOC (&global_info_obstack);
1062 bitmap_copy (node_g->statics_written,
1063 node_l->statics_written);
1064 }
1065
1066 propagate_bits (node_g, node);
1067 w_info = (struct ipa_dfs_info *) node->aux;
1068 w = w_info->next_cycle;
1069 while (w)
1070 {
1071 ipa_reference_vars_info_t w_ri =
1072 get_reference_vars_info (w);
1073 ipa_reference_local_vars_info_t w_l = w_ri->local;
1074
1075 /* These global bitmaps are initialized from the local info
1076 of all of the nodes in the region. However there is no
1077 need to do any work if the bitmaps were set to
1078 all_module_statics. */
1079 if (!read_all)
1080 bitmap_ior_into (node_g->statics_read,
1081 w_l->statics_read);
1082 if (!write_all)
1083 bitmap_ior_into (node_g->statics_written,
1084 w_l->statics_written);
1085 propagate_bits (node_g, w);
1086 w_info = (struct ipa_dfs_info *) w->aux;
1087 w = w_info->next_cycle;
1088 }
1089
1090 /* All nodes within a cycle have the same global info bitmaps. */
1091 node_info->global = node_g;
1092 w_info = (struct ipa_dfs_info *) node->aux;
1093 w = w_info->next_cycle;
1094 while (w)
1095 {
1096 ipa_reference_vars_info_t w_ri =
1097 get_reference_vars_info (w);
1098
1099 gcc_assert (!w_ri->global);
1100 w_ri->global = XCNEW (struct ipa_reference_global_vars_info_d);
1101 w_ri->global->statics_read = copy_global_bitmap (node_g->statics_read);
1102 w_ri->global->statics_written = copy_global_bitmap (node_g->statics_written);
1103
1104 w_info = (struct ipa_dfs_info *) w->aux;
1105 w = w_info->next_cycle;
1106 }
1107 }
1108
1109 if (dump_file)
1110 {
1111 for (i = 0; i < order_pos; i++ )
1112 {
1113 ipa_reference_vars_info_t node_info;
1114 ipa_reference_global_vars_info_t node_g;
1115 ipa_reference_local_vars_info_t node_l;
1116 unsigned int index;
1117 bitmap_iterator bi;
1118 struct ipa_dfs_info * w_info;
1119
1120 node = order[i];
1121 node_info = get_reference_vars_info (node);
1122 node_g = node_info->global;
1123 node_l = node_info->local;
1124 fprintf (dump_file,
1125 "\nFunction name:%s/%i:",
1126 cgraph_node_name (node), node->uid);
1127 fprintf (dump_file, "\n locals read: ");
1128 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
1129 0, index, bi)
1130 {
1131 fprintf (dump_file, "%s ",
1132 get_static_name (index));
1133 }
1134 fprintf (dump_file, "\n locals written: ");
1135 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
1136 0, index, bi)
1137 {
1138 fprintf(dump_file, "%s ",
1139 get_static_name (index));
1140 }
1141
1142 w_info = (struct ipa_dfs_info *) node->aux;
1143 w = w_info->next_cycle;
1144 while (w)
1145 {
1146 ipa_reference_vars_info_t w_ri =
1147 get_reference_vars_info (w);
1148 ipa_reference_local_vars_info_t w_l = w_ri->local;
1149 fprintf (dump_file, "\n next cycle: %s/%i ",
1150 cgraph_node_name (w), w->uid);
1151 fprintf (dump_file, "\n locals read: ");
1152 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
1153 0, index, bi)
1154 {
1155 fprintf (dump_file, "%s ",
1156 get_static_name (index));
1157 }
1158
1159 fprintf (dump_file, "\n locals written: ");
1160 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
1161 0, index, bi)
1162 {
1163 fprintf(dump_file, "%s ",
1164 get_static_name (index));
1165 }
1166
1167
1168 w_info = (struct ipa_dfs_info *) w->aux;
1169 w = w_info->next_cycle;
1170 }
1171 fprintf (dump_file, "\n globals read: ");
1172 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
1173 0, index, bi)
1174 {
1175 fprintf (dump_file, "%s ",
1176 get_static_name (index));
1177 }
1178 fprintf (dump_file, "\n globals written: ");
1179 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
1180 0, index, bi)
1181 {
1182 fprintf (dump_file, "%s ",
1183 get_static_name (index));
1184 }
1185 }
1186 }
1187
1188 /* Cleanup. */
1189 for (i = 0; i < order_pos; i++ )
1190 {
1191 ipa_reference_vars_info_t node_info;
1192 ipa_reference_global_vars_info_t node_g;
1193 node = order[i];
1194 node_info = get_reference_vars_info (node);
1195 node_g = node_info->global;
1196
1197 /* Create the complimentary sets. These are more useful for
1198 certain apis. */
1199 node_g->statics_not_read = BITMAP_ALLOC (&global_info_obstack);
1200 node_g->statics_not_written = BITMAP_ALLOC (&global_info_obstack);
1201
1202 if (node_g->statics_read != all_module_statics)
1203 bitmap_and_compl (node_g->statics_not_read,
1204 all_module_statics,
1205 node_g->statics_read);
1206
1207 if (node_g->statics_written
1208 != all_module_statics)
1209 bitmap_and_compl (node_g->statics_not_written,
1210 all_module_statics,
1211 node_g->statics_written);
1212 }
1213
1214 free (order);
1215
1216 for (node = cgraph_nodes; node; node = node->next)
1217 {
1218 ipa_reference_vars_info_t node_info;
1219 node_info = get_reference_vars_info (node);
1220 /* Get rid of the aux information. */
1221
1222 if (node->aux)
1223 {
1224 free (node->aux);
1225 node->aux = NULL;
1226 }
1227
1228 if (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)
1229 clean_function (node);
1230 else if (node_info)
1231 clean_function_local_data (node);
1232 }
1233 bitmap_obstack_release (&local_info_obstack);
1234 return 0;
1235 }
1236
1237
1238 static bool
1239 gate_reference (void)
1240 {
1241 return (flag_ipa_reference
1242 /* Don't bother doing anything if the program has errors. */
1243 && !(errorcount || sorrycount));
1244 }
1245
1246 struct ipa_opt_pass pass_ipa_reference =
1247 {
1248 {
1249 IPA_PASS,
1250 "static-var", /* name */
1251 gate_reference, /* gate */
1252 propagate, /* execute */
1253 NULL, /* sub */
1254 NULL, /* next */
1255 0, /* static_pass_number */
1256 TV_IPA_REFERENCE, /* tv_id */
1257 0, /* properties_required */
1258 0, /* properties_provided */
1259 0, /* properties_destroyed */
1260 0, /* todo_flags_start */
1261 0 /* todo_flags_finish */
1262 },
1263 generate_summary, /* generate_summary */
1264 NULL, /* write_summary */
1265 NULL, /* read_summary */
1266 NULL, /* function_read_summary */
1267 0, /* TODOs */
1268 NULL, /* function_transform */
1269 NULL /* variable_transform */
1270 };
1271
1272 #include "gt-ipa-reference.h"