xref: /netbsd-src/external/gpl3/gcc.old/dist/gcc/ipa-reference.c (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 /* Callgraph based analysis of static variables.
2    Copyright (C) 2004-2019 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    The transitive call site specific clobber effects are computed
25    for the variables whose scope is contained within this compilation
26    unit.
27 
28    First each function and static variable initialization is analyzed
29    to determine which local static variables are either read, written,
30    or have their address taken.  Any local static that has its address
31    taken is removed from consideration.  Once the local read and
32    writes are determined, a transitive closure of this information is
33    performed over the call graph to determine the worst case set of
34    side effects of each call.  In later parts of the compiler, these
35    local and global sets are examined to make the call clobbering less
36    traumatic, promote some statics to registers, and improve aliasing
37    information.  */
38 
39 #include "config.h"
40 #include "system.h"
41 #include "coretypes.h"
42 #include "backend.h"
43 #include "tree.h"
44 #include "gimple.h"
45 #include "tree-pass.h"
46 #include "cgraph.h"
47 #include "data-streamer.h"
48 #include "calls.h"
49 #include "splay-tree.h"
50 #include "ipa-utils.h"
51 #include "ipa-reference.h"
52 #include "symbol-summary.h"
53 
54 /* The static variables defined within the compilation unit that are
55    loaded or stored directly by function that owns this structure.  */
56 
57 struct ipa_reference_local_vars_info_d
58 {
59   bitmap statics_read;
60   bitmap statics_written;
61 };
62 
63 /* Statics that are read and written by some set of functions. The
64    local ones are based on the loads and stores local to the function.
65    The global ones are based on the local info as well as the
66    transitive closure of the functions that are called. */
67 
68 struct ipa_reference_global_vars_info_d
69 {
70   bitmap statics_read;
71   bitmap statics_written;
72 };
73 
74 /* Information we save about every function after ipa-reference is completed.  */
75 
76 struct ipa_reference_optimization_summary_d
77 {
78   bitmap statics_not_read;
79   bitmap statics_not_written;
80 };
81 
82 typedef ipa_reference_local_vars_info_d *ipa_reference_local_vars_info_t;
83 typedef ipa_reference_global_vars_info_d *ipa_reference_global_vars_info_t;
84 typedef ipa_reference_optimization_summary_d *
85   ipa_reference_optimization_summary_t;
86 
87 struct ipa_reference_vars_info_d
88 {
89   struct ipa_reference_local_vars_info_d local;
90   struct ipa_reference_global_vars_info_d global;
91 };
92 
93 typedef struct ipa_reference_vars_info_d *ipa_reference_vars_info_t;
94 
95 /* This splay tree contains all of the static variables that are
96    being considered by the compilation level alias analysis.  */
97 static splay_tree reference_vars_to_consider;
98 
99 /* Set of all interesting module statics.  A bit is set for every module
100    static we are considering.  This is added to the local info when asm
101    code is found that clobbers all memory.  */
102 static bitmap all_module_statics;
103 /* Set of all statics that should be ignored because they are touched by
104    -fno-ipa-reference code.  */
105 static bitmap ignore_module_statics;
106 
107 /* Obstack holding bitmaps of local analysis (live from analysis to
108    propagation)  */
109 static bitmap_obstack local_info_obstack;
110 /* Obstack holding global analysis live forever.  */
111 static bitmap_obstack optimization_summary_obstack;
112 
113 class ipa_ref_var_info_summary_t: public fast_function_summary
114 			  <ipa_reference_vars_info_d *, va_heap>
115 {
116 public:
117   ipa_ref_var_info_summary_t (symbol_table *symtab):
118     fast_function_summary <ipa_reference_vars_info_d *, va_heap> (symtab) {}
119 };
120 
121 static ipa_ref_var_info_summary_t *ipa_ref_var_info_summaries = NULL;
122 
123 class ipa_ref_opt_summary_t: public fast_function_summary
124 			     <ipa_reference_optimization_summary_d *, va_heap>
125 {
126 public:
127   ipa_ref_opt_summary_t (symbol_table *symtab):
128     fast_function_summary <ipa_reference_optimization_summary_d *, va_heap> (symtab) {}
129 
130   virtual void remove (cgraph_node *src_node,
131 		       ipa_reference_optimization_summary_d *data);
132   virtual void duplicate (cgraph_node *src_node, cgraph_node *dst_node,
133 			  ipa_reference_optimization_summary_d *src_data,
134 			  ipa_reference_optimization_summary_d *dst_data);
135 };
136 
137 static ipa_ref_opt_summary_t *ipa_ref_opt_sum_summaries = NULL;
138 
139 /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
140 static inline ipa_reference_vars_info_t
141 get_reference_vars_info (struct cgraph_node *node)
142 {
143   if (ipa_ref_var_info_summaries == NULL)
144     return NULL;
145 
146   ipa_reference_vars_info_t v = ipa_ref_var_info_summaries->get (node);
147   return v == NULL ? NULL : v;
148 }
149 
150 /* Return the ipa_reference_vars structure starting from the cgraph NODE.  */
151 static inline ipa_reference_optimization_summary_t
152 get_reference_optimization_summary (struct cgraph_node *node)
153 {
154   if (ipa_ref_opt_sum_summaries == NULL)
155     return NULL;
156 
157   ipa_reference_optimization_summary_t v
158     = ipa_ref_opt_sum_summaries->get (node);
159 
160   return v == NULL ? NULL : v;
161 }
162 
163 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
164    that are *not* read during the execution of the function FN.  Returns
165    NULL if no data is available.  */
166 
167 bitmap
168 ipa_reference_get_not_read_global (struct cgraph_node *fn)
169 {
170   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
171     return NULL;
172 
173   enum availability avail;
174   struct cgraph_node *fn2 = fn->function_symbol (&avail);
175   ipa_reference_optimization_summary_t info =
176     get_reference_optimization_summary (fn2);
177 
178   if (info
179       && (avail >= AVAIL_AVAILABLE
180 	  || (avail == AVAIL_INTERPOSABLE
181 	      && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
182       && opt_for_fn (fn2->decl, flag_ipa_reference))
183     return info->statics_not_read;
184   else if (avail == AVAIL_NOT_AVAILABLE
185 	   && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
186     return all_module_statics;
187   else
188     return NULL;
189 }
190 
191 /* Return a bitmap indexed by ipa_reference_var_uid for the static variables
192    that are *not* written during the execution of the function FN.  Note
193    that variables written may or may not be read during the function
194    call.  Returns NULL if no data is available.  */
195 
196 bitmap
197 ipa_reference_get_not_written_global (struct cgraph_node *fn)
198 {
199   if (!opt_for_fn (current_function_decl, flag_ipa_reference))
200     return NULL;
201 
202   enum availability avail;
203   struct cgraph_node *fn2 = fn->function_symbol (&avail);
204   ipa_reference_optimization_summary_t info =
205     get_reference_optimization_summary (fn2);
206 
207   if (info
208       && (avail >= AVAIL_AVAILABLE
209 	  || (avail == AVAIL_INTERPOSABLE
210 	      && flags_from_decl_or_type (fn->decl) & ECF_LEAF))
211       && opt_for_fn (fn2->decl, flag_ipa_reference))
212     return info->statics_not_written;
213   else if (avail == AVAIL_NOT_AVAILABLE
214 	   && flags_from_decl_or_type (fn->decl) & ECF_LEAF)
215     return all_module_statics;
216   else
217     return NULL;
218 }
219 
220 
221 /* Hepler for is_proper_for_analysis.  */
222 static bool
223 is_improper (symtab_node *n, void *v ATTRIBUTE_UNUSED)
224 {
225   tree t = n->decl;
226   /* If the variable has the "used" attribute, treat it as if it had a
227      been touched by the devil.  */
228   if (DECL_PRESERVE_P (t))
229     return true;
230 
231   /* Do not want to do anything with volatile except mark any
232      function that uses one to be not const or pure.  */
233   if (TREE_THIS_VOLATILE (t))
234     return true;
235 
236   /* We do not need to analyze readonly vars, we already know they do not
237      alias.  */
238   if (TREE_READONLY (t))
239     return true;
240 
241   /* We cannot track variables with address taken.  */
242   if (TREE_ADDRESSABLE (t))
243     return true;
244 
245   /* TODO: We could track public variables that are not addressable, but
246      currently frontends don't give us those.  */
247   if (TREE_PUBLIC (t))
248     return true;
249 
250   return false;
251 }
252 
253 /* Return true if the variable T is the right kind of static variable to
254    perform compilation unit scope escape analysis.  */
255 
256 static inline bool
257 is_proper_for_analysis (tree t)
258 {
259   if (bitmap_bit_p (ignore_module_statics, ipa_reference_var_uid (t)))
260     return false;
261 
262   if (symtab_node::get (t)
263 	->call_for_symbol_and_aliases (is_improper, NULL, true))
264     return false;
265 
266   return true;
267 }
268 
269 /* Lookup the tree node for the static variable that has UID and
270    convert the name to a string for debugging.  */
271 
272 static const char *
273 get_static_name (int index)
274 {
275   splay_tree_node stn =
276     splay_tree_lookup (reference_vars_to_consider, index);
277   return fndecl_name ((tree)(stn->value));
278 }
279 
280 /* Dump a set of static vars to FILE.  */
281 static void
282 dump_static_vars_set_to_file (FILE *f, bitmap set)
283 {
284   unsigned int index;
285   bitmap_iterator bi;
286   if (set == NULL)
287     return;
288   else if (set == all_module_statics)
289     fprintf (f, "ALL");
290   else
291     EXECUTE_IF_SET_IN_BITMAP (set, 0, index, bi)
292       {
293         fprintf (f, "%s ", get_static_name (index));
294       }
295 }
296 
297 /* Compute X |= Y, taking into account the possibility that
298    either X or Y is already the maximum set.
299    Return true if X is the maximum set after taking the union with Y.  */
300 
301 static bool
302 union_static_var_sets (bitmap &x, bitmap y)
303 {
304   if (x != all_module_statics)
305     {
306       if (y == all_module_statics)
307 	{
308 	  BITMAP_FREE (x);
309 	  x = all_module_statics;
310 	}
311       else if (bitmap_ior_into (x, y))
312 	{
313 	  /* The union may have reduced X to the maximum set.
314 	     In that case, we want to make that visible explicitly.
315 	     Even though bitmap_equal_p can be very expensive, it
316 	     turns out to be an overall win to check this here for
317 	     an LTO bootstrap of GCC itself.  Liberally extrapoliate
318 	     that result to be applicable to all cases.  */
319 	  if (bitmap_equal_p (x, all_module_statics))
320 	    {
321 	      BITMAP_FREE (x);
322 	      x = all_module_statics;
323 	    }
324 	}
325     }
326   return x == all_module_statics;
327 }
328 
329 /* Return a copy of SET on the bitmap obstack containing SET.
330    But if SET is NULL or the maximum set, return that instead.  */
331 
332 static bitmap
333 copy_static_var_set (bitmap set)
334 {
335   if (set == NULL || set == all_module_statics)
336     return set;
337   bitmap_obstack *o = set->obstack;
338   gcc_checking_assert (o);
339   bitmap copy = BITMAP_ALLOC (o);
340   bitmap_copy (copy, set);
341   return copy;
342 }
343 
344 /* Compute the union all of the statics read and written by every callee of X
345    into X_GLOBAL->statics_read and X_GLOBAL->statics_written.  X_GLOBAL is
346    actually the set representing the cycle containing X.  If the read and
347    written sets of X_GLOBAL has been reduced to the maximum set, we don't
348    have to look at the remaining callees.  */
349 
350 static void
351 propagate_bits (ipa_reference_global_vars_info_t x_global, struct cgraph_node *x)
352 {
353   struct cgraph_edge *e;
354   bool read_all = x_global->statics_read == all_module_statics;
355   bool write_all = x_global->statics_written == all_module_statics;
356   for (e = x->callees;
357        e && !(read_all && write_all);
358        e = e->next_callee)
359     {
360       enum availability avail;
361       struct cgraph_node *y = e->callee->function_symbol (&avail);
362       if (!y)
363 	continue;
364 
365       /* Only look into nodes we can propagate something.  */
366       int flags = flags_from_decl_or_type (y->decl);
367       if (opt_for_fn (y->decl, flag_ipa_reference)
368 	  && (avail > AVAIL_INTERPOSABLE
369 	      || (avail == AVAIL_INTERPOSABLE && (flags & ECF_LEAF))))
370 	{
371 	  if (get_reference_vars_info (y))
372 	    {
373 	      ipa_reference_vars_info_t y_info = get_reference_vars_info (y);
374 	      ipa_reference_global_vars_info_t y_global = &y_info->global;
375 
376 	      /* Calls in the current cycle do not have their global set
377 		 computed yet (but everything else does because we're
378 		 visiting nodes in topological order).  */
379 	      if (!y_global->statics_read)
380 		continue;
381 
382 	      /* If the function is const, it reads no memory even if it
383 		 seems so to local analysis.  */
384 	      if (flags & ECF_CONST)
385 		continue;
386 
387 	      union_static_var_sets (x_global->statics_read,
388 				     y_global->statics_read);
389 
390 	      /* If the function is pure, it has no stores even if it
391 		 seems so to local analysis.  If we cannot return from
392 		 the function, we can safely ignore the call.  */
393 	      if ((flags & ECF_PURE)
394 		  || e->cannot_lead_to_return_p ())
395 		continue;
396 
397 	      union_static_var_sets (x_global->statics_written,
398 				     y_global->statics_written);
399 	    }
400 	  else
401 	    gcc_unreachable ();
402 	}
403     }
404 }
405 
406 static bool ipa_init_p = false;
407 
408 /* The init routine for analyzing global static variable usage.  See
409    comments at top for description.  */
410 static void
411 ipa_init (void)
412 {
413   if (ipa_init_p)
414     return;
415 
416   ipa_init_p = true;
417 
418   if (dump_file)
419     reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
420 
421   bitmap_obstack_initialize (&local_info_obstack);
422   bitmap_obstack_initialize (&optimization_summary_obstack);
423   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
424   ignore_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
425 
426   if (ipa_ref_var_info_summaries == NULL)
427     ipa_ref_var_info_summaries = new ipa_ref_var_info_summary_t (symtab);
428 
429   if (ipa_ref_opt_sum_summaries != NULL)
430     {
431       delete ipa_ref_opt_sum_summaries;
432       ipa_ref_opt_sum_summaries = NULL;
433     }
434 }
435 
436 
437 /* Set up the persistent info for FN.  */
438 
439 static ipa_reference_local_vars_info_t
440 init_function_info (struct cgraph_node *fn)
441 {
442   ipa_reference_vars_info_t info
443     = ipa_ref_var_info_summaries->get_create (fn);
444 
445   info->local.statics_read = BITMAP_ALLOC (&local_info_obstack);
446   info->local.statics_written = BITMAP_ALLOC (&local_info_obstack);
447 
448   return &info->local;
449 }
450 
451 
452 /* This is the main routine for finding the reference patterns for
453    global variables within a function FN.  */
454 
455 static void
456 analyze_function (struct cgraph_node *fn)
457 {
458   ipa_reference_local_vars_info_t local;
459   struct ipa_ref *ref = NULL;
460   int i;
461   tree var;
462 
463   if (!opt_for_fn (fn->decl, flag_ipa_reference))
464     return;
465   local = init_function_info (fn);
466   for (i = 0; fn->iterate_reference (i, ref); i++)
467     {
468       if (!is_a <varpool_node *> (ref->referred))
469 	continue;
470       var = ref->referred->decl;
471       if (!is_proper_for_analysis (var))
472 	continue;
473       /* This is a variable we care about.  Check if we have seen it
474 	 before, and if not add it the set of variables we care about.  */
475       if (all_module_statics
476 	  && bitmap_set_bit (all_module_statics, ipa_reference_var_uid (var)))
477 	{
478 	  if (dump_file)
479 	    splay_tree_insert (reference_vars_to_consider,
480 			       ipa_reference_var_uid (var),
481 			       (splay_tree_value)var);
482 	}
483       switch (ref->use)
484 	{
485 	case IPA_REF_LOAD:
486           bitmap_set_bit (local->statics_read, ipa_reference_var_uid (var));
487 	  break;
488 	case IPA_REF_STORE:
489 	  if (ref->cannot_lead_to_return ())
490 	    break;
491           bitmap_set_bit (local->statics_written, ipa_reference_var_uid (var));
492 	  break;
493 	case IPA_REF_ADDR:
494 	  break;
495 	default:
496 	  gcc_unreachable ();
497 	}
498     }
499 
500   if (fn->cannot_return_p ())
501     bitmap_clear (local->statics_written);
502 }
503 
504 
505 /* Called when new clone is inserted to callgraph late.  */
506 
507 void
508 ipa_ref_opt_summary_t::duplicate (cgraph_node *, cgraph_node *,
509 				  ipa_reference_optimization_summary_d *ginfo,
510 				  ipa_reference_optimization_summary_d
511 				  *dst_ginfo)
512 {
513   dst_ginfo->statics_not_read =
514     copy_static_var_set (ginfo->statics_not_read);
515   dst_ginfo->statics_not_written =
516     copy_static_var_set (ginfo->statics_not_written);
517 }
518 
519 /* Called when node is removed.  */
520 
521 void
522 ipa_ref_opt_summary_t::remove (cgraph_node *,
523 			       ipa_reference_optimization_summary_d *ginfo)
524 {
525   if (ginfo->statics_not_read
526       && ginfo->statics_not_read != all_module_statics)
527     BITMAP_FREE (ginfo->statics_not_read);
528 
529   if (ginfo->statics_not_written
530       && ginfo->statics_not_written != all_module_statics)
531     BITMAP_FREE (ginfo->statics_not_written);
532 }
533 
534 /* Analyze each function in the cgraph to see which global or statics
535    are read or written.  */
536 
537 static void
538 generate_summary (void)
539 {
540   struct cgraph_node *node;
541   unsigned int index;
542   bitmap_iterator bi;
543 
544   ipa_init ();
545 
546   /* Process all of the functions next.  */
547   FOR_EACH_DEFINED_FUNCTION (node)
548     if (!node->alias && !opt_for_fn (node->decl, flag_ipa_reference))
549       {
550         struct ipa_ref *ref = NULL;
551         int i;
552         tree var;
553 	for (i = 0; node->iterate_reference (i, ref); i++)
554 	  {
555 	    if (!is_a <varpool_node *> (ref->referred))
556 	      continue;
557 	    var = ref->referred->decl;
558 	    if (!is_proper_for_analysis (var))
559 	      continue;
560 	    bitmap_set_bit (ignore_module_statics, ipa_reference_var_uid (var));
561 	  }
562       }
563   FOR_EACH_DEFINED_FUNCTION (node)
564     analyze_function (node);
565 
566   if (dump_file)
567     EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi)
568       {
569 	fprintf (dump_file, "\nPromotable global:%s (uid=%u)\n",
570 		 get_static_name (index), index);
571       }
572 
573   if (dump_file)
574     FOR_EACH_DEFINED_FUNCTION (node)
575       if (node->get_availability () >= AVAIL_INTERPOSABLE
576 	  && opt_for_fn (node->decl, flag_ipa_reference))
577 	{
578 	  ipa_reference_local_vars_info_t l;
579 	  unsigned int index;
580 	  bitmap_iterator bi;
581 
582 	  l = &get_reference_vars_info (node)->local;
583 	  fprintf (dump_file,
584 		   "\nFunction name:%s:", node->dump_name ());
585 	  fprintf (dump_file, "\n  locals read: ");
586 	  if (l->statics_read)
587 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_read,
588 				      0, index, bi)
589 	      {
590 	        fprintf (dump_file, "%s ",
591 		         get_static_name (index));
592 	      }
593 	  fprintf (dump_file, "\n  locals written: ");
594 	  if (l->statics_written)
595 	    EXECUTE_IF_SET_IN_BITMAP (l->statics_written,
596 				      0, index, bi)
597 	      {
598 	        fprintf (dump_file, "%s ", get_static_name (index));
599 	      }
600 	}
601 }
602 
603 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE.  */
604 
605 static void
606 read_write_all_from_decl (struct cgraph_node *node,
607 			  bool &read_all, bool &write_all)
608 {
609   tree decl = node->decl;
610   int flags = flags_from_decl_or_type (decl);
611   if ((flags & ECF_LEAF)
612       && node->get_availability () < AVAIL_INTERPOSABLE)
613     ;
614   else if (flags & ECF_CONST)
615     ;
616   else if ((flags & ECF_PURE) || node->cannot_return_p ())
617     {
618       read_all = true;
619       if (dump_file && (dump_flags & TDF_DETAILS))
620 	fprintf (dump_file, "   %s -> read all\n", node->dump_name ());
621     }
622   else
623     {
624        /* TODO: To be able to produce sane results, we should also handle
625 	  common builtins, in particular throw.  */
626       read_all = true;
627       write_all = true;
628       if (dump_file && (dump_flags & TDF_DETAILS))
629 	fprintf (dump_file, "   %s -> read all, write all\n",
630 		  node->dump_name ());
631     }
632 }
633 
634 /* Set READ_ALL/WRITE_ALL based on decl flags of NODE or any member
635    in the cycle of NODE.  */
636 
637 static void
638 get_read_write_all_from_node (struct cgraph_node *node,
639 			      bool &read_all, bool &write_all)
640 {
641   struct cgraph_edge *e, *ie;
642 
643   /* When function is overwritable, we cannot assume anything.  */
644   if (node->get_availability () <= AVAIL_INTERPOSABLE
645       || (node->analyzed && !opt_for_fn (node->decl, flag_ipa_reference)))
646     read_write_all_from_decl (node, read_all, write_all);
647 
648   for (e = node->callees;
649        e && !(read_all && write_all);
650        e = e->next_callee)
651     {
652       enum availability avail;
653       struct cgraph_node *callee = e->callee->function_symbol (&avail);
654       gcc_checking_assert (callee);
655       if (avail <= AVAIL_INTERPOSABLE
656 	  || (callee->analyzed && !opt_for_fn (callee->decl,
657 					       flag_ipa_reference)))
658 	read_write_all_from_decl (callee, read_all, write_all);
659     }
660 
661   for (ie = node->indirect_calls;
662        ie && !(read_all && write_all);
663        ie = ie->next_callee)
664     if (!(ie->indirect_info->ecf_flags & ECF_CONST))
665       {
666 	read_all = true;
667 	if (dump_file && (dump_flags & TDF_DETAILS))
668 	  fprintf (dump_file, "   indirect call -> read all\n");
669 	if (!ie->cannot_lead_to_return_p ()
670 	    && !(ie->indirect_info->ecf_flags & ECF_PURE))
671 	  {
672 	    if (dump_file && (dump_flags & TDF_DETAILS))
673 	      fprintf (dump_file, "   indirect call -> write all\n");
674 	    write_all = true;
675 	  }
676       }
677 }
678 
679 /* Skip edges from and to nodes without ipa_reference enables.  This leave
680    them out of strongy connected coponents and makes them easyto skip in the
681    propagation loop bellow.  */
682 
683 static bool
684 ignore_edge_p (cgraph_edge *e)
685 {
686   return (!opt_for_fn (e->caller->decl, flag_ipa_reference)
687           || !opt_for_fn (e->callee->function_symbol ()->decl,
688 			  flag_ipa_reference));
689 }
690 
691 /* Produce the global information by preforming a transitive closure
692    on the local information that was produced by ipa_analyze_function.  */
693 
694 static unsigned int
695 propagate (void)
696 {
697   struct cgraph_node *node;
698   struct cgraph_node **order =
699     XCNEWVEC (struct cgraph_node *, symtab->cgraph_count);
700   int order_pos;
701   int i;
702   bool remove_p;
703 
704   if (dump_file)
705     cgraph_node::dump_cgraph (dump_file);
706 
707   remove_p = ipa_discover_variable_flags ();
708   generate_summary ();
709 
710   /* Propagate the local information through the call graph to produce
711      the global information.  All the nodes within a cycle will have
712      the same info so we collapse cycles first.  Then we can do the
713      propagation in one pass from the leaves to the roots.  */
714   order_pos = ipa_reduced_postorder (order, true, ignore_edge_p);
715   if (dump_file)
716     ipa_print_order (dump_file, "reduced", order, order_pos);
717 
718   for (i = 0; i < order_pos; i++ )
719     {
720       unsigned x;
721       struct cgraph_node *w;
722       ipa_reference_vars_info_t node_info;
723       ipa_reference_global_vars_info_t node_g;
724       ipa_reference_local_vars_info_t node_l;
725       bool read_all = false;
726       bool write_all = false;
727 
728       node = order[i];
729       if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
730 	continue;
731 
732       node_info = get_reference_vars_info (node);
733       gcc_assert (node_info);
734       node_l = &node_info->local;
735       node_g = &node_info->global;
736 
737       if (dump_file && (dump_flags & TDF_DETAILS))
738 	fprintf (dump_file, "Starting cycle with %s\n", node->dump_name ());
739 
740       vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
741 
742       /* If any node in a cycle is read_all or write_all, they all are.  */
743       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
744 	{
745 	  if (dump_file && (dump_flags & TDF_DETAILS))
746 	    fprintf (dump_file, "  Visiting %s\n", w->dump_asm_name ());
747 	  get_read_write_all_from_node (w, read_all, write_all);
748 	  if (read_all && write_all)
749 	    break;
750 	}
751 
752       /* Initialized the bitmaps global sets for the reduced node.  */
753       if (read_all)
754 	node_g->statics_read = all_module_statics;
755       else
756 	node_g->statics_read = copy_static_var_set (node_l->statics_read);
757       if (write_all)
758 	node_g->statics_written = all_module_statics;
759       else
760 	node_g->statics_written = copy_static_var_set (node_l->statics_written);
761 
762       /* Merge the sets of this cycle with all sets of callees reached
763          from this cycle.  */
764       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
765 	{
766 	  if (read_all && write_all)
767 	    break;
768 
769 	  if (w != node)
770 	    {
771 	      ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
772 	      ipa_reference_local_vars_info_t w_l = &w_ri->local;
773 	      int flags = flags_from_decl_or_type (w->decl);
774 
775 	      if (!(flags & ECF_CONST))
776 		read_all = union_static_var_sets (node_g->statics_read,
777 						  w_l->statics_read);
778 	      if (!(flags & ECF_PURE)
779 		  && !w->cannot_return_p ())
780 		write_all = union_static_var_sets (node_g->statics_written,
781 						   w_l->statics_written);
782 	    }
783 
784 	  propagate_bits (node_g, w);
785 	}
786 
787       /* All nodes within a cycle have the same global info bitmaps.  */
788       FOR_EACH_VEC_ELT (cycle_nodes, x, w)
789 	{
790 	  ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
791           w_ri->global = *node_g;
792 	}
793 
794       cycle_nodes.release ();
795     }
796 
797   if (dump_file)
798     {
799       for (i = 0; i < order_pos; i++)
800 	{
801 	  unsigned x;
802 	  struct cgraph_node *w;
803 
804 	  node = order[i];
805           if (node->alias || !opt_for_fn (node->decl, flag_ipa_reference))
806 	    continue;
807 
808 	  fprintf (dump_file, "\nFunction name:%s:", node->dump_asm_name ());
809 
810 	  ipa_reference_vars_info_t node_info = get_reference_vars_info (node);
811 	  ipa_reference_global_vars_info_t node_g = &node_info->global;
812 
813 	  vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node);
814 	  FOR_EACH_VEC_ELT (cycle_nodes, x, w)
815 	    {
816 	      ipa_reference_vars_info_t w_ri = get_reference_vars_info (w);
817 	      ipa_reference_local_vars_info_t w_l = &w_ri->local;
818 	      if (w != node)
819 		fprintf (dump_file, "\n  next cycle: %s ", w->dump_asm_name ());
820 	      fprintf (dump_file, "\n    locals read: ");
821 	      dump_static_vars_set_to_file (dump_file, w_l->statics_read);
822 	      fprintf (dump_file, "\n    locals written: ");
823 	      dump_static_vars_set_to_file (dump_file, w_l->statics_written);
824 	    }
825 	  cycle_nodes.release ();
826 
827 	  fprintf (dump_file, "\n  globals read: ");
828 	  dump_static_vars_set_to_file (dump_file, node_g->statics_read);
829 	  fprintf (dump_file, "\n  globals written: ");
830 	  dump_static_vars_set_to_file (dump_file, node_g->statics_written);
831 	  fprintf (dump_file, "\n");
832 	}
833     }
834 
835   if (ipa_ref_opt_sum_summaries == NULL)
836     ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
837 
838   /* Cleanup. */
839   FOR_EACH_DEFINED_FUNCTION (node)
840     {
841       ipa_reference_vars_info_t node_info;
842       ipa_reference_global_vars_info_t node_g;
843 
844       node_info = get_reference_vars_info (node);
845       if (!node->alias && opt_for_fn (node->decl, flag_ipa_reference)
846 	  && (node->get_availability () > AVAIL_INTERPOSABLE
847 	      || (flags_from_decl_or_type (node->decl) & ECF_LEAF)))
848 	{
849 	  node_g = &node_info->global;
850 
851 	  ipa_reference_optimization_summary_d *opt
852 	    = ipa_ref_opt_sum_summaries->get_create (node);
853 
854 	  /* Create the complimentary sets.  */
855 
856 	  if (bitmap_empty_p (node_g->statics_read))
857 	    opt->statics_not_read = all_module_statics;
858 	  else
859 	    {
860 	      opt->statics_not_read
861 		 = BITMAP_ALLOC (&optimization_summary_obstack);
862 	      if (node_g->statics_read != all_module_statics)
863 		bitmap_and_compl (opt->statics_not_read,
864 				  all_module_statics,
865 				  node_g->statics_read);
866 	    }
867 
868 	  if (bitmap_empty_p (node_g->statics_written))
869 	    opt->statics_not_written = all_module_statics;
870 	  else
871 	    {
872 	      opt->statics_not_written
873 	        = BITMAP_ALLOC (&optimization_summary_obstack);
874 	      if (node_g->statics_written != all_module_statics)
875 		bitmap_and_compl (opt->statics_not_written,
876 				  all_module_statics,
877 				  node_g->statics_written);
878 	    }
879 	}
880    }
881 
882   ipa_free_postorder_info ();
883   free (order);
884 
885   bitmap_obstack_release (&local_info_obstack);
886 
887   if (ipa_ref_var_info_summaries == NULL)
888     {
889       delete ipa_ref_var_info_summaries;
890       ipa_ref_var_info_summaries = NULL;
891     }
892 
893   ipa_ref_var_info_summaries = NULL;
894   if (dump_file)
895     splay_tree_delete (reference_vars_to_consider);
896   reference_vars_to_consider = NULL;
897   return remove_p ? TODO_remove_functions : 0;
898 }
899 
900 /* Return true if we need to write summary of NODE. */
901 
902 static bool
903 write_node_summary_p (struct cgraph_node *node,
904 		      lto_symtab_encoder_t encoder,
905 		      bitmap ltrans_statics)
906 {
907   ipa_reference_optimization_summary_t info;
908 
909   /* See if we have (non-empty) info.  */
910   if (!node->definition || node->global.inlined_to)
911     return false;
912   info = get_reference_optimization_summary (node);
913   if (!info
914       || (bitmap_empty_p (info->statics_not_read)
915 	  && bitmap_empty_p (info->statics_not_written)))
916     return false;
917 
918   /* See if we want to encode it.
919      Encode also referenced functions since constant folding might turn it into
920      a direct call.
921 
922      In future we might also want to include summaries of functions references
923      by initializers of constant variables references in current unit.  */
924   if (!reachable_from_this_partition_p (node, encoder)
925       && !referenced_from_this_partition_p (node, encoder))
926     return false;
927 
928   /* See if the info has non-empty intersections with vars we want to encode.  */
929   if (!bitmap_intersect_p (info->statics_not_read, ltrans_statics)
930       && !bitmap_intersect_p (info->statics_not_written, ltrans_statics))
931     return false;
932   return true;
933 }
934 
935 /* Stream out BITS&LTRANS_STATICS as list of decls to OB.
936    LTRANS_STATICS_BITCOUNT specify number of bits in LTRANS_STATICS
937    or -1.  When it is positive, just output -1 when
938    BITS&LTRANS_STATICS == BITS&LTRANS_STATICS.  */
939 
940 static void
941 stream_out_bitmap (struct lto_simple_output_block *ob,
942 		   bitmap bits, bitmap ltrans_statics,
943 		   int ltrans_statics_bitcount)
944 {
945   int count = 0;
946   unsigned int index;
947   bitmap_iterator bi;
948   if (bits == all_module_statics)
949     {
950       streamer_write_hwi_stream (ob->main_stream, -1);
951       return;
952     }
953   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
954     count ++;
955   if (count == ltrans_statics_bitcount)
956     {
957       streamer_write_hwi_stream (ob->main_stream, -1);
958       return;
959     }
960   streamer_write_hwi_stream (ob->main_stream, count);
961   if (!count)
962     return;
963   EXECUTE_IF_AND_IN_BITMAP (bits, ltrans_statics, 0, index, bi)
964     {
965       tree decl = (tree)splay_tree_lookup (reference_vars_to_consider,
966 					   index)->value;
967       lto_output_var_decl_index (ob->decl_state, ob->main_stream, decl);
968     }
969 }
970 
971 /* Serialize the ipa info for lto.  */
972 
973 static void
974 ipa_reference_write_optimization_summary (void)
975 {
976   struct lto_simple_output_block *ob
977     = lto_create_simple_output_block (LTO_section_ipa_reference);
978   unsigned int count = 0;
979   int ltrans_statics_bitcount = 0;
980   lto_symtab_encoder_t encoder = ob->decl_state->symtab_node_encoder;
981   auto_bitmap ltrans_statics;
982   int i;
983 
984   reference_vars_to_consider = splay_tree_new (splay_tree_compare_ints, 0, 0);
985 
986   /* See what variables we are interested in.  */
987   for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
988     {
989       symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
990       varpool_node *vnode = dyn_cast <varpool_node *> (snode);
991       if (vnode
992 	  && bitmap_bit_p (all_module_statics,
993 			    ipa_reference_var_uid (vnode->decl))
994 	  && referenced_from_this_partition_p (vnode, encoder))
995 	{
996 	  tree decl = vnode->decl;
997 	  bitmap_set_bit (ltrans_statics, ipa_reference_var_uid (decl));
998 	  splay_tree_insert (reference_vars_to_consider,
999 			     ipa_reference_var_uid (decl),
1000 			     (splay_tree_value)decl);
1001 	  ltrans_statics_bitcount ++;
1002 	}
1003     }
1004 
1005 
1006   if (ltrans_statics_bitcount)
1007     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1008       {
1009 	symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1010 	cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1011 	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1012 	  count++;
1013       }
1014 
1015   streamer_write_uhwi_stream (ob->main_stream, count);
1016   if (count)
1017     stream_out_bitmap (ob, ltrans_statics, ltrans_statics,
1018 		       -1);
1019 
1020   /* Process all of the functions.  */
1021   if (ltrans_statics_bitcount)
1022     for (i = 0; i < lto_symtab_encoder_size (encoder); i++)
1023       {
1024 	symtab_node *snode = lto_symtab_encoder_deref (encoder, i);
1025 	cgraph_node *cnode = dyn_cast <cgraph_node *> (snode);
1026 	if (cnode && write_node_summary_p (cnode, encoder, ltrans_statics))
1027 	  {
1028 	    ipa_reference_optimization_summary_t info;
1029 	    int node_ref;
1030 
1031 	    info = get_reference_optimization_summary (cnode);
1032 	    node_ref = lto_symtab_encoder_encode (encoder, snode);
1033 	    streamer_write_uhwi_stream (ob->main_stream, node_ref);
1034 
1035 	    stream_out_bitmap (ob, info->statics_not_read, ltrans_statics,
1036 			       ltrans_statics_bitcount);
1037 	    stream_out_bitmap (ob, info->statics_not_written, ltrans_statics,
1038 			       ltrans_statics_bitcount);
1039 	  }
1040       }
1041   lto_destroy_simple_output_block (ob);
1042   splay_tree_delete (reference_vars_to_consider);
1043 }
1044 
1045 /* Deserialize the ipa info for lto.  */
1046 
1047 static void
1048 ipa_reference_read_optimization_summary (void)
1049 {
1050   struct lto_file_decl_data ** file_data_vec
1051     = lto_get_file_decl_data ();
1052   struct lto_file_decl_data * file_data;
1053   unsigned int j = 0;
1054   bitmap_obstack_initialize (&optimization_summary_obstack);
1055 
1056   if (ipa_ref_opt_sum_summaries == NULL)
1057     ipa_ref_opt_sum_summaries = new ipa_ref_opt_summary_t (symtab);
1058 
1059   all_module_statics = BITMAP_ALLOC (&optimization_summary_obstack);
1060 
1061   while ((file_data = file_data_vec[j++]))
1062     {
1063       const char *data;
1064       size_t len;
1065       struct lto_input_block *ib
1066 	= lto_create_simple_input_block (file_data,
1067 					 LTO_section_ipa_reference,
1068 					 &data, &len);
1069       if (ib)
1070 	{
1071 	  unsigned int i;
1072 	  unsigned int f_count = streamer_read_uhwi (ib);
1073 	  int b_count;
1074 	  if (!f_count)
1075 	    continue;
1076 	  b_count = streamer_read_hwi (ib);
1077 	  if (dump_file)
1078 	    fprintf (dump_file, "all module statics:");
1079 	  for (i = 0; i < (unsigned int)b_count; i++)
1080 	    {
1081 	      unsigned int var_index = streamer_read_uhwi (ib);
1082 	      tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1083 							     var_index);
1084 	      bitmap_set_bit (all_module_statics,
1085 			      ipa_reference_var_uid (v_decl));
1086 	      if (dump_file)
1087 		fprintf (dump_file, " %s", fndecl_name (v_decl));
1088 	    }
1089 
1090 	  for (i = 0; i < f_count; i++)
1091 	    {
1092 	      unsigned int j, index;
1093 	      struct cgraph_node *node;
1094 	      int v_count;
1095 	      lto_symtab_encoder_t encoder;
1096 
1097 	      index = streamer_read_uhwi (ib);
1098 	      encoder = file_data->symtab_node_encoder;
1099 	      node = dyn_cast<cgraph_node *> (lto_symtab_encoder_deref
1100 		(encoder, index));
1101 
1102 	      ipa_reference_optimization_summary_d *info
1103 		= ipa_ref_opt_sum_summaries->get_create (node);
1104 
1105 	      info->statics_not_read = BITMAP_ALLOC
1106 		(&optimization_summary_obstack);
1107 	      info->statics_not_written = BITMAP_ALLOC
1108 		(&optimization_summary_obstack);
1109 	      if (dump_file)
1110 		fprintf (dump_file,
1111 			 "\nFunction name:%s:\n  static not read:",
1112 			 node->dump_asm_name ());
1113 
1114 	      /* Set the statics not read.  */
1115 	      v_count = streamer_read_hwi (ib);
1116 	      if (v_count == -1)
1117 		{
1118 		  info->statics_not_read = all_module_statics;
1119 		  if (dump_file)
1120 		    fprintf (dump_file, " all module statics");
1121 		}
1122 	      else
1123 		for (j = 0; j < (unsigned int)v_count; j++)
1124 		  {
1125 		    unsigned int var_index = streamer_read_uhwi (ib);
1126 		    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1127 								   var_index);
1128 		    bitmap_set_bit (info->statics_not_read,
1129 				    ipa_reference_var_uid (v_decl));
1130 		    if (dump_file)
1131 		      fprintf (dump_file, " %s", fndecl_name (v_decl));
1132 		  }
1133 
1134 	      if (dump_file)
1135 		fprintf (dump_file,
1136 			 "\n  static not written:");
1137 	      /* Set the statics not written.  */
1138 	      v_count = streamer_read_hwi (ib);
1139 	      if (v_count == -1)
1140 		{
1141 		  info->statics_not_written = all_module_statics;
1142 		  if (dump_file)
1143 		    fprintf (dump_file, " all module statics");
1144 		}
1145 	      else
1146 		for (j = 0; j < (unsigned int)v_count; j++)
1147 		  {
1148 		    unsigned int var_index = streamer_read_uhwi (ib);
1149 		    tree v_decl = lto_file_decl_data_get_var_decl (file_data,
1150 								   var_index);
1151 		    bitmap_set_bit (info->statics_not_written,
1152 				    ipa_reference_var_uid (v_decl));
1153 		    if (dump_file)
1154 		      fprintf (dump_file, " %s", fndecl_name (v_decl));
1155 		  }
1156 	      if (dump_file)
1157 		fprintf (dump_file, "\n");
1158 	    }
1159 
1160 	  lto_destroy_simple_input_block (file_data,
1161 					  LTO_section_ipa_reference,
1162 					  ib, data, len);
1163 	}
1164       else
1165 	/* Fatal error here.  We do not want to support compiling ltrans units
1166 	   with different version of compiler or different flags than
1167 	   the WPA unit, so this should never happen.  */
1168 	fatal_error (input_location,
1169 		     "ipa reference summary is missing in ltrans unit");
1170     }
1171 }
1172 
1173 namespace {
1174 
1175 const pass_data pass_data_ipa_reference =
1176 {
1177   IPA_PASS, /* type */
1178   "static-var", /* name */
1179   OPTGROUP_NONE, /* optinfo_flags */
1180   TV_IPA_REFERENCE, /* tv_id */
1181   0, /* properties_required */
1182   0, /* properties_provided */
1183   0, /* properties_destroyed */
1184   0, /* todo_flags_start */
1185   0, /* todo_flags_finish */
1186 };
1187 
1188 class pass_ipa_reference : public ipa_opt_pass_d
1189 {
1190 public:
1191   pass_ipa_reference (gcc::context *ctxt)
1192     : ipa_opt_pass_d (pass_data_ipa_reference, ctxt,
1193 		      NULL, /* generate_summary */
1194 		      NULL, /* write_summary */
1195 		      NULL, /* read_summary */
1196 		      ipa_reference_write_optimization_summary, /*
1197 		      write_optimization_summary */
1198 		      ipa_reference_read_optimization_summary, /*
1199 		      read_optimization_summary */
1200 		      NULL, /* stmt_fixup */
1201 		      0, /* function_transform_todo_flags_start */
1202 		      NULL, /* function_transform */
1203 		      NULL) /* variable_transform */
1204     {}
1205 
1206   /* opt_pass methods: */
1207   virtual bool gate (function *)
1208     {
1209       return ((in_lto_p || flag_ipa_reference)
1210 	      /* Don't bother doing anything if the program has errors.  */
1211 	      && !seen_error ());
1212     }
1213 
1214   virtual unsigned int execute (function *) { return propagate (); }
1215 
1216 }; // class pass_ipa_reference
1217 
1218 } // anon namespace
1219 
1220 ipa_opt_pass_d *
1221 make_pass_ipa_reference (gcc::context *ctxt)
1222 {
1223   return new pass_ipa_reference (ctxt);
1224 }
1225 
1226 /* Reset all state within ipa-reference.c so that we can rerun the compiler
1227    within the same process.  For use by toplev::finalize.  */
1228 
1229 void
1230 ipa_reference_c_finalize (void)
1231 {
1232   if (ipa_ref_opt_sum_summaries != NULL)
1233     {
1234       delete ipa_ref_opt_sum_summaries;
1235       ipa_ref_opt_sum_summaries = NULL;
1236     }
1237 
1238   if (ipa_init_p)
1239     {
1240       bitmap_obstack_release (&optimization_summary_obstack);
1241       ipa_init_p = false;
1242     }
1243 }
1244