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