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