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