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