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