OSDN Git Service

* tree.h (memory_identifier_string): Remove.
[pf3gnuchains/gcc-fork.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 };