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