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