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