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