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