tree.h (memory_identifier_string): Remove.
[gcc.git] / gcc / ipa-reference.c
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>
5
6 This file is part of GCC.
7
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
11 version.
12
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
16 for more details.
17
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/>. */
21
22 /* This file gathers information about how variables whose scope is
23 confined to the compilation unit are used.
24
25 The transitive call site specific clobber effects are computed
26 for the variables whose scope is contained within this compilation
27 unit.
28
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
38 information. */
39
40 #include "config.h"
41 #include "system.h"
42 #include "coretypes.h"
43 #include "tm.h"
44 #include "tree.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"
51 #include "ggc.h"
52 #include "ipa-utils.h"
53 #include "ipa-reference.h"
54 #include "gimple.h"
55 #include "cgraph.h"
56 #include "output.h"
57 #include "flags.h"
58 #include "timevar.h"
59 #include "diagnostic.h"
60 #include "langhooks.h"
61 #include "lto-streamer.h"
62
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);
68
69 /* The static variables defined within the compilation unit that are
70 loaded or stored directly by function that owns this structure. */
71
72 struct ipa_reference_local_vars_info_d
73 {
74 bitmap statics_read;
75 bitmap statics_written;
76
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. */
82 bool calls_read_all;
83 bool calls_write_all;
84 };
85
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. */
90
91 struct ipa_reference_global_vars_info_d
92 {
93 bitmap statics_read;
94 bitmap statics_written;
95 };
96
97 /* Information we save about every function after ipa-reference is completted. */
98
99 struct ipa_reference_optimization_summary_d
100 {
101 bitmap statics_not_read;
102 bitmap statics_not_written;
103 };
104
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 typedef struct ipa_reference_optimization_summary_d *ipa_reference_optimization_summary_t;
108
109 struct ipa_reference_vars_info_d
110 {
111 struct ipa_reference_local_vars_info_d local;
112 struct ipa_reference_global_vars_info_d global;
113 };
114
115 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
116
117 /* This splay tree contains all of the static variables that are
118 being considered by the compilation level alias analysis. */
119 static splay_tree reference_vars_to_consider;
120
121 /* A bit is set for every module static we are considering. This is
122 ored into the local info when asm code is found that clobbers all
123 memory. */
124 static bitmap all_module_statics;
125
126 /* Obstack holding bitmaps of local analysis (live from analysis to
127 propagation) */
128 static bitmap_obstack local_info_obstack;
129 /* Obstack holding global analysis live forever. */
130 static bitmap_obstack optimization_summary_obstack;
131
132 /* Holders of ipa cgraph hooks: */
133 static struct cgraph_2node_hook_list *node_duplication_hook_holder;
134 static struct cgraph_node_hook_list *node_removal_hook_holder;
135
136 /* Vector where the reference var infos are actually stored. */
137 DEF_VEC_P (ipa_reference_vars_info_t);
138 DEF_VEC_ALLOC_P (ipa_reference_vars_info_t, heap);
139 static VEC (ipa_reference_vars_info_t, heap) *ipa_reference_vars_vector;
140 DEF_VEC_P (ipa_reference_optimization_summary_t);
141 DEF_VEC_ALLOC_P (ipa_reference_optimization_summary_t, heap);
142 static VEC (ipa_reference_optimization_summary_t, heap) *ipa_reference_opt_sum_vector;
143
144 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
145 static inline ipa_reference_vars_info_t
146 get_reference_vars_info (struct cgraph_node *node)
147 {
148 if (!ipa_reference_vars_vector
149 || VEC_length (ipa_reference_vars_info_t,
150 ipa_reference_vars_vector) <= (unsigned int) node->uid)
151 return NULL;
152 return VEC_index (ipa_reference_vars_info_t, ipa_reference_vars_vector,
153 node->uid);
154 }
155
156 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
157 static inline ipa_reference_optimization_summary_t
158 get_reference_optimization_summary (struct cgraph_node *node)
159 {
160 if (!ipa_reference_opt_sum_vector
161 || (VEC_length (ipa_reference_optimization_summary_t,
162 ipa_reference_opt_sum_vector)
163 <= (unsigned int) node->uid))
164 return NULL;
165 return VEC_index (ipa_reference_optimization_summary_t, ipa_reference_opt_sum_vector,
166 node->uid);
167 }
168
169 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
170 static inline void
171 set_reference_vars_info (struct cgraph_node *node,
172 ipa_reference_vars_info_t info)
173 {
174 if (!ipa_reference_vars_vector
175 || VEC_length (ipa_reference_vars_info_t,
176 ipa_reference_vars_vector) <= (unsigned int) node->uid)
177 VEC_safe_grow_cleared (ipa_reference_vars_info_t, heap,
178 ipa_reference_vars_vector, node->uid + 1);
179 VEC_replace (ipa_reference_vars_info_t, ipa_reference_vars_vector,
180 node->uid, info);
181 }
182
183 /* Return the ipa_reference_vars structure starting from the cgraph NODE. */
184 static inline void
185 set_reference_optimization_summary (struct cgraph_node *node,
186 ipa_reference_optimization_summary_t info)
187 {
188 if (!ipa_reference_opt_sum_vector
189 || (VEC_length (ipa_reference_optimization_summary_t,
190 ipa_reference_opt_sum_vector)
191 <= (unsigned int) node->uid))
192 VEC_safe_grow_cleared (ipa_reference_optimization_summary_t,
193 heap, ipa_reference_opt_sum_vector, node->uid + 1);
194 VEC_replace (ipa_reference_optimization_summary_t,
195 ipa_reference_opt_sum_vector, node->uid, info);
196 }
197
198 /* Return a bitmap indexed by_DECL_UID uid for the static variables
199 that are not read during the execution of the function FN. Returns
200 NULL if no data is available. */
201
202 bitmap
203 ipa_reference_get_not_read_global (struct cgraph_node *fn)
204 {
205 ipa_reference_optimization_summary_t info;
206
207 info = get_reference_optimization_summary (fn);
208 if (info)
209 return info->statics_not_read;
210 else
211 return NULL;
212 }
213
214 /* Return a bitmap indexed by DECL_UID uid for the static variables
215 that are not written during the execution of the function FN. Note
216 that variables written may or may not be read during the function
217 call. Returns NULL if no data is available. */
218
219 bitmap
220 ipa_reference_get_not_written_global (struct cgraph_node *fn)
221 {
222 ipa_reference_optimization_summary_t info;
223
224 info = get_reference_optimization_summary (fn);
225 if (info)
226 return info->statics_not_written;
227 else
228 return NULL;
229 }
230
231 \f
232
233 /* Add VAR to all_module_statics and the two
234 reference_vars_to_consider* sets. */
235
236 static inline void
237 add_static_var (tree var)
238 {
239 int uid = DECL_UID (var);
240 gcc_assert (TREE_CODE (var) == VAR_DECL);
241 if (!bitmap_bit_p (all_module_statics, uid))
242 {
243 if (dump_file)
244 splay_tree_insert (reference_vars_to_consider,
245 uid, (splay_tree_value)var);
246 bitmap_set_bit (all_module_statics, uid);
247 }
248 }
249
250 /* Return true if the variable T is the right kind of static variable to
251 perform compilation unit scope escape analysis. */
252
253 static inline bool
254 is_proper_for_analysis (tree t)
255 {
256 /* We handle only variables whose address is never taken. */
257 if (TREE_ADDRESSABLE (t))
258 return false;
259 /* If the variable has the "used" attribute, treat it as if it had a
260 been touched by the devil. */
261 if (DECL_PRESERVE_P (t))
262 return false;
263
264 /* Do not want to do anything with volatile except mark any
265 function that uses one to be not const or pure. */
266 if (TREE_THIS_VOLATILE (t))
267 return false;
268
269 /* We cannot touch decls where the type needs constructing. */
270 if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (t)))
271 return false;
272
273 /* This is a variable we care about. Check if we have seen it
274 before, and if not add it the set of variables we care about. */
275 if (!bitmap_bit_p (all_module_statics, DECL_UID (t)))
276 add_static_var (t);
277
278 return true;
279 }
280
281 /* Lookup the tree node for the static variable that has UID and
282 convert the name to a string for debugging. */
283
284 static const char *
285 get_static_name (int index)
286 {
287 splay_tree_node stn =
288 splay_tree_lookup (reference_vars_to_consider, index);
289 if (stn)
290 return lang_hooks.decl_printable_name ((tree)(stn->value), 2);
291 return NULL;
292 }
293
294 /* Or in all of the bits from every callee of X into X_GLOBAL, the caller's cycle,
295 bit vector. There are several cases to check to avoid the sparse
296 bitmap oring. */
297
298 static void
299 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
300 {
301 struct cgraph_edge *e;
302 for (e = x->callees; e; e = e->next_callee)
303 {
304 struct cgraph_node *y = e->callee;
305
306 /* Only look into nodes we can propagate something. */
307 if (cgraph_function_body_availability (e->callee) > AVAIL_OVERWRITABLE)
308 {
309 if (get_reference_vars_info (y))
310 {
311 ipa_reference_vars_info_t y_info
312 = get_reference_vars_info (y);
313 ipa_reference_global_vars_info_t y_global = &y_info->global;
314
315 /* Calls in current cycle do not have global computed yet. */
316 if (!y_global->statics_read)
317 continue;
318
319 if (x_global->statics_read
320 != all_module_statics)
321 {
322 if (y_global->statics_read
323 == all_module_statics)
324 {
325 BITMAP_FREE (x_global->statics_read);
326 x_global->statics_read
327 = all_module_statics;
328 }
329 /* Skip bitmaps that are pointer equal to node's bitmap
330 (no reason to spin within the cycle). */
331 else if (x_global->statics_read
332 != y_global->statics_read)
333 bitmap_ior_into (x_global->statics_read,
334 y_global->statics_read);
335 }
336
337 if (x_global->statics_written
338 != all_module_statics)
339 {
340 if (y_global->statics_written
341 == all_module_statics)
342 {
343 BITMAP_FREE (x_global->statics_written);
344 x_global->statics_written
345 = all_module_statics;
346 }
347 /* Skip bitmaps that are pointer equal to node's bitmap
348 (no reason to spin within the cycle). */
349 else if (x_global->statics_written
350 != y_global->statics_written)
351 bitmap_ior_into (x_global->statics_written,
352 y_global->statics_written);
353 }
354 }
355 else
356 gcc_unreachable ();
357 }
358 }
359 }
360
361 /* The init routine for analyzing global static variable usage. See
362 comments at top for description. */
363 static void
364 ipa_init (void)
365 {
366 static bool init_p = false;
367
368 if (init_p)
369 return;
370
371 init_p = true;
372
373 if (dump_file)
374 reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
375
376 bitmap_obstack_initialize (&local_info_obstack);
377 bitmap_obstack_initialize (&optimization_summary_obstack);
378 all_module_statics = BITMAP_ALLOC (&local_info_obstack);
379
380 node_removal_hook_holder =
381 cgraph_add_node_removal_hook (&remove_node_data, NULL);
382 node_duplication_hook_holder =
383 cgraph_add_node_duplication_hook (&duplicate_node_data, NULL);
384 }
385
386
387 /* Set up the persistent info for FN. */
388
389 static ipa_reference_local_vars_info_t
390 init_function_info (struct cgraph_node *fn)
391 {
392 ipa_reference_vars_info_t info
393 = XCNEW (struct ipa_reference_vars_info_d);
394
395 /* Add the info to the tree's annotation. */
396 set_reference_vars_info (fn, info);
397
398 info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
399 info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
400
401 return &info->local;
402 }
403
404
405 /* This is the main routine for finding the reference patterns for
406 global variables within a function FN. */
407
408 static void
409 analyze_function (struct cgraph_node *fn)
410 {
411 ipa_reference_local_vars_info_t local;
412 struct ipa_ref *ref;
413 int i;
414 tree var;
415 struct cgraph_edge *ie;
416
417 local = init_function_info (fn);
418 /* Process indirect calls. All direct calles are handled at propagation
419 time. */
420 for (ie = fn->indirect_calls; ie; ie = ie->next_callee)
421 if (!(ie->indirect_info->ecf_flags & ECF_CONST))
422 {
423 local->calls_read_all = true;
424 if (!(ie->indirect_info->ecf_flags & ECF_PURE)
425 && ((ie->indirect_info->ecf_flags & (ECF_NOTHROW | ECF_NORETURN))
426 != (ECF_NOTHROW | ECF_NORETURN)))
427 local->calls_write_all = true;
428 }
429 for (i = 0; ipa_ref_list_reference_iterate (&fn->ref_list, i, ref); i++)
430 {
431 if (ref->refered_type != IPA_REF_VARPOOL)
432 continue;
433 var = ipa_ref_varpool_node (ref)->decl;
434 if (ipa_ref_varpool_node (ref)->externally_visible
435 || !ipa_ref_varpool_node (ref)->analyzed
436 || !is_proper_for_analysis (var))
437 continue;
438 switch (ref->use)
439 {
440 case IPA_REF_LOAD:
441 bitmap_set_bit (local->statics_read, DECL_UID (var));
442 break;
443 case IPA_REF_STORE:
444 bitmap_set_bit (local->statics_written, DECL_UID (var));
445 break;
446 case IPA_REF_ADDR:
447 break;
448 }
449 }
450
451 if ((flags_from_decl_or_type (fn->decl) & (ECF_NOTHROW | ECF_NORETURN))
452 == (ECF_NOTHROW | ECF_NORETURN))
453 {
454 local->calls_write_all = false;
455 bitmap_clear (local->statics_written);
456 }
457
458 /* Free bitmaps of direct references if we can not use them anyway. */
459 if (local->calls_write_all)
460 BITMAP_FREE (local->statics_written);
461 if (local->calls_read_all)
462 BITMAP_FREE (local->statics_read);
463 }
464
465 static bitmap
466 copy_global_bitmap (bitmap src)
467 {
468 bitmap dst;
469 if (!src)
470 return NULL;
471 dst = BITMAP_ALLOC (&optimization_summary_obstack);
472 bitmap_copy (dst, src);
473 return dst;
474 }
475
476
477 /* Called when new clone is inserted to callgraph late. */
478
479 static void
480 duplicate_node_data (struct cgraph_node *src, struct cgraph_node *dst,
481 void *data ATTRIBUTE_UNUSED)
482 {
483 ipa_reference_optimization_summary_t ginfo;
484 ipa_reference_optimization_summary_t dst_ginfo;
485
486 ginfo = get_reference_optimization_summary (src);
487 if (!ginfo)
488 return;
489 dst_ginfo = XCNEW (struct ipa_reference_optimization_summary_d);
490 set_reference_optimization_summary (dst, dst_ginfo);
491 dst_ginfo->statics_not_read = copy_global_bitmap (ginfo->statics_not_read);
492 dst_ginfo->statics_not_written = copy_global_bitmap (ginfo->statics_not_written);
493 }
494
495 /* Called when node is removed. */
496
497 static void
498 remove_node_data (struct cgraph_node *node, void *data ATTRIBUTE_UNUSED)
499 {
500 ipa_reference_optimization_summary_t ginfo;
501 ginfo = get_reference_optimization_summary (node);
502 if (ginfo)
503 {
504 if (ginfo->statics_not_read
505 && ginfo->statics_not_read != all_module_statics)
506 BITMAP_FREE (ginfo->statics_not_read);
507
508 if (ginfo->statics_not_written
509 && ginfo->statics_not_written != all_module_statics)
510 BITMAP_FREE (ginfo->statics_not_written);
511 free (ginfo);
512 set_reference_optimization_summary (node, NULL);
513 }
514 }
515
516 /* Analyze each function in the cgraph to see which global or statics
517 are read or written. */
518
519 static void
520 generate_summary (void)
521 {
522 struct cgraph_node *node;
523 unsigned int index;
524 bitmap_iterator bi;
525 bitmap bm_temp;
526
527 ipa_init ();
528 bm_temp = BITMAP_ALLOC (&local_info_obstack);
529
530 /* Process all of the functions next. */
531 for (node = cgraph_nodes; node; node = node->next)
532 if (node->analyzed)
533 analyze_function (node);
534
535 if (dump_file)
536 EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
537 {
538 fprintf (dump_file, "\nPromotable global:%s",
539 get_static_name (index));
540 }
541
542 BITMAP_FREE(bm_temp);
543
544 if (dump_file)
545 for (node = cgraph_nodes; node; node = node->next)
546 if (cgraph_function_body_availability (node) >= AVAIL_OVERWRITABLE)
547 {
548 ipa_reference_local_vars_info_t l;
549 unsigned int index;
550 bitmap_iterator bi;
551
552 l = &get_reference_vars_info (node)->local;
553 fprintf (dump_file,
554 "\nFunction name:%s/%i:",
555 cgraph_node_name (node), node->uid);
556 fprintf (dump_file, "\n locals read: ");
557 if (l->statics_read)
558 EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
559 0, index, bi)
560 {
561 fprintf (dump_file, "%s ",
562 get_static_name (index));
563 }
564 fprintf (dump_file, "\n locals written: ");
565 if (l->statics_written)
566 EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
567 0, index, bi)
568 {
569 fprintf(dump_file, "%s ",
570 get_static_name (index));
571 }
572 if (l->calls_read_all)
573 fprintf (dump_file, "\n calls read all: ");
574 if (l->calls_write_all)
575 fprintf (dump_file, "\n calls read all: ");
576 }
577 }
578 \f
579 /* Set READ_ALL/WRITE_ALL based on DECL flags. */
580
581 static void
582 read_write_all_from_decl (tree decl, bool * read_all, bool * write_all)
583 {
584 int flags = flags_from_decl_or_type (decl);
585 if (flags & ECF_CONST)
586 ;
587 else if (flags & ECF_PURE)
588 *read_all = true;
589 else
590 {
591 /* TODO: To be able to produce sane results, we should also handle
592 common builtins, in particular throw. */
593 *read_all = true;
594 /* When function does not return, it is safe to ignore anythign it writes
595 to, because the effect will never happen. */
596 if ((flags & (ECF_NOTHROW | ECF_NORETURN))
597 != (ECF_NOTHROW | ECF_NORETURN))
598 *write_all = true;
599 }
600 }
601
602 /* Produce the global information by preforming a transitive closure
603 on the local information that was produced by ipa_analyze_function */
604
605 static unsigned int
606 propagate (void)
607 {
608 struct cgraph_node *node;
609 struct cgraph_node *w;
610 struct cgraph_node **order =
611 XCNEWVEC (struct cgraph_node *, cgraph_n_nodes);
612 int order_pos = ipa_utils_reduced_inorder (order, false, true, NULL);
613 int i;
614
615 if (dump_file)
616 dump_cgraph (dump_file);
617
618 ipa_discover_readonly_nonaddressable_vars ();
619 generate_summary ();
620
621 /* Propagate the local information thru the call graph to produce
622 the global information. All the nodes within a cycle will have
623 the same info so we collapse cycles first. Then we can do the
624 propagation in one pass from the leaves to the roots. */
625 order_pos = ipa_utils_reduced_inorder (order, true, true, NULL);
626 if (dump_file)
627 ipa_utils_print_order(dump_file, "reduced", order, order_pos);
628
629 for (i = 0; i < order_pos; i++ )
630 {
631 ipa_reference_vars_info_t node_info;
632 ipa_reference_global_vars_info_t node_g;
633 ipa_reference_local_vars_info_t node_l;
634 struct cgraph_edge *e;
635
636 bool read_all;
637 bool write_all;
638 struct ipa_dfs_info * w_info;
639
640 node = order[i];
641 node_info = get_reference_vars_info (node);
642 if (!node_info)
643 {
644 dump_cgraph_node (stderr, node);
645 dump_cgraph (stderr);
646 gcc_unreachable ();
647 }
648
649 node_l = &node_info->local;
650 node_g = &node_info->global;
651
652 read_all = node_l->calls_read_all;
653 write_all = node_l->calls_write_all;
654
655 /* When function is overwrittable, we can not assume anything. */
656 if (cgraph_function_body_availability (node) <= AVAIL_OVERWRITABLE)
657 read_write_all_from_decl (node->decl, &read_all, &write_all);
658
659 for (e = node->callees; e; e = e->next_callee)
660 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
661 read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
662
663
664 /* If any node in a cycle is calls_read_all or calls_write_all
665 they all are. */
666 w_info = (struct ipa_dfs_info *) node->aux;
667 w = w_info->next_cycle;
668 while (w)
669 {
670 ipa_reference_local_vars_info_t w_l =
671 &get_reference_vars_info (w)->local;
672
673 /* When function is overwrittable, we can not assume anything. */
674 if (cgraph_function_body_availability (w) <= AVAIL_OVERWRITABLE)
675 read_write_all_from_decl (w->decl, &read_all, &write_all);
676
677 for (e = w->callees; e; e = e->next_callee)
678 if (cgraph_function_body_availability (e->callee) <= AVAIL_OVERWRITABLE)
679 read_write_all_from_decl (e->callee->decl, &read_all, &write_all);
680
681 read_all |= w_l->calls_read_all;
682 write_all |= w_l->calls_write_all;
683
684 w_info = (struct ipa_dfs_info *) w->aux;
685 w = w_info->next_cycle;
686 }
687
688
689 /* Initialized the bitmaps for the reduced nodes */
690 if (read_all)
691 node_g->statics_read = all_module_statics;
692 else
693 {
694 node_g->statics_read = BITMAP_ALLOC (&local_info_obstack);
695 bitmap_copy (node_g->statics_read,
696 node_l->statics_read);
697 }
698 if (write_all)
699 node_g->statics_written = all_module_statics;
700 else
701 {
702 node_g->statics_written = BITMAP_ALLOC (&local_info_obstack);
703 bitmap_copy (node_g->statics_written,
704 node_l->statics_written);
705 }
706
707 propagate_bits (node_g, node);
708 w_info = (struct ipa_dfs_info *) node->aux;
709 w = w_info->next_cycle;
710 while (w)
711 {
712 ipa_reference_vars_info_t w_ri =
713 get_reference_vars_info (w);
714 ipa_reference_local_vars_info_t w_l = &w_ri->local;
715
716 /* These global bitmaps are initialized from the local info
717 of all of the nodes in the region. However there is no
718 need to do any work if the bitmaps were set to
719 all_module_statics. */
720 if (!read_all)
721 bitmap_ior_into (node_g->statics_read,
722 w_l->statics_read);
723 if (!write_all)
724 bitmap_ior_into (node_g->statics_written,
725 w_l->statics_written);
726 propagate_bits (node_g, w);
727 w_info = (struct ipa_dfs_info *) w->aux;
728 w = w_info->next_cycle;
729 }
730
731 /* All nodes within a cycle have the same global info bitmaps. */
732 node_info->global = *node_g;
733 w_info = (struct ipa_dfs_info *) node->aux;
734 w = w_info->next_cycle;
735 while (w)
736 {
737 ipa_reference_vars_info_t w_ri =
738 get_reference_vars_info (w);
739
740 w_ri->global = *node_g;
741
742 w_info = (struct ipa_dfs_info *) w->aux;
743 w = w_info->next_cycle;
744 }
745 }
746
747 if (dump_file)
748 {
749 for (i = 0; i < order_pos; i++ )
750 {
751 ipa_reference_vars_info_t node_info;
752 ipa_reference_global_vars_info_t node_g;
753 ipa_reference_local_vars_info_t node_l;
754 unsigned int index;
755 bitmap_iterator bi;
756 struct ipa_dfs_info * w_info;
757
758 node = order[i];
759 node_info = get_reference_vars_info (node);
760 node_g = &node_info->global;
761 node_l = &node_info->local;
762 fprintf (dump_file,
763 "\nFunction name:%s/%i:",
764 cgraph_node_name (node), node->uid);
765 fprintf (dump_file, "\n locals read: ");
766 if (node_l->statics_read)
767 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read,
768 0, index, bi)
769 {
770 fprintf (dump_file, "%s ",
771 get_static_name (index));
772 }
773 fprintf (dump_file, "\n locals written: ");
774 if (node_l->statics_written)
775 EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written,
776 0, index, bi)
777 {
778 fprintf(dump_file, "%s ",
779 get_static_name (index));
780 }
781
782 w_info = (struct ipa_dfs_info *) node->aux;
783 w = w_info->next_cycle;
784 while (w)
785 {
786 ipa_reference_vars_info_t w_ri =
787 get_reference_vars_info (w);
788 ipa_reference_local_vars_info_t w_l = &w_ri->local;
789 fprintf (dump_file, "\n next cycle: %s/%i ",
790 cgraph_node_name (w), w->uid);
791 fprintf (dump_file, "\n locals read: ");
792 if (w_l->statics_read)
793 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read,
794 0, index, bi)
795 {
796 fprintf (dump_file, "%s ",
797 get_static_name (index));
798 }
799
800 fprintf (dump_file, "\n locals written: ");
801 if (w_l->statics_written)
802 EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written,
803 0, index, bi)
804 {
805 fprintf (dump_file, "%s ",
806 get_static_name (index));
807 }
808
809 w_info = (struct ipa_dfs_info *) w->aux;
810 w = w_info->next_cycle;
811 }
812 fprintf (dump_file, "\n globals read: ");
813 if (node_g->statics_read == all_module_statics)
814 fprintf (dump_file, "ALL");
815 else
816 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read,
817 0, index, bi)
818 {
819 fprintf (dump_file, "%s ",
820 get_static_name (index));
821 }
822 fprintf (dump_file, "\n globals written: ");
823 if (node_g->statics_written == all_module_statics)
824 fprintf (dump_file, "ALL");
825 else
826 EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written,
827 0, index, bi)
828 {
829 fprintf (dump_file, "%s ",
830 get_static_name (index));
831 }
832 }
833 }
834
835 /* Cleanup. */
836 for (i = 0; i < order_pos; i++ )
837 {
838 ipa_reference_vars_info_t node_info;
839 ipa_reference_global_vars_info_t node_g;
840 ipa_reference_optimization_summary_t opt;
841
842 node = order[i];
843 node_info = get_reference_vars_info (node);
844 if (cgraph_function_body_availability (node) > AVAIL_OVERWRITABLE)
845 {
846 node_g = &node_info->global;
847
848 opt = XCNEW (struct ipa_reference_optimization_summary_d);
849 set_reference_optimization_summary (node, opt);
850
851 /* Create the complimentary sets. */
852 opt->statics_not_read = BITMAP_ALLOC (&optimization_summary_obstack);
853 opt->statics_not_written = BITMAP_ALLOC (&optimization_summary_obstack);
854
855 if (node_g->statics_read != all_module_statics)
856 bitmap_and_compl (opt->statics_not_read,
857 all_module_statics,
858 node_g->statics_read);
859
860 if (node_g->statics_written
861 != all_module_statics)
862 bitmap_and_compl (opt->statics_not_written,
863 all_module_statics,
864 node_g->statics_written);
865 }
866 if (node_info)
867 free (node_info);
868 if (node->aux)
869 {
870 free (node->aux);
871 node->aux = NULL;
872 }
873 }
874
875 free (order);
876
877 bitmap_obstack_release (&local_info_obstack);
878 VEC_free (ipa_reference_vars_info_t, heap, ipa_reference_vars_vector);
879 ipa_reference_vars_vector = NULL;
880 if (dump_file)
881 splay_tree_delete (reference_vars_to_consider);
882 reference_vars_to_consider = NULL;
883 all_module_statics = NULL;
884 return 0;
885 }
886
887
888 static bool
889 gate_reference (void)
890 {
891 return (flag_ipa_reference
892 /* Don't bother doing anything if the program has errors. */
893 && !(errorcount || sorrycount));
894 }
895
896 struct ipa_opt_pass_d pass_ipa_reference =
897 {
898 {
899 IPA_PASS,
900 "static-var", /* name */
901 gate_reference, /* gate */
902 propagate, /* execute */
903 NULL, /* sub */
904 NULL, /* next */
905 0, /* static_pass_number */
906 TV_IPA_REFERENCE, /* tv_id */
907 0, /* properties_required */
908 0, /* properties_provided */
909 0, /* properties_destroyed */
910 0, /* todo_flags_start */
911 0 /* todo_flags_finish */
912 },
913 NULL, /* generate_summary */
914 NULL, /* write_summary */
915 NULL, /* read_summary */
916 NULL, /* write_optimization_summary */
917 NULL, /* read_optimization_summary */
918 NULL, /* stmt_fixup */
919 0, /* TODOs */
920 NULL, /* function_transform */
921 NULL /* variable_transform */
922 };