1169689Skan/* Callgraph based analysis of static variables. 2169689Skan Copyright (C) 2004, 2005 Free Software Foundation, Inc. 3169689Skan Contributed by Kenneth Zadeck <zadeck@naturalbridge.com> 4169689Skan 5169689SkanThis file is part of GCC. 6169689Skan 7169689SkanGCC is free software; you can redistribute it and/or modify it under 8169689Skanthe terms of the GNU General Public License as published by the Free 9169689SkanSoftware Foundation; either version 2, or (at your option) any later 10169689Skanversion. 11169689Skan 12169689SkanGCC is distributed in the hope that it will be useful, but WITHOUT ANY 13169689SkanWARRANTY; without even the implied warranty of MERCHANTABILITY or 14169689SkanFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 15169689Skanfor more details. 16169689Skan 17169689SkanYou should have received a copy of the GNU General Public License 18169689Skanalong with GCC; see the file COPYING. If not, write to the Free 19169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 20169689Skan02110-1301, USA. 21169689Skan*/ 22169689Skan 23169689Skan/* This file gathers information about how variables whose scope is 24169689Skan confined to the compilation unit are used. 25169689Skan 26169689Skan There are two categories of information produced by this pass: 27169689Skan 28169689Skan 1) The addressable (TREE_ADDRESSABLE) bit and readonly 29169689Skan (TREE_READONLY) bit associated with these variables is properly set 30169689Skan based on scanning all of the code withing the compilation unit. 31169689Skan 32169689Skan 2) The transitive call site specific clobber effects are computed 33169689Skan for the variables whose scope is contained within this compilation 34169689Skan unit. 35169689Skan 36169689Skan First each function and static variable initialization is analyzed 37169689Skan to determine which local static variables are either read, written, 38169689Skan or have their address taken. Any local static that has its address 39169689Skan taken is removed from consideration. Once the local read and 40169689Skan writes are determined, a transitive closure of this information is 41169689Skan performed over the call graph to determine the worst case set of 42169689Skan side effects of each call. In later parts of the compiler, these 43169689Skan local and global sets are examined to make the call clobbering less 44169689Skan traumatic, promote some statics to registers, and improve aliasing 45169689Skan information. 46169689Skan 47169689Skan Currently must be run after inlining decisions have been made since 48169689Skan otherwise, the local sets will not contain information that is 49169689Skan consistent with post inlined state. The global sets are not prone 50169689Skan to this problem since they are by definition transitive. 51169689Skan*/ 52169689Skan 53169689Skan#include "config.h" 54169689Skan#include "system.h" 55169689Skan#include "coretypes.h" 56169689Skan#include "tm.h" 57169689Skan#include "tree.h" 58169689Skan#include "tree-flow.h" 59169689Skan#include "tree-inline.h" 60169689Skan#include "tree-pass.h" 61169689Skan#include "langhooks.h" 62169689Skan#include "pointer-set.h" 63169689Skan#include "ggc.h" 64169689Skan#include "ipa-utils.h" 65169689Skan#include "ipa-reference.h" 66169689Skan#include "c-common.h" 67169689Skan#include "tree-gimple.h" 68169689Skan#include "cgraph.h" 69169689Skan#include "output.h" 70169689Skan#include "flags.h" 71169689Skan#include "timevar.h" 72169689Skan#include "diagnostic.h" 73169689Skan#include "langhooks.h" 74169689Skan 75169689Skan/* This splay tree contains all of the static variables that are 76169689Skan being considered by the compilation level alias analysis. For 77169689Skan module_at_a_time compilation, this is the set of static but not 78169689Skan public variables. Any variables that either have their address 79169689Skan taken or participate in otherwise unsavory operations are deleted 80169689Skan from this list. */ 81169689Skanstatic GTY((param1_is(int), param2_is(tree))) 82169689Skan splay_tree reference_vars_to_consider; 83169689Skan 84169689Skan/* This bitmap is used to knock out the module static variables whose 85169689Skan addresses have been taken and passed around. */ 86169689Skanstatic bitmap module_statics_escape; 87169689Skan 88169689Skan/* This bitmap is used to knock out the module static variables that 89169689Skan are not readonly. */ 90169689Skanstatic bitmap module_statics_written; 91169689Skan 92169689Skan/* A bit is set for every module static we are considering. This is 93169689Skan ored into the local info when asm code is found that clobbers all 94169689Skan memory. */ 95169689Skanstatic bitmap all_module_statics; 96169689Skan 97169689Skanstatic struct pointer_set_t *visited_nodes; 98169689Skan 99169689Skanstatic bitmap_obstack ipa_obstack; 100169689Skan 101169689Skanenum initialization_status_t 102169689Skan{ 103169689Skan UNINITIALIZED, 104169689Skan RUNNING, 105169689Skan FINISHED 106169689Skan}; 107169689Skan 108169689Skantree memory_identifier_string; 109169689Skan 110169689Skan/* Return the ipa_reference_vars structure starting from the cgraph NODE. */ 111169689Skanstatic inline ipa_reference_vars_info_t 112169689Skanget_reference_vars_info_from_cgraph (struct cgraph_node * node) 113169689Skan{ 114169689Skan return get_function_ann (node->decl)->reference_vars_info; 115169689Skan} 116169689Skan 117169689Skan/* Get a bitmap that contains all of the locally referenced static 118169689Skan variables for function FN. */ 119169689Skanstatic ipa_reference_local_vars_info_t 120169689Skanget_local_reference_vars_info (tree fn) 121169689Skan{ 122169689Skan ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info; 123169689Skan 124169689Skan if (info) 125169689Skan return info->local; 126169689Skan else 127169689Skan /* This phase was not run. */ 128169689Skan return NULL; 129169689Skan} 130169689Skan 131169689Skan/* Get a bitmap that contains all of the globally referenced static 132169689Skan variables for function FN. */ 133169689Skan 134169689Skanstatic ipa_reference_global_vars_info_t 135169689Skanget_global_reference_vars_info (tree fn) 136169689Skan{ 137169689Skan ipa_reference_vars_info_t info = get_function_ann (fn)->reference_vars_info; 138169689Skan 139169689Skan if (info) 140169689Skan return info->global; 141169689Skan else 142169689Skan /* This phase was not run. */ 143169689Skan return NULL; 144169689Skan} 145169689Skan 146169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables 147169689Skan that may be read locally by the execution of the function fn. 148169689Skan Returns NULL if no data is available. */ 149169689Skan 150169689Skanbitmap 151169689Skanipa_reference_get_read_local (tree fn) 152169689Skan{ 153169689Skan ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn); 154169689Skan if (l) 155169689Skan return l->statics_read; 156169689Skan else 157169689Skan return NULL; 158169689Skan} 159169689Skan 160169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables 161169689Skan that may be written locally by the execution of the function fn. 162169689Skan Returns NULL if no data is available. */ 163169689Skan 164169689Skanbitmap 165169689Skanipa_reference_get_written_local (tree fn) 166169689Skan{ 167169689Skan ipa_reference_local_vars_info_t l = get_local_reference_vars_info (fn); 168169689Skan if (l) 169169689Skan return l->statics_written; 170169689Skan else 171169689Skan return NULL; 172169689Skan} 173169689Skan 174169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables 175169689Skan that are read during the execution of the function FN. Returns 176169689Skan NULL if no data is available. */ 177169689Skan 178169689Skanbitmap 179169689Skanipa_reference_get_read_global (tree fn) 180169689Skan{ 181169689Skan ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); 182169689Skan if (g) 183169689Skan return g->statics_read; 184169689Skan else 185169689Skan return NULL; 186169689Skan} 187169689Skan 188169689Skan/* Return a bitmap indexed by VAR_DECL uid for the static variables 189169689Skan that are written during the execution of the function FN. Note 190169689Skan that variables written may or may not be read during the function 191169689Skan call. Returns NULL if no data is available. */ 192169689Skan 193169689Skanbitmap 194169689Skanipa_reference_get_written_global (tree fn) 195169689Skan{ 196169689Skan ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); 197169689Skan if (g) 198169689Skan return g->statics_written; 199169689Skan else 200169689Skan return NULL; 201169689Skan} 202169689Skan 203169689Skan/* Return a bitmap indexed by_DECL_UID uid for the static variables 204169689Skan that are not read during the execution of the function FN. Returns 205169689Skan NULL if no data is available. */ 206169689Skan 207169689Skanbitmap 208169689Skanipa_reference_get_not_read_global (tree fn) 209169689Skan{ 210169689Skan ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); 211169689Skan if (g) 212169689Skan return g->statics_not_read; 213169689Skan else 214169689Skan return NULL; 215169689Skan} 216169689Skan 217169689Skan/* Return a bitmap indexed by DECL_UID uid for the static variables 218169689Skan that are not written during the execution of the function FN. Note 219169689Skan that variables written may or may not be read during the function 220169689Skan call. Returns NULL if no data is available. */ 221169689Skan 222169689Skanbitmap 223169689Skanipa_reference_get_not_written_global (tree fn) 224169689Skan{ 225169689Skan ipa_reference_global_vars_info_t g = get_global_reference_vars_info (fn); 226169689Skan if (g) 227169689Skan return g->statics_not_written; 228169689Skan else 229169689Skan return NULL; 230169689Skan} 231169689Skan 232169689Skan 233169689Skan 234169689Skan/* Add VAR to all_module_statics and the two 235169689Skan reference_vars_to_consider* sets. */ 236169689Skan 237169689Skanstatic inline void 238169689Skanadd_static_var (tree var) 239169689Skan{ 240169689Skan int uid = DECL_UID (var); 241169689Skan if (!bitmap_bit_p (all_module_statics, uid)) 242169689Skan { 243169689Skan splay_tree_insert (reference_vars_to_consider, 244169689Skan uid, (splay_tree_value)var); 245169689Skan bitmap_set_bit (all_module_statics, uid); 246169689Skan } 247169689Skan} 248169689Skan 249169689Skan/* Return true if the variable T is the right kind of static variable to 250169689Skan perform compilation unit scope escape analysis. */ 251169689Skan 252169689Skanstatic inline bool 253169689Skanhas_proper_scope_for_analysis (tree t) 254169689Skan{ 255169689Skan /* If the variable has the "used" attribute, treat it as if it had a 256169689Skan been touched by the devil. */ 257169689Skan if (lookup_attribute ("used", DECL_ATTRIBUTES (t))) 258169689Skan return false; 259169689Skan 260169689Skan /* Do not want to do anything with volatile except mark any 261169689Skan function that uses one to be not const or pure. */ 262169689Skan if (TREE_THIS_VOLATILE (t)) 263169689Skan return false; 264169689Skan 265169689Skan /* Do not care about a local automatic that is not static. */ 266169689Skan if (!TREE_STATIC (t) && !DECL_EXTERNAL (t)) 267169689Skan return false; 268169689Skan 269169689Skan if (DECL_EXTERNAL (t) || TREE_PUBLIC (t)) 270169689Skan return false; 271169689Skan 272169689Skan /* This is a variable we care about. Check if we have seen it 273169689Skan before, and if not add it the set of variables we care about. */ 274169689Skan if (!bitmap_bit_p (all_module_statics, DECL_UID (t))) 275169689Skan add_static_var (t); 276169689Skan 277169689Skan return true; 278169689Skan} 279169689Skan 280169689Skan/* If T is a VAR_DECL for a static that we are interested in, add the 281169689Skan uid to the bitmap. */ 282169689Skan 283169689Skanstatic void 284169689Skancheck_operand (ipa_reference_local_vars_info_t local, 285169689Skan tree t, bool checking_write) 286169689Skan{ 287169689Skan if (!t) return; 288169689Skan 289169689Skan if ((TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == FUNCTION_DECL) 290169689Skan && (has_proper_scope_for_analysis (t))) 291169689Skan { 292169689Skan if (checking_write) 293169689Skan { 294169689Skan if (local) 295169689Skan bitmap_set_bit (local->statics_written, DECL_UID (t)); 296169689Skan /* Mark the write so we can tell which statics are 297169689Skan readonly. */ 298169689Skan bitmap_set_bit (module_statics_written, DECL_UID (t)); 299169689Skan } 300169689Skan else if (local) 301169689Skan bitmap_set_bit (local->statics_read, DECL_UID (t)); 302169689Skan } 303169689Skan} 304169689Skan 305169689Skan/* Examine tree T for references to static variables. All internal 306169689Skan references like array references or indirect references are added 307169689Skan to the READ_BM. Direct references are added to either READ_BM or 308169689Skan WRITE_BM depending on the value of CHECKING_WRITE. */ 309169689Skan 310169689Skanstatic void 311169689Skancheck_tree (ipa_reference_local_vars_info_t local, tree t, bool checking_write) 312169689Skan{ 313169689Skan if ((TREE_CODE (t) == EXC_PTR_EXPR) || (TREE_CODE (t) == FILTER_EXPR)) 314169689Skan return; 315169689Skan 316169689Skan while (TREE_CODE (t) == REALPART_EXPR 317169689Skan || TREE_CODE (t) == IMAGPART_EXPR 318169689Skan || handled_component_p (t)) 319169689Skan { 320169689Skan if (TREE_CODE (t) == ARRAY_REF) 321169689Skan check_operand (local, TREE_OPERAND (t, 1), false); 322169689Skan t = TREE_OPERAND (t, 0); 323169689Skan } 324169689Skan 325169689Skan /* The bottom of an indirect reference can only be read, not 326169689Skan written. So just recurse and whatever we find, check it against 327169689Skan the read bitmaps. */ 328169689Skan 329169689Skan /* if (INDIRECT_REF_P (t) || TREE_CODE (t) == MEM_REF) */ 330169689Skan /* FIXME when we have array_ref's of pointers. */ 331169689Skan if (INDIRECT_REF_P (t)) 332169689Skan check_tree (local, TREE_OPERAND (t, 0), false); 333169689Skan 334169689Skan if (SSA_VAR_P (t)) 335169689Skan check_operand (local, t, checking_write); 336169689Skan} 337169689Skan 338169689Skan/* Scan tree T to see if there are any addresses taken in within T. */ 339169689Skan 340169689Skanstatic void 341169689Skanlook_for_address_of (tree t) 342169689Skan{ 343169689Skan if (TREE_CODE (t) == ADDR_EXPR) 344169689Skan { 345169689Skan tree x = get_base_var (t); 346169689Skan if (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == FUNCTION_DECL) 347169689Skan if (has_proper_scope_for_analysis (x)) 348169689Skan bitmap_set_bit (module_statics_escape, DECL_UID (x)); 349169689Skan } 350169689Skan} 351169689Skan 352169689Skan/* Check to see if T is a read or address of operation on a static var 353169689Skan we are interested in analyzing. LOCAL is passed in to get access 354169689Skan to its bit vectors. Local is NULL if this is called from a static 355169689Skan initializer. */ 356169689Skan 357169689Skanstatic void 358169689Skancheck_rhs_var (ipa_reference_local_vars_info_t local, tree t) 359169689Skan{ 360169689Skan look_for_address_of (t); 361169689Skan 362169689Skan if (local == NULL) 363169689Skan return; 364169689Skan 365169689Skan check_tree(local, t, false); 366169689Skan} 367169689Skan 368169689Skan/* Check to see if T is an assignment to a static var we are 369169689Skan interested in analyzing. LOCAL is passed in to get access to its bit 370169689Skan vectors. */ 371169689Skan 372169689Skanstatic void 373169689Skancheck_lhs_var (ipa_reference_local_vars_info_t local, tree t) 374169689Skan{ 375169689Skan if (local == NULL) 376169689Skan return; 377169689Skan 378169689Skan check_tree(local, t, true); 379169689Skan} 380169689Skan 381169689Skan/* This is a scaled down version of get_asm_expr_operands from 382169689Skan tree_ssa_operands.c. The version there runs much later and assumes 383169689Skan that aliasing information is already available. Here we are just 384169689Skan trying to find if the set of inputs and outputs contain references 385169689Skan or address of operations to local static variables. FN is the 386169689Skan function being analyzed and STMT is the actual asm statement. */ 387169689Skan 388169689Skanstatic void 389169689Skanget_asm_expr_operands (ipa_reference_local_vars_info_t local, tree stmt) 390169689Skan{ 391169689Skan int noutputs = list_length (ASM_OUTPUTS (stmt)); 392169689Skan const char **oconstraints 393169689Skan = (const char **) alloca ((noutputs) * sizeof (const char *)); 394169689Skan int i; 395169689Skan tree link; 396169689Skan const char *constraint; 397169689Skan bool allows_mem, allows_reg, is_inout; 398169689Skan 399169689Skan for (i=0, link = ASM_OUTPUTS (stmt); link; ++i, link = TREE_CHAIN (link)) 400169689Skan { 401169689Skan oconstraints[i] = constraint 402169689Skan = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); 403169689Skan parse_output_constraint (&constraint, i, 0, 0, 404169689Skan &allows_mem, &allows_reg, &is_inout); 405169689Skan 406169689Skan check_lhs_var (local, TREE_VALUE (link)); 407169689Skan } 408169689Skan 409169689Skan for (link = ASM_INPUTS (stmt); link; link = TREE_CHAIN (link)) 410169689Skan { 411169689Skan constraint 412169689Skan = TREE_STRING_POINTER (TREE_VALUE (TREE_PURPOSE (link))); 413169689Skan parse_input_constraint (&constraint, 0, 0, noutputs, 0, 414169689Skan oconstraints, &allows_mem, &allows_reg); 415169689Skan 416169689Skan check_rhs_var (local, TREE_VALUE (link)); 417169689Skan } 418169689Skan 419169689Skan for (link = ASM_CLOBBERS (stmt); link; link = TREE_CHAIN (link)) 420169689Skan if (simple_cst_equal(TREE_VALUE (link), memory_identifier_string) == 1) 421169689Skan { 422169689Skan /* Abandon all hope, ye who enter here. */ 423169689Skan local->calls_read_all = true; 424169689Skan local->calls_write_all = true; 425169689Skan } 426169689Skan} 427169689Skan 428169689Skan/* Check the parameters of a function call from CALLER to CALL_EXPR to 429169689Skan see if any of them are static vars. Also check to see if this is 430169689Skan either an indirect call, a call outside the compilation unit, or 431169689Skan has special attributes that effect the clobbers. The caller 432169689Skan parameter is the tree node for the caller and the second operand is 433169689Skan the tree node for the entire call expression. */ 434169689Skan 435169689Skanstatic void 436169689Skancheck_call (ipa_reference_local_vars_info_t local, tree call_expr) 437169689Skan{ 438169689Skan int flags = call_expr_flags (call_expr); 439169689Skan tree operand_list = TREE_OPERAND (call_expr, 1); 440169689Skan tree operand; 441169689Skan tree callee_t = get_callee_fndecl (call_expr); 442169689Skan enum availability avail = AVAIL_NOT_AVAILABLE; 443169689Skan 444169689Skan for (operand = operand_list; 445169689Skan operand != NULL_TREE; 446169689Skan operand = TREE_CHAIN (operand)) 447169689Skan { 448169689Skan tree argument = TREE_VALUE (operand); 449169689Skan check_rhs_var (local, argument); 450169689Skan } 451169689Skan 452169689Skan if (callee_t) 453169689Skan { 454169689Skan struct cgraph_node* callee = cgraph_node(callee_t); 455169689Skan avail = cgraph_function_body_availability (callee); 456169689Skan } 457169689Skan 458169689Skan if (avail == AVAIL_NOT_AVAILABLE || avail == AVAIL_OVERWRITABLE) 459169689Skan if (local) 460169689Skan { 461169689Skan if (flags & ECF_PURE) 462169689Skan local->calls_read_all = true; 463169689Skan else 464169689Skan { 465169689Skan local->calls_read_all = true; 466169689Skan local->calls_write_all = true; 467169689Skan } 468169689Skan } 469169689Skan} 470169689Skan 471169689Skan/* TP is the part of the tree currently under the microscope. 472169689Skan WALK_SUBTREES is part of the walk_tree api but is unused here. 473169689Skan DATA is cgraph_node of the function being walked. */ 474169689Skan 475169689Skan/* FIXME: When this is converted to run over SSA form, this code 476169689Skan should be converted to use the operand scanner. */ 477169689Skan 478169689Skanstatic tree 479169689Skanscan_for_static_refs (tree *tp, 480169689Skan int *walk_subtrees, 481169689Skan void *data) 482169689Skan{ 483169689Skan struct cgraph_node *fn = data; 484169689Skan tree t = *tp; 485169689Skan ipa_reference_local_vars_info_t local = NULL; 486169689Skan if (fn) 487169689Skan local = get_reference_vars_info_from_cgraph (fn)->local; 488169689Skan 489169689Skan switch (TREE_CODE (t)) 490169689Skan { 491169689Skan case VAR_DECL: 492169689Skan if (DECL_INITIAL (t)) 493169689Skan walk_tree (&DECL_INITIAL (t), scan_for_static_refs, fn, visited_nodes); 494169689Skan *walk_subtrees = 0; 495169689Skan break; 496169689Skan 497169689Skan case MODIFY_EXPR: 498169689Skan { 499169689Skan /* First look on the lhs and see what variable is stored to */ 500169689Skan tree lhs = TREE_OPERAND (t, 0); 501169689Skan tree rhs = TREE_OPERAND (t, 1); 502169689Skan check_lhs_var (local, lhs); 503169689Skan 504169689Skan /* For the purposes of figuring out what the cast affects */ 505169689Skan 506169689Skan /* Next check the operands on the rhs to see if they are ok. */ 507169689Skan switch (TREE_CODE_CLASS (TREE_CODE (rhs))) 508169689Skan { 509169689Skan case tcc_binary: 510169689Skan case tcc_comparison: 511169689Skan { 512169689Skan tree op0 = TREE_OPERAND (rhs, 0); 513169689Skan tree op1 = TREE_OPERAND (rhs, 1); 514169689Skan check_rhs_var (local, op0); 515169689Skan check_rhs_var (local, op1); 516169689Skan } 517169689Skan break; 518169689Skan case tcc_unary: 519169689Skan { 520169689Skan tree op0 = TREE_OPERAND (rhs, 0); 521169689Skan check_rhs_var (local, op0); 522169689Skan } 523169689Skan 524169689Skan break; 525169689Skan case tcc_reference: 526169689Skan check_rhs_var (local, rhs); 527169689Skan break; 528169689Skan case tcc_declaration: 529169689Skan check_rhs_var (local, rhs); 530169689Skan break; 531169689Skan case tcc_expression: 532169689Skan switch (TREE_CODE (rhs)) 533169689Skan { 534169689Skan case ADDR_EXPR: 535169689Skan check_rhs_var (local, rhs); 536169689Skan break; 537169689Skan case CALL_EXPR: 538169689Skan check_call (local, rhs); 539169689Skan break; 540169689Skan default: 541169689Skan break; 542169689Skan } 543169689Skan break; 544169689Skan default: 545169689Skan break; 546169689Skan } 547169689Skan *walk_subtrees = 0; 548169689Skan } 549169689Skan break; 550169689Skan 551169689Skan case ADDR_EXPR: 552169689Skan /* This case is here to find addresses on rhs of constructors in 553169689Skan decl_initial of static variables. */ 554169689Skan check_rhs_var (local, t); 555169689Skan *walk_subtrees = 0; 556169689Skan break; 557169689Skan 558169689Skan case LABEL_EXPR: 559169689Skan if (DECL_NONLOCAL (TREE_OPERAND (t, 0))) 560169689Skan { 561169689Skan /* Target of long jump. */ 562169689Skan local->calls_read_all = true; 563169689Skan local->calls_write_all = true; 564169689Skan } 565169689Skan break; 566169689Skan 567169689Skan case CALL_EXPR: 568169689Skan check_call (local, t); 569169689Skan *walk_subtrees = 0; 570169689Skan break; 571169689Skan 572169689Skan case ASM_EXPR: 573169689Skan get_asm_expr_operands (local, t); 574169689Skan *walk_subtrees = 0; 575169689Skan break; 576169689Skan 577169689Skan default: 578169689Skan break; 579169689Skan } 580169689Skan return NULL; 581169689Skan} 582169689Skan 583169689Skan 584169689Skan/* Lookup the tree node for the static variable that has UID. */ 585169689Skanstatic tree 586169689Skanget_static_decl (int index) 587169689Skan{ 588169689Skan splay_tree_node stn = 589169689Skan splay_tree_lookup (reference_vars_to_consider, index); 590169689Skan if (stn) 591169689Skan return (tree)stn->value; 592169689Skan return NULL; 593169689Skan} 594169689Skan 595169689Skan/* Lookup the tree node for the static variable that has UID and 596169689Skan convert the name to a string for debugging. */ 597169689Skan 598169689Skanstatic const char * 599169689Skanget_static_name (int index) 600169689Skan{ 601169689Skan splay_tree_node stn = 602169689Skan splay_tree_lookup (reference_vars_to_consider, index); 603169689Skan if (stn) 604169689Skan return lang_hooks.decl_printable_name ((tree)(stn->value), 2); 605169689Skan return NULL; 606169689Skan} 607169689Skan 608169689Skan/* Or in all of the bits from every callee into X, the caller's, bit 609169689Skan vector. There are several cases to check to avoid the sparse 610169689Skan bitmap oring. */ 611169689Skan 612169689Skanstatic void 613169689Skanpropagate_bits (struct cgraph_node *x) 614169689Skan{ 615169689Skan ipa_reference_vars_info_t x_info = get_reference_vars_info_from_cgraph (x); 616169689Skan ipa_reference_global_vars_info_t x_global = x_info->global; 617169689Skan 618169689Skan struct cgraph_edge *e; 619169689Skan for (e = x->callees; e; e = e->next_callee) 620169689Skan { 621169689Skan struct cgraph_node *y = e->callee; 622169689Skan 623169689Skan /* Only look at the master nodes and skip external nodes. */ 624169689Skan y = cgraph_master_clone (y); 625169689Skan if (y) 626169689Skan { 627169689Skan if (get_reference_vars_info_from_cgraph (y)) 628169689Skan { 629169689Skan ipa_reference_vars_info_t y_info = get_reference_vars_info_from_cgraph (y); 630169689Skan ipa_reference_global_vars_info_t y_global = y_info->global; 631169689Skan 632169689Skan if (x_global->statics_read 633169689Skan != all_module_statics) 634169689Skan { 635169689Skan if (y_global->statics_read 636169689Skan == all_module_statics) 637169689Skan { 638169689Skan BITMAP_FREE (x_global->statics_read); 639169689Skan x_global->statics_read 640169689Skan = all_module_statics; 641169689Skan } 642169689Skan /* Skip bitmaps that are pointer equal to node's bitmap 643169689Skan (no reason to spin within the cycle). */ 644169689Skan else if (x_global->statics_read 645169689Skan != y_global->statics_read) 646169689Skan bitmap_ior_into (x_global->statics_read, 647169689Skan y_global->statics_read); 648169689Skan } 649169689Skan 650169689Skan if (x_global->statics_written 651169689Skan != all_module_statics) 652169689Skan { 653169689Skan if (y_global->statics_written 654169689Skan == all_module_statics) 655169689Skan { 656169689Skan BITMAP_FREE (x_global->statics_written); 657169689Skan x_global->statics_written 658169689Skan = all_module_statics; 659169689Skan } 660169689Skan /* Skip bitmaps that are pointer equal to node's bitmap 661169689Skan (no reason to spin within the cycle). */ 662169689Skan else if (x_global->statics_written 663169689Skan != y_global->statics_written) 664169689Skan bitmap_ior_into (x_global->statics_written, 665169689Skan y_global->statics_written); 666169689Skan } 667169689Skan } 668169689Skan else 669169689Skan { 670169689Skan gcc_unreachable (); 671169689Skan } 672169689Skan } 673169689Skan } 674169689Skan} 675169689Skan 676169689Skan/* Look at all of the callees of X to see which ones represent inlined 677169689Skan calls. For each of these callees, merge their local info into 678169689Skan TARGET and check their children recursively. 679169689Skan 680169689Skan This function goes away when Jan changes the inliner and IPA 681169689Skan analysis so that this is not run between the time when inlining 682169689Skan decisions are made and when the inlining actually occurs. */ 683169689Skan 684169689Skanstatic void 685169689Skanmerge_callee_local_info (struct cgraph_node *target, 686169689Skan struct cgraph_node *x) 687169689Skan{ 688169689Skan struct cgraph_edge *e; 689169689Skan ipa_reference_local_vars_info_t x_l = 690169689Skan get_reference_vars_info_from_cgraph (target)->local; 691169689Skan 692169689Skan /* Make the world safe for tail recursion. */ 693169689Skan struct ipa_dfs_info *node_info = x->aux; 694169689Skan 695169689Skan if (node_info->aux) 696169689Skan return; 697169689Skan 698169689Skan node_info->aux = x; 699169689Skan 700169689Skan for (e = x->callees; e; e = e->next_callee) 701169689Skan { 702169689Skan struct cgraph_node *y = e->callee; 703169689Skan if (y->global.inlined_to) 704169689Skan { 705169689Skan ipa_reference_vars_info_t y_info; 706169689Skan ipa_reference_local_vars_info_t y_l; 707169689Skan struct cgraph_node* orig_y = y; 708169689Skan 709169689Skan y = cgraph_master_clone (y); 710169689Skan if (y) 711169689Skan { 712169689Skan y_info = get_reference_vars_info_from_cgraph (y); 713169689Skan y_l = y_info->local; 714169689Skan if (x_l != y_l) 715169689Skan { 716169689Skan bitmap_ior_into (x_l->statics_read, 717169689Skan y_l->statics_read); 718169689Skan bitmap_ior_into (x_l->statics_written, 719169689Skan y_l->statics_written); 720169689Skan } 721169689Skan x_l->calls_read_all |= y_l->calls_read_all; 722169689Skan x_l->calls_write_all |= y_l->calls_write_all; 723169689Skan merge_callee_local_info (target, y); 724169689Skan } 725169689Skan else 726169689Skan { 727169689Skan fprintf(stderr, "suspect inlining of "); 728169689Skan dump_cgraph_node (stderr, orig_y); 729169689Skan fprintf(stderr, "\ninto "); 730169689Skan dump_cgraph_node (stderr, target); 731169689Skan dump_cgraph (stderr); 732169689Skan gcc_assert(false); 733169689Skan } 734169689Skan } 735169689Skan } 736169689Skan 737169689Skan node_info->aux = NULL; 738169689Skan} 739169689Skan 740169689Skan/* The init routine for analyzing global static variable usage. See 741169689Skan comments at top for description. */ 742169689Skanstatic void 743169689Skanipa_init (void) 744169689Skan{ 745169689Skan struct cgraph_node *node; 746169689Skan memory_identifier_string = build_string(7, "memory"); 747169689Skan 748169689Skan reference_vars_to_consider = 749169689Skan splay_tree_new_ggc (splay_tree_compare_ints); 750169689Skan 751169689Skan bitmap_obstack_initialize (&ipa_obstack); 752169689Skan module_statics_escape = BITMAP_ALLOC (&ipa_obstack); 753169689Skan module_statics_written = BITMAP_ALLOC (&ipa_obstack); 754169689Skan all_module_statics = BITMAP_ALLOC (&ipa_obstack); 755169689Skan 756169689Skan /* This will add NODE->DECL to the splay trees. */ 757169689Skan for (node = cgraph_nodes; node; node = node->next) 758169689Skan has_proper_scope_for_analysis (node->decl); 759169689Skan 760169689Skan /* There are some shared nodes, in particular the initializers on 761169689Skan static declarations. We do not need to scan them more than once 762169689Skan since all we would be interested in are the addressof 763169689Skan operations. */ 764169689Skan visited_nodes = pointer_set_create (); 765169689Skan} 766169689Skan 767169689Skan/* Check out the rhs of a static or global initialization VNODE to see 768169689Skan if any of them contain addressof operations. Note that some of 769169689Skan these variables may not even be referenced in the code in this 770169689Skan compilation unit but their right hand sides may contain references 771169689Skan to variables defined within this unit. */ 772169689Skan 773169689Skanstatic void 774169689Skananalyze_variable (struct cgraph_varpool_node *vnode) 775169689Skan{ 776169689Skan tree global = vnode->decl; 777169689Skan if (TREE_CODE (global) == VAR_DECL) 778169689Skan { 779169689Skan if (DECL_INITIAL (global)) 780169689Skan walk_tree (&DECL_INITIAL (global), scan_for_static_refs, 781169689Skan NULL, visited_nodes); 782169689Skan } 783169689Skan else gcc_unreachable (); 784169689Skan} 785169689Skan 786169689Skan/* This is the main routine for finding the reference patterns for 787169689Skan global variables within a function FN. */ 788169689Skan 789169689Skanstatic void 790169689Skananalyze_function (struct cgraph_node *fn) 791169689Skan{ 792169689Skan ipa_reference_vars_info_t info 793169689Skan = xcalloc (1, sizeof (struct ipa_reference_vars_info_d)); 794169689Skan ipa_reference_local_vars_info_t l 795169689Skan = xcalloc (1, sizeof (struct ipa_reference_local_vars_info_d)); 796169689Skan tree decl = fn->decl; 797169689Skan 798169689Skan /* Add the info to the tree's annotation. */ 799169689Skan get_function_ann (fn->decl)->reference_vars_info = info; 800169689Skan 801169689Skan info->local = l; 802169689Skan l->statics_read = BITMAP_ALLOC (&ipa_obstack); 803169689Skan l->statics_written = BITMAP_ALLOC (&ipa_obstack); 804169689Skan 805169689Skan if (dump_file) 806169689Skan fprintf (dump_file, "\n local analysis of %s\n", cgraph_node_name (fn)); 807169689Skan 808169689Skan { 809169689Skan struct function *this_cfun = DECL_STRUCT_FUNCTION (decl); 810169689Skan basic_block this_block; 811169689Skan 812169689Skan FOR_EACH_BB_FN (this_block, this_cfun) 813169689Skan { 814169689Skan block_stmt_iterator bsi; 815169689Skan for (bsi = bsi_start (this_block); !bsi_end_p (bsi); bsi_next (&bsi)) 816169689Skan walk_tree (bsi_stmt_ptr (bsi), scan_for_static_refs, 817169689Skan fn, visited_nodes); 818169689Skan } 819169689Skan } 820169689Skan 821169689Skan /* There may be const decls with interesting right hand sides. */ 822169689Skan if (DECL_STRUCT_FUNCTION (decl)) 823169689Skan { 824169689Skan tree step; 825169689Skan for (step = DECL_STRUCT_FUNCTION (decl)->unexpanded_var_list; 826169689Skan step; 827169689Skan step = TREE_CHAIN (step)) 828169689Skan { 829169689Skan tree var = TREE_VALUE (step); 830169689Skan if (TREE_CODE (var) == VAR_DECL 831169689Skan && DECL_INITIAL (var) 832169689Skan && !TREE_STATIC (var)) 833169689Skan walk_tree (&DECL_INITIAL (var), scan_for_static_refs, 834169689Skan fn, visited_nodes); 835169689Skan } 836169689Skan } 837169689Skan} 838169689Skan 839169689Skan/* If FN is avail == AVAIL_OVERWRITABLE, replace the effects bit 840169689Skan vectors with worst case bit vectors. We had to analyze it above to 841169689Skan find out if it took the address of any statics. However, now that 842169689Skan we know that, we can get rid of all of the other side effects. */ 843169689Skan 844169689Skanstatic void 845169689Skanclean_function (struct cgraph_node *fn) 846169689Skan{ 847169689Skan ipa_reference_vars_info_t info = get_reference_vars_info_from_cgraph (fn); 848169689Skan ipa_reference_local_vars_info_t l = info->local; 849169689Skan ipa_reference_global_vars_info_t g = info->global; 850169689Skan 851169689Skan if (l) 852169689Skan { 853169689Skan if (l->statics_read 854169689Skan && l->statics_read != all_module_statics) 855169689Skan BITMAP_FREE (l->statics_read); 856169689Skan if (l->statics_written 857169689Skan &&l->statics_written != all_module_statics) 858169689Skan BITMAP_FREE (l->statics_written); 859169689Skan free (l); 860169689Skan } 861169689Skan 862169689Skan if (g) 863169689Skan { 864169689Skan if (g->statics_read 865169689Skan && g->statics_read != all_module_statics) 866169689Skan BITMAP_FREE (g->statics_read); 867169689Skan 868169689Skan if (g->statics_written 869169689Skan && g->statics_written != all_module_statics) 870169689Skan BITMAP_FREE (g->statics_written); 871169689Skan 872169689Skan if (g->statics_not_read 873169689Skan && g->statics_not_read != all_module_statics) 874169689Skan BITMAP_FREE (g->statics_not_read); 875169689Skan 876169689Skan if (g->statics_not_written 877169689Skan && g->statics_not_written != all_module_statics) 878169689Skan BITMAP_FREE (g->statics_not_written); 879169689Skan free (g); 880169689Skan } 881169689Skan 882169689Skan 883169689Skan free (get_function_ann (fn->decl)->reference_vars_info); 884169689Skan get_function_ann (fn->decl)->reference_vars_info = NULL; 885169689Skan} 886169689Skan 887169689Skan 888169689Skan/* Produce the global information by preforming a transitive closure 889169689Skan on the local information that was produced by ipa_analyze_function 890169689Skan and ipa_analyze_variable. */ 891169689Skan 892169689Skanstatic unsigned int 893169689Skanstatic_execute (void) 894169689Skan{ 895169689Skan struct cgraph_node *node; 896169689Skan struct cgraph_varpool_node *vnode; 897169689Skan struct cgraph_node *w; 898169689Skan struct cgraph_node **order = 899169689Skan xcalloc (cgraph_n_nodes, sizeof (struct cgraph_node *)); 900169689Skan int order_pos = order_pos = ipa_utils_reduced_inorder (order, false, true); 901169689Skan int i; 902169689Skan 903169689Skan ipa_init (); 904169689Skan 905169689Skan /* Process all of the variables first. */ 906169689Skan for (vnode = cgraph_varpool_nodes_queue; vnode; vnode = vnode->next_needed) 907169689Skan analyze_variable (vnode); 908169689Skan 909169689Skan /* Process all of the functions next. 910169689Skan 911169689Skan We do not want to process any of the clones so we check that this 912169689Skan is a master clone. However, we do need to process any 913169689Skan AVAIL_OVERWRITABLE functions (these are never clones) because 914169689Skan they may cause a static variable to escape. The code that can 915169689Skan overwrite such a function cannot access the statics because it 916169689Skan would not be in the same compilation unit. When the analysis is 917169689Skan finished, the computed information of these AVAIL_OVERWRITABLE is 918169689Skan replaced with worst case info. 919169689Skan */ 920169689Skan for (node = cgraph_nodes; node; node = node->next) 921169689Skan if (node->analyzed 922169689Skan && (cgraph_is_master_clone (node) 923169689Skan || (cgraph_function_body_availability (node) 924169689Skan == AVAIL_OVERWRITABLE))) 925169689Skan analyze_function (node); 926169689Skan 927169689Skan pointer_set_destroy (visited_nodes); 928169689Skan visited_nodes = NULL; 929169689Skan if (dump_file) 930169689Skan dump_cgraph (dump_file); 931169689Skan 932169689Skan /* Prune out the variables that were found to behave badly 933169689Skan (i.e. have their address taken). */ 934169689Skan { 935169689Skan unsigned int index; 936169689Skan bitmap_iterator bi; 937169689Skan bitmap module_statics_readonly = BITMAP_ALLOC (&ipa_obstack); 938169689Skan bitmap module_statics_const = BITMAP_ALLOC (&ipa_obstack); 939169689Skan bitmap bm_temp = BITMAP_ALLOC (&ipa_obstack); 940169689Skan 941169689Skan EXECUTE_IF_SET_IN_BITMAP (module_statics_escape, 0, index, bi) 942169689Skan { 943169689Skan splay_tree_remove (reference_vars_to_consider, index); 944169689Skan } 945169689Skan 946169689Skan bitmap_and_compl_into (all_module_statics, 947169689Skan module_statics_escape); 948169689Skan 949169689Skan bitmap_and_compl (module_statics_readonly, all_module_statics, 950169689Skan module_statics_written); 951169689Skan 952169689Skan /* If the address is not taken, we can unset the addressable bit 953169689Skan on this variable. */ 954169689Skan EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) 955169689Skan { 956169689Skan tree var = get_static_decl (index); 957169689Skan TREE_ADDRESSABLE (var) = 0; 958169689Skan if (dump_file) 959169689Skan fprintf (dump_file, "Not TREE_ADDRESSABLE var %s\n", 960169689Skan get_static_name (index)); 961169689Skan } 962169689Skan 963169689Skan /* If the variable is never written, we can set the TREE_READONLY 964169689Skan flag. Additionally if it has a DECL_INITIAL that is made up of 965169689Skan constants we can treat the entire global as a constant. */ 966169689Skan 967169689Skan bitmap_and_compl (module_statics_readonly, all_module_statics, 968169689Skan module_statics_written); 969169689Skan EXECUTE_IF_SET_IN_BITMAP (module_statics_readonly, 0, index, bi) 970169689Skan { 971169689Skan tree var = get_static_decl (index); 972169689Skan 973169689Skan /* Readonly on a function decl is very different from the 974169689Skan variable. */ 975169689Skan if (TREE_CODE (var) == FUNCTION_DECL) 976169689Skan continue; 977169689Skan 978169689Skan /* Ignore variables in named sections - changing TREE_READONLY 979169689Skan changes the section flags, potentially causing conflicts with 980169689Skan other variables in the same named section. */ 981169689Skan if (DECL_SECTION_NAME (var) == NULL_TREE) 982169689Skan { 983169689Skan TREE_READONLY (var) = 1; 984169689Skan if (dump_file) 985169689Skan fprintf (dump_file, "read-only var %s\n", 986169689Skan get_static_name (index)); 987169689Skan } 988169689Skan if (DECL_INITIAL (var) 989169689Skan && is_gimple_min_invariant (DECL_INITIAL (var))) 990169689Skan { 991169689Skan bitmap_set_bit (module_statics_const, index); 992169689Skan if (dump_file) 993169689Skan fprintf (dump_file, "read-only constant %s\n", 994169689Skan get_static_name (index)); 995169689Skan } 996169689Skan } 997169689Skan 998169689Skan BITMAP_FREE(module_statics_escape); 999169689Skan BITMAP_FREE(module_statics_written); 1000169689Skan 1001169689Skan if (dump_file) 1002169689Skan EXECUTE_IF_SET_IN_BITMAP (all_module_statics, 0, index, bi) 1003169689Skan { 1004169689Skan fprintf (dump_file, "\nPromotable global:%s", 1005169689Skan get_static_name (index)); 1006169689Skan } 1007169689Skan 1008169689Skan for (i = 0; i < order_pos; i++ ) 1009169689Skan { 1010169689Skan ipa_reference_local_vars_info_t l; 1011169689Skan node = order[i]; 1012169689Skan l = get_reference_vars_info_from_cgraph (node)->local; 1013169689Skan 1014169689Skan /* Any variables that are not in all_module_statics are 1015169689Skan removed from the local maps. This will include all of the 1016169689Skan variables that were found to escape in the function 1017169689Skan scanning. */ 1018169689Skan bitmap_and_into (l->statics_read, 1019169689Skan all_module_statics); 1020169689Skan bitmap_and_into (l->statics_written, 1021169689Skan all_module_statics); 1022169689Skan } 1023169689Skan 1024169689Skan BITMAP_FREE(module_statics_readonly); 1025169689Skan BITMAP_FREE(module_statics_const); 1026169689Skan BITMAP_FREE(bm_temp); 1027169689Skan } 1028169689Skan 1029169689Skan if (dump_file) 1030169689Skan { 1031169689Skan for (i = 0; i < order_pos; i++ ) 1032169689Skan { 1033169689Skan unsigned int index; 1034169689Skan ipa_reference_local_vars_info_t l; 1035169689Skan bitmap_iterator bi; 1036169689Skan 1037169689Skan node = order[i]; 1038169689Skan l = get_reference_vars_info_from_cgraph (node)->local; 1039169689Skan fprintf (dump_file, 1040169689Skan "\nFunction name:%s/%i:", 1041169689Skan cgraph_node_name (node), node->uid); 1042169689Skan fprintf (dump_file, "\n locals read: "); 1043169689Skan EXECUTE_IF_SET_IN_BITMAP (l->statics_read, 1044169689Skan 0, index, bi) 1045169689Skan { 1046169689Skan fprintf (dump_file, "%s ", 1047169689Skan get_static_name (index)); 1048169689Skan } 1049169689Skan fprintf (dump_file, "\n locals written: "); 1050169689Skan EXECUTE_IF_SET_IN_BITMAP (l->statics_written, 1051169689Skan 0, index, bi) 1052169689Skan { 1053169689Skan fprintf(dump_file, "%s ", 1054169689Skan get_static_name (index)); 1055169689Skan } 1056169689Skan } 1057169689Skan } 1058169689Skan 1059169689Skan /* Propagate the local information thru the call graph to produce 1060169689Skan the global information. All the nodes within a cycle will have 1061169689Skan the same info so we collapse cycles first. Then we can do the 1062169689Skan propagation in one pass from the leaves to the roots. */ 1063169689Skan order_pos = ipa_utils_reduced_inorder (order, true, true); 1064169689Skan if (dump_file) 1065169689Skan ipa_utils_print_order(dump_file, "reduced", order, order_pos); 1066169689Skan 1067169689Skan for (i = 0; i < order_pos; i++ ) 1068169689Skan { 1069169689Skan ipa_reference_vars_info_t node_info; 1070169689Skan ipa_reference_global_vars_info_t node_g = 1071169689Skan xcalloc (1, sizeof (struct ipa_reference_global_vars_info_d)); 1072169689Skan ipa_reference_local_vars_info_t node_l; 1073169689Skan 1074169689Skan bool read_all; 1075169689Skan bool write_all; 1076169689Skan struct ipa_dfs_info * w_info; 1077169689Skan 1078169689Skan node = order[i]; 1079169689Skan node_info = get_reference_vars_info_from_cgraph (node); 1080169689Skan if (!node_info) 1081169689Skan { 1082169689Skan dump_cgraph_node (stderr, node); 1083169689Skan dump_cgraph (stderr); 1084169689Skan gcc_unreachable (); 1085169689Skan } 1086169689Skan 1087169689Skan node_info->global = node_g; 1088169689Skan node_l = node_info->local; 1089169689Skan 1090169689Skan read_all = node_l->calls_read_all; 1091169689Skan write_all = node_l->calls_write_all; 1092169689Skan 1093169689Skan /* If any node in a cycle is calls_read_all or calls_write_all 1094169689Skan they all are. */ 1095169689Skan w_info = node->aux; 1096169689Skan w = w_info->next_cycle; 1097169689Skan while (w) 1098169689Skan { 1099169689Skan ipa_reference_local_vars_info_t w_l = 1100169689Skan get_reference_vars_info_from_cgraph (w)->local; 1101169689Skan read_all |= w_l->calls_read_all; 1102169689Skan write_all |= w_l->calls_write_all; 1103169689Skan 1104169689Skan w_info = w->aux; 1105169689Skan w = w_info->next_cycle; 1106169689Skan } 1107169689Skan 1108169689Skan /* Initialized the bitmaps for the reduced nodes */ 1109169689Skan if (read_all) 1110169689Skan node_g->statics_read = all_module_statics; 1111169689Skan else 1112169689Skan { 1113169689Skan node_g->statics_read = BITMAP_ALLOC (&ipa_obstack); 1114169689Skan bitmap_copy (node_g->statics_read, 1115169689Skan node_l->statics_read); 1116169689Skan } 1117169689Skan 1118169689Skan if (write_all) 1119169689Skan node_g->statics_written = all_module_statics; 1120169689Skan else 1121169689Skan { 1122169689Skan node_g->statics_written = BITMAP_ALLOC (&ipa_obstack); 1123169689Skan bitmap_copy (node_g->statics_written, 1124169689Skan node_l->statics_written); 1125169689Skan } 1126169689Skan 1127169689Skan w_info = node->aux; 1128169689Skan w = w_info->next_cycle; 1129169689Skan while (w) 1130169689Skan { 1131169689Skan ipa_reference_vars_info_t w_ri = 1132169689Skan get_reference_vars_info_from_cgraph (w); 1133169689Skan ipa_reference_local_vars_info_t w_l = w_ri->local; 1134169689Skan 1135169689Skan /* All nodes within a cycle share the same global info bitmaps. */ 1136169689Skan w_ri->global = node_g; 1137169689Skan 1138169689Skan /* These global bitmaps are initialized from the local info 1139169689Skan of all of the nodes in the region. However there is no 1140169689Skan need to do any work if the bitmaps were set to 1141169689Skan all_module_statics. */ 1142169689Skan if (!read_all) 1143169689Skan bitmap_ior_into (node_g->statics_read, 1144169689Skan w_l->statics_read); 1145169689Skan if (!write_all) 1146169689Skan bitmap_ior_into (node_g->statics_written, 1147169689Skan w_l->statics_written); 1148169689Skan w_info = w->aux; 1149169689Skan w = w_info->next_cycle; 1150169689Skan } 1151169689Skan 1152169689Skan w = node; 1153169689Skan while (w) 1154169689Skan { 1155169689Skan propagate_bits (w); 1156169689Skan w_info = w->aux; 1157169689Skan w = w_info->next_cycle; 1158169689Skan } 1159169689Skan } 1160169689Skan 1161169689Skan /* Need to fix up the local information sets. The information that 1162169689Skan has been gathered so far is preinlining. However, the 1163169689Skan compilation will progress post inlining so the local sets for the 1164169689Skan inlined calls need to be merged into the callers. Note that the 1165169689Skan local sets are not shared between all of the nodes in a cycle so 1166169689Skan those nodes in the cycle must be processed explicitly. */ 1167169689Skan for (i = 0; i < order_pos; i++ ) 1168169689Skan { 1169169689Skan struct ipa_dfs_info * w_info; 1170169689Skan node = order[i]; 1171169689Skan merge_callee_local_info (node, node); 1172169689Skan 1173169689Skan w_info = node->aux; 1174169689Skan w = w_info->next_cycle; 1175169689Skan while (w) 1176169689Skan { 1177169689Skan merge_callee_local_info (w, w); 1178169689Skan w_info = w->aux; 1179169689Skan w = w_info->next_cycle; 1180169689Skan } 1181169689Skan } 1182169689Skan 1183169689Skan if (dump_file) 1184169689Skan { 1185169689Skan for (i = 0; i < order_pos; i++ ) 1186169689Skan { 1187169689Skan ipa_reference_vars_info_t node_info; 1188169689Skan ipa_reference_global_vars_info_t node_g; 1189169689Skan ipa_reference_local_vars_info_t node_l; 1190169689Skan unsigned int index; 1191169689Skan bitmap_iterator bi; 1192169689Skan struct ipa_dfs_info * w_info; 1193169689Skan 1194169689Skan node = order[i]; 1195169689Skan node_info = get_reference_vars_info_from_cgraph (node); 1196169689Skan node_g = node_info->global; 1197169689Skan node_l = node_info->local; 1198169689Skan fprintf (dump_file, 1199169689Skan "\nFunction name:%s/%i:", 1200169689Skan cgraph_node_name (node), node->uid); 1201169689Skan fprintf (dump_file, "\n locals read: "); 1202169689Skan EXECUTE_IF_SET_IN_BITMAP (node_l->statics_read, 1203169689Skan 0, index, bi) 1204169689Skan { 1205169689Skan fprintf (dump_file, "%s ", 1206169689Skan get_static_name (index)); 1207169689Skan } 1208169689Skan fprintf (dump_file, "\n locals written: "); 1209169689Skan EXECUTE_IF_SET_IN_BITMAP (node_l->statics_written, 1210169689Skan 0, index, bi) 1211169689Skan { 1212169689Skan fprintf(dump_file, "%s ", 1213169689Skan get_static_name (index)); 1214169689Skan } 1215169689Skan 1216169689Skan w_info = node->aux; 1217169689Skan w = w_info->next_cycle; 1218169689Skan while (w) 1219169689Skan { 1220169689Skan ipa_reference_vars_info_t w_ri = 1221169689Skan get_reference_vars_info_from_cgraph (w); 1222169689Skan ipa_reference_local_vars_info_t w_l = w_ri->local; 1223169689Skan fprintf (dump_file, "\n next cycle: %s/%i ", 1224169689Skan cgraph_node_name (w), w->uid); 1225169689Skan fprintf (dump_file, "\n locals read: "); 1226169689Skan EXECUTE_IF_SET_IN_BITMAP (w_l->statics_read, 1227169689Skan 0, index, bi) 1228169689Skan { 1229169689Skan fprintf (dump_file, "%s ", 1230169689Skan get_static_name (index)); 1231169689Skan } 1232169689Skan 1233169689Skan fprintf (dump_file, "\n locals written: "); 1234169689Skan EXECUTE_IF_SET_IN_BITMAP (w_l->statics_written, 1235169689Skan 0, index, bi) 1236169689Skan { 1237169689Skan fprintf(dump_file, "%s ", 1238169689Skan get_static_name (index)); 1239169689Skan } 1240169689Skan 1241169689Skan 1242169689Skan w_info = w->aux; 1243169689Skan w = w_info->next_cycle; 1244169689Skan } 1245169689Skan fprintf (dump_file, "\n globals read: "); 1246169689Skan EXECUTE_IF_SET_IN_BITMAP (node_g->statics_read, 1247169689Skan 0, index, bi) 1248169689Skan { 1249169689Skan fprintf (dump_file, "%s ", 1250169689Skan get_static_name (index)); 1251169689Skan } 1252169689Skan fprintf (dump_file, "\n globals written: "); 1253169689Skan EXECUTE_IF_SET_IN_BITMAP (node_g->statics_written, 1254169689Skan 0, index, bi) 1255169689Skan { 1256169689Skan fprintf (dump_file, "%s ", 1257169689Skan get_static_name (index)); 1258169689Skan } 1259169689Skan } 1260169689Skan } 1261169689Skan 1262169689Skan /* Cleanup. */ 1263169689Skan for (i = 0; i < order_pos; i++ ) 1264169689Skan { 1265169689Skan ipa_reference_vars_info_t node_info; 1266169689Skan ipa_reference_global_vars_info_t node_g; 1267169689Skan node = order[i]; 1268169689Skan node_info = get_reference_vars_info_from_cgraph (node); 1269169689Skan node_g = node_info->global; 1270169689Skan 1271169689Skan /* Create the complimentary sets. These are more useful for 1272169689Skan certain apis. */ 1273169689Skan node_g->statics_not_read = BITMAP_ALLOC (&ipa_obstack); 1274169689Skan node_g->statics_not_written = BITMAP_ALLOC (&ipa_obstack); 1275169689Skan 1276169689Skan if (node_g->statics_read != all_module_statics) 1277169689Skan { 1278169689Skan bitmap_and_compl (node_g->statics_not_read, 1279169689Skan all_module_statics, 1280169689Skan node_g->statics_read); 1281169689Skan } 1282169689Skan 1283169689Skan if (node_g->statics_written 1284169689Skan != all_module_statics) 1285169689Skan bitmap_and_compl (node_g->statics_not_written, 1286169689Skan all_module_statics, 1287169689Skan node_g->statics_written); 1288169689Skan } 1289169689Skan 1290169689Skan free (order); 1291169689Skan 1292169689Skan for (node = cgraph_nodes; node; node = node->next) 1293169689Skan { 1294169689Skan /* Get rid of the aux information. */ 1295169689Skan 1296169689Skan if (node->aux) 1297169689Skan { 1298169689Skan free (node->aux); 1299169689Skan node->aux = NULL; 1300169689Skan } 1301169689Skan 1302169689Skan if (node->analyzed 1303169689Skan && (cgraph_function_body_availability (node) == AVAIL_OVERWRITABLE)) 1304169689Skan clean_function (node); 1305169689Skan } 1306169689Skan return 0; 1307169689Skan} 1308169689Skan 1309169689Skan 1310169689Skanstatic bool 1311169689Skangate_reference (void) 1312169689Skan{ 1313169689Skan return (flag_unit_at_a_time != 0 && flag_ipa_reference 1314169689Skan /* Don't bother doing anything if the program has errors. */ 1315169689Skan && !(errorcount || sorrycount)); 1316169689Skan} 1317169689Skan 1318169689Skanstruct tree_opt_pass pass_ipa_reference = 1319169689Skan{ 1320169689Skan "static-var", /* name */ 1321169689Skan gate_reference, /* gate */ 1322169689Skan static_execute, /* execute */ 1323169689Skan NULL, /* sub */ 1324169689Skan NULL, /* next */ 1325169689Skan 0, /* static_pass_number */ 1326169689Skan TV_IPA_REFERENCE, /* tv_id */ 1327169689Skan 0, /* properties_required */ 1328169689Skan 0, /* properties_provided */ 1329169689Skan 0, /* properties_destroyed */ 1330169689Skan 0, /* todo_flags_start */ 1331169689Skan 0, /* todo_flags_finish */ 1332169689Skan 0 /* letter */ 1333169689Skan}; 1334169689Skan 1335169689Skan#include "gt-ipa-reference.h" 1336169689Skan 1337