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