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