1169689Skan/* Interprocedural constant propagation 2169689Skan Copyright (C) 2005 Free Software Foundation, Inc. 3169689Skan Contributed by Razya Ladelsky <RAZYA@il.ibm.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/* Interprocedural constant propagation. 23169689Skan The aim of interprocedural constant propagation (IPCP) is to find which 24169689Skan function's argument has the same constant value in each invocation throughout 25169689Skan the whole program. For example, for an application consisting of two files, 26169689Skan foo1.c, foo2.c: 27169689Skan 28169689Skan foo1.c contains : 29169689Skan 30169689Skan int f (int x) 31169689Skan { 32169689Skan g (x); 33169689Skan } 34169689Skan void main (void) 35169689Skan { 36169689Skan f (3); 37169689Skan h (3); 38169689Skan } 39169689Skan 40169689Skan foo2.c contains : 41169689Skan 42169689Skan int h (int y) 43169689Skan { 44169689Skan g (y); 45169689Skan } 46169689Skan int g (int y) 47169689Skan { 48169689Skan printf ("value is %d",y); 49169689Skan } 50169689Skan 51169689Skan The IPCP algorithm will find that g's formal argument y 52169689Skan is always called with the value 3. 53169689Skan 54169689Skan The algorithm used is based on "Interprocedural Constant Propagation", 55169689Skan by Challahan David, Keith D Cooper, Ken Kennedy, Linda Torczon, Comp86, 56169689Skan pg 152-161 57169689Skan 58169689Skan The optimization is divided into three stages: 59169689Skan 60169689Skan First stage - intraprocedural analysis 61169689Skan ======================================= 62169689Skan This phase computes jump_function and modify information. 63169689Skan 64169689Skan A jump function for a callsite represents the values passed as actual 65169689Skan arguments 66169689Skan of the callsite. There are three types of values : 67169689Skan Formal - the caller's formal parameter is passed as an actual argument. 68169689Skan Constant - a constant is passed as a an actual argument. 69169689Skan Unknown - neither of the above. 70169689Skan 71169689Skan In order to compute the jump functions, we need the modify information for 72169689Skan the formal parameters of methods. 73169689Skan 74169689Skan The jump function info, ipa_jump_func, is defined in ipa_edge 75169689Skan structure (defined in ipa_prop.h and pointed to by cgraph_node->aux) 76169689Skan The modify info, ipa_modify, is defined in ipa_node structure 77169689Skan (defined in ipa_prop.h and pointed to by cgraph_edge->aux). 78169689Skan 79169689Skan -ipcp_init_stage() is the first stage driver. 80169689Skan 81169689Skan Second stage - interprocedural analysis 82169689Skan ======================================== 83169689Skan This phase does the interprocedural constant propagation. 84169689Skan It computes for all formal parameters in the program 85169689Skan their cval value that may be: 86169689Skan TOP - unknown. 87169689Skan BOTTOM - non constant. 88169689Skan CONSTANT_TYPE - constant value. 89169689Skan 90169689Skan Cval of formal f will have a constant value if all callsites to this 91169689Skan function have the same constant value passed to f. 92169689Skan 93169689Skan The cval info, ipcp_formal, is defined in ipa_node structure 94169689Skan (defined in ipa_prop.h and pointed to by cgraph_edge->aux). 95169689Skan 96169689Skan -ipcp_iterate_stage() is the second stage driver. 97169689Skan 98169689Skan Third phase - transformation of methods code 99169689Skan ============================================ 100169689Skan Propagates the constant-valued formals into the function. 101169689Skan For each method mt, whose parameters are consts, we create a clone/version. 102169689Skan 103169689Skan We use two ways to annotate the versioned function with the constant 104169689Skan formal information: 105169689Skan 1. We insert an assignment statement 'parameter = const' at the beginning 106169689Skan of the cloned method. 107169689Skan 2. For read-only formals whose address is not taken, we replace all uses 108169689Skan of the formal with the constant (we provide versioning with an 109169689Skan ipa_replace_map struct representing the trees we want to replace). 110169689Skan 111169689Skan We also need to modify some callsites to call to the cloned methods instead 112169689Skan of the original ones. For a callsite passing an argument found to be a 113169689Skan constant by IPCP, there are two different cases to handle: 114169689Skan 1. A constant is passed as an argument. 115169689Skan 2. A parameter (of the caller) passed as an argument (pass through argument). 116169689Skan 117169689Skan In the first case, the callsite in the original caller should be redirected 118169689Skan to call the cloned callee. 119169689Skan In the second case, both the caller and the callee have clones 120169689Skan and the callsite of the cloned caller would be redirected to call to 121169689Skan the cloned callee. 122169689Skan 123169689Skan The callgraph is updated accordingly. 124169689Skan 125169689Skan This update is done in two stages: 126169689Skan First all cloned methods are created during a traversal of the callgraph, 127169689Skan during which all callsites are redirected to call the cloned method. 128169689Skan Then the callsites are traversed and updated as described above. 129169689Skan 130169689Skan -ipcp_insert_stage() is the third phase driver. 131169689Skan 132169689Skan*/ 133169689Skan 134169689Skan#include "config.h" 135169689Skan#include "system.h" 136169689Skan#include "coretypes.h" 137169689Skan#include "tree.h" 138169689Skan#include "target.h" 139169689Skan#include "cgraph.h" 140169689Skan#include "ipa-prop.h" 141169689Skan#include "tree-flow.h" 142169689Skan#include "tree-pass.h" 143169689Skan#include "flags.h" 144169689Skan#include "timevar.h" 145169689Skan#include "diagnostic.h" 146169689Skan 147169689Skan/* Get orig node field of ipa_node associated with method MT. */ 148169689Skanstatic inline struct cgraph_node * 149169689Skanipcp_method_orig_node (struct cgraph_node *mt) 150169689Skan{ 151169689Skan return IPA_NODE_REF (mt)->ipcp_orig_node; 152169689Skan} 153169689Skan 154169689Skan/* Return true if NODE is a cloned/versioned method. */ 155169689Skanstatic inline bool 156169689Skanipcp_method_is_cloned (struct cgraph_node *node) 157169689Skan{ 158169689Skan return (ipcp_method_orig_node (node) != NULL); 159169689Skan} 160169689Skan 161169689Skan/* Set ORIG_NODE in ipa_node associated with method NODE. */ 162169689Skanstatic inline void 163169689Skanipcp_method_set_orig_node (struct cgraph_node *node, 164169689Skan struct cgraph_node *orig_node) 165169689Skan{ 166169689Skan IPA_NODE_REF (node)->ipcp_orig_node = orig_node; 167169689Skan} 168169689Skan 169169689Skan/* Create ipa_node and its data structures for NEW_NODE. 170169689Skan Set ORIG_NODE as the orig_node field in ipa_node. */ 171169689Skanstatic void 172169689Skanipcp_cloned_create (struct cgraph_node *orig_node, 173169689Skan struct cgraph_node *new_node) 174169689Skan{ 175169689Skan ipa_node_create (new_node); 176169689Skan ipcp_method_set_orig_node (new_node, orig_node); 177169689Skan ipa_method_formal_compute_count (new_node); 178169689Skan ipa_method_compute_tree_map (new_node); 179169689Skan} 180169689Skan 181169689Skan/* Return cval_type field of CVAL. */ 182169689Skanstatic inline enum cvalue_type 183169689Skanipcp_cval_get_cvalue_type (struct ipcp_formal *cval) 184169689Skan{ 185169689Skan return cval->cval_type; 186169689Skan} 187169689Skan 188169689Skan/* Return scale for MT. */ 189169689Skanstatic inline gcov_type 190169689Skanipcp_method_get_scale (struct cgraph_node *mt) 191169689Skan{ 192169689Skan return IPA_NODE_REF (mt)->count_scale; 193169689Skan} 194169689Skan 195169689Skan/* Set COUNT as scale for MT. */ 196169689Skanstatic inline void 197169689Skanipcp_method_set_scale (struct cgraph_node *node, gcov_type count) 198169689Skan{ 199169689Skan IPA_NODE_REF (node)->count_scale = count; 200169689Skan} 201169689Skan 202169689Skan/* Set TYPE as cval_type field of CVAL. */ 203169689Skanstatic inline void 204169689Skanipcp_cval_set_cvalue_type (struct ipcp_formal *cval, enum cvalue_type type) 205169689Skan{ 206169689Skan cval->cval_type = type; 207169689Skan} 208169689Skan 209169689Skan/* Return cvalue field of CVAL. */ 210169689Skanstatic inline union parameter_info * 211169689Skanipcp_cval_get_cvalue (struct ipcp_formal *cval) 212169689Skan{ 213169689Skan return &(cval->cvalue); 214169689Skan} 215169689Skan 216169689Skan/* Set VALUE as cvalue field CVAL. */ 217169689Skanstatic inline void 218169689Skanipcp_cval_set_cvalue (struct ipcp_formal *cval, union parameter_info *value, 219169689Skan enum cvalue_type type) 220169689Skan{ 221169689Skan if (type == CONST_VALUE || type == CONST_VALUE_REF) 222169689Skan cval->cvalue.value = value->value; 223169689Skan} 224169689Skan 225169689Skan/* Return whether TYPE is a constant type. */ 226169689Skanstatic bool 227169689Skanipcp_type_is_const (enum cvalue_type type) 228169689Skan{ 229169689Skan if (type == CONST_VALUE || type == CONST_VALUE_REF) 230169689Skan return true; 231169689Skan else 232169689Skan return false; 233169689Skan} 234169689Skan 235169689Skan/* Return true if CONST_VAL1 and CONST_VAL2 are equal. */ 236169689Skanstatic inline bool 237169689Skanipcp_cval_equal_cvalues (union parameter_info *const_val1, 238169689Skan union parameter_info *const_val2, 239169689Skan enum cvalue_type type1, enum cvalue_type type2) 240169689Skan{ 241169689Skan gcc_assert (ipcp_type_is_const (type1) && ipcp_type_is_const (type2)); 242169689Skan if (type1 != type2) 243169689Skan return false; 244169689Skan 245169689Skan if (operand_equal_p (const_val1->value, const_val2->value, 0)) 246169689Skan return true; 247169689Skan 248169689Skan return false; 249169689Skan} 250169689Skan 251169689Skan/* Compute Meet arithmetics: 252169689Skan Meet (BOTTOM, x) = BOTTOM 253169689Skan Meet (TOP,x) = x 254169689Skan Meet (const_a,const_b) = BOTTOM, if const_a != const_b. 255169689Skan MEET (const_a,const_b) = const_a, if const_a == const_b.*/ 256169689Skanstatic void 257169689Skanipcp_cval_meet (struct ipcp_formal *cval, struct ipcp_formal *cval1, 258169689Skan struct ipcp_formal *cval2) 259169689Skan{ 260169689Skan if (ipcp_cval_get_cvalue_type (cval1) == BOTTOM 261169689Skan || ipcp_cval_get_cvalue_type (cval2) == BOTTOM) 262169689Skan { 263169689Skan ipcp_cval_set_cvalue_type (cval, BOTTOM); 264169689Skan return; 265169689Skan } 266169689Skan if (ipcp_cval_get_cvalue_type (cval1) == TOP) 267169689Skan { 268169689Skan ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval2)); 269169689Skan ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval2), 270169689Skan ipcp_cval_get_cvalue_type (cval2)); 271169689Skan return; 272169689Skan } 273169689Skan if (ipcp_cval_get_cvalue_type (cval2) == TOP) 274169689Skan { 275169689Skan ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1)); 276169689Skan ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1), 277169689Skan ipcp_cval_get_cvalue_type (cval1)); 278169689Skan return; 279169689Skan } 280169689Skan if (!ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1), 281169689Skan ipcp_cval_get_cvalue (cval2), 282169689Skan ipcp_cval_get_cvalue_type (cval1), 283169689Skan ipcp_cval_get_cvalue_type (cval2))) 284169689Skan { 285169689Skan ipcp_cval_set_cvalue_type (cval, BOTTOM); 286169689Skan return; 287169689Skan } 288169689Skan ipcp_cval_set_cvalue_type (cval, ipcp_cval_get_cvalue_type (cval1)); 289169689Skan ipcp_cval_set_cvalue (cval, ipcp_cval_get_cvalue (cval1), 290169689Skan ipcp_cval_get_cvalue_type (cval1)); 291169689Skan} 292169689Skan 293169689Skan/* Return cval structure for the formal at index INFO_TYPE in MT. */ 294169689Skanstatic inline struct ipcp_formal * 295169689Skanipcp_method_cval (struct cgraph_node *mt, int info_type) 296169689Skan{ 297169689Skan return &(IPA_NODE_REF (mt)->ipcp_cval[info_type]); 298169689Skan} 299169689Skan 300169689Skan/* Given the jump function (TYPE, INFO_TYPE), compute a new value of CVAL. 301169689Skan If TYPE is FORMAL_IPA_TYPE, the cval of the corresponding formal is 302169689Skan drawn from MT. */ 303169689Skanstatic void 304169689Skanipcp_cval_compute (struct ipcp_formal *cval, struct cgraph_node *mt, 305169689Skan enum jump_func_type type, union parameter_info *info_type) 306169689Skan{ 307169689Skan if (type == UNKNOWN_IPATYPE) 308169689Skan ipcp_cval_set_cvalue_type (cval, BOTTOM); 309169689Skan else if (type == CONST_IPATYPE) 310169689Skan { 311169689Skan ipcp_cval_set_cvalue_type (cval, CONST_VALUE); 312169689Skan ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE); 313169689Skan } 314169689Skan else if (type == CONST_IPATYPE_REF) 315169689Skan { 316169689Skan ipcp_cval_set_cvalue_type (cval, CONST_VALUE_REF); 317169689Skan ipcp_cval_set_cvalue (cval, info_type, CONST_VALUE_REF); 318169689Skan } 319169689Skan else if (type == FORMAL_IPATYPE) 320169689Skan { 321169689Skan enum cvalue_type type = 322169689Skan ipcp_cval_get_cvalue_type (ipcp_method_cval 323169689Skan (mt, info_type->formal_id)); 324169689Skan ipcp_cval_set_cvalue_type (cval, type); 325169689Skan ipcp_cval_set_cvalue (cval, 326169689Skan ipcp_cval_get_cvalue (ipcp_method_cval 327169689Skan (mt, info_type->formal_id)), 328169689Skan type); 329169689Skan } 330169689Skan} 331169689Skan 332169689Skan/* True when CVAL1 and CVAL2 values are not the same. */ 333169689Skanstatic bool 334169689Skanipcp_cval_changed (struct ipcp_formal *cval1, struct ipcp_formal *cval2) 335169689Skan{ 336169689Skan if (ipcp_cval_get_cvalue_type (cval1) == ipcp_cval_get_cvalue_type (cval2)) 337169689Skan { 338169689Skan if (ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE && 339169689Skan ipcp_cval_get_cvalue_type (cval1) != CONST_VALUE_REF) 340169689Skan return false; 341169689Skan if (ipcp_cval_equal_cvalues (ipcp_cval_get_cvalue (cval1), 342169689Skan ipcp_cval_get_cvalue (cval2), 343169689Skan ipcp_cval_get_cvalue_type (cval1), 344169689Skan ipcp_cval_get_cvalue_type (cval2))) 345169689Skan return false; 346169689Skan } 347169689Skan return true; 348169689Skan} 349169689Skan 350169689Skan/* Create cval structure for method MT. */ 351169689Skanstatic inline void 352169689Skanipcp_formal_create (struct cgraph_node *mt) 353169689Skan{ 354169689Skan IPA_NODE_REF (mt)->ipcp_cval = 355169689Skan XCNEWVEC (struct ipcp_formal, ipa_method_formal_count (mt)); 356169689Skan} 357169689Skan 358169689Skan/* Set cval structure of I-th formal of MT to CVAL. */ 359169689Skanstatic inline void 360169689Skanipcp_method_cval_set (struct cgraph_node *mt, int i, struct ipcp_formal *cval) 361169689Skan{ 362169689Skan IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval->cval_type; 363169689Skan ipcp_cval_set_cvalue (ipcp_method_cval (mt, i), 364169689Skan ipcp_cval_get_cvalue (cval), cval->cval_type); 365169689Skan} 366169689Skan 367169689Skan/* Set type of cval structure of formal I of MT to CVAL_TYPE1. */ 368169689Skanstatic inline void 369169689Skanipcp_method_cval_set_cvalue_type (struct cgraph_node *mt, int i, 370169689Skan enum cvalue_type cval_type1) 371169689Skan{ 372169689Skan IPA_NODE_REF (mt)->ipcp_cval[i].cval_type = cval_type1; 373169689Skan} 374169689Skan 375169689Skan/* Print ipcp_cval data structures to F. */ 376169689Skanstatic void 377169689Skanipcp_method_cval_print (FILE * f) 378169689Skan{ 379169689Skan struct cgraph_node *node; 380169689Skan int i, count; 381169689Skan tree cvalue; 382169689Skan 383169689Skan fprintf (f, "\nCVAL PRINT\n"); 384169689Skan for (node = cgraph_nodes; node; node = node->next) 385169689Skan { 386169689Skan fprintf (f, "Printing cvals %s:\n", cgraph_node_name (node)); 387169689Skan count = ipa_method_formal_count (node); 388169689Skan for (i = 0; i < count; i++) 389169689Skan { 390169689Skan if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) 391169689Skan == CONST_VALUE 392169689Skan || ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == 393169689Skan CONST_VALUE_REF) 394169689Skan { 395169689Skan fprintf (f, " param [%d]: ", i); 396169689Skan fprintf (f, "type is CONST "); 397169689Skan cvalue = 398169689Skan ipcp_cval_get_cvalue (ipcp_method_cval (node, i))-> 399169689Skan value; 400169689Skan print_generic_expr (f, cvalue, 0); 401169689Skan fprintf (f, "\n"); 402169689Skan } 403169689Skan else if (ipcp_method_cval (node, i)->cval_type == TOP) 404169689Skan fprintf (f, "param [%d]: type is TOP \n", i); 405169689Skan else 406169689Skan fprintf (f, "param [%d]: type is BOTTOM \n", i); 407169689Skan } 408169689Skan } 409169689Skan} 410169689Skan 411169689Skan/* Initialize ipcp_cval array of MT with TOP values. 412169689Skan All cvals for a method's formal parameters are initialized to BOTTOM 413169689Skan The currently supported types are integer types, real types and 414169689Skan Fortran constants (i.e. references to constants defined as 415169689Skan const_decls). All other types are not analyzed and therefore are 416169689Skan assigned with BOTTOM. */ 417169689Skanstatic void 418169689Skanipcp_method_cval_init (struct cgraph_node *mt) 419169689Skan{ 420169689Skan int i; 421169689Skan tree parm_tree; 422169689Skan 423169689Skan ipcp_formal_create (mt); 424169689Skan for (i = 0; i < ipa_method_formal_count (mt); i++) 425169689Skan { 426169689Skan parm_tree = ipa_method_get_tree (mt, i); 427169689Skan if (INTEGRAL_TYPE_P (TREE_TYPE (parm_tree)) 428169689Skan || SCALAR_FLOAT_TYPE_P (TREE_TYPE (parm_tree)) 429169689Skan || POINTER_TYPE_P (TREE_TYPE (parm_tree))) 430169689Skan ipcp_method_cval_set_cvalue_type (mt, i, TOP); 431169689Skan else 432169689Skan ipcp_method_cval_set_cvalue_type (mt, i, BOTTOM); 433169689Skan } 434169689Skan} 435169689Skan 436169689Skan/* Create a new assignment statment and make 437169689Skan it the first statement in the function FN 438169689Skan tree. 439169689Skan PARM1 is the lhs of the assignment and 440169689Skan VAL is the rhs. */ 441169689Skanstatic void 442169689Skanconstant_val_insert (tree fn, tree parm1, tree val) 443169689Skan{ 444169689Skan struct function *func; 445169689Skan tree init_stmt; 446169689Skan edge e_step; 447169689Skan edge_iterator ei; 448169689Skan 449169689Skan init_stmt = build2 (MODIFY_EXPR, void_type_node, parm1, val); 450169689Skan func = DECL_STRUCT_FUNCTION (fn); 451169689Skan cfun = func; 452169689Skan current_function_decl = fn; 453169689Skan if (ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs) 454169689Skan FOR_EACH_EDGE (e_step, ei, ENTRY_BLOCK_PTR_FOR_FUNCTION (func)->succs) 455169689Skan bsi_insert_on_edge_immediate (e_step, init_stmt); 456169689Skan} 457169689Skan 458169689Skan/* build INTEGER_CST tree with type TREE_TYPE and 459169689Skan value according to CVALUE. Return the tree. */ 460169689Skanstatic tree 461169689Skanbuild_const_val (union parameter_info *cvalue, enum cvalue_type type, 462169689Skan tree tree_type) 463169689Skan{ 464169689Skan tree const_val = NULL; 465169689Skan 466169689Skan gcc_assert (ipcp_type_is_const (type)); 467169689Skan const_val = fold_convert (tree_type, cvalue->value); 468169689Skan return const_val; 469169689Skan} 470169689Skan 471169689Skan/* Build the tree representing the constant and call 472169689Skan constant_val_insert(). */ 473169689Skanstatic void 474169689Skanipcp_propagate_const (struct cgraph_node *mt, int param, 475169689Skan union parameter_info *cvalue ,enum cvalue_type type) 476169689Skan{ 477169689Skan tree fndecl; 478169689Skan tree const_val; 479169689Skan tree parm_tree; 480169689Skan 481169689Skan if (dump_file) 482169689Skan fprintf (dump_file, "propagating const to %s\n", cgraph_node_name (mt)); 483169689Skan fndecl = mt->decl; 484169689Skan parm_tree = ipa_method_get_tree (mt, param); 485169689Skan const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree)); 486169689Skan constant_val_insert (fndecl, parm_tree, const_val); 487169689Skan} 488169689Skan 489169689Skan/* Compute the proper scale for NODE. It is the ratio between 490169689Skan the number of direct calls (represented on the incoming 491169689Skan cgraph_edges) and sum of all invocations of NODE (represented 492169689Skan as count in cgraph_node). */ 493169689Skanstatic void 494169689Skanipcp_method_compute_scale (struct cgraph_node *node) 495169689Skan{ 496169689Skan gcov_type sum; 497169689Skan struct cgraph_edge *cs; 498169689Skan 499169689Skan sum = 0; 500169689Skan /* Compute sum of all counts of callers. */ 501169689Skan for (cs = node->callers; cs != NULL; cs = cs->next_caller) 502169689Skan sum += cs->count; 503169689Skan if (node->count == 0) 504169689Skan ipcp_method_set_scale (node, 0); 505169689Skan else 506169689Skan ipcp_method_set_scale (node, sum * REG_BR_PROB_BASE / node->count); 507169689Skan} 508169689Skan 509169689Skan/* Initialization and computation of IPCP data structures. 510169689Skan It is an intraprocedural 511169689Skan analysis of methods, which gathers information to be propagated 512169689Skan later on. */ 513169689Skanstatic void 514169689Skanipcp_init_stage (void) 515169689Skan{ 516169689Skan struct cgraph_node *node; 517169689Skan struct cgraph_edge *cs; 518169689Skan 519169689Skan for (node = cgraph_nodes; node; node = node->next) 520169689Skan { 521169689Skan ipa_method_formal_compute_count (node); 522169689Skan ipa_method_compute_tree_map (node); 523169689Skan ipcp_method_cval_init (node); 524169689Skan ipa_method_compute_modify (node); 525169689Skan ipcp_method_compute_scale (node); 526169689Skan } 527169689Skan for (node = cgraph_nodes; node; node = node->next) 528169689Skan { 529169689Skan /* building jump functions */ 530169689Skan for (cs = node->callees; cs; cs = cs->next_callee) 531169689Skan { 532169689Skan ipa_callsite_compute_count (cs); 533169689Skan if (ipa_callsite_param_count (cs) 534169689Skan != ipa_method_formal_count (cs->callee)) 535169689Skan { 536169689Skan /* Handle cases of functions with 537169689Skan a variable number of parameters. */ 538169689Skan ipa_callsite_param_count_set (cs, 0); 539169689Skan ipa_method_formal_count_set (cs->callee, 0); 540169689Skan } 541169689Skan else 542169689Skan ipa_callsite_compute_param (cs); 543169689Skan } 544169689Skan } 545169689Skan} 546169689Skan 547169689Skan/* Return true if there are some formal parameters whose value is TOP. 548169689Skan Change their values to BOTTOM, since they weren't determined. */ 549169689Skanstatic bool 550169689Skanipcp_after_propagate (void) 551169689Skan{ 552169689Skan int i, count; 553169689Skan struct cgraph_node *node; 554169689Skan bool prop_again; 555169689Skan 556169689Skan prop_again = false; 557169689Skan for (node = cgraph_nodes; node; node = node->next) 558169689Skan { 559169689Skan count = ipa_method_formal_count (node); 560169689Skan for (i = 0; i < count; i++) 561169689Skan if (ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)) == TOP) 562169689Skan { 563169689Skan prop_again = true; 564169689Skan ipcp_method_cval_set_cvalue_type (node, i, BOTTOM); 565169689Skan } 566169689Skan } 567169689Skan return prop_again; 568169689Skan} 569169689Skan 570169689Skan/* Interprocedural analysis. The algorithm propagates constants from 571169689Skan the caller's parameters to the callee's arguments. */ 572169689Skanstatic void 573169689Skanipcp_propagate_stage (void) 574169689Skan{ 575169689Skan int i; 576169689Skan struct ipcp_formal cval1 = { 0, {0} }, cval = { 0,{0} }; 577169689Skan struct ipcp_formal *cval2; 578169689Skan struct cgraph_node *mt, *callee; 579169689Skan struct cgraph_edge *cs; 580169689Skan struct ipa_jump_func *jump_func; 581169689Skan enum jump_func_type type; 582169689Skan union parameter_info *info_type; 583169689Skan ipa_methodlist_p wl; 584169689Skan int count; 585169689Skan 586169689Skan /* Initialize worklist to contain all methods. */ 587169689Skan wl = ipa_methodlist_init (); 588169689Skan while (ipa_methodlist_not_empty (wl)) 589169689Skan { 590169689Skan mt = ipa_remove_method (&wl); 591169689Skan for (cs = mt->callees; cs; cs = cs->next_callee) 592169689Skan { 593169689Skan callee = ipa_callsite_callee (cs); 594169689Skan count = ipa_callsite_param_count (cs); 595169689Skan for (i = 0; i < count; i++) 596169689Skan { 597169689Skan jump_func = ipa_callsite_param (cs, i); 598169689Skan type = get_type (jump_func); 599169689Skan info_type = ipa_jf_get_info_type (jump_func); 600169689Skan ipcp_cval_compute (&cval1, mt, type, info_type); 601169689Skan cval2 = ipcp_method_cval (callee, i); 602169689Skan ipcp_cval_meet (&cval, &cval1, cval2); 603169689Skan if (ipcp_cval_changed (&cval, cval2)) 604169689Skan { 605169689Skan ipcp_method_cval_set (callee, i, &cval); 606169689Skan ipa_add_method (&wl, callee); 607169689Skan } 608169689Skan } 609169689Skan } 610169689Skan } 611169689Skan} 612169689Skan 613169689Skan/* Call the constant propagation algorithm and re-call it if necessary 614169689Skan (if there are undetermined values left). */ 615169689Skanstatic void 616169689Skanipcp_iterate_stage (void) 617169689Skan{ 618169689Skan ipcp_propagate_stage (); 619169689Skan if (ipcp_after_propagate ()) 620169689Skan /* Some cvals have changed from TOP to BOTTOM. 621169689Skan This change should be propagated. */ 622169689Skan ipcp_propagate_stage (); 623169689Skan} 624169689Skan 625169689Skan/* Check conditions to forbid constant insertion to MT. */ 626169689Skanstatic bool 627169689Skanipcp_method_dont_insert_const (struct cgraph_node *mt) 628169689Skan{ 629169689Skan /* ??? Handle pending sizes case. */ 630169689Skan if (DECL_UNINLINABLE (mt->decl)) 631169689Skan return true; 632169689Skan return false; 633169689Skan} 634169689Skan 635169689Skan/* Print ipa_jump_func data structures to F. */ 636169689Skanstatic void 637169689Skanipcp_callsite_param_print (FILE * f) 638169689Skan{ 639169689Skan struct cgraph_node *node; 640169689Skan int i, count; 641169689Skan struct cgraph_edge *cs; 642169689Skan struct ipa_jump_func *jump_func; 643169689Skan enum jump_func_type type; 644169689Skan tree info_type; 645169689Skan 646169689Skan fprintf (f, "\nCALLSITE PARAM PRINT\n"); 647169689Skan for (node = cgraph_nodes; node; node = node->next) 648169689Skan { 649169689Skan for (cs = node->callees; cs; cs = cs->next_callee) 650169689Skan { 651169689Skan fprintf (f, "callsite %s ", cgraph_node_name (node)); 652169689Skan fprintf (f, "-> %s :: \n", cgraph_node_name (cs->callee)); 653169689Skan count = ipa_callsite_param_count (cs); 654169689Skan for (i = 0; i < count; i++) 655169689Skan { 656169689Skan jump_func = ipa_callsite_param (cs, i); 657169689Skan type = get_type (jump_func); 658169689Skan 659169689Skan fprintf (f, " param %d: ", i); 660169689Skan if (type == UNKNOWN_IPATYPE) 661169689Skan fprintf (f, "UNKNOWN\n"); 662169689Skan else if (type == CONST_IPATYPE || type == CONST_IPATYPE_REF) 663169689Skan { 664169689Skan info_type = 665169689Skan ipa_jf_get_info_type (jump_func)->value; 666169689Skan fprintf (f, "CONST : "); 667169689Skan print_generic_expr (f, info_type, 0); 668169689Skan fprintf (f, "\n"); 669169689Skan } 670169689Skan else if (type == FORMAL_IPATYPE) 671169689Skan { 672169689Skan fprintf (f, "FORMAL : "); 673169689Skan fprintf (f, "%d\n", 674169689Skan ipa_jf_get_info_type (jump_func)->formal_id); 675169689Skan } 676169689Skan } 677169689Skan } 678169689Skan } 679169689Skan} 680169689Skan 681169689Skan/* Print count scale data structures. */ 682169689Skanstatic void 683169689Skanipcp_method_scale_print (FILE * f) 684169689Skan{ 685169689Skan struct cgraph_node *node; 686169689Skan 687169689Skan for (node = cgraph_nodes; node; node = node->next) 688169689Skan { 689169689Skan fprintf (f, "printing scale for %s: ", cgraph_node_name (node)); 690169689Skan fprintf (f, "value is " HOST_WIDE_INT_PRINT_DEC 691169689Skan " \n", (HOST_WIDE_INT) ipcp_method_get_scale (node)); 692169689Skan } 693169689Skan} 694169689Skan 695169689Skan/* Print counts of all cgraph nodes. */ 696169689Skanstatic void 697169689Skanipcp_profile_mt_count_print (FILE * f) 698169689Skan{ 699169689Skan struct cgraph_node *node; 700169689Skan 701169689Skan for (node = cgraph_nodes; node; node = node->next) 702169689Skan { 703169689Skan fprintf (f, "method %s: ", cgraph_node_name (node)); 704169689Skan fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC 705169689Skan " \n", (HOST_WIDE_INT) node->count); 706169689Skan } 707169689Skan} 708169689Skan 709169689Skan/* Print counts of all cgraph edges. */ 710169689Skanstatic void 711169689Skanipcp_profile_cs_count_print (FILE * f) 712169689Skan{ 713169689Skan struct cgraph_node *node; 714169689Skan struct cgraph_edge *cs; 715169689Skan 716169689Skan for (node = cgraph_nodes; node; node = node->next) 717169689Skan { 718169689Skan for (cs = node->callees; cs; cs = cs->next_callee) 719169689Skan { 720169689Skan fprintf (f, "%s -> %s ", cgraph_node_name (cs->caller), 721169689Skan cgraph_node_name (cs->callee)); 722169689Skan fprintf (f, "count is " HOST_WIDE_INT_PRINT_DEC " \n", 723169689Skan (HOST_WIDE_INT) cs->count); 724169689Skan } 725169689Skan } 726169689Skan} 727169689Skan 728169689Skan/* Print all counts and probabilities of cfg edges of all methods. */ 729169689Skanstatic void 730169689Skanipcp_profile_edge_print (FILE * f) 731169689Skan{ 732169689Skan struct cgraph_node *node; 733169689Skan basic_block bb; 734169689Skan edge_iterator ei; 735169689Skan edge e; 736169689Skan 737169689Skan for (node = cgraph_nodes; node; node = node->next) 738169689Skan { 739169689Skan fprintf (f, "method %s: \n", cgraph_node_name (node)); 740169689Skan if (DECL_SAVED_TREE (node->decl)) 741169689Skan { 742169689Skan bb = 743169689Skan ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl)); 744169689Skan fprintf (f, "ENTRY: "); 745169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 746169689Skan " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency); 747169689Skan 748169689Skan if (bb->succs) 749169689Skan FOR_EACH_EDGE (e, ei, bb->succs) 750169689Skan { 751169689Skan if (e->dest == 752169689Skan EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION 753169689Skan (node->decl))) 754169689Skan fprintf (f, "edge ENTRY -> EXIT, Count"); 755169689Skan else 756169689Skan fprintf (f, "edge ENTRY -> %d, Count", e->dest->index); 757169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 758169689Skan " Prob %d\n", (HOST_WIDE_INT) e->count, 759169689Skan e->probability); 760169689Skan } 761169689Skan FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 762169689Skan { 763169689Skan fprintf (f, "bb[%d]: ", bb->index); 764169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 765169689Skan " %d\n", (HOST_WIDE_INT) bb->count, bb->frequency); 766169689Skan FOR_EACH_EDGE (e, ei, bb->succs) 767169689Skan { 768169689Skan if (e->dest == 769169689Skan EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION 770169689Skan (node->decl))) 771169689Skan fprintf (f, "edge %d -> EXIT, Count", e->src->index); 772169689Skan else 773169689Skan fprintf (f, "edge %d -> %d, Count", e->src->index, 774169689Skan e->dest->index); 775169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC " Prob %d\n", 776169689Skan (HOST_WIDE_INT) e->count, e->probability); 777169689Skan } 778169689Skan } 779169689Skan } 780169689Skan } 781169689Skan} 782169689Skan 783169689Skan/* Print counts and frequencies for all basic blocks of all methods. */ 784169689Skanstatic void 785169689Skanipcp_profile_bb_print (FILE * f) 786169689Skan{ 787169689Skan basic_block bb; 788169689Skan struct cgraph_node *node; 789169689Skan 790169689Skan for (node = cgraph_nodes; node; node = node->next) 791169689Skan { 792169689Skan fprintf (f, "method %s: \n", cgraph_node_name (node)); 793169689Skan if (DECL_SAVED_TREE (node->decl)) 794169689Skan { 795169689Skan bb = 796169689Skan ENTRY_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl)); 797169689Skan fprintf (f, "ENTRY: Count"); 798169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 799169689Skan " Frquency %d\n", (HOST_WIDE_INT) bb->count, 800169689Skan bb->frequency); 801169689Skan 802169689Skan FOR_EACH_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 803169689Skan { 804169689Skan fprintf (f, "bb[%d]: Count", bb->index); 805169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 806169689Skan " Frequency %d\n", (HOST_WIDE_INT) bb->count, 807169689Skan bb->frequency); 808169689Skan } 809169689Skan bb = 810169689Skan EXIT_BLOCK_PTR_FOR_FUNCTION (DECL_STRUCT_FUNCTION (node->decl)); 811169689Skan fprintf (f, "EXIT: Count"); 812169689Skan fprintf (f, " " HOST_WIDE_INT_PRINT_DEC 813169689Skan " Frequency %d\n", (HOST_WIDE_INT) bb->count, 814169689Skan bb->frequency); 815169689Skan 816169689Skan } 817169689Skan } 818169689Skan} 819169689Skan 820169689Skan/* Print all IPCP data structures to F. */ 821169689Skanstatic void 822169689Skanipcp_structures_print (FILE * f) 823169689Skan{ 824169689Skan ipcp_method_cval_print (f); 825169689Skan ipcp_method_scale_print (f); 826169689Skan ipa_method_tree_print (f); 827169689Skan ipa_method_modify_print (f); 828169689Skan ipcp_callsite_param_print (f); 829169689Skan} 830169689Skan 831169689Skan/* Print profile info for all methods. */ 832169689Skanstatic void 833169689Skanipcp_profile_print (FILE * f) 834169689Skan{ 835169689Skan fprintf (f, "\nNODE COUNTS :\n"); 836169689Skan ipcp_profile_mt_count_print (f); 837169689Skan fprintf (f, "\nCS COUNTS stage:\n"); 838169689Skan ipcp_profile_cs_count_print (f); 839169689Skan fprintf (f, "\nBB COUNTS and FREQUENCIES :\n"); 840169689Skan ipcp_profile_bb_print (f); 841169689Skan fprintf (f, "\nCFG EDGES COUNTS and PROBABILITIES :\n"); 842169689Skan ipcp_profile_edge_print (f); 843169689Skan} 844169689Skan 845169689Skan/* Build and initialize ipa_replace_map struct 846169689Skan according to TYPE. This struct is read by versioning, which 847169689Skan operates according to the flags sent. PARM_TREE is the 848169689Skan formal's tree found to be constant. CVALUE represents the constant. */ 849169689Skanstatic struct ipa_replace_map * 850169689Skanipcp_replace_map_create (enum cvalue_type type, tree parm_tree, 851169689Skan union parameter_info *cvalue) 852169689Skan{ 853169689Skan struct ipa_replace_map *replace_map; 854169689Skan tree const_val; 855169689Skan 856169689Skan replace_map = XCNEW (struct ipa_replace_map); 857169689Skan gcc_assert (ipcp_type_is_const (type)); 858169689Skan if (type == CONST_VALUE_REF ) 859169689Skan { 860169689Skan const_val = 861169689Skan build_const_val (cvalue, type, TREE_TYPE (TREE_TYPE (parm_tree))); 862169689Skan replace_map->old_tree = parm_tree; 863169689Skan replace_map->new_tree = const_val; 864169689Skan replace_map->replace_p = true; 865169689Skan replace_map->ref_p = true; 866169689Skan } 867169689Skan else if (TREE_READONLY (parm_tree) && !TREE_ADDRESSABLE (parm_tree)) 868169689Skan { 869169689Skan const_val = build_const_val (cvalue, type, TREE_TYPE (parm_tree)); 870169689Skan replace_map->old_tree = parm_tree; 871169689Skan replace_map->new_tree = const_val; 872169689Skan replace_map->replace_p = true; 873169689Skan replace_map->ref_p = false; 874169689Skan } 875169689Skan else 876169689Skan { 877169689Skan replace_map->old_tree = NULL; 878169689Skan replace_map->new_tree = NULL; 879169689Skan replace_map->replace_p = false; 880169689Skan replace_map->ref_p = false; 881169689Skan } 882169689Skan 883169689Skan return replace_map; 884169689Skan} 885169689Skan 886169689Skan/* Return true if this callsite should be redirected to 887169689Skan the orig callee (instead of the cloned one). */ 888169689Skanstatic bool 889169689Skanipcp_redirect (struct cgraph_edge *cs) 890169689Skan{ 891169689Skan struct cgraph_node *caller, *callee, *orig_callee; 892169689Skan int i, count; 893169689Skan struct ipa_jump_func *jump_func; 894169689Skan enum jump_func_type type; 895169689Skan enum cvalue_type cval_type; 896169689Skan 897169689Skan caller = cs->caller; 898169689Skan callee = cs->callee; 899169689Skan orig_callee = ipcp_method_orig_node (callee); 900169689Skan count = ipa_method_formal_count (orig_callee); 901169689Skan for (i = 0; i < count; i++) 902169689Skan { 903169689Skan cval_type = 904169689Skan ipcp_cval_get_cvalue_type (ipcp_method_cval (orig_callee, i)); 905169689Skan if (ipcp_type_is_const (cval_type)) 906169689Skan { 907169689Skan jump_func = ipa_callsite_param (cs, i); 908169689Skan type = get_type (jump_func); 909169689Skan if (type != CONST_IPATYPE 910169689Skan && type != CONST_IPATYPE_REF) 911169689Skan return true; 912169689Skan } 913169689Skan } 914169689Skan 915169689Skan return false; 916169689Skan} 917169689Skan 918169689Skan/* Fix the callsites and the callgraph after function cloning was done. */ 919169689Skanstatic void 920169689Skanipcp_update_callgraph (void) 921169689Skan{ 922169689Skan struct cgraph_node *node, *orig_callee; 923169689Skan struct cgraph_edge *cs; 924169689Skan 925169689Skan for (node = cgraph_nodes; node; node = node->next) 926169689Skan { 927169689Skan /* want to fix only original nodes */ 928169689Skan if (ipcp_method_is_cloned (node)) 929169689Skan continue; 930169689Skan for (cs = node->callees; cs; cs = cs->next_callee) 931169689Skan if (ipcp_method_is_cloned (cs->callee)) 932169689Skan { 933169689Skan /* Callee is a cloned node */ 934169689Skan orig_callee = ipcp_method_orig_node (cs->callee); 935169689Skan if (ipcp_redirect (cs)) 936169689Skan { 937169689Skan cgraph_redirect_edge_callee (cs, orig_callee); 938169689Skan TREE_OPERAND (TREE_OPERAND 939169689Skan (get_call_expr_in (cs->call_stmt), 0), 0) = 940169689Skan orig_callee->decl; 941169689Skan } 942169689Skan } 943169689Skan } 944169689Skan} 945169689Skan 946169689Skan/* Update all cfg basic blocks in NODE according to SCALE. */ 947169689Skanstatic void 948169689Skanipcp_update_bb_counts (struct cgraph_node *node, gcov_type scale) 949169689Skan{ 950169689Skan basic_block bb; 951169689Skan 952169689Skan FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 953169689Skan bb->count = bb->count * scale / REG_BR_PROB_BASE; 954169689Skan} 955169689Skan 956169689Skan/* Update all cfg edges in NODE according to SCALE. */ 957169689Skanstatic void 958169689Skanipcp_update_edges_counts (struct cgraph_node *node, gcov_type scale) 959169689Skan{ 960169689Skan basic_block bb; 961169689Skan edge_iterator ei; 962169689Skan edge e; 963169689Skan 964169689Skan FOR_ALL_BB_FN (bb, DECL_STRUCT_FUNCTION (node->decl)) 965169689Skan FOR_EACH_EDGE (e, ei, bb->succs) 966169689Skan e->count = e->count * scale / REG_BR_PROB_BASE; 967169689Skan} 968169689Skan 969169689Skan/* Update profiling info for versioned methods and the 970169689Skan methods they were versioned from. */ 971169689Skanstatic void 972169689Skanipcp_update_profiling (void) 973169689Skan{ 974169689Skan struct cgraph_node *node, *orig_node; 975169689Skan gcov_type scale, scale_complement; 976169689Skan struct cgraph_edge *cs; 977169689Skan 978169689Skan for (node = cgraph_nodes; node; node = node->next) 979169689Skan { 980169689Skan if (ipcp_method_is_cloned (node)) 981169689Skan { 982169689Skan orig_node = ipcp_method_orig_node (node); 983169689Skan scale = ipcp_method_get_scale (orig_node); 984169689Skan node->count = orig_node->count * scale / REG_BR_PROB_BASE; 985169689Skan scale_complement = REG_BR_PROB_BASE - scale; 986169689Skan orig_node->count = 987169689Skan orig_node->count * scale_complement / REG_BR_PROB_BASE; 988169689Skan for (cs = node->callees; cs; cs = cs->next_callee) 989169689Skan cs->count = cs->count * scale / REG_BR_PROB_BASE; 990169689Skan for (cs = orig_node->callees; cs; cs = cs->next_callee) 991169689Skan cs->count = cs->count * scale_complement / REG_BR_PROB_BASE; 992169689Skan ipcp_update_bb_counts (node, scale); 993169689Skan ipcp_update_bb_counts (orig_node, scale_complement); 994169689Skan ipcp_update_edges_counts (node, scale); 995169689Skan ipcp_update_edges_counts (orig_node, scale_complement); 996169689Skan } 997169689Skan } 998169689Skan} 999169689Skan 1000169689Skan/* Propagate the constant parameters found by ipcp_iterate_stage() 1001169689Skan to the function's code. */ 1002169689Skanstatic void 1003169689Skanipcp_insert_stage (void) 1004169689Skan{ 1005169689Skan struct cgraph_node *node, *node1 = NULL; 1006169689Skan int i, const_param; 1007169689Skan union parameter_info *cvalue; 1008169689Skan VEC(cgraph_edge_p,heap) *redirect_callers; 1009169689Skan varray_type replace_trees; 1010169689Skan struct cgraph_edge *cs; 1011169689Skan int node_callers, count; 1012169689Skan tree parm_tree; 1013169689Skan enum cvalue_type type; 1014169689Skan struct ipa_replace_map *replace_param; 1015169689Skan 1016169689Skan for (node = cgraph_nodes; node; node = node->next) 1017169689Skan { 1018169689Skan /* Propagation of the constant is forbidden in 1019169689Skan certain conditions. */ 1020169689Skan if (ipcp_method_dont_insert_const (node)) 1021169689Skan continue; 1022169689Skan const_param = 0; 1023169689Skan count = ipa_method_formal_count (node); 1024169689Skan for (i = 0; i < count; i++) 1025169689Skan { 1026169689Skan type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); 1027169689Skan if (ipcp_type_is_const (type)) 1028169689Skan const_param++; 1029169689Skan } 1030169689Skan if (const_param == 0) 1031169689Skan continue; 1032169689Skan VARRAY_GENERIC_PTR_INIT (replace_trees, const_param, "replace_trees"); 1033169689Skan for (i = 0; i < count; i++) 1034169689Skan { 1035169689Skan type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); 1036169689Skan if (ipcp_type_is_const (type)) 1037169689Skan { 1038169689Skan cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); 1039169689Skan parm_tree = ipa_method_get_tree (node, i); 1040169689Skan replace_param = 1041169689Skan ipcp_replace_map_create (type, parm_tree, cvalue); 1042169689Skan VARRAY_PUSH_GENERIC_PTR (replace_trees, replace_param); 1043169689Skan } 1044169689Skan } 1045169689Skan /* Compute how many callers node has. */ 1046169689Skan node_callers = 0; 1047169689Skan for (cs = node->callers; cs != NULL; cs = cs->next_caller) 1048169689Skan node_callers++; 1049169689Skan redirect_callers = VEC_alloc (cgraph_edge_p, heap, node_callers); 1050169689Skan for (cs = node->callers; cs != NULL; cs = cs->next_caller) 1051169689Skan VEC_quick_push (cgraph_edge_p, redirect_callers, cs); 1052169689Skan /* Redirecting all the callers of the node to the 1053169689Skan new versioned node. */ 1054169689Skan node1 = 1055169689Skan cgraph_function_versioning (node, redirect_callers, replace_trees); 1056169689Skan VEC_free (cgraph_edge_p, heap, redirect_callers); 1057169689Skan VARRAY_CLEAR (replace_trees); 1058169689Skan if (node1 == NULL) 1059169689Skan continue; 1060169689Skan if (dump_file) 1061169689Skan fprintf (dump_file, "versioned function %s\n", 1062169689Skan cgraph_node_name (node)); 1063169689Skan ipcp_cloned_create (node, node1); 1064169689Skan for (i = 0; i < count; i++) 1065169689Skan { 1066169689Skan type = ipcp_cval_get_cvalue_type (ipcp_method_cval (node, i)); 1067169689Skan if (ipcp_type_is_const (type)) 1068169689Skan { 1069169689Skan cvalue = ipcp_cval_get_cvalue (ipcp_method_cval (node, i)); 1070169689Skan parm_tree = ipa_method_get_tree (node, i); 1071169689Skan if (type != CONST_VALUE_REF 1072169689Skan && !TREE_READONLY (parm_tree)) 1073169689Skan ipcp_propagate_const (node1, i, cvalue, type); 1074169689Skan } 1075169689Skan } 1076169689Skan } 1077169689Skan ipcp_update_callgraph (); 1078169689Skan ipcp_update_profiling (); 1079169689Skan} 1080169689Skan 1081169689Skan/* The IPCP driver. */ 1082169689Skanunsigned int 1083169689Skanipcp_driver (void) 1084169689Skan{ 1085169689Skan if (dump_file) 1086169689Skan fprintf (dump_file, "\nIPA constant propagation start:\n"); 1087169689Skan ipa_nodes_create (); 1088169689Skan ipa_edges_create (); 1089169689Skan /* 1. Call the init stage to initialize 1090169689Skan the ipa_node and ipa_edge structures. */ 1091169689Skan ipcp_init_stage (); 1092169689Skan if (dump_file) 1093169689Skan { 1094169689Skan fprintf (dump_file, "\nIPA structures before propagation:\n"); 1095169689Skan ipcp_structures_print (dump_file); 1096169689Skan } 1097169689Skan /* 2. Do the interprocedural propagation. */ 1098169689Skan ipcp_iterate_stage (); 1099169689Skan if (dump_file) 1100169689Skan { 1101169689Skan fprintf (dump_file, "\nIPA structures after propagation:\n"); 1102169689Skan ipcp_structures_print (dump_file); 1103169689Skan fprintf (dump_file, "\nProfiling info before insert stage:\n"); 1104169689Skan ipcp_profile_print (dump_file); 1105169689Skan } 1106169689Skan /* 3. Insert the constants found to the functions. */ 1107169689Skan ipcp_insert_stage (); 1108169689Skan if (dump_file) 1109169689Skan { 1110169689Skan fprintf (dump_file, "\nProfiling info after insert stage:\n"); 1111169689Skan ipcp_profile_print (dump_file); 1112169689Skan } 1113169689Skan /* Free all IPCP structures. */ 1114169689Skan ipa_free (); 1115169689Skan ipa_nodes_free (); 1116169689Skan ipa_edges_free (); 1117169689Skan if (dump_file) 1118169689Skan fprintf (dump_file, "\nIPA constant propagation end\n"); 1119169689Skan cgraph_remove_unreachable_nodes (true, NULL); 1120169689Skan return 0; 1121169689Skan} 1122169689Skan 1123169689Skan/* Gate for IPCP optimization. */ 1124169689Skanstatic bool 1125169689Skancgraph_gate_cp (void) 1126169689Skan{ 1127169689Skan return flag_ipa_cp; 1128169689Skan} 1129169689Skan 1130169689Skanstruct tree_opt_pass pass_ipa_cp = { 1131169689Skan "cp", /* name */ 1132169689Skan cgraph_gate_cp, /* gate */ 1133169689Skan ipcp_driver, /* execute */ 1134169689Skan NULL, /* sub */ 1135169689Skan NULL, /* next */ 1136169689Skan 0, /* static_pass_number */ 1137169689Skan TV_IPA_CONSTANT_PROP, /* tv_id */ 1138169689Skan 0, /* properties_required */ 1139169689Skan PROP_trees, /* properties_provided */ 1140169689Skan 0, /* properties_destroyed */ 1141169689Skan 0, /* todo_flags_start */ 1142169689Skan TODO_dump_cgraph | TODO_dump_func, /* todo_flags_finish */ 1143169689Skan 0 /* letter */ 1144169689Skan}; 1145