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