1 /* Interprocedural constant propagation 2 Copyright (C) 2005-2017 Free Software Foundation, Inc. 3 4 Contributed by Razya Ladelsky <RAZYA@il.ibm.com> and Martin Jambor 5 <mjambor@suse.cz> 6 7 This file is part of GCC. 8 9 GCC is free software; you can redistribute it and/or modify it under 10 the terms of the GNU General Public License as published by the Free 11 Software Foundation; either version 3, or (at your option) any later 12 version. 13 14 GCC is distributed in the hope that it will be useful, but WITHOUT ANY 15 WARRANTY; without even the implied warranty of MERCHANTABILITY or 16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 17 for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with GCC; see the file COPYING3. If not see 21 <http://www.gnu.org/licenses/>. */ 22 23 /* Interprocedural constant propagation (IPA-CP). 24 25 The goal of this transformation is to 26 27 1) discover functions which are always invoked with some arguments with the 28 same known constant values and modify the functions so that the 29 subsequent optimizations can take advantage of the knowledge, and 30 31 2) partial specialization - create specialized versions of functions 32 transformed in this way if some parameters are known constants only in 33 certain contexts but the estimated tradeoff between speedup and cost size 34 is deemed good. 35 36 The algorithm also propagates types and attempts to perform type based 37 devirtualization. Types are propagated much like constants. 38 39 The algorithm basically consists of three stages. In the first, functions 40 are analyzed one at a time and jump functions are constructed for all known 41 call-sites. In the second phase, the pass propagates information from the 42 jump functions across the call to reveal what values are available at what 43 call sites, performs estimations of effects of known values on functions and 44 their callees, and finally decides what specialized extra versions should be 45 created. In the third, the special versions materialize and appropriate 46 calls are redirected. 47 48 The algorithm used is to a certain extent based on "Interprocedural Constant 49 Propagation", by David Callahan, Keith D Cooper, Ken Kennedy, Linda Torczon, 50 Comp86, pg 152-161 and "A Methodology for Procedure Cloning" by Keith D 51 Cooper, Mary W. Hall, and Ken Kennedy. 52 53 54 First stage - intraprocedural analysis 55 ======================================= 56 57 This phase computes jump_function and modification flags. 58 59 A jump function for a call-site represents the values passed as an actual 60 arguments of a given call-site. In principle, there are three types of 61 values: 62 63 Pass through - the caller's formal parameter is passed as an actual 64 argument, plus an operation on it can be performed. 65 Constant - a constant is passed as an actual argument. 66 Unknown - neither of the above. 67 68 All jump function types are described in detail in ipa-prop.h, together with 69 the data structures that represent them and methods of accessing them. 70 71 ipcp_generate_summary() is the main function of the first stage. 72 73 Second stage - interprocedural analysis 74 ======================================== 75 76 This stage is itself divided into two phases. In the first, we propagate 77 known values over the call graph, in the second, we make cloning decisions. 78 It uses a different algorithm than the original Callahan's paper. 79 80 First, we traverse the functions topologically from callers to callees and, 81 for each strongly connected component (SCC), we propagate constants 82 according to previously computed jump functions. We also record what known 83 values depend on other known values and estimate local effects. Finally, we 84 propagate cumulative information about these effects from dependent values 85 to those on which they depend. 86 87 Second, we again traverse the call graph in the same topological order and 88 make clones for functions which we know are called with the same values in 89 all contexts and decide about extra specialized clones of functions just for 90 some contexts - these decisions are based on both local estimates and 91 cumulative estimates propagated from callees. 92 93 ipcp_propagate_stage() and ipcp_decision_stage() together constitute the 94 third stage. 95 96 Third phase - materialization of clones, call statement updates. 97 ============================================ 98 99 This stage is currently performed by call graph code (mainly in cgraphunit.c 100 and tree-inline.c) according to instructions inserted to the call graph by 101 the second stage. */ 102 103 #include "config.h" 104 #include "system.h" 105 #include "coretypes.h" 106 #include "backend.h" 107 #include "tree.h" 108 #include "gimple-expr.h" 109 #include "predict.h" 110 #include "alloc-pool.h" 111 #include "tree-pass.h" 112 #include "cgraph.h" 113 #include "diagnostic.h" 114 #include "fold-const.h" 115 #include "gimple-fold.h" 116 #include "symbol-summary.h" 117 #include "tree-vrp.h" 118 #include "ipa-prop.h" 119 #include "tree-pretty-print.h" 120 #include "tree-inline.h" 121 #include "params.h" 122 #include "ipa-inline.h" 123 #include "ipa-utils.h" 124 #include "tree-ssa-ccp.h" 125 126 template <typename valtype> class ipcp_value; 127 128 /* Describes a particular source for an IPA-CP value. */ 129 130 template <typename valtype> 131 class ipcp_value_source 132 { 133 public: 134 /* Aggregate offset of the source, negative if the source is scalar value of 135 the argument itself. */ 136 HOST_WIDE_INT offset; 137 /* The incoming edge that brought the value. */ 138 cgraph_edge *cs; 139 /* If the jump function that resulted into his value was a pass-through or an 140 ancestor, this is the ipcp_value of the caller from which the described 141 value has been derived. Otherwise it is NULL. */ 142 ipcp_value<valtype> *val; 143 /* Next pointer in a linked list of sources of a value. */ 144 ipcp_value_source *next; 145 /* If the jump function that resulted into his value was a pass-through or an 146 ancestor, this is the index of the parameter of the caller the jump 147 function references. */ 148 int index; 149 }; 150 151 /* Common ancestor for all ipcp_value instantiations. */ 152 153 class ipcp_value_base 154 { 155 public: 156 /* Time benefit and size cost that specializing the function for this value 157 would bring about in this function alone. */ 158 int local_time_benefit, local_size_cost; 159 /* Time benefit and size cost that specializing the function for this value 160 can bring about in it's callees (transitively). */ 161 int prop_time_benefit, prop_size_cost; 162 }; 163 164 /* Describes one particular value stored in struct ipcp_lattice. */ 165 166 template <typename valtype> 167 class ipcp_value : public ipcp_value_base 168 { 169 public: 170 /* The actual value for the given parameter. */ 171 valtype value; 172 /* The list of sources from which this value originates. */ 173 ipcp_value_source <valtype> *sources; 174 /* Next pointers in a linked list of all values in a lattice. */ 175 ipcp_value *next; 176 /* Next pointers in a linked list of values in a strongly connected component 177 of values. */ 178 ipcp_value *scc_next; 179 /* Next pointers in a linked list of SCCs of values sorted topologically 180 according their sources. */ 181 ipcp_value *topo_next; 182 /* A specialized node created for this value, NULL if none has been (so far) 183 created. */ 184 cgraph_node *spec_node; 185 /* Depth first search number and low link for topological sorting of 186 values. */ 187 int dfs, low_link; 188 /* True if this valye is currently on the topo-sort stack. */ 189 bool on_stack; 190 191 void add_source (cgraph_edge *cs, ipcp_value *src_val, int src_idx, 192 HOST_WIDE_INT offset); 193 }; 194 195 /* Lattice describing potential values of a formal parameter of a function, or 196 a part of an aggregate. TOP is represented by a lattice with zero values 197 and with contains_variable and bottom flags cleared. BOTTOM is represented 198 by a lattice with the bottom flag set. In that case, values and 199 contains_variable flag should be disregarded. */ 200 201 template <typename valtype> 202 class ipcp_lattice 203 { 204 public: 205 /* The list of known values and types in this lattice. Note that values are 206 not deallocated if a lattice is set to bottom because there may be value 207 sources referencing them. */ 208 ipcp_value<valtype> *values; 209 /* Number of known values and types in this lattice. */ 210 int values_count; 211 /* The lattice contains a variable component (in addition to values). */ 212 bool contains_variable; 213 /* The value of the lattice is bottom (i.e. variable and unusable for any 214 propagation). */ 215 bool bottom; 216 217 inline bool is_single_const (); 218 inline bool set_to_bottom (); 219 inline bool set_contains_variable (); 220 bool add_value (valtype newval, cgraph_edge *cs, 221 ipcp_value<valtype> *src_val = NULL, 222 int src_idx = 0, HOST_WIDE_INT offset = -1); 223 void print (FILE * f, bool dump_sources, bool dump_benefits); 224 }; 225 226 /* Lattice of tree values with an offset to describe a part of an 227 aggregate. */ 228 229 class ipcp_agg_lattice : public ipcp_lattice<tree> 230 { 231 public: 232 /* Offset that is being described by this lattice. */ 233 HOST_WIDE_INT offset; 234 /* Size so that we don't have to re-compute it every time we traverse the 235 list. Must correspond to TYPE_SIZE of all lat values. */ 236 HOST_WIDE_INT size; 237 /* Next element of the linked list. */ 238 struct ipcp_agg_lattice *next; 239 }; 240 241 /* Lattice of known bits, only capable of holding one value. 242 Bitwise constant propagation propagates which bits of a 243 value are constant. 244 For eg: 245 int f(int x) 246 { 247 return some_op (x); 248 } 249 250 int f1(int y) 251 { 252 if (cond) 253 return f (y & 0xff); 254 else 255 return f (y & 0xf); 256 } 257 258 In the above case, the param 'x' will always have all 259 the bits (except the bits in lsb) set to 0. 260 Hence the mask of 'x' would be 0xff. The mask 261 reflects that the bits in lsb are unknown. 262 The actual propagated value is given by m_value & ~m_mask. */ 263 264 class ipcp_bits_lattice 265 { 266 public: 267 bool bottom_p () { return m_lattice_val == IPA_BITS_VARYING; } 268 bool top_p () { return m_lattice_val == IPA_BITS_UNDEFINED; } 269 bool constant_p () { return m_lattice_val == IPA_BITS_CONSTANT; } 270 bool set_to_bottom (); 271 bool set_to_constant (widest_int, widest_int); 272 273 widest_int get_value () { return m_value; } 274 widest_int get_mask () { return m_mask; } 275 276 bool meet_with (ipcp_bits_lattice& other, unsigned, signop, 277 enum tree_code, tree); 278 279 bool meet_with (widest_int, widest_int, unsigned); 280 281 void print (FILE *); 282 283 private: 284 enum { IPA_BITS_UNDEFINED, IPA_BITS_CONSTANT, IPA_BITS_VARYING } m_lattice_val; 285 286 /* Similar to ccp_lattice_t, mask represents which bits of value are constant. 287 If a bit in mask is set to 0, then the corresponding bit in 288 value is known to be constant. */ 289 widest_int m_value, m_mask; 290 291 bool meet_with_1 (widest_int, widest_int, unsigned); 292 void get_value_and_mask (tree, widest_int *, widest_int *); 293 }; 294 295 /* Lattice of value ranges. */ 296 297 class ipcp_vr_lattice 298 { 299 public: 300 value_range m_vr; 301 302 inline bool bottom_p () const; 303 inline bool top_p () const; 304 inline bool set_to_bottom (); 305 bool meet_with (const value_range *p_vr); 306 bool meet_with (const ipcp_vr_lattice &other); 307 void init () { m_vr.type = VR_UNDEFINED; } 308 void print (FILE * f); 309 310 private: 311 bool meet_with_1 (const value_range *other_vr); 312 }; 313 314 /* Structure containing lattices for a parameter itself and for pieces of 315 aggregates that are passed in the parameter or by a reference in a parameter 316 plus some other useful flags. */ 317 318 class ipcp_param_lattices 319 { 320 public: 321 /* Lattice describing the value of the parameter itself. */ 322 ipcp_lattice<tree> itself; 323 /* Lattice describing the polymorphic contexts of a parameter. */ 324 ipcp_lattice<ipa_polymorphic_call_context> ctxlat; 325 /* Lattices describing aggregate parts. */ 326 ipcp_agg_lattice *aggs; 327 /* Lattice describing known bits. */ 328 ipcp_bits_lattice bits_lattice; 329 /* Lattice describing value range. */ 330 ipcp_vr_lattice m_value_range; 331 /* Number of aggregate lattices */ 332 int aggs_count; 333 /* True if aggregate data were passed by reference (as opposed to by 334 value). */ 335 bool aggs_by_ref; 336 /* All aggregate lattices contain a variable component (in addition to 337 values). */ 338 bool aggs_contain_variable; 339 /* The value of all aggregate lattices is bottom (i.e. variable and unusable 340 for any propagation). */ 341 bool aggs_bottom; 342 343 /* There is a virtual call based on this parameter. */ 344 bool virt_call; 345 }; 346 347 /* Allocation pools for values and their sources in ipa-cp. */ 348 349 object_allocator<ipcp_value<tree> > ipcp_cst_values_pool 350 ("IPA-CP constant values"); 351 352 object_allocator<ipcp_value<ipa_polymorphic_call_context> > 353 ipcp_poly_ctx_values_pool ("IPA-CP polymorphic contexts"); 354 355 object_allocator<ipcp_value_source<tree> > ipcp_sources_pool 356 ("IPA-CP value sources"); 357 358 object_allocator<ipcp_agg_lattice> ipcp_agg_lattice_pool 359 ("IPA_CP aggregate lattices"); 360 361 /* Maximal count found in program. */ 362 363 static gcov_type max_count; 364 365 /* Original overall size of the program. */ 366 367 static long overall_size, max_new_size; 368 369 /* Return the param lattices structure corresponding to the Ith formal 370 parameter of the function described by INFO. */ 371 static inline struct ipcp_param_lattices * 372 ipa_get_parm_lattices (struct ipa_node_params *info, int i) 373 { 374 gcc_assert (i >= 0 && i < ipa_get_param_count (info)); 375 gcc_checking_assert (!info->ipcp_orig_node); 376 gcc_checking_assert (info->lattices); 377 return &(info->lattices[i]); 378 } 379 380 /* Return the lattice corresponding to the scalar value of the Ith formal 381 parameter of the function described by INFO. */ 382 static inline ipcp_lattice<tree> * 383 ipa_get_scalar_lat (struct ipa_node_params *info, int i) 384 { 385 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 386 return &plats->itself; 387 } 388 389 /* Return the lattice corresponding to the scalar value of the Ith formal 390 parameter of the function described by INFO. */ 391 static inline ipcp_lattice<ipa_polymorphic_call_context> * 392 ipa_get_poly_ctx_lat (struct ipa_node_params *info, int i) 393 { 394 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 395 return &plats->ctxlat; 396 } 397 398 /* Return the lattice corresponding to the value range of the Ith formal 399 parameter of the function described by INFO. */ 400 401 static inline ipcp_vr_lattice * 402 ipa_get_vr_lat (struct ipa_node_params *info, int i) 403 { 404 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 405 return &plats->m_value_range; 406 } 407 408 /* Return whether LAT is a lattice with a single constant and without an 409 undefined value. */ 410 411 template <typename valtype> 412 inline bool 413 ipcp_lattice<valtype>::is_single_const () 414 { 415 if (bottom || contains_variable || values_count != 1) 416 return false; 417 else 418 return true; 419 } 420 421 /* Print V which is extracted from a value in a lattice to F. */ 422 423 static void 424 print_ipcp_constant_value (FILE * f, tree v) 425 { 426 if (TREE_CODE (v) == ADDR_EXPR 427 && TREE_CODE (TREE_OPERAND (v, 0)) == CONST_DECL) 428 { 429 fprintf (f, "& "); 430 print_generic_expr (f, DECL_INITIAL (TREE_OPERAND (v, 0)), 0); 431 } 432 else 433 print_generic_expr (f, v, 0); 434 } 435 436 /* Print V which is extracted from a value in a lattice to F. */ 437 438 static void 439 print_ipcp_constant_value (FILE * f, ipa_polymorphic_call_context v) 440 { 441 v.dump(f, false); 442 } 443 444 /* Print a lattice LAT to F. */ 445 446 template <typename valtype> 447 void 448 ipcp_lattice<valtype>::print (FILE * f, bool dump_sources, bool dump_benefits) 449 { 450 ipcp_value<valtype> *val; 451 bool prev = false; 452 453 if (bottom) 454 { 455 fprintf (f, "BOTTOM\n"); 456 return; 457 } 458 459 if (!values_count && !contains_variable) 460 { 461 fprintf (f, "TOP\n"); 462 return; 463 } 464 465 if (contains_variable) 466 { 467 fprintf (f, "VARIABLE"); 468 prev = true; 469 if (dump_benefits) 470 fprintf (f, "\n"); 471 } 472 473 for (val = values; val; val = val->next) 474 { 475 if (dump_benefits && prev) 476 fprintf (f, " "); 477 else if (!dump_benefits && prev) 478 fprintf (f, ", "); 479 else 480 prev = true; 481 482 print_ipcp_constant_value (f, val->value); 483 484 if (dump_sources) 485 { 486 ipcp_value_source<valtype> *s; 487 488 fprintf (f, " [from:"); 489 for (s = val->sources; s; s = s->next) 490 fprintf (f, " %i(%i)", s->cs->caller->order, 491 s->cs->frequency); 492 fprintf (f, "]"); 493 } 494 495 if (dump_benefits) 496 fprintf (f, " [loc_time: %i, loc_size: %i, " 497 "prop_time: %i, prop_size: %i]\n", 498 val->local_time_benefit, val->local_size_cost, 499 val->prop_time_benefit, val->prop_size_cost); 500 } 501 if (!dump_benefits) 502 fprintf (f, "\n"); 503 } 504 505 void 506 ipcp_bits_lattice::print (FILE *f) 507 { 508 if (top_p ()) 509 fprintf (f, " Bits unknown (TOP)\n"); 510 else if (bottom_p ()) 511 fprintf (f, " Bits unusable (BOTTOM)\n"); 512 else 513 { 514 fprintf (f, " Bits: value = "); print_hex (get_value (), f); 515 fprintf (f, ", mask = "); print_hex (get_mask (), f); 516 fprintf (f, "\n"); 517 } 518 } 519 520 /* Print value range lattice to F. */ 521 522 void 523 ipcp_vr_lattice::print (FILE * f) 524 { 525 dump_value_range (f, &m_vr); 526 } 527 528 /* Print all ipcp_lattices of all functions to F. */ 529 530 static void 531 print_all_lattices (FILE * f, bool dump_sources, bool dump_benefits) 532 { 533 struct cgraph_node *node; 534 int i, count; 535 536 fprintf (f, "\nLattices:\n"); 537 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 538 { 539 struct ipa_node_params *info; 540 541 info = IPA_NODE_REF (node); 542 fprintf (f, " Node: %s/%i:\n", node->name (), 543 node->order); 544 count = ipa_get_param_count (info); 545 for (i = 0; i < count; i++) 546 { 547 struct ipcp_agg_lattice *aglat; 548 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 549 fprintf (f, " param [%d]: ", i); 550 plats->itself.print (f, dump_sources, dump_benefits); 551 fprintf (f, " ctxs: "); 552 plats->ctxlat.print (f, dump_sources, dump_benefits); 553 plats->bits_lattice.print (f); 554 fprintf (f, " "); 555 plats->m_value_range.print (f); 556 fprintf (f, "\n"); 557 if (plats->virt_call) 558 fprintf (f, " virt_call flag set\n"); 559 560 if (plats->aggs_bottom) 561 { 562 fprintf (f, " AGGS BOTTOM\n"); 563 continue; 564 } 565 if (plats->aggs_contain_variable) 566 fprintf (f, " AGGS VARIABLE\n"); 567 for (aglat = plats->aggs; aglat; aglat = aglat->next) 568 { 569 fprintf (f, " %soffset " HOST_WIDE_INT_PRINT_DEC ": ", 570 plats->aggs_by_ref ? "ref " : "", aglat->offset); 571 aglat->print (f, dump_sources, dump_benefits); 572 } 573 } 574 } 575 } 576 577 /* Determine whether it is at all technically possible to create clones of NODE 578 and store this information in the ipa_node_params structure associated 579 with NODE. */ 580 581 static void 582 determine_versionability (struct cgraph_node *node, 583 struct ipa_node_params *info) 584 { 585 const char *reason = NULL; 586 587 /* There are a number of generic reasons functions cannot be versioned. We 588 also cannot remove parameters if there are type attributes such as fnspec 589 present. */ 590 if (node->alias || node->thunk.thunk_p) 591 reason = "alias or thunk"; 592 else if (!node->local.versionable) 593 reason = "not a tree_versionable_function"; 594 else if (node->get_availability () <= AVAIL_INTERPOSABLE) 595 reason = "insufficient body availability"; 596 else if (!opt_for_fn (node->decl, optimize) 597 || !opt_for_fn (node->decl, flag_ipa_cp)) 598 reason = "non-optimized function"; 599 else if (lookup_attribute ("omp declare simd", DECL_ATTRIBUTES (node->decl))) 600 { 601 /* Ideally we should clone the SIMD clones themselves and create 602 vector copies of them, so IPA-cp and SIMD clones can happily 603 coexist, but that may not be worth the effort. */ 604 reason = "function has SIMD clones"; 605 } 606 else if (lookup_attribute ("target_clones", DECL_ATTRIBUTES (node->decl))) 607 { 608 /* Ideally we should clone the target clones themselves and create 609 copies of them, so IPA-cp and target clones can happily 610 coexist, but that may not be worth the effort. */ 611 reason = "function target_clones attribute"; 612 } 613 /* Don't clone decls local to a comdat group; it breaks and for C++ 614 decloned constructors, inlining is always better anyway. */ 615 else if (node->comdat_local_p ()) 616 reason = "comdat-local function"; 617 else if (node->calls_comdat_local) 618 { 619 /* TODO: call is versionable if we make sure that all 620 callers are inside of a comdat group. */ 621 reason = "calls comdat-local function"; 622 } 623 624 /* Functions calling BUILT_IN_VA_ARG_PACK and BUILT_IN_VA_ARG_PACK_LEN 625 works only when inlined. Cloning them may still lead to better code 626 becuase ipa-cp will not give up on cloning further. If the function is 627 external this however leads to wrong code becuase we may end up producing 628 offline copy of the function. */ 629 if (DECL_EXTERNAL (node->decl)) 630 for (cgraph_edge *edge = node->callees; !reason && edge; 631 edge = edge->next_callee) 632 if (DECL_BUILT_IN (edge->callee->decl) 633 && DECL_BUILT_IN_CLASS (edge->callee->decl) == BUILT_IN_NORMAL) 634 { 635 if (DECL_FUNCTION_CODE (edge->callee->decl) == BUILT_IN_VA_ARG_PACK) 636 reason = "external function which calls va_arg_pack"; 637 if (DECL_FUNCTION_CODE (edge->callee->decl) 638 == BUILT_IN_VA_ARG_PACK_LEN) 639 reason = "external function which calls va_arg_pack_len"; 640 } 641 642 if (reason && dump_file && !node->alias && !node->thunk.thunk_p) 643 fprintf (dump_file, "Function %s/%i is not versionable, reason: %s.\n", 644 node->name (), node->order, reason); 645 646 info->versionable = (reason == NULL); 647 } 648 649 /* Return true if it is at all technically possible to create clones of a 650 NODE. */ 651 652 static bool 653 ipcp_versionable_function_p (struct cgraph_node *node) 654 { 655 return IPA_NODE_REF (node)->versionable; 656 } 657 658 /* Structure holding accumulated information about callers of a node. */ 659 660 struct caller_statistics 661 { 662 gcov_type count_sum; 663 int n_calls, n_hot_calls, freq_sum; 664 }; 665 666 /* Initialize fields of STAT to zeroes. */ 667 668 static inline void 669 init_caller_stats (struct caller_statistics *stats) 670 { 671 stats->count_sum = 0; 672 stats->n_calls = 0; 673 stats->n_hot_calls = 0; 674 stats->freq_sum = 0; 675 } 676 677 /* Worker callback of cgraph_for_node_and_aliases accumulating statistics of 678 non-thunk incoming edges to NODE. */ 679 680 static bool 681 gather_caller_stats (struct cgraph_node *node, void *data) 682 { 683 struct caller_statistics *stats = (struct caller_statistics *) data; 684 struct cgraph_edge *cs; 685 686 for (cs = node->callers; cs; cs = cs->next_caller) 687 if (!cs->caller->thunk.thunk_p) 688 { 689 stats->count_sum += cs->count; 690 stats->freq_sum += cs->frequency; 691 stats->n_calls++; 692 if (cs->maybe_hot_p ()) 693 stats->n_hot_calls ++; 694 } 695 return false; 696 697 } 698 699 /* Return true if this NODE is viable candidate for cloning. */ 700 701 static bool 702 ipcp_cloning_candidate_p (struct cgraph_node *node) 703 { 704 struct caller_statistics stats; 705 706 gcc_checking_assert (node->has_gimple_body_p ()); 707 708 if (!opt_for_fn (node->decl, flag_ipa_cp_clone)) 709 { 710 if (dump_file) 711 fprintf (dump_file, "Not considering %s for cloning; " 712 "-fipa-cp-clone disabled.\n", 713 node->name ()); 714 return false; 715 } 716 717 if (node->optimize_for_size_p ()) 718 { 719 if (dump_file) 720 fprintf (dump_file, "Not considering %s for cloning; " 721 "optimizing it for size.\n", 722 node->name ()); 723 return false; 724 } 725 726 init_caller_stats (&stats); 727 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, false); 728 729 if (inline_summaries->get (node)->self_size < stats.n_calls) 730 { 731 if (dump_file) 732 fprintf (dump_file, "Considering %s for cloning; code might shrink.\n", 733 node->name ()); 734 return true; 735 } 736 737 /* When profile is available and function is hot, propagate into it even if 738 calls seems cold; constant propagation can improve function's speed 739 significantly. */ 740 if (max_count) 741 { 742 if (stats.count_sum > node->count * 90 / 100) 743 { 744 if (dump_file) 745 fprintf (dump_file, "Considering %s for cloning; " 746 "usually called directly.\n", 747 node->name ()); 748 return true; 749 } 750 } 751 if (!stats.n_hot_calls) 752 { 753 if (dump_file) 754 fprintf (dump_file, "Not considering %s for cloning; no hot calls.\n", 755 node->name ()); 756 return false; 757 } 758 if (dump_file) 759 fprintf (dump_file, "Considering %s for cloning.\n", 760 node->name ()); 761 return true; 762 } 763 764 template <typename valtype> 765 class value_topo_info 766 { 767 public: 768 /* Head of the linked list of topologically sorted values. */ 769 ipcp_value<valtype> *values_topo; 770 /* Stack for creating SCCs, represented by a linked list too. */ 771 ipcp_value<valtype> *stack; 772 /* Counter driving the algorithm in add_val_to_toposort. */ 773 int dfs_counter; 774 775 value_topo_info () : values_topo (NULL), stack (NULL), dfs_counter (0) 776 {} 777 void add_val (ipcp_value<valtype> *cur_val); 778 void propagate_effects (); 779 }; 780 781 /* Arrays representing a topological ordering of call graph nodes and a stack 782 of nodes used during constant propagation and also data required to perform 783 topological sort of values and propagation of benefits in the determined 784 order. */ 785 786 class ipa_topo_info 787 { 788 public: 789 /* Array with obtained topological order of cgraph nodes. */ 790 struct cgraph_node **order; 791 /* Stack of cgraph nodes used during propagation within SCC until all values 792 in the SCC stabilize. */ 793 struct cgraph_node **stack; 794 int nnodes, stack_top; 795 796 value_topo_info<tree> constants; 797 value_topo_info<ipa_polymorphic_call_context> contexts; 798 799 ipa_topo_info () : order(NULL), stack(NULL), nnodes(0), stack_top(0), 800 constants () 801 {} 802 }; 803 804 /* Allocate the arrays in TOPO and topologically sort the nodes into order. */ 805 806 static void 807 build_toporder_info (struct ipa_topo_info *topo) 808 { 809 topo->order = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); 810 topo->stack = XCNEWVEC (struct cgraph_node *, symtab->cgraph_count); 811 812 gcc_checking_assert (topo->stack_top == 0); 813 topo->nnodes = ipa_reduced_postorder (topo->order, true, true, NULL); 814 } 815 816 /* Free information about strongly connected components and the arrays in 817 TOPO. */ 818 819 static void 820 free_toporder_info (struct ipa_topo_info *topo) 821 { 822 ipa_free_postorder_info (); 823 free (topo->order); 824 free (topo->stack); 825 } 826 827 /* Add NODE to the stack in TOPO, unless it is already there. */ 828 829 static inline void 830 push_node_to_stack (struct ipa_topo_info *topo, struct cgraph_node *node) 831 { 832 struct ipa_node_params *info = IPA_NODE_REF (node); 833 if (info->node_enqueued) 834 return; 835 info->node_enqueued = 1; 836 topo->stack[topo->stack_top++] = node; 837 } 838 839 /* Pop a node from the stack in TOPO and return it or return NULL if the stack 840 is empty. */ 841 842 static struct cgraph_node * 843 pop_node_from_stack (struct ipa_topo_info *topo) 844 { 845 if (topo->stack_top) 846 { 847 struct cgraph_node *node; 848 topo->stack_top--; 849 node = topo->stack[topo->stack_top]; 850 IPA_NODE_REF (node)->node_enqueued = 0; 851 return node; 852 } 853 else 854 return NULL; 855 } 856 857 /* Set lattice LAT to bottom and return true if it previously was not set as 858 such. */ 859 860 template <typename valtype> 861 inline bool 862 ipcp_lattice<valtype>::set_to_bottom () 863 { 864 bool ret = !bottom; 865 bottom = true; 866 return ret; 867 } 868 869 /* Mark lattice as containing an unknown value and return true if it previously 870 was not marked as such. */ 871 872 template <typename valtype> 873 inline bool 874 ipcp_lattice<valtype>::set_contains_variable () 875 { 876 bool ret = !contains_variable; 877 contains_variable = true; 878 return ret; 879 } 880 881 /* Set all aggegate lattices in PLATS to bottom and return true if they were 882 not previously set as such. */ 883 884 static inline bool 885 set_agg_lats_to_bottom (struct ipcp_param_lattices *plats) 886 { 887 bool ret = !plats->aggs_bottom; 888 plats->aggs_bottom = true; 889 return ret; 890 } 891 892 /* Mark all aggegate lattices in PLATS as containing an unknown value and 893 return true if they were not previously marked as such. */ 894 895 static inline bool 896 set_agg_lats_contain_variable (struct ipcp_param_lattices *plats) 897 { 898 bool ret = !plats->aggs_contain_variable; 899 plats->aggs_contain_variable = true; 900 return ret; 901 } 902 903 bool 904 ipcp_vr_lattice::meet_with (const ipcp_vr_lattice &other) 905 { 906 return meet_with_1 (&other.m_vr); 907 } 908 909 /* Meet the current value of the lattice with value ranfge described by VR 910 lattice. */ 911 912 bool 913 ipcp_vr_lattice::meet_with (const value_range *p_vr) 914 { 915 return meet_with_1 (p_vr); 916 } 917 918 /* Meet the current value of the lattice with value ranfge described by 919 OTHER_VR lattice. */ 920 921 bool 922 ipcp_vr_lattice::meet_with_1 (const value_range *other_vr) 923 { 924 tree min = m_vr.min, max = m_vr.max; 925 value_range_type type = m_vr.type; 926 927 if (bottom_p ()) 928 return false; 929 930 if (other_vr->type == VR_VARYING) 931 return set_to_bottom (); 932 933 vrp_meet (&m_vr, other_vr); 934 if (type != m_vr.type 935 || min != m_vr.min 936 || max != m_vr.max) 937 return true; 938 else 939 return false; 940 } 941 942 /* Return true if value range information in the lattice is yet unknown. */ 943 944 bool 945 ipcp_vr_lattice::top_p () const 946 { 947 return m_vr.type == VR_UNDEFINED; 948 } 949 950 /* Return true if value range information in the lattice is known to be 951 unusable. */ 952 953 bool 954 ipcp_vr_lattice::bottom_p () const 955 { 956 return m_vr.type == VR_VARYING; 957 } 958 959 /* Set value range information in the lattice to bottom. Return true if it 960 previously was in a different state. */ 961 962 bool 963 ipcp_vr_lattice::set_to_bottom () 964 { 965 if (m_vr.type == VR_VARYING) 966 return false; 967 m_vr.type = VR_VARYING; 968 return true; 969 } 970 971 /* Set lattice value to bottom, if it already isn't the case. */ 972 973 bool 974 ipcp_bits_lattice::set_to_bottom () 975 { 976 if (bottom_p ()) 977 return false; 978 m_lattice_val = IPA_BITS_VARYING; 979 m_value = 0; 980 m_mask = -1; 981 return true; 982 } 983 984 /* Set to constant if it isn't already. Only meant to be called 985 when switching state from TOP. */ 986 987 bool 988 ipcp_bits_lattice::set_to_constant (widest_int value, widest_int mask) 989 { 990 gcc_assert (top_p ()); 991 m_lattice_val = IPA_BITS_CONSTANT; 992 m_value = value; 993 m_mask = mask; 994 return true; 995 } 996 997 /* Convert operand to value, mask form. */ 998 999 void 1000 ipcp_bits_lattice::get_value_and_mask (tree operand, widest_int *valuep, widest_int *maskp) 1001 { 1002 wide_int get_nonzero_bits (const_tree); 1003 1004 if (TREE_CODE (operand) == INTEGER_CST) 1005 { 1006 *valuep = wi::to_widest (operand); 1007 *maskp = 0; 1008 } 1009 else 1010 { 1011 *valuep = 0; 1012 *maskp = -1; 1013 } 1014 } 1015 1016 /* Meet operation, similar to ccp_lattice_meet, we xor values 1017 if this->value, value have different values at same bit positions, we want 1018 to drop that bit to varying. Return true if mask is changed. 1019 This function assumes that the lattice value is in CONSTANT state */ 1020 1021 bool 1022 ipcp_bits_lattice::meet_with_1 (widest_int value, widest_int mask, 1023 unsigned precision) 1024 { 1025 gcc_assert (constant_p ()); 1026 1027 widest_int old_mask = m_mask; 1028 m_mask = (m_mask | mask) | (m_value ^ value); 1029 1030 if (wi::sext (m_mask, precision) == -1) 1031 return set_to_bottom (); 1032 1033 return m_mask != old_mask; 1034 } 1035 1036 /* Meet the bits lattice with operand 1037 described by <value, mask, sgn, precision. */ 1038 1039 bool 1040 ipcp_bits_lattice::meet_with (widest_int value, widest_int mask, 1041 unsigned precision) 1042 { 1043 if (bottom_p ()) 1044 return false; 1045 1046 if (top_p ()) 1047 { 1048 if (wi::sext (mask, precision) == -1) 1049 return set_to_bottom (); 1050 return set_to_constant (value, mask); 1051 } 1052 1053 return meet_with_1 (value, mask, precision); 1054 } 1055 1056 /* Meet bits lattice with the result of bit_value_binop (other, operand) 1057 if code is binary operation or bit_value_unop (other) if code is unary op. 1058 In the case when code is nop_expr, no adjustment is required. */ 1059 1060 bool 1061 ipcp_bits_lattice::meet_with (ipcp_bits_lattice& other, unsigned precision, 1062 signop sgn, enum tree_code code, tree operand) 1063 { 1064 if (other.bottom_p ()) 1065 return set_to_bottom (); 1066 1067 if (bottom_p () || other.top_p ()) 1068 return false; 1069 1070 widest_int adjusted_value, adjusted_mask; 1071 1072 if (TREE_CODE_CLASS (code) == tcc_binary) 1073 { 1074 tree type = TREE_TYPE (operand); 1075 gcc_assert (INTEGRAL_TYPE_P (type)); 1076 widest_int o_value, o_mask; 1077 get_value_and_mask (operand, &o_value, &o_mask); 1078 1079 bit_value_binop (code, sgn, precision, &adjusted_value, &adjusted_mask, 1080 sgn, precision, other.get_value (), other.get_mask (), 1081 TYPE_SIGN (type), TYPE_PRECISION (type), o_value, o_mask); 1082 1083 if (wi::sext (adjusted_mask, precision) == -1) 1084 return set_to_bottom (); 1085 } 1086 1087 else if (TREE_CODE_CLASS (code) == tcc_unary) 1088 { 1089 bit_value_unop (code, sgn, precision, &adjusted_value, 1090 &adjusted_mask, sgn, precision, other.get_value (), 1091 other.get_mask ()); 1092 1093 if (wi::sext (adjusted_mask, precision) == -1) 1094 return set_to_bottom (); 1095 } 1096 1097 else 1098 return set_to_bottom (); 1099 1100 if (top_p ()) 1101 { 1102 if (wi::sext (adjusted_mask, precision) == -1) 1103 return set_to_bottom (); 1104 return set_to_constant (adjusted_value, adjusted_mask); 1105 } 1106 else 1107 return meet_with_1 (adjusted_value, adjusted_mask, precision); 1108 } 1109 1110 /* Mark bot aggregate and scalar lattices as containing an unknown variable, 1111 return true is any of them has not been marked as such so far. */ 1112 1113 static inline bool 1114 set_all_contains_variable (struct ipcp_param_lattices *plats) 1115 { 1116 bool ret; 1117 ret = plats->itself.set_contains_variable (); 1118 ret |= plats->ctxlat.set_contains_variable (); 1119 ret |= set_agg_lats_contain_variable (plats); 1120 ret |= plats->bits_lattice.set_to_bottom (); 1121 ret |= plats->m_value_range.set_to_bottom (); 1122 return ret; 1123 } 1124 1125 /* Worker of call_for_symbol_thunks_and_aliases, increment the integer DATA 1126 points to by the number of callers to NODE. */ 1127 1128 static bool 1129 count_callers (cgraph_node *node, void *data) 1130 { 1131 int *caller_count = (int *) data; 1132 1133 for (cgraph_edge *cs = node->callers; cs; cs = cs->next_caller) 1134 /* Local thunks can be handled transparently, but if the thunk can not 1135 be optimized out, count it as a real use. */ 1136 if (!cs->caller->thunk.thunk_p || !cs->caller->local.local) 1137 ++*caller_count; 1138 return false; 1139 } 1140 1141 /* Worker of call_for_symbol_thunks_and_aliases, it is supposed to be called on 1142 the one caller of some other node. Set the caller's corresponding flag. */ 1143 1144 static bool 1145 set_single_call_flag (cgraph_node *node, void *) 1146 { 1147 cgraph_edge *cs = node->callers; 1148 /* Local thunks can be handled transparently, skip them. */ 1149 while (cs && cs->caller->thunk.thunk_p && cs->caller->local.local) 1150 cs = cs->next_caller; 1151 if (cs) 1152 { 1153 IPA_NODE_REF (cs->caller)->node_calling_single_call = true; 1154 return true; 1155 } 1156 return false; 1157 } 1158 1159 /* Initialize ipcp_lattices. */ 1160 1161 static void 1162 initialize_node_lattices (struct cgraph_node *node) 1163 { 1164 struct ipa_node_params *info = IPA_NODE_REF (node); 1165 struct cgraph_edge *ie; 1166 bool disable = false, variable = false; 1167 int i; 1168 1169 gcc_checking_assert (node->has_gimple_body_p ()); 1170 if (cgraph_local_p (node)) 1171 { 1172 int caller_count = 0; 1173 node->call_for_symbol_thunks_and_aliases (count_callers, &caller_count, 1174 true); 1175 gcc_checking_assert (caller_count > 0); 1176 if (caller_count == 1) 1177 node->call_for_symbol_thunks_and_aliases (set_single_call_flag, 1178 NULL, true); 1179 } 1180 else 1181 { 1182 /* When cloning is allowed, we can assume that externally visible 1183 functions are not called. We will compensate this by cloning 1184 later. */ 1185 if (ipcp_versionable_function_p (node) 1186 && ipcp_cloning_candidate_p (node)) 1187 variable = true; 1188 else 1189 disable = true; 1190 } 1191 1192 for (i = 0; i < ipa_get_param_count (info); i++) 1193 { 1194 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 1195 plats->m_value_range.init (); 1196 } 1197 1198 if (disable || variable) 1199 { 1200 for (i = 0; i < ipa_get_param_count (info); i++) 1201 { 1202 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 1203 if (disable) 1204 { 1205 plats->itself.set_to_bottom (); 1206 plats->ctxlat.set_to_bottom (); 1207 set_agg_lats_to_bottom (plats); 1208 plats->bits_lattice.set_to_bottom (); 1209 plats->m_value_range.set_to_bottom (); 1210 } 1211 else 1212 set_all_contains_variable (plats); 1213 } 1214 if (dump_file && (dump_flags & TDF_DETAILS) 1215 && !node->alias && !node->thunk.thunk_p) 1216 fprintf (dump_file, "Marking all lattices of %s/%i as %s\n", 1217 node->name (), node->order, 1218 disable ? "BOTTOM" : "VARIABLE"); 1219 } 1220 1221 for (ie = node->indirect_calls; ie; ie = ie->next_callee) 1222 if (ie->indirect_info->polymorphic 1223 && ie->indirect_info->param_index >= 0) 1224 { 1225 gcc_checking_assert (ie->indirect_info->param_index >= 0); 1226 ipa_get_parm_lattices (info, 1227 ie->indirect_info->param_index)->virt_call = 1; 1228 } 1229 } 1230 1231 /* Return the result of a (possibly arithmetic) pass through jump function 1232 JFUNC on the constant value INPUT. Return NULL_TREE if that cannot be 1233 determined or be considered an interprocedural invariant. */ 1234 1235 static tree 1236 ipa_get_jf_pass_through_result (struct ipa_jump_func *jfunc, tree input) 1237 { 1238 tree restype, res; 1239 1240 if (ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) 1241 return input; 1242 if (!is_gimple_ip_invariant (input)) 1243 return NULL_TREE; 1244 1245 tree_code opcode = ipa_get_jf_pass_through_operation (jfunc); 1246 if (TREE_CODE_CLASS (opcode) == tcc_comparison) 1247 restype = boolean_type_node; 1248 else if (expr_type_first_operand_type_p (opcode)) 1249 restype = TREE_TYPE (input); 1250 else 1251 return NULL_TREE; 1252 1253 if (TREE_CODE_CLASS (opcode) == tcc_unary) 1254 res = fold_unary (opcode, restype, input); 1255 else 1256 res = fold_binary (opcode, restype, input, 1257 ipa_get_jf_pass_through_operand (jfunc)); 1258 1259 if (res && !is_gimple_ip_invariant (res)) 1260 return NULL_TREE; 1261 1262 return res; 1263 } 1264 1265 /* Return the result of an ancestor jump function JFUNC on the constant value 1266 INPUT. Return NULL_TREE if that cannot be determined. */ 1267 1268 static tree 1269 ipa_get_jf_ancestor_result (struct ipa_jump_func *jfunc, tree input) 1270 { 1271 gcc_checking_assert (TREE_CODE (input) != TREE_BINFO); 1272 if (TREE_CODE (input) == ADDR_EXPR) 1273 { 1274 tree t = TREE_OPERAND (input, 0); 1275 t = build_ref_for_offset (EXPR_LOCATION (t), t, 1276 ipa_get_jf_ancestor_offset (jfunc), false, 1277 ptr_type_node, NULL, false); 1278 return build_fold_addr_expr (t); 1279 } 1280 else 1281 return NULL_TREE; 1282 } 1283 1284 /* Determine whether JFUNC evaluates to a single known constant value and if 1285 so, return it. Otherwise return NULL. INFO describes the caller node or 1286 the one it is inlined to, so that pass-through jump functions can be 1287 evaluated. */ 1288 1289 tree 1290 ipa_value_from_jfunc (struct ipa_node_params *info, struct ipa_jump_func *jfunc) 1291 { 1292 if (jfunc->type == IPA_JF_CONST) 1293 return ipa_get_jf_constant (jfunc); 1294 else if (jfunc->type == IPA_JF_PASS_THROUGH 1295 || jfunc->type == IPA_JF_ANCESTOR) 1296 { 1297 tree input; 1298 int idx; 1299 1300 if (jfunc->type == IPA_JF_PASS_THROUGH) 1301 idx = ipa_get_jf_pass_through_formal_id (jfunc); 1302 else 1303 idx = ipa_get_jf_ancestor_formal_id (jfunc); 1304 1305 if (info->ipcp_orig_node) 1306 input = info->known_csts[idx]; 1307 else 1308 { 1309 ipcp_lattice<tree> *lat; 1310 1311 if (!info->lattices 1312 || idx >= ipa_get_param_count (info)) 1313 return NULL_TREE; 1314 lat = ipa_get_scalar_lat (info, idx); 1315 if (!lat->is_single_const ()) 1316 return NULL_TREE; 1317 input = lat->values->value; 1318 } 1319 1320 if (!input) 1321 return NULL_TREE; 1322 1323 if (jfunc->type == IPA_JF_PASS_THROUGH) 1324 return ipa_get_jf_pass_through_result (jfunc, input); 1325 else 1326 return ipa_get_jf_ancestor_result (jfunc, input); 1327 } 1328 else 1329 return NULL_TREE; 1330 } 1331 1332 /* Determie whether JFUNC evaluates to single known polymorphic context, given 1333 that INFO describes the caller node or the one it is inlined to, CS is the 1334 call graph edge corresponding to JFUNC and CSIDX index of the described 1335 parameter. */ 1336 1337 ipa_polymorphic_call_context 1338 ipa_context_from_jfunc (ipa_node_params *info, cgraph_edge *cs, int csidx, 1339 ipa_jump_func *jfunc) 1340 { 1341 ipa_edge_args *args = IPA_EDGE_REF (cs); 1342 ipa_polymorphic_call_context ctx; 1343 ipa_polymorphic_call_context *edge_ctx 1344 = cs ? ipa_get_ith_polymorhic_call_context (args, csidx) : NULL; 1345 1346 if (edge_ctx && !edge_ctx->useless_p ()) 1347 ctx = *edge_ctx; 1348 1349 if (jfunc->type == IPA_JF_PASS_THROUGH 1350 || jfunc->type == IPA_JF_ANCESTOR) 1351 { 1352 ipa_polymorphic_call_context srcctx; 1353 int srcidx; 1354 bool type_preserved = true; 1355 if (jfunc->type == IPA_JF_PASS_THROUGH) 1356 { 1357 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) 1358 return ctx; 1359 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc); 1360 srcidx = ipa_get_jf_pass_through_formal_id (jfunc); 1361 } 1362 else 1363 { 1364 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc); 1365 srcidx = ipa_get_jf_ancestor_formal_id (jfunc); 1366 } 1367 if (info->ipcp_orig_node) 1368 { 1369 if (info->known_contexts.exists ()) 1370 srcctx = info->known_contexts[srcidx]; 1371 } 1372 else 1373 { 1374 if (!info->lattices 1375 || srcidx >= ipa_get_param_count (info)) 1376 return ctx; 1377 ipcp_lattice<ipa_polymorphic_call_context> *lat; 1378 lat = ipa_get_poly_ctx_lat (info, srcidx); 1379 if (!lat->is_single_const ()) 1380 return ctx; 1381 srcctx = lat->values->value; 1382 } 1383 if (srcctx.useless_p ()) 1384 return ctx; 1385 if (jfunc->type == IPA_JF_ANCESTOR) 1386 srcctx.offset_by (ipa_get_jf_ancestor_offset (jfunc)); 1387 if (!type_preserved) 1388 srcctx.possible_dynamic_type_change (cs->in_polymorphic_cdtor); 1389 srcctx.combine_with (ctx); 1390 return srcctx; 1391 } 1392 1393 return ctx; 1394 } 1395 1396 /* If checking is enabled, verify that no lattice is in the TOP state, i.e. not 1397 bottom, not containing a variable component and without any known value at 1398 the same time. */ 1399 1400 DEBUG_FUNCTION void 1401 ipcp_verify_propagated_values (void) 1402 { 1403 struct cgraph_node *node; 1404 1405 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 1406 { 1407 struct ipa_node_params *info = IPA_NODE_REF (node); 1408 int i, count = ipa_get_param_count (info); 1409 1410 for (i = 0; i < count; i++) 1411 { 1412 ipcp_lattice<tree> *lat = ipa_get_scalar_lat (info, i); 1413 1414 if (!lat->bottom 1415 && !lat->contains_variable 1416 && lat->values_count == 0) 1417 { 1418 if (dump_file) 1419 { 1420 symtab_node::dump_table (dump_file); 1421 fprintf (dump_file, "\nIPA lattices after constant " 1422 "propagation, before gcc_unreachable:\n"); 1423 print_all_lattices (dump_file, true, false); 1424 } 1425 1426 gcc_unreachable (); 1427 } 1428 } 1429 } 1430 } 1431 1432 /* Return true iff X and Y should be considered equal values by IPA-CP. */ 1433 1434 static bool 1435 values_equal_for_ipcp_p (tree x, tree y) 1436 { 1437 gcc_checking_assert (x != NULL_TREE && y != NULL_TREE); 1438 1439 if (x == y) 1440 return true; 1441 1442 if (TREE_CODE (x) == ADDR_EXPR 1443 && TREE_CODE (y) == ADDR_EXPR 1444 && TREE_CODE (TREE_OPERAND (x, 0)) == CONST_DECL 1445 && TREE_CODE (TREE_OPERAND (y, 0)) == CONST_DECL) 1446 return operand_equal_p (DECL_INITIAL (TREE_OPERAND (x, 0)), 1447 DECL_INITIAL (TREE_OPERAND (y, 0)), 0); 1448 else 1449 return operand_equal_p (x, y, 0); 1450 } 1451 1452 /* Return true iff X and Y should be considered equal contexts by IPA-CP. */ 1453 1454 static bool 1455 values_equal_for_ipcp_p (ipa_polymorphic_call_context x, 1456 ipa_polymorphic_call_context y) 1457 { 1458 return x.equal_to (y); 1459 } 1460 1461 1462 /* Add a new value source to the value represented by THIS, marking that a 1463 value comes from edge CS and (if the underlying jump function is a 1464 pass-through or an ancestor one) from a caller value SRC_VAL of a caller 1465 parameter described by SRC_INDEX. OFFSET is negative if the source was the 1466 scalar value of the parameter itself or the offset within an aggregate. */ 1467 1468 template <typename valtype> 1469 void 1470 ipcp_value<valtype>::add_source (cgraph_edge *cs, ipcp_value *src_val, 1471 int src_idx, HOST_WIDE_INT offset) 1472 { 1473 ipcp_value_source<valtype> *src; 1474 1475 src = new (ipcp_sources_pool.allocate ()) ipcp_value_source<valtype>; 1476 src->offset = offset; 1477 src->cs = cs; 1478 src->val = src_val; 1479 src->index = src_idx; 1480 1481 src->next = sources; 1482 sources = src; 1483 } 1484 1485 /* Allocate a new ipcp_value holding a tree constant, initialize its value to 1486 SOURCE and clear all other fields. */ 1487 1488 static ipcp_value<tree> * 1489 allocate_and_init_ipcp_value (tree source) 1490 { 1491 ipcp_value<tree> *val; 1492 1493 val = ipcp_cst_values_pool.allocate (); 1494 memset (val, 0, sizeof (*val)); 1495 val->value = source; 1496 return val; 1497 } 1498 1499 /* Allocate a new ipcp_value holding a polymorphic context, initialize its 1500 value to SOURCE and clear all other fields. */ 1501 1502 static ipcp_value<ipa_polymorphic_call_context> * 1503 allocate_and_init_ipcp_value (ipa_polymorphic_call_context source) 1504 { 1505 ipcp_value<ipa_polymorphic_call_context> *val; 1506 1507 // TODO 1508 val = ipcp_poly_ctx_values_pool.allocate (); 1509 memset (val, 0, sizeof (*val)); 1510 val->value = source; 1511 return val; 1512 } 1513 1514 /* Try to add NEWVAL to LAT, potentially creating a new ipcp_value for it. CS, 1515 SRC_VAL SRC_INDEX and OFFSET are meant for add_source and have the same 1516 meaning. OFFSET -1 means the source is scalar and not a part of an 1517 aggregate. */ 1518 1519 template <typename valtype> 1520 bool 1521 ipcp_lattice<valtype>::add_value (valtype newval, cgraph_edge *cs, 1522 ipcp_value<valtype> *src_val, 1523 int src_idx, HOST_WIDE_INT offset) 1524 { 1525 ipcp_value<valtype> *val; 1526 1527 if (bottom) 1528 return false; 1529 1530 for (val = values; val; val = val->next) 1531 if (values_equal_for_ipcp_p (val->value, newval)) 1532 { 1533 if (ipa_edge_within_scc (cs)) 1534 { 1535 ipcp_value_source<valtype> *s; 1536 for (s = val->sources; s; s = s->next) 1537 if (s->cs == cs) 1538 break; 1539 if (s) 1540 return false; 1541 } 1542 1543 val->add_source (cs, src_val, src_idx, offset); 1544 return false; 1545 } 1546 1547 if (values_count == PARAM_VALUE (PARAM_IPA_CP_VALUE_LIST_SIZE)) 1548 { 1549 /* We can only free sources, not the values themselves, because sources 1550 of other values in this SCC might point to them. */ 1551 for (val = values; val; val = val->next) 1552 { 1553 while (val->sources) 1554 { 1555 ipcp_value_source<valtype> *src = val->sources; 1556 val->sources = src->next; 1557 ipcp_sources_pool.remove ((ipcp_value_source<tree>*)src); 1558 } 1559 } 1560 1561 values = NULL; 1562 return set_to_bottom (); 1563 } 1564 1565 values_count++; 1566 val = allocate_and_init_ipcp_value (newval); 1567 val->add_source (cs, src_val, src_idx, offset); 1568 val->next = values; 1569 values = val; 1570 return true; 1571 } 1572 1573 /* Propagate values through a pass-through jump function JFUNC associated with 1574 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX 1575 is the index of the source parameter. */ 1576 1577 static bool 1578 propagate_vals_across_pass_through (cgraph_edge *cs, ipa_jump_func *jfunc, 1579 ipcp_lattice<tree> *src_lat, 1580 ipcp_lattice<tree> *dest_lat, int src_idx) 1581 { 1582 ipcp_value<tree> *src_val; 1583 bool ret = false; 1584 1585 /* Do not create new values when propagating within an SCC because if there 1586 are arithmetic functions with circular dependencies, there is infinite 1587 number of them and we would just make lattices bottom. */ 1588 if ((ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) 1589 && ipa_edge_within_scc (cs)) 1590 ret = dest_lat->set_contains_variable (); 1591 else 1592 for (src_val = src_lat->values; src_val; src_val = src_val->next) 1593 { 1594 tree cstval = ipa_get_jf_pass_through_result (jfunc, src_val->value); 1595 1596 if (cstval) 1597 ret |= dest_lat->add_value (cstval, cs, src_val, src_idx); 1598 else 1599 ret |= dest_lat->set_contains_variable (); 1600 } 1601 1602 return ret; 1603 } 1604 1605 /* Propagate values through an ancestor jump function JFUNC associated with 1606 edge CS, taking values from SRC_LAT and putting them into DEST_LAT. SRC_IDX 1607 is the index of the source parameter. */ 1608 1609 static bool 1610 propagate_vals_across_ancestor (struct cgraph_edge *cs, 1611 struct ipa_jump_func *jfunc, 1612 ipcp_lattice<tree> *src_lat, 1613 ipcp_lattice<tree> *dest_lat, int src_idx) 1614 { 1615 ipcp_value<tree> *src_val; 1616 bool ret = false; 1617 1618 if (ipa_edge_within_scc (cs)) 1619 return dest_lat->set_contains_variable (); 1620 1621 for (src_val = src_lat->values; src_val; src_val = src_val->next) 1622 { 1623 tree t = ipa_get_jf_ancestor_result (jfunc, src_val->value); 1624 1625 if (t) 1626 ret |= dest_lat->add_value (t, cs, src_val, src_idx); 1627 else 1628 ret |= dest_lat->set_contains_variable (); 1629 } 1630 1631 return ret; 1632 } 1633 1634 /* Propagate scalar values across jump function JFUNC that is associated with 1635 edge CS and put the values into DEST_LAT. */ 1636 1637 static bool 1638 propagate_scalar_across_jump_function (struct cgraph_edge *cs, 1639 struct ipa_jump_func *jfunc, 1640 ipcp_lattice<tree> *dest_lat) 1641 { 1642 if (dest_lat->bottom) 1643 return false; 1644 1645 if (jfunc->type == IPA_JF_CONST) 1646 { 1647 tree val = ipa_get_jf_constant (jfunc); 1648 return dest_lat->add_value (val, cs, NULL, 0); 1649 } 1650 else if (jfunc->type == IPA_JF_PASS_THROUGH 1651 || jfunc->type == IPA_JF_ANCESTOR) 1652 { 1653 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 1654 ipcp_lattice<tree> *src_lat; 1655 int src_idx; 1656 bool ret; 1657 1658 if (jfunc->type == IPA_JF_PASS_THROUGH) 1659 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 1660 else 1661 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); 1662 1663 src_lat = ipa_get_scalar_lat (caller_info, src_idx); 1664 if (src_lat->bottom) 1665 return dest_lat->set_contains_variable (); 1666 1667 /* If we would need to clone the caller and cannot, do not propagate. */ 1668 if (!ipcp_versionable_function_p (cs->caller) 1669 && (src_lat->contains_variable 1670 || (src_lat->values_count > 1))) 1671 return dest_lat->set_contains_variable (); 1672 1673 if (jfunc->type == IPA_JF_PASS_THROUGH) 1674 ret = propagate_vals_across_pass_through (cs, jfunc, src_lat, 1675 dest_lat, src_idx); 1676 else 1677 ret = propagate_vals_across_ancestor (cs, jfunc, src_lat, dest_lat, 1678 src_idx); 1679 1680 if (src_lat->contains_variable) 1681 ret |= dest_lat->set_contains_variable (); 1682 1683 return ret; 1684 } 1685 1686 /* TODO: We currently do not handle member method pointers in IPA-CP (we only 1687 use it for indirect inlining), we should propagate them too. */ 1688 return dest_lat->set_contains_variable (); 1689 } 1690 1691 /* Propagate scalar values across jump function JFUNC that is associated with 1692 edge CS and describes argument IDX and put the values into DEST_LAT. */ 1693 1694 static bool 1695 propagate_context_across_jump_function (cgraph_edge *cs, 1696 ipa_jump_func *jfunc, int idx, 1697 ipcp_lattice<ipa_polymorphic_call_context> *dest_lat) 1698 { 1699 ipa_edge_args *args = IPA_EDGE_REF (cs); 1700 if (dest_lat->bottom) 1701 return false; 1702 bool ret = false; 1703 bool added_sth = false; 1704 bool type_preserved = true; 1705 1706 ipa_polymorphic_call_context edge_ctx, *edge_ctx_ptr 1707 = ipa_get_ith_polymorhic_call_context (args, idx); 1708 1709 if (edge_ctx_ptr) 1710 edge_ctx = *edge_ctx_ptr; 1711 1712 if (jfunc->type == IPA_JF_PASS_THROUGH 1713 || jfunc->type == IPA_JF_ANCESTOR) 1714 { 1715 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 1716 int src_idx; 1717 ipcp_lattice<ipa_polymorphic_call_context> *src_lat; 1718 1719 /* TODO: Once we figure out how to propagate speculations, it will 1720 probably be a good idea to switch to speculation if type_preserved is 1721 not set instead of punting. */ 1722 if (jfunc->type == IPA_JF_PASS_THROUGH) 1723 { 1724 if (ipa_get_jf_pass_through_operation (jfunc) != NOP_EXPR) 1725 goto prop_fail; 1726 type_preserved = ipa_get_jf_pass_through_type_preserved (jfunc); 1727 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 1728 } 1729 else 1730 { 1731 type_preserved = ipa_get_jf_ancestor_type_preserved (jfunc); 1732 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); 1733 } 1734 1735 src_lat = ipa_get_poly_ctx_lat (caller_info, src_idx); 1736 /* If we would need to clone the caller and cannot, do not propagate. */ 1737 if (!ipcp_versionable_function_p (cs->caller) 1738 && (src_lat->contains_variable 1739 || (src_lat->values_count > 1))) 1740 goto prop_fail; 1741 1742 ipcp_value<ipa_polymorphic_call_context> *src_val; 1743 for (src_val = src_lat->values; src_val; src_val = src_val->next) 1744 { 1745 ipa_polymorphic_call_context cur = src_val->value; 1746 1747 if (!type_preserved) 1748 cur.possible_dynamic_type_change (cs->in_polymorphic_cdtor); 1749 if (jfunc->type == IPA_JF_ANCESTOR) 1750 cur.offset_by (ipa_get_jf_ancestor_offset (jfunc)); 1751 /* TODO: In cases we know how the context is going to be used, 1752 we can improve the result by passing proper OTR_TYPE. */ 1753 cur.combine_with (edge_ctx); 1754 if (!cur.useless_p ()) 1755 { 1756 if (src_lat->contains_variable 1757 && !edge_ctx.equal_to (cur)) 1758 ret |= dest_lat->set_contains_variable (); 1759 ret |= dest_lat->add_value (cur, cs, src_val, src_idx); 1760 added_sth = true; 1761 } 1762 } 1763 1764 } 1765 1766 prop_fail: 1767 if (!added_sth) 1768 { 1769 if (!edge_ctx.useless_p ()) 1770 ret |= dest_lat->add_value (edge_ctx, cs); 1771 else 1772 ret |= dest_lat->set_contains_variable (); 1773 } 1774 1775 return ret; 1776 } 1777 1778 /* Propagate bits across jfunc that is associated with 1779 edge cs and update dest_lattice accordingly. */ 1780 1781 bool 1782 propagate_bits_across_jump_function (cgraph_edge *cs, int idx, 1783 ipa_jump_func *jfunc, 1784 ipcp_bits_lattice *dest_lattice) 1785 { 1786 if (dest_lattice->bottom_p ()) 1787 return false; 1788 1789 enum availability availability; 1790 cgraph_node *callee = cs->callee->function_symbol (&availability); 1791 struct ipa_node_params *callee_info = IPA_NODE_REF (callee); 1792 tree parm_type = ipa_get_type (callee_info, idx); 1793 1794 /* For K&R C programs, ipa_get_type() could return NULL_TREE. 1795 Avoid the transform for these cases. */ 1796 if (!parm_type) 1797 { 1798 if (dump_file && (dump_flags & TDF_DETAILS)) 1799 fprintf (dump_file, "Setting dest_lattice to bottom, because" 1800 " param %i type is NULL for %s\n", idx, 1801 cs->callee->name ()); 1802 1803 return dest_lattice->set_to_bottom (); 1804 } 1805 1806 unsigned precision = TYPE_PRECISION (parm_type); 1807 signop sgn = TYPE_SIGN (parm_type); 1808 1809 if (jfunc->type == IPA_JF_PASS_THROUGH 1810 || jfunc->type == IPA_JF_ANCESTOR) 1811 { 1812 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 1813 tree operand = NULL_TREE; 1814 enum tree_code code; 1815 unsigned src_idx; 1816 1817 if (jfunc->type == IPA_JF_PASS_THROUGH) 1818 { 1819 code = ipa_get_jf_pass_through_operation (jfunc); 1820 src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 1821 if (code != NOP_EXPR) 1822 operand = ipa_get_jf_pass_through_operand (jfunc); 1823 } 1824 else 1825 { 1826 code = POINTER_PLUS_EXPR; 1827 src_idx = ipa_get_jf_ancestor_formal_id (jfunc); 1828 unsigned HOST_WIDE_INT offset = ipa_get_jf_ancestor_offset (jfunc) / BITS_PER_UNIT; 1829 operand = build_int_cstu (size_type_node, offset); 1830 } 1831 1832 struct ipcp_param_lattices *src_lats 1833 = ipa_get_parm_lattices (caller_info, src_idx); 1834 1835 /* Try to propagate bits if src_lattice is bottom, but jfunc is known. 1836 for eg consider: 1837 int f(int x) 1838 { 1839 g (x & 0xff); 1840 } 1841 Assume lattice for x is bottom, however we can still propagate 1842 result of x & 0xff == 0xff, which gets computed during ccp1 pass 1843 and we store it in jump function during analysis stage. */ 1844 1845 if (src_lats->bits_lattice.bottom_p () 1846 && jfunc->bits) 1847 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask, 1848 precision); 1849 else 1850 return dest_lattice->meet_with (src_lats->bits_lattice, precision, sgn, 1851 code, operand); 1852 } 1853 1854 else if (jfunc->type == IPA_JF_ANCESTOR) 1855 return dest_lattice->set_to_bottom (); 1856 else if (jfunc->bits) 1857 return dest_lattice->meet_with (jfunc->bits->value, jfunc->bits->mask, 1858 precision); 1859 else 1860 return dest_lattice->set_to_bottom (); 1861 } 1862 1863 /* Emulate effects of unary OPERATION and/or conversion from SRC_TYPE to 1864 DST_TYPE on value range in SRC_VR and store it to DST_VR. Return true if 1865 the result is a range or an anti-range. */ 1866 1867 static bool 1868 ipa_vr_operation_and_type_effects (value_range *dst_vr, value_range *src_vr, 1869 enum tree_code operation, 1870 tree dst_type, tree src_type) 1871 { 1872 memset (dst_vr, 0, sizeof (*dst_vr)); 1873 extract_range_from_unary_expr (dst_vr, operation, dst_type, src_vr, src_type); 1874 if (dst_vr->type == VR_RANGE || dst_vr->type == VR_ANTI_RANGE) 1875 return true; 1876 else 1877 return false; 1878 } 1879 1880 /* Propagate value range across jump function JFUNC that is associated with 1881 edge CS with param of callee of PARAM_TYPE and update DEST_PLATS 1882 accordingly. */ 1883 1884 static bool 1885 propagate_vr_across_jump_function (cgraph_edge *cs, ipa_jump_func *jfunc, 1886 struct ipcp_param_lattices *dest_plats, 1887 tree param_type) 1888 { 1889 ipcp_vr_lattice *dest_lat = &dest_plats->m_value_range; 1890 1891 if (dest_lat->bottom_p ()) 1892 return false; 1893 1894 if (!param_type 1895 || (!INTEGRAL_TYPE_P (param_type) 1896 && !POINTER_TYPE_P (param_type))) 1897 return dest_lat->set_to_bottom (); 1898 1899 if (jfunc->type == IPA_JF_PASS_THROUGH) 1900 { 1901 enum tree_code operation = ipa_get_jf_pass_through_operation (jfunc); 1902 1903 if (TREE_CODE_CLASS (operation) == tcc_unary) 1904 { 1905 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 1906 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 1907 tree operand_type = ipa_get_type (caller_info, src_idx); 1908 struct ipcp_param_lattices *src_lats 1909 = ipa_get_parm_lattices (caller_info, src_idx); 1910 1911 if (src_lats->m_value_range.bottom_p ()) 1912 return dest_lat->set_to_bottom (); 1913 value_range vr; 1914 if (ipa_vr_operation_and_type_effects (&vr, 1915 &src_lats->m_value_range.m_vr, 1916 operation, param_type, 1917 operand_type)) 1918 return dest_lat->meet_with (&vr); 1919 } 1920 } 1921 else if (jfunc->type == IPA_JF_CONST) 1922 { 1923 tree val = ipa_get_jf_constant (jfunc); 1924 if (TREE_CODE (val) == INTEGER_CST) 1925 { 1926 val = fold_convert (param_type, val); 1927 if (TREE_OVERFLOW_P (val)) 1928 val = drop_tree_overflow (val); 1929 1930 value_range tmpvr; 1931 memset (&tmpvr, 0, sizeof (tmpvr)); 1932 tmpvr.type = VR_RANGE; 1933 tmpvr.min = val; 1934 tmpvr.max = val; 1935 return dest_lat->meet_with (&tmpvr); 1936 } 1937 } 1938 1939 value_range vr; 1940 if (jfunc->m_vr 1941 && ipa_vr_operation_and_type_effects (&vr, jfunc->m_vr, NOP_EXPR, 1942 param_type, 1943 TREE_TYPE (jfunc->m_vr->min))) 1944 return dest_lat->meet_with (&vr); 1945 else 1946 return dest_lat->set_to_bottom (); 1947 } 1948 1949 /* If DEST_PLATS already has aggregate items, check that aggs_by_ref matches 1950 NEW_AGGS_BY_REF and if not, mark all aggs as bottoms and return true (in all 1951 other cases, return false). If there are no aggregate items, set 1952 aggs_by_ref to NEW_AGGS_BY_REF. */ 1953 1954 static bool 1955 set_check_aggs_by_ref (struct ipcp_param_lattices *dest_plats, 1956 bool new_aggs_by_ref) 1957 { 1958 if (dest_plats->aggs) 1959 { 1960 if (dest_plats->aggs_by_ref != new_aggs_by_ref) 1961 { 1962 set_agg_lats_to_bottom (dest_plats); 1963 return true; 1964 } 1965 } 1966 else 1967 dest_plats->aggs_by_ref = new_aggs_by_ref; 1968 return false; 1969 } 1970 1971 /* Walk aggregate lattices in DEST_PLATS from ***AGLAT on, until ***aglat is an 1972 already existing lattice for the given OFFSET and SIZE, marking all skipped 1973 lattices as containing variable and checking for overlaps. If there is no 1974 already existing lattice for the OFFSET and VAL_SIZE, create one, initialize 1975 it with offset, size and contains_variable to PRE_EXISTING, and return true, 1976 unless there are too many already. If there are two many, return false. If 1977 there are overlaps turn whole DEST_PLATS to bottom and return false. If any 1978 skipped lattices were newly marked as containing variable, set *CHANGE to 1979 true. */ 1980 1981 static bool 1982 merge_agg_lats_step (struct ipcp_param_lattices *dest_plats, 1983 HOST_WIDE_INT offset, HOST_WIDE_INT val_size, 1984 struct ipcp_agg_lattice ***aglat, 1985 bool pre_existing, bool *change) 1986 { 1987 gcc_checking_assert (offset >= 0); 1988 1989 while (**aglat && (**aglat)->offset < offset) 1990 { 1991 if ((**aglat)->offset + (**aglat)->size > offset) 1992 { 1993 set_agg_lats_to_bottom (dest_plats); 1994 return false; 1995 } 1996 *change |= (**aglat)->set_contains_variable (); 1997 *aglat = &(**aglat)->next; 1998 } 1999 2000 if (**aglat && (**aglat)->offset == offset) 2001 { 2002 if ((**aglat)->size != val_size 2003 || ((**aglat)->next 2004 && (**aglat)->next->offset < offset + val_size)) 2005 { 2006 set_agg_lats_to_bottom (dest_plats); 2007 return false; 2008 } 2009 gcc_checking_assert (!(**aglat)->next 2010 || (**aglat)->next->offset >= offset + val_size); 2011 return true; 2012 } 2013 else 2014 { 2015 struct ipcp_agg_lattice *new_al; 2016 2017 if (**aglat && (**aglat)->offset < offset + val_size) 2018 { 2019 set_agg_lats_to_bottom (dest_plats); 2020 return false; 2021 } 2022 if (dest_plats->aggs_count == PARAM_VALUE (PARAM_IPA_MAX_AGG_ITEMS)) 2023 return false; 2024 dest_plats->aggs_count++; 2025 new_al = ipcp_agg_lattice_pool.allocate (); 2026 memset (new_al, 0, sizeof (*new_al)); 2027 2028 new_al->offset = offset; 2029 new_al->size = val_size; 2030 new_al->contains_variable = pre_existing; 2031 2032 new_al->next = **aglat; 2033 **aglat = new_al; 2034 return true; 2035 } 2036 } 2037 2038 /* Set all AGLAT and all other aggregate lattices reachable by next pointers as 2039 containing an unknown value. */ 2040 2041 static bool 2042 set_chain_of_aglats_contains_variable (struct ipcp_agg_lattice *aglat) 2043 { 2044 bool ret = false; 2045 while (aglat) 2046 { 2047 ret |= aglat->set_contains_variable (); 2048 aglat = aglat->next; 2049 } 2050 return ret; 2051 } 2052 2053 /* Merge existing aggregate lattices in SRC_PLATS to DEST_PLATS, subtracting 2054 DELTA_OFFSET. CS is the call graph edge and SRC_IDX the index of the source 2055 parameter used for lattice value sources. Return true if DEST_PLATS changed 2056 in any way. */ 2057 2058 static bool 2059 merge_aggregate_lattices (struct cgraph_edge *cs, 2060 struct ipcp_param_lattices *dest_plats, 2061 struct ipcp_param_lattices *src_plats, 2062 int src_idx, HOST_WIDE_INT offset_delta) 2063 { 2064 bool pre_existing = dest_plats->aggs != NULL; 2065 struct ipcp_agg_lattice **dst_aglat; 2066 bool ret = false; 2067 2068 if (set_check_aggs_by_ref (dest_plats, src_plats->aggs_by_ref)) 2069 return true; 2070 if (src_plats->aggs_bottom) 2071 return set_agg_lats_contain_variable (dest_plats); 2072 if (src_plats->aggs_contain_variable) 2073 ret |= set_agg_lats_contain_variable (dest_plats); 2074 dst_aglat = &dest_plats->aggs; 2075 2076 for (struct ipcp_agg_lattice *src_aglat = src_plats->aggs; 2077 src_aglat; 2078 src_aglat = src_aglat->next) 2079 { 2080 HOST_WIDE_INT new_offset = src_aglat->offset - offset_delta; 2081 2082 if (new_offset < 0) 2083 continue; 2084 if (merge_agg_lats_step (dest_plats, new_offset, src_aglat->size, 2085 &dst_aglat, pre_existing, &ret)) 2086 { 2087 struct ipcp_agg_lattice *new_al = *dst_aglat; 2088 2089 dst_aglat = &(*dst_aglat)->next; 2090 if (src_aglat->bottom) 2091 { 2092 ret |= new_al->set_contains_variable (); 2093 continue; 2094 } 2095 if (src_aglat->contains_variable) 2096 ret |= new_al->set_contains_variable (); 2097 for (ipcp_value<tree> *val = src_aglat->values; 2098 val; 2099 val = val->next) 2100 ret |= new_al->add_value (val->value, cs, val, src_idx, 2101 src_aglat->offset); 2102 } 2103 else if (dest_plats->aggs_bottom) 2104 return true; 2105 } 2106 ret |= set_chain_of_aglats_contains_variable (*dst_aglat); 2107 return ret; 2108 } 2109 2110 /* Determine whether there is anything to propagate FROM SRC_PLATS through a 2111 pass-through JFUNC and if so, whether it has conform and conforms to the 2112 rules about propagating values passed by reference. */ 2113 2114 static bool 2115 agg_pass_through_permissible_p (struct ipcp_param_lattices *src_plats, 2116 struct ipa_jump_func *jfunc) 2117 { 2118 return src_plats->aggs 2119 && (!src_plats->aggs_by_ref 2120 || ipa_get_jf_pass_through_agg_preserved (jfunc)); 2121 } 2122 2123 /* Propagate scalar values across jump function JFUNC that is associated with 2124 edge CS and put the values into DEST_LAT. */ 2125 2126 static bool 2127 propagate_aggs_across_jump_function (struct cgraph_edge *cs, 2128 struct ipa_jump_func *jfunc, 2129 struct ipcp_param_lattices *dest_plats) 2130 { 2131 bool ret = false; 2132 2133 if (dest_plats->aggs_bottom) 2134 return false; 2135 2136 if (jfunc->type == IPA_JF_PASS_THROUGH 2137 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) 2138 { 2139 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 2140 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 2141 struct ipcp_param_lattices *src_plats; 2142 2143 src_plats = ipa_get_parm_lattices (caller_info, src_idx); 2144 if (agg_pass_through_permissible_p (src_plats, jfunc)) 2145 { 2146 /* Currently we do not produce clobber aggregate jump 2147 functions, replace with merging when we do. */ 2148 gcc_assert (!jfunc->agg.items); 2149 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, 2150 src_idx, 0); 2151 } 2152 else 2153 ret |= set_agg_lats_contain_variable (dest_plats); 2154 } 2155 else if (jfunc->type == IPA_JF_ANCESTOR 2156 && ipa_get_jf_ancestor_agg_preserved (jfunc)) 2157 { 2158 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 2159 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); 2160 struct ipcp_param_lattices *src_plats; 2161 2162 src_plats = ipa_get_parm_lattices (caller_info, src_idx); 2163 if (src_plats->aggs && src_plats->aggs_by_ref) 2164 { 2165 /* Currently we do not produce clobber aggregate jump 2166 functions, replace with merging when we do. */ 2167 gcc_assert (!jfunc->agg.items); 2168 ret |= merge_aggregate_lattices (cs, dest_plats, src_plats, src_idx, 2169 ipa_get_jf_ancestor_offset (jfunc)); 2170 } 2171 else if (!src_plats->aggs_by_ref) 2172 ret |= set_agg_lats_to_bottom (dest_plats); 2173 else 2174 ret |= set_agg_lats_contain_variable (dest_plats); 2175 } 2176 else if (jfunc->agg.items) 2177 { 2178 bool pre_existing = dest_plats->aggs != NULL; 2179 struct ipcp_agg_lattice **aglat = &dest_plats->aggs; 2180 struct ipa_agg_jf_item *item; 2181 int i; 2182 2183 if (set_check_aggs_by_ref (dest_plats, jfunc->agg.by_ref)) 2184 return true; 2185 2186 FOR_EACH_VEC_ELT (*jfunc->agg.items, i, item) 2187 { 2188 HOST_WIDE_INT val_size; 2189 2190 if (item->offset < 0) 2191 continue; 2192 gcc_checking_assert (is_gimple_ip_invariant (item->value)); 2193 val_size = tree_to_uhwi (TYPE_SIZE (TREE_TYPE (item->value))); 2194 2195 if (merge_agg_lats_step (dest_plats, item->offset, val_size, 2196 &aglat, pre_existing, &ret)) 2197 { 2198 ret |= (*aglat)->add_value (item->value, cs, NULL, 0, 0); 2199 aglat = &(*aglat)->next; 2200 } 2201 else if (dest_plats->aggs_bottom) 2202 return true; 2203 } 2204 2205 ret |= set_chain_of_aglats_contains_variable (*aglat); 2206 } 2207 else 2208 ret |= set_agg_lats_contain_variable (dest_plats); 2209 2210 return ret; 2211 } 2212 2213 /* Return true if on the way cfrom CS->caller to the final (non-alias and 2214 non-thunk) destination, the call passes through a thunk. */ 2215 2216 static bool 2217 call_passes_through_thunk_p (cgraph_edge *cs) 2218 { 2219 cgraph_node *alias_or_thunk = cs->callee; 2220 while (alias_or_thunk->alias) 2221 alias_or_thunk = alias_or_thunk->get_alias_target (); 2222 return alias_or_thunk->thunk.thunk_p; 2223 } 2224 2225 /* Propagate constants from the caller to the callee of CS. INFO describes the 2226 caller. */ 2227 2228 static bool 2229 propagate_constants_across_call (struct cgraph_edge *cs) 2230 { 2231 struct ipa_node_params *callee_info; 2232 enum availability availability; 2233 cgraph_node *callee; 2234 struct ipa_edge_args *args; 2235 bool ret = false; 2236 int i, args_count, parms_count; 2237 2238 callee = cs->callee->function_symbol (&availability); 2239 if (!callee->definition) 2240 return false; 2241 gcc_checking_assert (callee->has_gimple_body_p ()); 2242 callee_info = IPA_NODE_REF (callee); 2243 2244 args = IPA_EDGE_REF (cs); 2245 args_count = ipa_get_cs_argument_count (args); 2246 parms_count = ipa_get_param_count (callee_info); 2247 if (parms_count == 0) 2248 return false; 2249 2250 /* No propagation through instrumentation thunks is available yet. 2251 It should be possible with proper mapping of call args and 2252 instrumented callee params in the propagation loop below. But 2253 this case mostly occurs when legacy code calls instrumented code 2254 and it is not a primary target for optimizations. 2255 We detect instrumentation thunks in aliases and thunks chain by 2256 checking instrumentation_clone flag for chain source and target. 2257 Going through instrumentation thunks we always have it changed 2258 from 0 to 1 and all other nodes do not change it. */ 2259 if (!cs->callee->instrumentation_clone 2260 && callee->instrumentation_clone) 2261 { 2262 for (i = 0; i < parms_count; i++) 2263 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, 2264 i)); 2265 return ret; 2266 } 2267 2268 /* If this call goes through a thunk we must not propagate to the first (0th) 2269 parameter. However, we might need to uncover a thunk from below a series 2270 of aliases first. */ 2271 if (call_passes_through_thunk_p (cs)) 2272 { 2273 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, 2274 0)); 2275 i = 1; 2276 } 2277 else 2278 i = 0; 2279 2280 for (; (i < args_count) && (i < parms_count); i++) 2281 { 2282 struct ipa_jump_func *jump_func = ipa_get_ith_jump_func (args, i); 2283 struct ipcp_param_lattices *dest_plats; 2284 tree param_type = ipa_get_type (callee_info, i); 2285 2286 dest_plats = ipa_get_parm_lattices (callee_info, i); 2287 if (availability == AVAIL_INTERPOSABLE) 2288 ret |= set_all_contains_variable (dest_plats); 2289 else 2290 { 2291 ret |= propagate_scalar_across_jump_function (cs, jump_func, 2292 &dest_plats->itself); 2293 ret |= propagate_context_across_jump_function (cs, jump_func, i, 2294 &dest_plats->ctxlat); 2295 ret 2296 |= propagate_bits_across_jump_function (cs, i, jump_func, 2297 &dest_plats->bits_lattice); 2298 ret |= propagate_aggs_across_jump_function (cs, jump_func, 2299 dest_plats); 2300 if (opt_for_fn (callee->decl, flag_ipa_vrp)) 2301 ret |= propagate_vr_across_jump_function (cs, jump_func, 2302 dest_plats, param_type); 2303 else 2304 ret |= dest_plats->m_value_range.set_to_bottom (); 2305 } 2306 } 2307 for (; i < parms_count; i++) 2308 ret |= set_all_contains_variable (ipa_get_parm_lattices (callee_info, i)); 2309 2310 return ret; 2311 } 2312 2313 /* If an indirect edge IE can be turned into a direct one based on KNOWN_VALS 2314 KNOWN_CONTEXTS, KNOWN_AGGS or AGG_REPS return the destination. The latter 2315 three can be NULL. If AGG_REPS is not NULL, KNOWN_AGGS is ignored. */ 2316 2317 static tree 2318 ipa_get_indirect_edge_target_1 (struct cgraph_edge *ie, 2319 vec<tree> known_csts, 2320 vec<ipa_polymorphic_call_context> known_contexts, 2321 vec<ipa_agg_jump_function_p> known_aggs, 2322 struct ipa_agg_replacement_value *agg_reps, 2323 bool *speculative) 2324 { 2325 int param_index = ie->indirect_info->param_index; 2326 HOST_WIDE_INT anc_offset; 2327 tree t; 2328 tree target = NULL; 2329 2330 *speculative = false; 2331 2332 if (param_index == -1 2333 || known_csts.length () <= (unsigned int) param_index) 2334 return NULL_TREE; 2335 2336 if (!ie->indirect_info->polymorphic) 2337 { 2338 tree t; 2339 2340 if (ie->indirect_info->agg_contents) 2341 { 2342 t = NULL; 2343 if (agg_reps && ie->indirect_info->guaranteed_unmodified) 2344 { 2345 while (agg_reps) 2346 { 2347 if (agg_reps->index == param_index 2348 && agg_reps->offset == ie->indirect_info->offset 2349 && agg_reps->by_ref == ie->indirect_info->by_ref) 2350 { 2351 t = agg_reps->value; 2352 break; 2353 } 2354 agg_reps = agg_reps->next; 2355 } 2356 } 2357 if (!t) 2358 { 2359 struct ipa_agg_jump_function *agg; 2360 if (known_aggs.length () > (unsigned int) param_index) 2361 agg = known_aggs[param_index]; 2362 else 2363 agg = NULL; 2364 bool from_global_constant; 2365 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], 2366 ie->indirect_info->offset, 2367 ie->indirect_info->by_ref, 2368 &from_global_constant); 2369 if (t 2370 && !from_global_constant 2371 && !ie->indirect_info->guaranteed_unmodified) 2372 t = NULL_TREE; 2373 } 2374 } 2375 else 2376 t = known_csts[param_index]; 2377 2378 if (t 2379 && TREE_CODE (t) == ADDR_EXPR 2380 && TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL) 2381 return TREE_OPERAND (t, 0); 2382 else 2383 return NULL_TREE; 2384 } 2385 2386 if (!opt_for_fn (ie->caller->decl, flag_devirtualize)) 2387 return NULL_TREE; 2388 2389 gcc_assert (!ie->indirect_info->agg_contents); 2390 anc_offset = ie->indirect_info->offset; 2391 2392 t = NULL; 2393 2394 /* Try to work out value of virtual table pointer value in replacemnets. */ 2395 if (!t && agg_reps && !ie->indirect_info->by_ref) 2396 { 2397 while (agg_reps) 2398 { 2399 if (agg_reps->index == param_index 2400 && agg_reps->offset == ie->indirect_info->offset 2401 && agg_reps->by_ref) 2402 { 2403 t = agg_reps->value; 2404 break; 2405 } 2406 agg_reps = agg_reps->next; 2407 } 2408 } 2409 2410 /* Try to work out value of virtual table pointer value in known 2411 aggregate values. */ 2412 if (!t && known_aggs.length () > (unsigned int) param_index 2413 && !ie->indirect_info->by_ref) 2414 { 2415 struct ipa_agg_jump_function *agg; 2416 agg = known_aggs[param_index]; 2417 t = ipa_find_agg_cst_for_param (agg, known_csts[param_index], 2418 ie->indirect_info->offset, true); 2419 } 2420 2421 /* If we found the virtual table pointer, lookup the target. */ 2422 if (t) 2423 { 2424 tree vtable; 2425 unsigned HOST_WIDE_INT offset; 2426 if (vtable_pointer_value_to_vtable (t, &vtable, &offset)) 2427 { 2428 bool can_refer; 2429 target = gimple_get_virt_method_for_vtable (ie->indirect_info->otr_token, 2430 vtable, offset, &can_refer); 2431 if (can_refer) 2432 { 2433 if (!target 2434 || (TREE_CODE (TREE_TYPE (target)) == FUNCTION_TYPE 2435 && DECL_FUNCTION_CODE (target) == BUILT_IN_UNREACHABLE) 2436 || !possible_polymorphic_call_target_p 2437 (ie, cgraph_node::get (target))) 2438 { 2439 /* Do not speculate builtin_unreachable, it is stupid! */ 2440 if (ie->indirect_info->vptr_changed) 2441 return NULL; 2442 target = ipa_impossible_devirt_target (ie, target); 2443 } 2444 *speculative = ie->indirect_info->vptr_changed; 2445 if (!*speculative) 2446 return target; 2447 } 2448 } 2449 } 2450 2451 /* Do we know the constant value of pointer? */ 2452 if (!t) 2453 t = known_csts[param_index]; 2454 2455 gcc_checking_assert (!t || TREE_CODE (t) != TREE_BINFO); 2456 2457 ipa_polymorphic_call_context context; 2458 if (known_contexts.length () > (unsigned int) param_index) 2459 { 2460 context = known_contexts[param_index]; 2461 context.offset_by (anc_offset); 2462 if (ie->indirect_info->vptr_changed) 2463 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor, 2464 ie->indirect_info->otr_type); 2465 if (t) 2466 { 2467 ipa_polymorphic_call_context ctx2 = ipa_polymorphic_call_context 2468 (t, ie->indirect_info->otr_type, anc_offset); 2469 if (!ctx2.useless_p ()) 2470 context.combine_with (ctx2, ie->indirect_info->otr_type); 2471 } 2472 } 2473 else if (t) 2474 { 2475 context = ipa_polymorphic_call_context (t, ie->indirect_info->otr_type, 2476 anc_offset); 2477 if (ie->indirect_info->vptr_changed) 2478 context.possible_dynamic_type_change (ie->in_polymorphic_cdtor, 2479 ie->indirect_info->otr_type); 2480 } 2481 else 2482 return NULL_TREE; 2483 2484 vec <cgraph_node *>targets; 2485 bool final; 2486 2487 targets = possible_polymorphic_call_targets 2488 (ie->indirect_info->otr_type, 2489 ie->indirect_info->otr_token, 2490 context, &final); 2491 if (!final || targets.length () > 1) 2492 { 2493 struct cgraph_node *node; 2494 if (*speculative) 2495 return target; 2496 if (!opt_for_fn (ie->caller->decl, flag_devirtualize_speculatively) 2497 || ie->speculative || !ie->maybe_hot_p ()) 2498 return NULL; 2499 node = try_speculative_devirtualization (ie->indirect_info->otr_type, 2500 ie->indirect_info->otr_token, 2501 context); 2502 if (node) 2503 { 2504 *speculative = true; 2505 target = node->decl; 2506 } 2507 else 2508 return NULL; 2509 } 2510 else 2511 { 2512 *speculative = false; 2513 if (targets.length () == 1) 2514 target = targets[0]->decl; 2515 else 2516 target = ipa_impossible_devirt_target (ie, NULL_TREE); 2517 } 2518 2519 if (target && !possible_polymorphic_call_target_p (ie, 2520 cgraph_node::get (target))) 2521 { 2522 if (*speculative) 2523 return NULL; 2524 target = ipa_impossible_devirt_target (ie, target); 2525 } 2526 2527 return target; 2528 } 2529 2530 2531 /* If an indirect edge IE can be turned into a direct one based on KNOWN_CSTS, 2532 KNOWN_CONTEXTS (which can be vNULL) or KNOWN_AGGS (which also can be vNULL) 2533 return the destination. */ 2534 2535 tree 2536 ipa_get_indirect_edge_target (struct cgraph_edge *ie, 2537 vec<tree> known_csts, 2538 vec<ipa_polymorphic_call_context> known_contexts, 2539 vec<ipa_agg_jump_function_p> known_aggs, 2540 bool *speculative) 2541 { 2542 return ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, 2543 known_aggs, NULL, speculative); 2544 } 2545 2546 /* Calculate devirtualization time bonus for NODE, assuming we know KNOWN_CSTS 2547 and KNOWN_CONTEXTS. */ 2548 2549 static int 2550 devirtualization_time_bonus (struct cgraph_node *node, 2551 vec<tree> known_csts, 2552 vec<ipa_polymorphic_call_context> known_contexts, 2553 vec<ipa_agg_jump_function_p> known_aggs) 2554 { 2555 struct cgraph_edge *ie; 2556 int res = 0; 2557 2558 for (ie = node->indirect_calls; ie; ie = ie->next_callee) 2559 { 2560 struct cgraph_node *callee; 2561 struct inline_summary *isummary; 2562 enum availability avail; 2563 tree target; 2564 bool speculative; 2565 2566 target = ipa_get_indirect_edge_target (ie, known_csts, known_contexts, 2567 known_aggs, &speculative); 2568 if (!target) 2569 continue; 2570 2571 /* Only bare minimum benefit for clearly un-inlineable targets. */ 2572 res += 1; 2573 callee = cgraph_node::get (target); 2574 if (!callee || !callee->definition) 2575 continue; 2576 callee = callee->function_symbol (&avail); 2577 if (avail < AVAIL_AVAILABLE) 2578 continue; 2579 isummary = inline_summaries->get (callee); 2580 if (!isummary->inlinable) 2581 continue; 2582 2583 /* FIXME: The values below need re-considering and perhaps also 2584 integrating into the cost metrics, at lest in some very basic way. */ 2585 if (isummary->size <= MAX_INLINE_INSNS_AUTO / 4) 2586 res += 31 / ((int)speculative + 1); 2587 else if (isummary->size <= MAX_INLINE_INSNS_AUTO / 2) 2588 res += 15 / ((int)speculative + 1); 2589 else if (isummary->size <= MAX_INLINE_INSNS_AUTO 2590 || DECL_DECLARED_INLINE_P (callee->decl)) 2591 res += 7 / ((int)speculative + 1); 2592 } 2593 2594 return res; 2595 } 2596 2597 /* Return time bonus incurred because of HINTS. */ 2598 2599 static int 2600 hint_time_bonus (inline_hints hints) 2601 { 2602 int result = 0; 2603 if (hints & (INLINE_HINT_loop_iterations | INLINE_HINT_loop_stride)) 2604 result += PARAM_VALUE (PARAM_IPA_CP_LOOP_HINT_BONUS); 2605 if (hints & INLINE_HINT_array_index) 2606 result += PARAM_VALUE (PARAM_IPA_CP_ARRAY_INDEX_HINT_BONUS); 2607 return result; 2608 } 2609 2610 /* If there is a reason to penalize the function described by INFO in the 2611 cloning goodness evaluation, do so. */ 2612 2613 static inline int64_t 2614 incorporate_penalties (ipa_node_params *info, int64_t evaluation) 2615 { 2616 if (info->node_within_scc) 2617 evaluation = (evaluation 2618 * (100 - PARAM_VALUE (PARAM_IPA_CP_RECURSION_PENALTY))) / 100; 2619 2620 if (info->node_calling_single_call) 2621 evaluation = (evaluation 2622 * (100 - PARAM_VALUE (PARAM_IPA_CP_SINGLE_CALL_PENALTY))) 2623 / 100; 2624 2625 return evaluation; 2626 } 2627 2628 /* Return true if cloning NODE is a good idea, given the estimated TIME_BENEFIT 2629 and SIZE_COST and with the sum of frequencies of incoming edges to the 2630 potential new clone in FREQUENCIES. */ 2631 2632 static bool 2633 good_cloning_opportunity_p (struct cgraph_node *node, int time_benefit, 2634 int freq_sum, gcov_type count_sum, int size_cost) 2635 { 2636 if (time_benefit == 0 2637 || !opt_for_fn (node->decl, flag_ipa_cp_clone) 2638 || node->optimize_for_size_p ()) 2639 return false; 2640 2641 gcc_assert (size_cost > 0); 2642 2643 struct ipa_node_params *info = IPA_NODE_REF (node); 2644 if (max_count) 2645 { 2646 int factor = (count_sum * 1000) / max_count; 2647 int64_t evaluation = (((int64_t) time_benefit * factor) 2648 / size_cost); 2649 evaluation = incorporate_penalties (info, evaluation); 2650 2651 if (dump_file && (dump_flags & TDF_DETAILS)) 2652 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " 2653 "size: %i, count_sum: " HOST_WIDE_INT_PRINT_DEC 2654 "%s%s) -> evaluation: " "%" PRId64 2655 ", threshold: %i\n", 2656 time_benefit, size_cost, (HOST_WIDE_INT) count_sum, 2657 info->node_within_scc ? ", scc" : "", 2658 info->node_calling_single_call ? ", single_call" : "", 2659 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); 2660 2661 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); 2662 } 2663 else 2664 { 2665 int64_t evaluation = (((int64_t) time_benefit * freq_sum) 2666 / size_cost); 2667 evaluation = incorporate_penalties (info, evaluation); 2668 2669 if (dump_file && (dump_flags & TDF_DETAILS)) 2670 fprintf (dump_file, " good_cloning_opportunity_p (time: %i, " 2671 "size: %i, freq_sum: %i%s%s) -> evaluation: " 2672 "%" PRId64 ", threshold: %i\n", 2673 time_benefit, size_cost, freq_sum, 2674 info->node_within_scc ? ", scc" : "", 2675 info->node_calling_single_call ? ", single_call" : "", 2676 evaluation, PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD)); 2677 2678 return evaluation >= PARAM_VALUE (PARAM_IPA_CP_EVAL_THRESHOLD); 2679 } 2680 } 2681 2682 /* Return all context independent values from aggregate lattices in PLATS in a 2683 vector. Return NULL if there are none. */ 2684 2685 static vec<ipa_agg_jf_item, va_gc> * 2686 context_independent_aggregate_values (struct ipcp_param_lattices *plats) 2687 { 2688 vec<ipa_agg_jf_item, va_gc> *res = NULL; 2689 2690 if (plats->aggs_bottom 2691 || plats->aggs_contain_variable 2692 || plats->aggs_count == 0) 2693 return NULL; 2694 2695 for (struct ipcp_agg_lattice *aglat = plats->aggs; 2696 aglat; 2697 aglat = aglat->next) 2698 if (aglat->is_single_const ()) 2699 { 2700 struct ipa_agg_jf_item item; 2701 item.offset = aglat->offset; 2702 item.value = aglat->values->value; 2703 vec_safe_push (res, item); 2704 } 2705 return res; 2706 } 2707 2708 /* Allocate KNOWN_CSTS, KNOWN_CONTEXTS and, if non-NULL, KNOWN_AGGS and 2709 populate them with values of parameters that are known independent of the 2710 context. INFO describes the function. If REMOVABLE_PARAMS_COST is 2711 non-NULL, the movement cost of all removable parameters will be stored in 2712 it. */ 2713 2714 static bool 2715 gather_context_independent_values (struct ipa_node_params *info, 2716 vec<tree> *known_csts, 2717 vec<ipa_polymorphic_call_context> 2718 *known_contexts, 2719 vec<ipa_agg_jump_function> *known_aggs, 2720 int *removable_params_cost) 2721 { 2722 int i, count = ipa_get_param_count (info); 2723 bool ret = false; 2724 2725 known_csts->create (0); 2726 known_contexts->create (0); 2727 known_csts->safe_grow_cleared (count); 2728 known_contexts->safe_grow_cleared (count); 2729 if (known_aggs) 2730 { 2731 known_aggs->create (0); 2732 known_aggs->safe_grow_cleared (count); 2733 } 2734 2735 if (removable_params_cost) 2736 *removable_params_cost = 0; 2737 2738 for (i = 0; i < count; i++) 2739 { 2740 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 2741 ipcp_lattice<tree> *lat = &plats->itself; 2742 2743 if (lat->is_single_const ()) 2744 { 2745 ipcp_value<tree> *val = lat->values; 2746 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); 2747 (*known_csts)[i] = val->value; 2748 if (removable_params_cost) 2749 *removable_params_cost 2750 += estimate_move_cost (TREE_TYPE (val->value), false); 2751 ret = true; 2752 } 2753 else if (removable_params_cost 2754 && !ipa_is_param_used (info, i)) 2755 *removable_params_cost 2756 += ipa_get_param_move_cost (info, i); 2757 2758 if (!ipa_is_param_used (info, i)) 2759 continue; 2760 2761 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; 2762 /* Do not account known context as reason for cloning. We can see 2763 if it permits devirtualization. */ 2764 if (ctxlat->is_single_const ()) 2765 (*known_contexts)[i] = ctxlat->values->value; 2766 2767 if (known_aggs) 2768 { 2769 vec<ipa_agg_jf_item, va_gc> *agg_items; 2770 struct ipa_agg_jump_function *ajf; 2771 2772 agg_items = context_independent_aggregate_values (plats); 2773 ajf = &(*known_aggs)[i]; 2774 ajf->items = agg_items; 2775 ajf->by_ref = plats->aggs_by_ref; 2776 ret |= agg_items != NULL; 2777 } 2778 } 2779 2780 return ret; 2781 } 2782 2783 /* The current interface in ipa-inline-analysis requires a pointer vector. 2784 Create it. 2785 2786 FIXME: That interface should be re-worked, this is slightly silly. Still, 2787 I'd like to discuss how to change it first and this demonstrates the 2788 issue. */ 2789 2790 static vec<ipa_agg_jump_function_p> 2791 agg_jmp_p_vec_for_t_vec (vec<ipa_agg_jump_function> known_aggs) 2792 { 2793 vec<ipa_agg_jump_function_p> ret; 2794 struct ipa_agg_jump_function *ajf; 2795 int i; 2796 2797 ret.create (known_aggs.length ()); 2798 FOR_EACH_VEC_ELT (known_aggs, i, ajf) 2799 ret.quick_push (ajf); 2800 return ret; 2801 } 2802 2803 /* Perform time and size measurement of NODE with the context given in 2804 KNOWN_CSTS, KNOWN_CONTEXTS and KNOWN_AGGS, calculate the benefit and cost 2805 given BASE_TIME of the node without specialization, REMOVABLE_PARAMS_COST of 2806 all context-independent removable parameters and EST_MOVE_COST of estimated 2807 movement of the considered parameter and store it into VAL. */ 2808 2809 static void 2810 perform_estimation_of_a_value (cgraph_node *node, vec<tree> known_csts, 2811 vec<ipa_polymorphic_call_context> known_contexts, 2812 vec<ipa_agg_jump_function_p> known_aggs_ptrs, 2813 int base_time, int removable_params_cost, 2814 int est_move_cost, ipcp_value_base *val) 2815 { 2816 int time, size, time_benefit; 2817 inline_hints hints; 2818 2819 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, 2820 known_aggs_ptrs, &size, &time, 2821 &hints); 2822 time_benefit = base_time - time 2823 + devirtualization_time_bonus (node, known_csts, known_contexts, 2824 known_aggs_ptrs) 2825 + hint_time_bonus (hints) 2826 + removable_params_cost + est_move_cost; 2827 2828 gcc_checking_assert (size >=0); 2829 /* The inliner-heuristics based estimates may think that in certain 2830 contexts some functions do not have any size at all but we want 2831 all specializations to have at least a tiny cost, not least not to 2832 divide by zero. */ 2833 if (size == 0) 2834 size = 1; 2835 2836 val->local_time_benefit = time_benefit; 2837 val->local_size_cost = size; 2838 } 2839 2840 /* Iterate over known values of parameters of NODE and estimate the local 2841 effects in terms of time and size they have. */ 2842 2843 static void 2844 estimate_local_effects (struct cgraph_node *node) 2845 { 2846 struct ipa_node_params *info = IPA_NODE_REF (node); 2847 int i, count = ipa_get_param_count (info); 2848 vec<tree> known_csts; 2849 vec<ipa_polymorphic_call_context> known_contexts; 2850 vec<ipa_agg_jump_function> known_aggs; 2851 vec<ipa_agg_jump_function_p> known_aggs_ptrs; 2852 bool always_const; 2853 int base_time = inline_summaries->get (node)->time; 2854 int removable_params_cost; 2855 2856 if (!count || !ipcp_versionable_function_p (node)) 2857 return; 2858 2859 if (dump_file && (dump_flags & TDF_DETAILS)) 2860 fprintf (dump_file, "\nEstimating effects for %s/%i, base_time: %i.\n", 2861 node->name (), node->order, base_time); 2862 2863 always_const = gather_context_independent_values (info, &known_csts, 2864 &known_contexts, &known_aggs, 2865 &removable_params_cost); 2866 known_aggs_ptrs = agg_jmp_p_vec_for_t_vec (known_aggs); 2867 int devirt_bonus = devirtualization_time_bonus (node, known_csts, 2868 known_contexts, known_aggs_ptrs); 2869 if (always_const || devirt_bonus 2870 || (removable_params_cost && node->local.can_change_signature)) 2871 { 2872 struct caller_statistics stats; 2873 inline_hints hints; 2874 int time, size; 2875 2876 init_caller_stats (&stats); 2877 node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, 2878 false); 2879 estimate_ipcp_clone_size_and_time (node, known_csts, known_contexts, 2880 known_aggs_ptrs, &size, &time, &hints); 2881 time -= devirt_bonus; 2882 time -= hint_time_bonus (hints); 2883 time -= removable_params_cost; 2884 size -= stats.n_calls * removable_params_cost; 2885 2886 if (dump_file) 2887 fprintf (dump_file, " - context independent values, size: %i, " 2888 "time_benefit: %i\n", size, base_time - time); 2889 2890 if (size <= 0 || node->local.local) 2891 { 2892 info->do_clone_for_all_contexts = true; 2893 base_time = time; 2894 2895 if (dump_file) 2896 fprintf (dump_file, " Decided to specialize for all " 2897 "known contexts, code not going to grow.\n"); 2898 } 2899 else if (good_cloning_opportunity_p (node, base_time - time, 2900 stats.freq_sum, stats.count_sum, 2901 size)) 2902 { 2903 if (size + overall_size <= max_new_size) 2904 { 2905 info->do_clone_for_all_contexts = true; 2906 base_time = time; 2907 overall_size += size; 2908 2909 if (dump_file) 2910 fprintf (dump_file, " Decided to specialize for all " 2911 "known contexts, growth deemed beneficial.\n"); 2912 } 2913 else if (dump_file && (dump_flags & TDF_DETAILS)) 2914 fprintf (dump_file, " Not cloning for all contexts because " 2915 "max_new_size would be reached with %li.\n", 2916 size + overall_size); 2917 } 2918 else if (dump_file && (dump_flags & TDF_DETAILS)) 2919 fprintf (dump_file, " Not cloning for all contexts because " 2920 "!good_cloning_opportunity_p.\n"); 2921 2922 } 2923 2924 for (i = 0; i < count; i++) 2925 { 2926 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 2927 ipcp_lattice<tree> *lat = &plats->itself; 2928 ipcp_value<tree> *val; 2929 2930 if (lat->bottom 2931 || !lat->values 2932 || known_csts[i]) 2933 continue; 2934 2935 for (val = lat->values; val; val = val->next) 2936 { 2937 gcc_checking_assert (TREE_CODE (val->value) != TREE_BINFO); 2938 known_csts[i] = val->value; 2939 2940 int emc = estimate_move_cost (TREE_TYPE (val->value), true); 2941 perform_estimation_of_a_value (node, known_csts, known_contexts, 2942 known_aggs_ptrs, base_time, 2943 removable_params_cost, emc, val); 2944 2945 if (dump_file && (dump_flags & TDF_DETAILS)) 2946 { 2947 fprintf (dump_file, " - estimates for value "); 2948 print_ipcp_constant_value (dump_file, val->value); 2949 fprintf (dump_file, " for "); 2950 ipa_dump_param (dump_file, info, i); 2951 fprintf (dump_file, ": time_benefit: %i, size: %i\n", 2952 val->local_time_benefit, val->local_size_cost); 2953 } 2954 } 2955 known_csts[i] = NULL_TREE; 2956 } 2957 2958 for (i = 0; i < count; i++) 2959 { 2960 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 2961 2962 if (!plats->virt_call) 2963 continue; 2964 2965 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; 2966 ipcp_value<ipa_polymorphic_call_context> *val; 2967 2968 if (ctxlat->bottom 2969 || !ctxlat->values 2970 || !known_contexts[i].useless_p ()) 2971 continue; 2972 2973 for (val = ctxlat->values; val; val = val->next) 2974 { 2975 known_contexts[i] = val->value; 2976 perform_estimation_of_a_value (node, known_csts, known_contexts, 2977 known_aggs_ptrs, base_time, 2978 removable_params_cost, 0, val); 2979 2980 if (dump_file && (dump_flags & TDF_DETAILS)) 2981 { 2982 fprintf (dump_file, " - estimates for polymorphic context "); 2983 print_ipcp_constant_value (dump_file, val->value); 2984 fprintf (dump_file, " for "); 2985 ipa_dump_param (dump_file, info, i); 2986 fprintf (dump_file, ": time_benefit: %i, size: %i\n", 2987 val->local_time_benefit, val->local_size_cost); 2988 } 2989 } 2990 known_contexts[i] = ipa_polymorphic_call_context (); 2991 } 2992 2993 for (i = 0; i < count; i++) 2994 { 2995 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 2996 struct ipa_agg_jump_function *ajf; 2997 struct ipcp_agg_lattice *aglat; 2998 2999 if (plats->aggs_bottom || !plats->aggs) 3000 continue; 3001 3002 ajf = &known_aggs[i]; 3003 for (aglat = plats->aggs; aglat; aglat = aglat->next) 3004 { 3005 ipcp_value<tree> *val; 3006 if (aglat->bottom || !aglat->values 3007 /* If the following is true, the one value is in known_aggs. */ 3008 || (!plats->aggs_contain_variable 3009 && aglat->is_single_const ())) 3010 continue; 3011 3012 for (val = aglat->values; val; val = val->next) 3013 { 3014 struct ipa_agg_jf_item item; 3015 3016 item.offset = aglat->offset; 3017 item.value = val->value; 3018 vec_safe_push (ajf->items, item); 3019 3020 perform_estimation_of_a_value (node, known_csts, known_contexts, 3021 known_aggs_ptrs, base_time, 3022 removable_params_cost, 0, val); 3023 3024 if (dump_file && (dump_flags & TDF_DETAILS)) 3025 { 3026 fprintf (dump_file, " - estimates for value "); 3027 print_ipcp_constant_value (dump_file, val->value); 3028 fprintf (dump_file, " for "); 3029 ipa_dump_param (dump_file, info, i); 3030 fprintf (dump_file, "[%soffset: " HOST_WIDE_INT_PRINT_DEC 3031 "]: time_benefit: %i, size: %i\n", 3032 plats->aggs_by_ref ? "ref " : "", 3033 aglat->offset, 3034 val->local_time_benefit, val->local_size_cost); 3035 } 3036 3037 ajf->items->pop (); 3038 } 3039 } 3040 } 3041 3042 for (i = 0; i < count; i++) 3043 vec_free (known_aggs[i].items); 3044 3045 known_csts.release (); 3046 known_contexts.release (); 3047 known_aggs.release (); 3048 known_aggs_ptrs.release (); 3049 } 3050 3051 3052 /* Add value CUR_VAL and all yet-unsorted values it is dependent on to the 3053 topological sort of values. */ 3054 3055 template <typename valtype> 3056 void 3057 value_topo_info<valtype>::add_val (ipcp_value<valtype> *cur_val) 3058 { 3059 ipcp_value_source<valtype> *src; 3060 3061 if (cur_val->dfs) 3062 return; 3063 3064 dfs_counter++; 3065 cur_val->dfs = dfs_counter; 3066 cur_val->low_link = dfs_counter; 3067 3068 cur_val->topo_next = stack; 3069 stack = cur_val; 3070 cur_val->on_stack = true; 3071 3072 for (src = cur_val->sources; src; src = src->next) 3073 if (src->val) 3074 { 3075 if (src->val->dfs == 0) 3076 { 3077 add_val (src->val); 3078 if (src->val->low_link < cur_val->low_link) 3079 cur_val->low_link = src->val->low_link; 3080 } 3081 else if (src->val->on_stack 3082 && src->val->dfs < cur_val->low_link) 3083 cur_val->low_link = src->val->dfs; 3084 } 3085 3086 if (cur_val->dfs == cur_val->low_link) 3087 { 3088 ipcp_value<valtype> *v, *scc_list = NULL; 3089 3090 do 3091 { 3092 v = stack; 3093 stack = v->topo_next; 3094 v->on_stack = false; 3095 3096 v->scc_next = scc_list; 3097 scc_list = v; 3098 } 3099 while (v != cur_val); 3100 3101 cur_val->topo_next = values_topo; 3102 values_topo = cur_val; 3103 } 3104 } 3105 3106 /* Add all values in lattices associated with NODE to the topological sort if 3107 they are not there yet. */ 3108 3109 static void 3110 add_all_node_vals_to_toposort (cgraph_node *node, ipa_topo_info *topo) 3111 { 3112 struct ipa_node_params *info = IPA_NODE_REF (node); 3113 int i, count = ipa_get_param_count (info); 3114 3115 for (i = 0; i < count; i++) 3116 { 3117 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 3118 ipcp_lattice<tree> *lat = &plats->itself; 3119 struct ipcp_agg_lattice *aglat; 3120 3121 if (!lat->bottom) 3122 { 3123 ipcp_value<tree> *val; 3124 for (val = lat->values; val; val = val->next) 3125 topo->constants.add_val (val); 3126 } 3127 3128 if (!plats->aggs_bottom) 3129 for (aglat = plats->aggs; aglat; aglat = aglat->next) 3130 if (!aglat->bottom) 3131 { 3132 ipcp_value<tree> *val; 3133 for (val = aglat->values; val; val = val->next) 3134 topo->constants.add_val (val); 3135 } 3136 3137 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; 3138 if (!ctxlat->bottom) 3139 { 3140 ipcp_value<ipa_polymorphic_call_context> *ctxval; 3141 for (ctxval = ctxlat->values; ctxval; ctxval = ctxval->next) 3142 topo->contexts.add_val (ctxval); 3143 } 3144 } 3145 } 3146 3147 /* One pass of constants propagation along the call graph edges, from callers 3148 to callees (requires topological ordering in TOPO), iterate over strongly 3149 connected components. */ 3150 3151 static void 3152 propagate_constants_topo (struct ipa_topo_info *topo) 3153 { 3154 int i; 3155 3156 for (i = topo->nnodes - 1; i >= 0; i--) 3157 { 3158 unsigned j; 3159 struct cgraph_node *v, *node = topo->order[i]; 3160 vec<cgraph_node *> cycle_nodes = ipa_get_nodes_in_cycle (node); 3161 3162 /* First, iteratively propagate within the strongly connected component 3163 until all lattices stabilize. */ 3164 FOR_EACH_VEC_ELT (cycle_nodes, j, v) 3165 if (v->has_gimple_body_p ()) 3166 push_node_to_stack (topo, v); 3167 3168 v = pop_node_from_stack (topo); 3169 while (v) 3170 { 3171 struct cgraph_edge *cs; 3172 3173 for (cs = v->callees; cs; cs = cs->next_callee) 3174 if (ipa_edge_within_scc (cs)) 3175 { 3176 IPA_NODE_REF (v)->node_within_scc = true; 3177 if (propagate_constants_across_call (cs)) 3178 push_node_to_stack (topo, cs->callee->function_symbol ()); 3179 } 3180 v = pop_node_from_stack (topo); 3181 } 3182 3183 /* Afterwards, propagate along edges leading out of the SCC, calculates 3184 the local effects of the discovered constants and all valid values to 3185 their topological sort. */ 3186 FOR_EACH_VEC_ELT (cycle_nodes, j, v) 3187 if (v->has_gimple_body_p ()) 3188 { 3189 struct cgraph_edge *cs; 3190 3191 estimate_local_effects (v); 3192 add_all_node_vals_to_toposort (v, topo); 3193 for (cs = v->callees; cs; cs = cs->next_callee) 3194 if (!ipa_edge_within_scc (cs)) 3195 propagate_constants_across_call (cs); 3196 } 3197 cycle_nodes.release (); 3198 } 3199 } 3200 3201 3202 /* Return the sum of A and B if none of them is bigger than INT_MAX/2, return 3203 the bigger one if otherwise. */ 3204 3205 static int 3206 safe_add (int a, int b) 3207 { 3208 if (a > INT_MAX/2 || b > INT_MAX/2) 3209 return a > b ? a : b; 3210 else 3211 return a + b; 3212 } 3213 3214 3215 /* Propagate the estimated effects of individual values along the topological 3216 from the dependent values to those they depend on. */ 3217 3218 template <typename valtype> 3219 void 3220 value_topo_info<valtype>::propagate_effects () 3221 { 3222 ipcp_value<valtype> *base; 3223 3224 for (base = values_topo; base; base = base->topo_next) 3225 { 3226 ipcp_value_source<valtype> *src; 3227 ipcp_value<valtype> *val; 3228 int time = 0, size = 0; 3229 3230 for (val = base; val; val = val->scc_next) 3231 { 3232 time = safe_add (time, 3233 val->local_time_benefit + val->prop_time_benefit); 3234 size = safe_add (size, val->local_size_cost + val->prop_size_cost); 3235 } 3236 3237 for (val = base; val; val = val->scc_next) 3238 for (src = val->sources; src; src = src->next) 3239 if (src->val 3240 && src->cs->maybe_hot_p ()) 3241 { 3242 src->val->prop_time_benefit = safe_add (time, 3243 src->val->prop_time_benefit); 3244 src->val->prop_size_cost = safe_add (size, 3245 src->val->prop_size_cost); 3246 } 3247 } 3248 } 3249 3250 3251 /* Propagate constants, polymorphic contexts and their effects from the 3252 summaries interprocedurally. */ 3253 3254 static void 3255 ipcp_propagate_stage (struct ipa_topo_info *topo) 3256 { 3257 struct cgraph_node *node; 3258 3259 if (dump_file) 3260 fprintf (dump_file, "\n Propagating constants:\n\n"); 3261 3262 if (in_lto_p) 3263 ipa_update_after_lto_read (); 3264 3265 3266 FOR_EACH_DEFINED_FUNCTION (node) 3267 { 3268 struct ipa_node_params *info = IPA_NODE_REF (node); 3269 3270 determine_versionability (node, info); 3271 if (node->has_gimple_body_p ()) 3272 { 3273 info->lattices = XCNEWVEC (struct ipcp_param_lattices, 3274 ipa_get_param_count (info)); 3275 initialize_node_lattices (node); 3276 } 3277 if (node->definition && !node->alias) 3278 overall_size += inline_summaries->get (node)->self_size; 3279 if (node->count > max_count) 3280 max_count = node->count; 3281 } 3282 3283 max_new_size = overall_size; 3284 if (max_new_size < PARAM_VALUE (PARAM_LARGE_UNIT_INSNS)) 3285 max_new_size = PARAM_VALUE (PARAM_LARGE_UNIT_INSNS); 3286 max_new_size += max_new_size * PARAM_VALUE (PARAM_IPCP_UNIT_GROWTH) / 100 + 1; 3287 3288 if (dump_file) 3289 fprintf (dump_file, "\noverall_size: %li, max_new_size: %li\n", 3290 overall_size, max_new_size); 3291 3292 propagate_constants_topo (topo); 3293 if (flag_checking) 3294 ipcp_verify_propagated_values (); 3295 topo->constants.propagate_effects (); 3296 topo->contexts.propagate_effects (); 3297 3298 if (dump_file) 3299 { 3300 fprintf (dump_file, "\nIPA lattices after all propagation:\n"); 3301 print_all_lattices (dump_file, (dump_flags & TDF_DETAILS), true); 3302 } 3303 } 3304 3305 /* Discover newly direct outgoing edges from NODE which is a new clone with 3306 known KNOWN_CSTS and make them direct. */ 3307 3308 static void 3309 ipcp_discover_new_direct_edges (struct cgraph_node *node, 3310 vec<tree> known_csts, 3311 vec<ipa_polymorphic_call_context> 3312 known_contexts, 3313 struct ipa_agg_replacement_value *aggvals) 3314 { 3315 struct cgraph_edge *ie, *next_ie; 3316 bool found = false; 3317 3318 for (ie = node->indirect_calls; ie; ie = next_ie) 3319 { 3320 tree target; 3321 bool speculative; 3322 3323 next_ie = ie->next_callee; 3324 target = ipa_get_indirect_edge_target_1 (ie, known_csts, known_contexts, 3325 vNULL, aggvals, &speculative); 3326 if (target) 3327 { 3328 bool agg_contents = ie->indirect_info->agg_contents; 3329 bool polymorphic = ie->indirect_info->polymorphic; 3330 int param_index = ie->indirect_info->param_index; 3331 struct cgraph_edge *cs = ipa_make_edge_direct_to_target (ie, target, 3332 speculative); 3333 found = true; 3334 3335 if (cs && !agg_contents && !polymorphic) 3336 { 3337 struct ipa_node_params *info = IPA_NODE_REF (node); 3338 int c = ipa_get_controlled_uses (info, param_index); 3339 if (c != IPA_UNDESCRIBED_USE) 3340 { 3341 struct ipa_ref *to_del; 3342 3343 c--; 3344 ipa_set_controlled_uses (info, param_index, c); 3345 if (dump_file && (dump_flags & TDF_DETAILS)) 3346 fprintf (dump_file, " controlled uses count of param " 3347 "%i bumped down to %i\n", param_index, c); 3348 if (c == 0 3349 && (to_del = node->find_reference (cs->callee, NULL, 0))) 3350 { 3351 if (dump_file && (dump_flags & TDF_DETAILS)) 3352 fprintf (dump_file, " and even removing its " 3353 "cloning-created reference\n"); 3354 to_del->remove_reference (); 3355 } 3356 } 3357 } 3358 } 3359 } 3360 /* Turning calls to direct calls will improve overall summary. */ 3361 if (found) 3362 inline_update_overall_summary (node); 3363 } 3364 3365 /* Vector of pointers which for linked lists of clones of an original crgaph 3366 edge. */ 3367 3368 static vec<cgraph_edge *> next_edge_clone; 3369 static vec<cgraph_edge *> prev_edge_clone; 3370 3371 static inline void 3372 grow_edge_clone_vectors (void) 3373 { 3374 if (next_edge_clone.length () 3375 <= (unsigned) symtab->edges_max_uid) 3376 next_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); 3377 if (prev_edge_clone.length () 3378 <= (unsigned) symtab->edges_max_uid) 3379 prev_edge_clone.safe_grow_cleared (symtab->edges_max_uid + 1); 3380 } 3381 3382 /* Edge duplication hook to grow the appropriate linked list in 3383 next_edge_clone. */ 3384 3385 static void 3386 ipcp_edge_duplication_hook (struct cgraph_edge *src, struct cgraph_edge *dst, 3387 void *) 3388 { 3389 grow_edge_clone_vectors (); 3390 3391 struct cgraph_edge *old_next = next_edge_clone[src->uid]; 3392 if (old_next) 3393 prev_edge_clone[old_next->uid] = dst; 3394 prev_edge_clone[dst->uid] = src; 3395 3396 next_edge_clone[dst->uid] = old_next; 3397 next_edge_clone[src->uid] = dst; 3398 } 3399 3400 /* Hook that is called by cgraph.c when an edge is removed. */ 3401 3402 static void 3403 ipcp_edge_removal_hook (struct cgraph_edge *cs, void *) 3404 { 3405 grow_edge_clone_vectors (); 3406 3407 struct cgraph_edge *prev = prev_edge_clone[cs->uid]; 3408 struct cgraph_edge *next = next_edge_clone[cs->uid]; 3409 if (prev) 3410 next_edge_clone[prev->uid] = next; 3411 if (next) 3412 prev_edge_clone[next->uid] = prev; 3413 } 3414 3415 /* See if NODE is a clone with a known aggregate value at a given OFFSET of a 3416 parameter with the given INDEX. */ 3417 3418 static tree 3419 get_clone_agg_value (struct cgraph_node *node, HOST_WIDE_INT offset, 3420 int index) 3421 { 3422 struct ipa_agg_replacement_value *aggval; 3423 3424 aggval = ipa_get_agg_replacements_for_node (node); 3425 while (aggval) 3426 { 3427 if (aggval->offset == offset 3428 && aggval->index == index) 3429 return aggval->value; 3430 aggval = aggval->next; 3431 } 3432 return NULL_TREE; 3433 } 3434 3435 /* Return true is NODE is DEST or its clone for all contexts. */ 3436 3437 static bool 3438 same_node_or_its_all_contexts_clone_p (cgraph_node *node, cgraph_node *dest) 3439 { 3440 if (node == dest) 3441 return true; 3442 3443 struct ipa_node_params *info = IPA_NODE_REF (node); 3444 return info->is_all_contexts_clone && info->ipcp_orig_node == dest; 3445 } 3446 3447 /* Return true if edge CS does bring about the value described by SRC to node 3448 DEST or its clone for all contexts. */ 3449 3450 static bool 3451 cgraph_edge_brings_value_p (cgraph_edge *cs, ipcp_value_source<tree> *src, 3452 cgraph_node *dest) 3453 { 3454 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 3455 enum availability availability; 3456 cgraph_node *real_dest = cs->callee->function_symbol (&availability); 3457 3458 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) 3459 || availability <= AVAIL_INTERPOSABLE 3460 || caller_info->node_dead) 3461 return false; 3462 if (!src->val) 3463 return true; 3464 3465 if (caller_info->ipcp_orig_node) 3466 { 3467 tree t; 3468 if (src->offset == -1) 3469 t = caller_info->known_csts[src->index]; 3470 else 3471 t = get_clone_agg_value (cs->caller, src->offset, src->index); 3472 return (t != NULL_TREE 3473 && values_equal_for_ipcp_p (src->val->value, t)); 3474 } 3475 else 3476 { 3477 struct ipcp_agg_lattice *aglat; 3478 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, 3479 src->index); 3480 if (src->offset == -1) 3481 return (plats->itself.is_single_const () 3482 && values_equal_for_ipcp_p (src->val->value, 3483 plats->itself.values->value)); 3484 else 3485 { 3486 if (plats->aggs_bottom || plats->aggs_contain_variable) 3487 return false; 3488 for (aglat = plats->aggs; aglat; aglat = aglat->next) 3489 if (aglat->offset == src->offset) 3490 return (aglat->is_single_const () 3491 && values_equal_for_ipcp_p (src->val->value, 3492 aglat->values->value)); 3493 } 3494 return false; 3495 } 3496 } 3497 3498 /* Return true if edge CS does bring about the value described by SRC to node 3499 DEST or its clone for all contexts. */ 3500 3501 static bool 3502 cgraph_edge_brings_value_p (cgraph_edge *cs, 3503 ipcp_value_source<ipa_polymorphic_call_context> *src, 3504 cgraph_node *dest) 3505 { 3506 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 3507 cgraph_node *real_dest = cs->callee->function_symbol (); 3508 3509 if (!same_node_or_its_all_contexts_clone_p (real_dest, dest) 3510 || caller_info->node_dead) 3511 return false; 3512 if (!src->val) 3513 return true; 3514 3515 if (caller_info->ipcp_orig_node) 3516 return (caller_info->known_contexts.length () > (unsigned) src->index) 3517 && values_equal_for_ipcp_p (src->val->value, 3518 caller_info->known_contexts[src->index]); 3519 3520 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (caller_info, 3521 src->index); 3522 return plats->ctxlat.is_single_const () 3523 && values_equal_for_ipcp_p (src->val->value, 3524 plats->ctxlat.values->value); 3525 } 3526 3527 /* Get the next clone in the linked list of clones of an edge. */ 3528 3529 static inline struct cgraph_edge * 3530 get_next_cgraph_edge_clone (struct cgraph_edge *cs) 3531 { 3532 return next_edge_clone[cs->uid]; 3533 } 3534 3535 /* Given VAL that is intended for DEST, iterate over all its sources and if 3536 they still hold, add their edge frequency and their number into *FREQUENCY 3537 and *CALLER_COUNT respectively. */ 3538 3539 template <typename valtype> 3540 static bool 3541 get_info_about_necessary_edges (ipcp_value<valtype> *val, cgraph_node *dest, 3542 int *freq_sum, 3543 gcov_type *count_sum, int *caller_count) 3544 { 3545 ipcp_value_source<valtype> *src; 3546 int freq = 0, count = 0; 3547 gcov_type cnt = 0; 3548 bool hot = false; 3549 3550 for (src = val->sources; src; src = src->next) 3551 { 3552 struct cgraph_edge *cs = src->cs; 3553 while (cs) 3554 { 3555 if (cgraph_edge_brings_value_p (cs, src, dest)) 3556 { 3557 count++; 3558 freq += cs->frequency; 3559 cnt += cs->count; 3560 hot |= cs->maybe_hot_p (); 3561 } 3562 cs = get_next_cgraph_edge_clone (cs); 3563 } 3564 } 3565 3566 *freq_sum = freq; 3567 *count_sum = cnt; 3568 *caller_count = count; 3569 return hot; 3570 } 3571 3572 /* Return a vector of incoming edges that do bring value VAL to node DEST. It 3573 is assumed their number is known and equal to CALLER_COUNT. */ 3574 3575 template <typename valtype> 3576 static vec<cgraph_edge *> 3577 gather_edges_for_value (ipcp_value<valtype> *val, cgraph_node *dest, 3578 int caller_count) 3579 { 3580 ipcp_value_source<valtype> *src; 3581 vec<cgraph_edge *> ret; 3582 3583 ret.create (caller_count); 3584 for (src = val->sources; src; src = src->next) 3585 { 3586 struct cgraph_edge *cs = src->cs; 3587 while (cs) 3588 { 3589 if (cgraph_edge_brings_value_p (cs, src, dest)) 3590 ret.quick_push (cs); 3591 cs = get_next_cgraph_edge_clone (cs); 3592 } 3593 } 3594 3595 return ret; 3596 } 3597 3598 /* Construct a replacement map for a know VALUE for a formal parameter PARAM. 3599 Return it or NULL if for some reason it cannot be created. */ 3600 3601 static struct ipa_replace_map * 3602 get_replacement_map (struct ipa_node_params *info, tree value, int parm_num) 3603 { 3604 struct ipa_replace_map *replace_map; 3605 3606 3607 replace_map = ggc_alloc<ipa_replace_map> (); 3608 if (dump_file) 3609 { 3610 fprintf (dump_file, " replacing "); 3611 ipa_dump_param (dump_file, info, parm_num); 3612 3613 fprintf (dump_file, " with const "); 3614 print_generic_expr (dump_file, value, 0); 3615 fprintf (dump_file, "\n"); 3616 } 3617 replace_map->old_tree = NULL; 3618 replace_map->parm_num = parm_num; 3619 replace_map->new_tree = value; 3620 replace_map->replace_p = true; 3621 replace_map->ref_p = false; 3622 3623 return replace_map; 3624 } 3625 3626 /* Dump new profiling counts */ 3627 3628 static void 3629 dump_profile_updates (struct cgraph_node *orig_node, 3630 struct cgraph_node *new_node) 3631 { 3632 struct cgraph_edge *cs; 3633 3634 fprintf (dump_file, " setting count of the specialized node to " 3635 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) new_node->count); 3636 for (cs = new_node->callees; cs; cs = cs->next_callee) 3637 fprintf (dump_file, " edge to %s has count " 3638 HOST_WIDE_INT_PRINT_DEC "\n", 3639 cs->callee->name (), (HOST_WIDE_INT) cs->count); 3640 3641 fprintf (dump_file, " setting count of the original node to " 3642 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) orig_node->count); 3643 for (cs = orig_node->callees; cs; cs = cs->next_callee) 3644 fprintf (dump_file, " edge to %s is left with " 3645 HOST_WIDE_INT_PRINT_DEC "\n", 3646 cs->callee->name (), (HOST_WIDE_INT) cs->count); 3647 } 3648 3649 /* After a specialized NEW_NODE version of ORIG_NODE has been created, update 3650 their profile information to reflect this. */ 3651 3652 static void 3653 update_profiling_info (struct cgraph_node *orig_node, 3654 struct cgraph_node *new_node) 3655 { 3656 struct cgraph_edge *cs; 3657 struct caller_statistics stats; 3658 gcov_type new_sum, orig_sum; 3659 gcov_type remainder, orig_node_count = orig_node->count; 3660 3661 if (orig_node_count == 0) 3662 return; 3663 3664 init_caller_stats (&stats); 3665 orig_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, 3666 false); 3667 orig_sum = stats.count_sum; 3668 init_caller_stats (&stats); 3669 new_node->call_for_symbol_thunks_and_aliases (gather_caller_stats, &stats, 3670 false); 3671 new_sum = stats.count_sum; 3672 3673 if (orig_node_count < orig_sum + new_sum) 3674 { 3675 if (dump_file) 3676 fprintf (dump_file, " Problem: node %s/%i has too low count " 3677 HOST_WIDE_INT_PRINT_DEC " while the sum of incoming " 3678 "counts is " HOST_WIDE_INT_PRINT_DEC "\n", 3679 orig_node->name (), orig_node->order, 3680 (HOST_WIDE_INT) orig_node_count, 3681 (HOST_WIDE_INT) (orig_sum + new_sum)); 3682 3683 orig_node_count = (orig_sum + new_sum) * 12 / 10; 3684 if (dump_file) 3685 fprintf (dump_file, " proceeding by pretending it was " 3686 HOST_WIDE_INT_PRINT_DEC "\n", 3687 (HOST_WIDE_INT) orig_node_count); 3688 } 3689 3690 new_node->count = new_sum; 3691 remainder = orig_node_count - new_sum; 3692 orig_node->count = remainder; 3693 3694 for (cs = new_node->callees; cs; cs = cs->next_callee) 3695 if (cs->frequency) 3696 cs->count = apply_probability (cs->count, 3697 GCOV_COMPUTE_SCALE (new_sum, 3698 orig_node_count)); 3699 else 3700 cs->count = 0; 3701 3702 for (cs = orig_node->callees; cs; cs = cs->next_callee) 3703 cs->count = apply_probability (cs->count, 3704 GCOV_COMPUTE_SCALE (remainder, 3705 orig_node_count)); 3706 3707 if (dump_file) 3708 dump_profile_updates (orig_node, new_node); 3709 } 3710 3711 /* Update the respective profile of specialized NEW_NODE and the original 3712 ORIG_NODE after additional edges with cumulative count sum REDIRECTED_SUM 3713 have been redirected to the specialized version. */ 3714 3715 static void 3716 update_specialized_profile (struct cgraph_node *new_node, 3717 struct cgraph_node *orig_node, 3718 gcov_type redirected_sum) 3719 { 3720 struct cgraph_edge *cs; 3721 gcov_type new_node_count, orig_node_count = orig_node->count; 3722 3723 if (dump_file) 3724 fprintf (dump_file, " the sum of counts of redirected edges is " 3725 HOST_WIDE_INT_PRINT_DEC "\n", (HOST_WIDE_INT) redirected_sum); 3726 if (orig_node_count == 0) 3727 return; 3728 3729 gcc_assert (orig_node_count >= redirected_sum); 3730 3731 new_node_count = new_node->count; 3732 new_node->count += redirected_sum; 3733 orig_node->count -= redirected_sum; 3734 3735 for (cs = new_node->callees; cs; cs = cs->next_callee) 3736 if (cs->frequency) 3737 cs->count += apply_probability (cs->count, 3738 GCOV_COMPUTE_SCALE (redirected_sum, 3739 new_node_count)); 3740 else 3741 cs->count = 0; 3742 3743 for (cs = orig_node->callees; cs; cs = cs->next_callee) 3744 { 3745 gcov_type dec = apply_probability (cs->count, 3746 GCOV_COMPUTE_SCALE (redirected_sum, 3747 orig_node_count)); 3748 if (dec < cs->count) 3749 cs->count -= dec; 3750 else 3751 cs->count = 0; 3752 } 3753 3754 if (dump_file) 3755 dump_profile_updates (orig_node, new_node); 3756 } 3757 3758 /* Create a specialized version of NODE with known constants in KNOWN_CSTS, 3759 known contexts in KNOWN_CONTEXTS and known aggregate values in AGGVALS and 3760 redirect all edges in CALLERS to it. */ 3761 3762 static struct cgraph_node * 3763 create_specialized_node (struct cgraph_node *node, 3764 vec<tree> known_csts, 3765 vec<ipa_polymorphic_call_context> known_contexts, 3766 struct ipa_agg_replacement_value *aggvals, 3767 vec<cgraph_edge *> callers) 3768 { 3769 struct ipa_node_params *new_info, *info = IPA_NODE_REF (node); 3770 vec<ipa_replace_map *, va_gc> *replace_trees = NULL; 3771 struct ipa_agg_replacement_value *av; 3772 struct cgraph_node *new_node; 3773 int i, count = ipa_get_param_count (info); 3774 bitmap args_to_skip; 3775 3776 gcc_assert (!info->ipcp_orig_node); 3777 3778 if (node->local.can_change_signature) 3779 { 3780 args_to_skip = BITMAP_GGC_ALLOC (); 3781 for (i = 0; i < count; i++) 3782 { 3783 tree t = known_csts[i]; 3784 3785 if (t || !ipa_is_param_used (info, i)) 3786 bitmap_set_bit (args_to_skip, i); 3787 } 3788 } 3789 else 3790 { 3791 args_to_skip = NULL; 3792 if (dump_file && (dump_flags & TDF_DETAILS)) 3793 fprintf (dump_file, " cannot change function signature\n"); 3794 } 3795 3796 for (i = 0; i < count; i++) 3797 { 3798 tree t = known_csts[i]; 3799 if (t) 3800 { 3801 struct ipa_replace_map *replace_map; 3802 3803 gcc_checking_assert (TREE_CODE (t) != TREE_BINFO); 3804 replace_map = get_replacement_map (info, t, i); 3805 if (replace_map) 3806 vec_safe_push (replace_trees, replace_map); 3807 } 3808 } 3809 3810 new_node = node->create_virtual_clone (callers, replace_trees, 3811 args_to_skip, "constprop"); 3812 ipa_set_node_agg_value_chain (new_node, aggvals); 3813 for (av = aggvals; av; av = av->next) 3814 new_node->maybe_create_reference (av->value, NULL); 3815 3816 if (dump_file && (dump_flags & TDF_DETAILS)) 3817 { 3818 fprintf (dump_file, " the new node is %s/%i.\n", 3819 new_node->name (), new_node->order); 3820 if (known_contexts.exists ()) 3821 { 3822 for (i = 0; i < count; i++) 3823 if (!known_contexts[i].useless_p ()) 3824 { 3825 fprintf (dump_file, " known ctx %i is ", i); 3826 known_contexts[i].dump (dump_file); 3827 } 3828 } 3829 if (aggvals) 3830 ipa_dump_agg_replacement_values (dump_file, aggvals); 3831 } 3832 ipa_check_create_node_params (); 3833 update_profiling_info (node, new_node); 3834 new_info = IPA_NODE_REF (new_node); 3835 new_info->ipcp_orig_node = node; 3836 new_info->known_csts = known_csts; 3837 new_info->known_contexts = known_contexts; 3838 3839 ipcp_discover_new_direct_edges (new_node, known_csts, known_contexts, aggvals); 3840 3841 callers.release (); 3842 return new_node; 3843 } 3844 3845 /* Given a NODE, and a subset of its CALLERS, try to populate blanks slots in 3846 KNOWN_CSTS with constants that are also known for all of the CALLERS. */ 3847 3848 static void 3849 find_more_scalar_values_for_callers_subset (struct cgraph_node *node, 3850 vec<tree> known_csts, 3851 vec<cgraph_edge *> callers) 3852 { 3853 struct ipa_node_params *info = IPA_NODE_REF (node); 3854 int i, count = ipa_get_param_count (info); 3855 3856 for (i = 0; i < count; i++) 3857 { 3858 struct cgraph_edge *cs; 3859 tree newval = NULL_TREE; 3860 int j; 3861 bool first = true; 3862 3863 if (ipa_get_scalar_lat (info, i)->bottom || known_csts[i]) 3864 continue; 3865 3866 FOR_EACH_VEC_ELT (callers, j, cs) 3867 { 3868 struct ipa_jump_func *jump_func; 3869 tree t; 3870 3871 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs)) 3872 || (i == 0 3873 && call_passes_through_thunk_p (cs)) 3874 || (!cs->callee->instrumentation_clone 3875 && cs->callee->function_symbol ()->instrumentation_clone)) 3876 { 3877 newval = NULL_TREE; 3878 break; 3879 } 3880 jump_func = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), i); 3881 t = ipa_value_from_jfunc (IPA_NODE_REF (cs->caller), jump_func); 3882 if (!t 3883 || (newval 3884 && !values_equal_for_ipcp_p (t, newval)) 3885 || (!first && !newval)) 3886 { 3887 newval = NULL_TREE; 3888 break; 3889 } 3890 else 3891 newval = t; 3892 first = false; 3893 } 3894 3895 if (newval) 3896 { 3897 if (dump_file && (dump_flags & TDF_DETAILS)) 3898 { 3899 fprintf (dump_file, " adding an extra known scalar value "); 3900 print_ipcp_constant_value (dump_file, newval); 3901 fprintf (dump_file, " for "); 3902 ipa_dump_param (dump_file, info, i); 3903 fprintf (dump_file, "\n"); 3904 } 3905 3906 known_csts[i] = newval; 3907 } 3908 } 3909 } 3910 3911 /* Given a NODE and a subset of its CALLERS, try to populate plank slots in 3912 KNOWN_CONTEXTS with polymorphic contexts that are also known for all of the 3913 CALLERS. */ 3914 3915 static void 3916 find_more_contexts_for_caller_subset (cgraph_node *node, 3917 vec<ipa_polymorphic_call_context> 3918 *known_contexts, 3919 vec<cgraph_edge *> callers) 3920 { 3921 ipa_node_params *info = IPA_NODE_REF (node); 3922 int i, count = ipa_get_param_count (info); 3923 3924 for (i = 0; i < count; i++) 3925 { 3926 cgraph_edge *cs; 3927 3928 if (ipa_get_poly_ctx_lat (info, i)->bottom 3929 || (known_contexts->exists () 3930 && !(*known_contexts)[i].useless_p ())) 3931 continue; 3932 3933 ipa_polymorphic_call_context newval; 3934 bool first = true; 3935 int j; 3936 3937 FOR_EACH_VEC_ELT (callers, j, cs) 3938 { 3939 if (i >= ipa_get_cs_argument_count (IPA_EDGE_REF (cs))) 3940 return; 3941 ipa_jump_func *jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), 3942 i); 3943 ipa_polymorphic_call_context ctx; 3944 ctx = ipa_context_from_jfunc (IPA_NODE_REF (cs->caller), cs, i, 3945 jfunc); 3946 if (first) 3947 { 3948 newval = ctx; 3949 first = false; 3950 } 3951 else 3952 newval.meet_with (ctx); 3953 if (newval.useless_p ()) 3954 break; 3955 } 3956 3957 if (!newval.useless_p ()) 3958 { 3959 if (dump_file && (dump_flags & TDF_DETAILS)) 3960 { 3961 fprintf (dump_file, " adding an extra known polymorphic " 3962 "context "); 3963 print_ipcp_constant_value (dump_file, newval); 3964 fprintf (dump_file, " for "); 3965 ipa_dump_param (dump_file, info, i); 3966 fprintf (dump_file, "\n"); 3967 } 3968 3969 if (!known_contexts->exists ()) 3970 known_contexts->safe_grow_cleared (ipa_get_param_count (info)); 3971 (*known_contexts)[i] = newval; 3972 } 3973 3974 } 3975 } 3976 3977 /* Go through PLATS and create a vector of values consisting of values and 3978 offsets (minus OFFSET) of lattices that contain only a single value. */ 3979 3980 static vec<ipa_agg_jf_item> 3981 copy_plats_to_inter (struct ipcp_param_lattices *plats, HOST_WIDE_INT offset) 3982 { 3983 vec<ipa_agg_jf_item> res = vNULL; 3984 3985 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) 3986 return vNULL; 3987 3988 for (struct ipcp_agg_lattice *aglat = plats->aggs; aglat; aglat = aglat->next) 3989 if (aglat->is_single_const ()) 3990 { 3991 struct ipa_agg_jf_item ti; 3992 ti.offset = aglat->offset - offset; 3993 ti.value = aglat->values->value; 3994 res.safe_push (ti); 3995 } 3996 return res; 3997 } 3998 3999 /* Intersect all values in INTER with single value lattices in PLATS (while 4000 subtracting OFFSET). */ 4001 4002 static void 4003 intersect_with_plats (struct ipcp_param_lattices *plats, 4004 vec<ipa_agg_jf_item> *inter, 4005 HOST_WIDE_INT offset) 4006 { 4007 struct ipcp_agg_lattice *aglat; 4008 struct ipa_agg_jf_item *item; 4009 int k; 4010 4011 if (!plats->aggs || plats->aggs_contain_variable || plats->aggs_bottom) 4012 { 4013 inter->release (); 4014 return; 4015 } 4016 4017 aglat = plats->aggs; 4018 FOR_EACH_VEC_ELT (*inter, k, item) 4019 { 4020 bool found = false; 4021 if (!item->value) 4022 continue; 4023 while (aglat) 4024 { 4025 if (aglat->offset - offset > item->offset) 4026 break; 4027 if (aglat->offset - offset == item->offset) 4028 { 4029 gcc_checking_assert (item->value); 4030 if (aglat->is_single_const () 4031 && values_equal_for_ipcp_p (item->value, 4032 aglat->values->value)) 4033 found = true; 4034 break; 4035 } 4036 aglat = aglat->next; 4037 } 4038 if (!found) 4039 item->value = NULL_TREE; 4040 } 4041 } 4042 4043 /* Copy aggregate replacement values of NODE (which is an IPA-CP clone) to the 4044 vector result while subtracting OFFSET from the individual value offsets. */ 4045 4046 static vec<ipa_agg_jf_item> 4047 agg_replacements_to_vector (struct cgraph_node *node, int index, 4048 HOST_WIDE_INT offset) 4049 { 4050 struct ipa_agg_replacement_value *av; 4051 vec<ipa_agg_jf_item> res = vNULL; 4052 4053 for (av = ipa_get_agg_replacements_for_node (node); av; av = av->next) 4054 if (av->index == index 4055 && (av->offset - offset) >= 0) 4056 { 4057 struct ipa_agg_jf_item item; 4058 gcc_checking_assert (av->value); 4059 item.offset = av->offset - offset; 4060 item.value = av->value; 4061 res.safe_push (item); 4062 } 4063 4064 return res; 4065 } 4066 4067 /* Intersect all values in INTER with those that we have already scheduled to 4068 be replaced in parameter number INDEX of NODE, which is an IPA-CP clone 4069 (while subtracting OFFSET). */ 4070 4071 static void 4072 intersect_with_agg_replacements (struct cgraph_node *node, int index, 4073 vec<ipa_agg_jf_item> *inter, 4074 HOST_WIDE_INT offset) 4075 { 4076 struct ipa_agg_replacement_value *srcvals; 4077 struct ipa_agg_jf_item *item; 4078 int i; 4079 4080 srcvals = ipa_get_agg_replacements_for_node (node); 4081 if (!srcvals) 4082 { 4083 inter->release (); 4084 return; 4085 } 4086 4087 FOR_EACH_VEC_ELT (*inter, i, item) 4088 { 4089 struct ipa_agg_replacement_value *av; 4090 bool found = false; 4091 if (!item->value) 4092 continue; 4093 for (av = srcvals; av; av = av->next) 4094 { 4095 gcc_checking_assert (av->value); 4096 if (av->index == index 4097 && av->offset - offset == item->offset) 4098 { 4099 if (values_equal_for_ipcp_p (item->value, av->value)) 4100 found = true; 4101 break; 4102 } 4103 } 4104 if (!found) 4105 item->value = NULL_TREE; 4106 } 4107 } 4108 4109 /* Intersect values in INTER with aggregate values that come along edge CS to 4110 parameter number INDEX and return it. If INTER does not actually exist yet, 4111 copy all incoming values to it. If we determine we ended up with no values 4112 whatsoever, return a released vector. */ 4113 4114 static vec<ipa_agg_jf_item> 4115 intersect_aggregates_with_edge (struct cgraph_edge *cs, int index, 4116 vec<ipa_agg_jf_item> inter) 4117 { 4118 struct ipa_jump_func *jfunc; 4119 jfunc = ipa_get_ith_jump_func (IPA_EDGE_REF (cs), index); 4120 if (jfunc->type == IPA_JF_PASS_THROUGH 4121 && ipa_get_jf_pass_through_operation (jfunc) == NOP_EXPR) 4122 { 4123 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 4124 int src_idx = ipa_get_jf_pass_through_formal_id (jfunc); 4125 4126 if (caller_info->ipcp_orig_node) 4127 { 4128 struct cgraph_node *orig_node = caller_info->ipcp_orig_node; 4129 struct ipcp_param_lattices *orig_plats; 4130 orig_plats = ipa_get_parm_lattices (IPA_NODE_REF (orig_node), 4131 src_idx); 4132 if (agg_pass_through_permissible_p (orig_plats, jfunc)) 4133 { 4134 if (!inter.exists ()) 4135 inter = agg_replacements_to_vector (cs->caller, src_idx, 0); 4136 else 4137 intersect_with_agg_replacements (cs->caller, src_idx, 4138 &inter, 0); 4139 } 4140 else 4141 { 4142 inter.release (); 4143 return vNULL; 4144 } 4145 } 4146 else 4147 { 4148 struct ipcp_param_lattices *src_plats; 4149 src_plats = ipa_get_parm_lattices (caller_info, src_idx); 4150 if (agg_pass_through_permissible_p (src_plats, jfunc)) 4151 { 4152 /* Currently we do not produce clobber aggregate jump 4153 functions, adjust when we do. */ 4154 gcc_checking_assert (!jfunc->agg.items); 4155 if (!inter.exists ()) 4156 inter = copy_plats_to_inter (src_plats, 0); 4157 else 4158 intersect_with_plats (src_plats, &inter, 0); 4159 } 4160 else 4161 { 4162 inter.release (); 4163 return vNULL; 4164 } 4165 } 4166 } 4167 else if (jfunc->type == IPA_JF_ANCESTOR 4168 && ipa_get_jf_ancestor_agg_preserved (jfunc)) 4169 { 4170 struct ipa_node_params *caller_info = IPA_NODE_REF (cs->caller); 4171 int src_idx = ipa_get_jf_ancestor_formal_id (jfunc); 4172 struct ipcp_param_lattices *src_plats; 4173 HOST_WIDE_INT delta = ipa_get_jf_ancestor_offset (jfunc); 4174 4175 if (caller_info->ipcp_orig_node) 4176 { 4177 if (!inter.exists ()) 4178 inter = agg_replacements_to_vector (cs->caller, src_idx, delta); 4179 else 4180 intersect_with_agg_replacements (cs->caller, src_idx, &inter, 4181 delta); 4182 } 4183 else 4184 { 4185 src_plats = ipa_get_parm_lattices (caller_info, src_idx);; 4186 /* Currently we do not produce clobber aggregate jump 4187 functions, adjust when we do. */ 4188 gcc_checking_assert (!src_plats->aggs || !jfunc->agg.items); 4189 if (!inter.exists ()) 4190 inter = copy_plats_to_inter (src_plats, delta); 4191 else 4192 intersect_with_plats (src_plats, &inter, delta); 4193 } 4194 } 4195 else if (jfunc->agg.items) 4196 { 4197 struct ipa_agg_jf_item *item; 4198 int k; 4199 4200 if (!inter.exists ()) 4201 for (unsigned i = 0; i < jfunc->agg.items->length (); i++) 4202 inter.safe_push ((*jfunc->agg.items)[i]); 4203 else 4204 FOR_EACH_VEC_ELT (inter, k, item) 4205 { 4206 int l = 0; 4207 bool found = false;; 4208 4209 if (!item->value) 4210 continue; 4211 4212 while ((unsigned) l < jfunc->agg.items->length ()) 4213 { 4214 struct ipa_agg_jf_item *ti; 4215 ti = &(*jfunc->agg.items)[l]; 4216 if (ti->offset > item->offset) 4217 break; 4218 if (ti->offset == item->offset) 4219 { 4220 gcc_checking_assert (ti->value); 4221 if (values_equal_for_ipcp_p (item->value, 4222 ti->value)) 4223 found = true; 4224 break; 4225 } 4226 l++; 4227 } 4228 if (!found) 4229 item->value = NULL; 4230 } 4231 } 4232 else 4233 { 4234 inter.release (); 4235 return vec<ipa_agg_jf_item>(); 4236 } 4237 return inter; 4238 } 4239 4240 /* Look at edges in CALLERS and collect all known aggregate values that arrive 4241 from all of them. */ 4242 4243 static struct ipa_agg_replacement_value * 4244 find_aggregate_values_for_callers_subset (struct cgraph_node *node, 4245 vec<cgraph_edge *> callers) 4246 { 4247 struct ipa_node_params *dest_info = IPA_NODE_REF (node); 4248 struct ipa_agg_replacement_value *res; 4249 struct ipa_agg_replacement_value **tail = &res; 4250 struct cgraph_edge *cs; 4251 int i, j, count = ipa_get_param_count (dest_info); 4252 4253 FOR_EACH_VEC_ELT (callers, j, cs) 4254 { 4255 int c = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); 4256 if (c < count) 4257 count = c; 4258 } 4259 4260 for (i = 0; i < count; i++) 4261 { 4262 struct cgraph_edge *cs; 4263 vec<ipa_agg_jf_item> inter = vNULL; 4264 struct ipa_agg_jf_item *item; 4265 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (dest_info, i); 4266 int j; 4267 4268 /* Among other things, the following check should deal with all by_ref 4269 mismatches. */ 4270 if (plats->aggs_bottom) 4271 continue; 4272 4273 FOR_EACH_VEC_ELT (callers, j, cs) 4274 { 4275 inter = intersect_aggregates_with_edge (cs, i, inter); 4276 4277 if (!inter.exists ()) 4278 goto next_param; 4279 } 4280 4281 FOR_EACH_VEC_ELT (inter, j, item) 4282 { 4283 struct ipa_agg_replacement_value *v; 4284 4285 if (!item->value) 4286 continue; 4287 4288 v = ggc_alloc<ipa_agg_replacement_value> (); 4289 v->index = i; 4290 v->offset = item->offset; 4291 v->value = item->value; 4292 v->by_ref = plats->aggs_by_ref; 4293 *tail = v; 4294 tail = &v->next; 4295 } 4296 4297 next_param: 4298 if (inter.exists ()) 4299 inter.release (); 4300 } 4301 *tail = NULL; 4302 return res; 4303 } 4304 4305 /* Turn KNOWN_AGGS into a list of aggregate replacement values. */ 4306 4307 static struct ipa_agg_replacement_value * 4308 known_aggs_to_agg_replacement_list (vec<ipa_agg_jump_function> known_aggs) 4309 { 4310 struct ipa_agg_replacement_value *res; 4311 struct ipa_agg_replacement_value **tail = &res; 4312 struct ipa_agg_jump_function *aggjf; 4313 struct ipa_agg_jf_item *item; 4314 int i, j; 4315 4316 FOR_EACH_VEC_ELT (known_aggs, i, aggjf) 4317 FOR_EACH_VEC_SAFE_ELT (aggjf->items, j, item) 4318 { 4319 struct ipa_agg_replacement_value *v; 4320 v = ggc_alloc<ipa_agg_replacement_value> (); 4321 v->index = i; 4322 v->offset = item->offset; 4323 v->value = item->value; 4324 v->by_ref = aggjf->by_ref; 4325 *tail = v; 4326 tail = &v->next; 4327 } 4328 *tail = NULL; 4329 return res; 4330 } 4331 4332 /* Determine whether CS also brings all scalar values that the NODE is 4333 specialized for. */ 4334 4335 static bool 4336 cgraph_edge_brings_all_scalars_for_node (struct cgraph_edge *cs, 4337 struct cgraph_node *node) 4338 { 4339 struct ipa_node_params *dest_info = IPA_NODE_REF (node); 4340 int count = ipa_get_param_count (dest_info); 4341 struct ipa_node_params *caller_info; 4342 struct ipa_edge_args *args; 4343 int i; 4344 4345 caller_info = IPA_NODE_REF (cs->caller); 4346 args = IPA_EDGE_REF (cs); 4347 for (i = 0; i < count; i++) 4348 { 4349 struct ipa_jump_func *jump_func; 4350 tree val, t; 4351 4352 val = dest_info->known_csts[i]; 4353 if (!val) 4354 continue; 4355 4356 if (i >= ipa_get_cs_argument_count (args)) 4357 return false; 4358 jump_func = ipa_get_ith_jump_func (args, i); 4359 t = ipa_value_from_jfunc (caller_info, jump_func); 4360 if (!t || !values_equal_for_ipcp_p (val, t)) 4361 return false; 4362 } 4363 return true; 4364 } 4365 4366 /* Determine whether CS also brings all aggregate values that NODE is 4367 specialized for. */ 4368 static bool 4369 cgraph_edge_brings_all_agg_vals_for_node (struct cgraph_edge *cs, 4370 struct cgraph_node *node) 4371 { 4372 struct ipa_node_params *orig_caller_info = IPA_NODE_REF (cs->caller); 4373 struct ipa_node_params *orig_node_info; 4374 struct ipa_agg_replacement_value *aggval; 4375 int i, ec, count; 4376 4377 aggval = ipa_get_agg_replacements_for_node (node); 4378 if (!aggval) 4379 return true; 4380 4381 count = ipa_get_param_count (IPA_NODE_REF (node)); 4382 ec = ipa_get_cs_argument_count (IPA_EDGE_REF (cs)); 4383 if (ec < count) 4384 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) 4385 if (aggval->index >= ec) 4386 return false; 4387 4388 orig_node_info = IPA_NODE_REF (IPA_NODE_REF (node)->ipcp_orig_node); 4389 if (orig_caller_info->ipcp_orig_node) 4390 orig_caller_info = IPA_NODE_REF (orig_caller_info->ipcp_orig_node); 4391 4392 for (i = 0; i < count; i++) 4393 { 4394 static vec<ipa_agg_jf_item> values = vec<ipa_agg_jf_item>(); 4395 struct ipcp_param_lattices *plats; 4396 bool interesting = false; 4397 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) 4398 if (aggval->index == i) 4399 { 4400 interesting = true; 4401 break; 4402 } 4403 if (!interesting) 4404 continue; 4405 4406 plats = ipa_get_parm_lattices (orig_node_info, aggval->index); 4407 if (plats->aggs_bottom) 4408 return false; 4409 4410 values = intersect_aggregates_with_edge (cs, i, values); 4411 if (!values.exists ()) 4412 return false; 4413 4414 for (struct ipa_agg_replacement_value *av = aggval; av; av = av->next) 4415 if (aggval->index == i) 4416 { 4417 struct ipa_agg_jf_item *item; 4418 int j; 4419 bool found = false; 4420 FOR_EACH_VEC_ELT (values, j, item) 4421 if (item->value 4422 && item->offset == av->offset 4423 && values_equal_for_ipcp_p (item->value, av->value)) 4424 { 4425 found = true; 4426 break; 4427 } 4428 if (!found) 4429 { 4430 values.release (); 4431 return false; 4432 } 4433 } 4434 } 4435 return true; 4436 } 4437 4438 /* Given an original NODE and a VAL for which we have already created a 4439 specialized clone, look whether there are incoming edges that still lead 4440 into the old node but now also bring the requested value and also conform to 4441 all other criteria such that they can be redirected the special node. 4442 This function can therefore redirect the final edge in a SCC. */ 4443 4444 template <typename valtype> 4445 static void 4446 perhaps_add_new_callers (cgraph_node *node, ipcp_value<valtype> *val) 4447 { 4448 ipcp_value_source<valtype> *src; 4449 gcov_type redirected_sum = 0; 4450 4451 for (src = val->sources; src; src = src->next) 4452 { 4453 struct cgraph_edge *cs = src->cs; 4454 while (cs) 4455 { 4456 if (cgraph_edge_brings_value_p (cs, src, node) 4457 && cgraph_edge_brings_all_scalars_for_node (cs, val->spec_node) 4458 && cgraph_edge_brings_all_agg_vals_for_node (cs, val->spec_node)) 4459 { 4460 if (dump_file) 4461 fprintf (dump_file, " - adding an extra caller %s/%i" 4462 " of %s/%i\n", 4463 xstrdup_for_dump (cs->caller->name ()), 4464 cs->caller->order, 4465 xstrdup_for_dump (val->spec_node->name ()), 4466 val->spec_node->order); 4467 4468 cs->redirect_callee_duplicating_thunks (val->spec_node); 4469 val->spec_node->expand_all_artificial_thunks (); 4470 redirected_sum += cs->count; 4471 } 4472 cs = get_next_cgraph_edge_clone (cs); 4473 } 4474 } 4475 4476 if (redirected_sum) 4477 update_specialized_profile (val->spec_node, node, redirected_sum); 4478 } 4479 4480 /* Return true if KNOWN_CONTEXTS contain at least one useful context. */ 4481 4482 static bool 4483 known_contexts_useful_p (vec<ipa_polymorphic_call_context> known_contexts) 4484 { 4485 ipa_polymorphic_call_context *ctx; 4486 int i; 4487 4488 FOR_EACH_VEC_ELT (known_contexts, i, ctx) 4489 if (!ctx->useless_p ()) 4490 return true; 4491 return false; 4492 } 4493 4494 /* Return a copy of KNOWN_CSTS if it is not empty, otherwise return vNULL. */ 4495 4496 static vec<ipa_polymorphic_call_context> 4497 copy_useful_known_contexts (vec<ipa_polymorphic_call_context> known_contexts) 4498 { 4499 if (known_contexts_useful_p (known_contexts)) 4500 return known_contexts.copy (); 4501 else 4502 return vNULL; 4503 } 4504 4505 /* Copy KNOWN_CSTS and modify the copy according to VAL and INDEX. If 4506 non-empty, replace KNOWN_CONTEXTS with its copy too. */ 4507 4508 static void 4509 modify_known_vectors_with_val (vec<tree> *known_csts, 4510 vec<ipa_polymorphic_call_context> *known_contexts, 4511 ipcp_value<tree> *val, 4512 int index) 4513 { 4514 *known_csts = known_csts->copy (); 4515 *known_contexts = copy_useful_known_contexts (*known_contexts); 4516 (*known_csts)[index] = val->value; 4517 } 4518 4519 /* Replace KNOWN_CSTS with its copy. Also copy KNOWN_CONTEXTS and modify the 4520 copy according to VAL and INDEX. */ 4521 4522 static void 4523 modify_known_vectors_with_val (vec<tree> *known_csts, 4524 vec<ipa_polymorphic_call_context> *known_contexts, 4525 ipcp_value<ipa_polymorphic_call_context> *val, 4526 int index) 4527 { 4528 *known_csts = known_csts->copy (); 4529 *known_contexts = known_contexts->copy (); 4530 (*known_contexts)[index] = val->value; 4531 } 4532 4533 /* Return true if OFFSET indicates this was not an aggregate value or there is 4534 a replacement equivalent to VALUE, INDEX and OFFSET among those in the 4535 AGGVALS list. */ 4536 4537 DEBUG_FUNCTION bool 4538 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *aggvals, 4539 int index, HOST_WIDE_INT offset, tree value) 4540 { 4541 if (offset == -1) 4542 return true; 4543 4544 while (aggvals) 4545 { 4546 if (aggvals->index == index 4547 && aggvals->offset == offset 4548 && values_equal_for_ipcp_p (aggvals->value, value)) 4549 return true; 4550 aggvals = aggvals->next; 4551 } 4552 return false; 4553 } 4554 4555 /* Return true if offset is minus one because source of a polymorphic contect 4556 cannot be an aggregate value. */ 4557 4558 DEBUG_FUNCTION bool 4559 ipcp_val_agg_replacement_ok_p (ipa_agg_replacement_value *, 4560 int , HOST_WIDE_INT offset, 4561 ipa_polymorphic_call_context) 4562 { 4563 return offset == -1; 4564 } 4565 4566 /* Decide wheter to create a special version of NODE for value VAL of parameter 4567 at the given INDEX. If OFFSET is -1, the value is for the parameter itself, 4568 otherwise it is stored at the given OFFSET of the parameter. KNOWN_CSTS, 4569 KNOWN_CONTEXTS and KNOWN_AGGS describe the other already known values. */ 4570 4571 template <typename valtype> 4572 static bool 4573 decide_about_value (struct cgraph_node *node, int index, HOST_WIDE_INT offset, 4574 ipcp_value<valtype> *val, vec<tree> known_csts, 4575 vec<ipa_polymorphic_call_context> known_contexts) 4576 { 4577 struct ipa_agg_replacement_value *aggvals; 4578 int freq_sum, caller_count; 4579 gcov_type count_sum; 4580 vec<cgraph_edge *> callers; 4581 4582 if (val->spec_node) 4583 { 4584 perhaps_add_new_callers (node, val); 4585 return false; 4586 } 4587 else if (val->local_size_cost + overall_size > max_new_size) 4588 { 4589 if (dump_file && (dump_flags & TDF_DETAILS)) 4590 fprintf (dump_file, " Ignoring candidate value because " 4591 "max_new_size would be reached with %li.\n", 4592 val->local_size_cost + overall_size); 4593 return false; 4594 } 4595 else if (!get_info_about_necessary_edges (val, node, &freq_sum, &count_sum, 4596 &caller_count)) 4597 return false; 4598 4599 if (dump_file && (dump_flags & TDF_DETAILS)) 4600 { 4601 fprintf (dump_file, " - considering value "); 4602 print_ipcp_constant_value (dump_file, val->value); 4603 fprintf (dump_file, " for "); 4604 ipa_dump_param (dump_file, IPA_NODE_REF (node), index); 4605 if (offset != -1) 4606 fprintf (dump_file, ", offset: " HOST_WIDE_INT_PRINT_DEC, offset); 4607 fprintf (dump_file, " (caller_count: %i)\n", caller_count); 4608 } 4609 4610 if (!good_cloning_opportunity_p (node, val->local_time_benefit, 4611 freq_sum, count_sum, 4612 val->local_size_cost) 4613 && !good_cloning_opportunity_p (node, 4614 val->local_time_benefit 4615 + val->prop_time_benefit, 4616 freq_sum, count_sum, 4617 val->local_size_cost 4618 + val->prop_size_cost)) 4619 return false; 4620 4621 if (dump_file) 4622 fprintf (dump_file, " Creating a specialized node of %s/%i.\n", 4623 node->name (), node->order); 4624 4625 callers = gather_edges_for_value (val, node, caller_count); 4626 if (offset == -1) 4627 modify_known_vectors_with_val (&known_csts, &known_contexts, val, index); 4628 else 4629 { 4630 known_csts = known_csts.copy (); 4631 known_contexts = copy_useful_known_contexts (known_contexts); 4632 } 4633 find_more_scalar_values_for_callers_subset (node, known_csts, callers); 4634 find_more_contexts_for_caller_subset (node, &known_contexts, callers); 4635 aggvals = find_aggregate_values_for_callers_subset (node, callers); 4636 gcc_checking_assert (ipcp_val_agg_replacement_ok_p (aggvals, index, 4637 offset, val->value)); 4638 val->spec_node = create_specialized_node (node, known_csts, known_contexts, 4639 aggvals, callers); 4640 overall_size += val->local_size_cost; 4641 4642 /* TODO: If for some lattice there is only one other known value 4643 left, make a special node for it too. */ 4644 4645 return true; 4646 } 4647 4648 /* Decide whether and what specialized clones of NODE should be created. */ 4649 4650 static bool 4651 decide_whether_version_node (struct cgraph_node *node) 4652 { 4653 struct ipa_node_params *info = IPA_NODE_REF (node); 4654 int i, count = ipa_get_param_count (info); 4655 vec<tree> known_csts; 4656 vec<ipa_polymorphic_call_context> known_contexts; 4657 vec<ipa_agg_jump_function> known_aggs = vNULL; 4658 bool ret = false; 4659 4660 if (count == 0) 4661 return false; 4662 4663 if (dump_file && (dump_flags & TDF_DETAILS)) 4664 fprintf (dump_file, "\nEvaluating opportunities for %s/%i.\n", 4665 node->name (), node->order); 4666 4667 gather_context_independent_values (info, &known_csts, &known_contexts, 4668 info->do_clone_for_all_contexts ? &known_aggs 4669 : NULL, NULL); 4670 4671 for (i = 0; i < count;i++) 4672 { 4673 struct ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 4674 ipcp_lattice<tree> *lat = &plats->itself; 4675 ipcp_lattice<ipa_polymorphic_call_context> *ctxlat = &plats->ctxlat; 4676 4677 if (!lat->bottom 4678 && !known_csts[i]) 4679 { 4680 ipcp_value<tree> *val; 4681 for (val = lat->values; val; val = val->next) 4682 ret |= decide_about_value (node, i, -1, val, known_csts, 4683 known_contexts); 4684 } 4685 4686 if (!plats->aggs_bottom) 4687 { 4688 struct ipcp_agg_lattice *aglat; 4689 ipcp_value<tree> *val; 4690 for (aglat = plats->aggs; aglat; aglat = aglat->next) 4691 if (!aglat->bottom && aglat->values 4692 /* If the following is false, the one value is in 4693 known_aggs. */ 4694 && (plats->aggs_contain_variable 4695 || !aglat->is_single_const ())) 4696 for (val = aglat->values; val; val = val->next) 4697 ret |= decide_about_value (node, i, aglat->offset, val, 4698 known_csts, known_contexts); 4699 } 4700 4701 if (!ctxlat->bottom 4702 && known_contexts[i].useless_p ()) 4703 { 4704 ipcp_value<ipa_polymorphic_call_context> *val; 4705 for (val = ctxlat->values; val; val = val->next) 4706 ret |= decide_about_value (node, i, -1, val, known_csts, 4707 known_contexts); 4708 } 4709 4710 info = IPA_NODE_REF (node); 4711 } 4712 4713 if (info->do_clone_for_all_contexts) 4714 { 4715 struct cgraph_node *clone; 4716 vec<cgraph_edge *> callers; 4717 4718 if (dump_file) 4719 fprintf (dump_file, " - Creating a specialized node of %s/%i " 4720 "for all known contexts.\n", node->name (), 4721 node->order); 4722 4723 callers = node->collect_callers (); 4724 4725 if (!known_contexts_useful_p (known_contexts)) 4726 { 4727 known_contexts.release (); 4728 known_contexts = vNULL; 4729 } 4730 clone = create_specialized_node (node, known_csts, known_contexts, 4731 known_aggs_to_agg_replacement_list (known_aggs), 4732 callers); 4733 info = IPA_NODE_REF (node); 4734 info->do_clone_for_all_contexts = false; 4735 IPA_NODE_REF (clone)->is_all_contexts_clone = true; 4736 for (i = 0; i < count; i++) 4737 vec_free (known_aggs[i].items); 4738 known_aggs.release (); 4739 ret = true; 4740 } 4741 else 4742 { 4743 known_csts.release (); 4744 known_contexts.release (); 4745 } 4746 4747 return ret; 4748 } 4749 4750 /* Transitively mark all callees of NODE within the same SCC as not dead. */ 4751 4752 static void 4753 spread_undeadness (struct cgraph_node *node) 4754 { 4755 struct cgraph_edge *cs; 4756 4757 for (cs = node->callees; cs; cs = cs->next_callee) 4758 if (ipa_edge_within_scc (cs)) 4759 { 4760 struct cgraph_node *callee; 4761 struct ipa_node_params *info; 4762 4763 callee = cs->callee->function_symbol (NULL); 4764 info = IPA_NODE_REF (callee); 4765 4766 if (info->node_dead) 4767 { 4768 info->node_dead = 0; 4769 spread_undeadness (callee); 4770 } 4771 } 4772 } 4773 4774 /* Return true if NODE has a caller from outside of its SCC that is not 4775 dead. Worker callback for cgraph_for_node_and_aliases. */ 4776 4777 static bool 4778 has_undead_caller_from_outside_scc_p (struct cgraph_node *node, 4779 void *data ATTRIBUTE_UNUSED) 4780 { 4781 struct cgraph_edge *cs; 4782 4783 for (cs = node->callers; cs; cs = cs->next_caller) 4784 if (cs->caller->thunk.thunk_p 4785 && cs->caller->call_for_symbol_thunks_and_aliases 4786 (has_undead_caller_from_outside_scc_p, NULL, true)) 4787 return true; 4788 else if (!ipa_edge_within_scc (cs) 4789 && !IPA_NODE_REF (cs->caller)->node_dead) 4790 return true; 4791 return false; 4792 } 4793 4794 4795 /* Identify nodes within the same SCC as NODE which are no longer needed 4796 because of new clones and will be removed as unreachable. */ 4797 4798 static void 4799 identify_dead_nodes (struct cgraph_node *node) 4800 { 4801 struct cgraph_node *v; 4802 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) 4803 if (v->local.local 4804 && !v->call_for_symbol_thunks_and_aliases 4805 (has_undead_caller_from_outside_scc_p, NULL, true)) 4806 IPA_NODE_REF (v)->node_dead = 1; 4807 4808 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) 4809 if (!IPA_NODE_REF (v)->node_dead) 4810 spread_undeadness (v); 4811 4812 if (dump_file && (dump_flags & TDF_DETAILS)) 4813 { 4814 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) 4815 if (IPA_NODE_REF (v)->node_dead) 4816 fprintf (dump_file, " Marking node as dead: %s/%i.\n", 4817 v->name (), v->order); 4818 } 4819 } 4820 4821 /* The decision stage. Iterate over the topological order of call graph nodes 4822 TOPO and make specialized clones if deemed beneficial. */ 4823 4824 static void 4825 ipcp_decision_stage (struct ipa_topo_info *topo) 4826 { 4827 int i; 4828 4829 if (dump_file) 4830 fprintf (dump_file, "\nIPA decision stage:\n\n"); 4831 4832 for (i = topo->nnodes - 1; i >= 0; i--) 4833 { 4834 struct cgraph_node *node = topo->order[i]; 4835 bool change = false, iterate = true; 4836 4837 while (iterate) 4838 { 4839 struct cgraph_node *v; 4840 iterate = false; 4841 for (v = node; v; v = ((struct ipa_dfs_info *) v->aux)->next_cycle) 4842 if (v->has_gimple_body_p () 4843 && ipcp_versionable_function_p (v)) 4844 iterate |= decide_whether_version_node (v); 4845 4846 change |= iterate; 4847 } 4848 if (change) 4849 identify_dead_nodes (node); 4850 } 4851 } 4852 4853 /* Look up all the bits information that we have discovered and copy it over 4854 to the transformation summary. */ 4855 4856 static void 4857 ipcp_store_bits_results (void) 4858 { 4859 cgraph_node *node; 4860 4861 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 4862 { 4863 ipa_node_params *info = IPA_NODE_REF (node); 4864 bool dumped_sth = false; 4865 bool found_useful_result = false; 4866 4867 if (!opt_for_fn (node->decl, flag_ipa_bit_cp)) 4868 { 4869 if (dump_file) 4870 fprintf (dump_file, "Not considering %s for ipa bitwise propagation " 4871 "; -fipa-bit-cp: disabled.\n", 4872 node->name ()); 4873 continue; 4874 } 4875 4876 if (info->ipcp_orig_node) 4877 info = IPA_NODE_REF (info->ipcp_orig_node); 4878 4879 unsigned count = ipa_get_param_count (info); 4880 for (unsigned i = 0; i < count; i++) 4881 { 4882 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 4883 if (plats->bits_lattice.constant_p ()) 4884 { 4885 found_useful_result = true; 4886 break; 4887 } 4888 } 4889 4890 if (!found_useful_result) 4891 continue; 4892 4893 ipcp_grow_transformations_if_necessary (); 4894 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); 4895 vec_safe_reserve_exact (ts->bits, count); 4896 4897 for (unsigned i = 0; i < count; i++) 4898 { 4899 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 4900 ipa_bits *jfbits; 4901 4902 if (plats->bits_lattice.constant_p ()) 4903 jfbits 4904 = ipa_get_ipa_bits_for_value (plats->bits_lattice.get_value (), 4905 plats->bits_lattice.get_mask ()); 4906 else 4907 jfbits = NULL; 4908 4909 ts->bits->quick_push (jfbits); 4910 if (!dump_file || !jfbits) 4911 continue; 4912 if (!dumped_sth) 4913 { 4914 fprintf (dump_file, "Propagated bits info for function %s/%i:\n", 4915 node->name (), node->order); 4916 dumped_sth = true; 4917 } 4918 fprintf (dump_file, " param %i: value = ", i); 4919 print_hex (jfbits->value, dump_file); 4920 fprintf (dump_file, ", mask = "); 4921 print_hex (jfbits->mask, dump_file); 4922 fprintf (dump_file, "\n"); 4923 } 4924 } 4925 } 4926 4927 /* Look up all VR information that we have discovered and copy it over 4928 to the transformation summary. */ 4929 4930 static void 4931 ipcp_store_vr_results (void) 4932 { 4933 cgraph_node *node; 4934 4935 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 4936 { 4937 ipa_node_params *info = IPA_NODE_REF (node); 4938 bool found_useful_result = false; 4939 4940 if (!opt_for_fn (node->decl, flag_ipa_vrp)) 4941 { 4942 if (dump_file) 4943 fprintf (dump_file, "Not considering %s for VR discovery " 4944 "and propagate; -fipa-ipa-vrp: disabled.\n", 4945 node->name ()); 4946 continue; 4947 } 4948 4949 if (info->ipcp_orig_node) 4950 info = IPA_NODE_REF (info->ipcp_orig_node); 4951 4952 unsigned count = ipa_get_param_count (info); 4953 for (unsigned i = 0; i < count; i++) 4954 { 4955 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 4956 if (!plats->m_value_range.bottom_p () 4957 && !plats->m_value_range.top_p ()) 4958 { 4959 found_useful_result = true; 4960 break; 4961 } 4962 } 4963 if (!found_useful_result) 4964 continue; 4965 4966 ipcp_grow_transformations_if_necessary (); 4967 ipcp_transformation_summary *ts = ipcp_get_transformation_summary (node); 4968 vec_safe_reserve_exact (ts->m_vr, count); 4969 4970 for (unsigned i = 0; i < count; i++) 4971 { 4972 ipcp_param_lattices *plats = ipa_get_parm_lattices (info, i); 4973 ipa_vr vr; 4974 4975 if (!plats->m_value_range.bottom_p () 4976 && !plats->m_value_range.top_p ()) 4977 { 4978 vr.known = true; 4979 vr.type = plats->m_value_range.m_vr.type; 4980 vr.min = plats->m_value_range.m_vr.min; 4981 vr.max = plats->m_value_range.m_vr.max; 4982 } 4983 else 4984 { 4985 vr.known = false; 4986 vr.type = VR_VARYING; 4987 vr.min = vr.max = wi::zero (INT_TYPE_SIZE); 4988 } 4989 ts->m_vr->quick_push (vr); 4990 } 4991 } 4992 } 4993 4994 /* The IPCP driver. */ 4995 4996 static unsigned int 4997 ipcp_driver (void) 4998 { 4999 struct cgraph_2edge_hook_list *edge_duplication_hook_holder; 5000 struct cgraph_edge_hook_list *edge_removal_hook_holder; 5001 struct ipa_topo_info topo; 5002 5003 ipa_check_create_node_params (); 5004 ipa_check_create_edge_args (); 5005 grow_edge_clone_vectors (); 5006 edge_duplication_hook_holder 5007 = symtab->add_edge_duplication_hook (&ipcp_edge_duplication_hook, NULL); 5008 edge_removal_hook_holder 5009 = symtab->add_edge_removal_hook (&ipcp_edge_removal_hook, NULL); 5010 5011 if (dump_file) 5012 { 5013 fprintf (dump_file, "\nIPA structures before propagation:\n"); 5014 if (dump_flags & TDF_DETAILS) 5015 ipa_print_all_params (dump_file); 5016 ipa_print_all_jump_functions (dump_file); 5017 } 5018 5019 /* Topological sort. */ 5020 build_toporder_info (&topo); 5021 /* Do the interprocedural propagation. */ 5022 ipcp_propagate_stage (&topo); 5023 /* Decide what constant propagation and cloning should be performed. */ 5024 ipcp_decision_stage (&topo); 5025 /* Store results of bits propagation. */ 5026 ipcp_store_bits_results (); 5027 /* Store results of value range propagation. */ 5028 ipcp_store_vr_results (); 5029 5030 /* Free all IPCP structures. */ 5031 free_toporder_info (&topo); 5032 next_edge_clone.release (); 5033 prev_edge_clone.release (); 5034 symtab->remove_edge_removal_hook (edge_removal_hook_holder); 5035 symtab->remove_edge_duplication_hook (edge_duplication_hook_holder); 5036 ipa_free_all_structures_after_ipa_cp (); 5037 if (dump_file) 5038 fprintf (dump_file, "\nIPA constant propagation end\n"); 5039 return 0; 5040 } 5041 5042 /* Initialization and computation of IPCP data structures. This is the initial 5043 intraprocedural analysis of functions, which gathers information to be 5044 propagated later on. */ 5045 5046 static void 5047 ipcp_generate_summary (void) 5048 { 5049 struct cgraph_node *node; 5050 5051 if (dump_file) 5052 fprintf (dump_file, "\nIPA constant propagation start:\n"); 5053 ipa_register_cgraph_hooks (); 5054 5055 FOR_EACH_FUNCTION_WITH_GIMPLE_BODY (node) 5056 ipa_analyze_node (node); 5057 } 5058 5059 /* Write ipcp summary for nodes in SET. */ 5060 5061 static void 5062 ipcp_write_summary (void) 5063 { 5064 ipa_prop_write_jump_functions (); 5065 } 5066 5067 /* Read ipcp summary. */ 5068 5069 static void 5070 ipcp_read_summary (void) 5071 { 5072 ipa_prop_read_jump_functions (); 5073 } 5074 5075 namespace { 5076 5077 const pass_data pass_data_ipa_cp = 5078 { 5079 IPA_PASS, /* type */ 5080 "cp", /* name */ 5081 OPTGROUP_NONE, /* optinfo_flags */ 5082 TV_IPA_CONSTANT_PROP, /* tv_id */ 5083 0, /* properties_required */ 5084 0, /* properties_provided */ 5085 0, /* properties_destroyed */ 5086 0, /* todo_flags_start */ 5087 ( TODO_dump_symtab | TODO_remove_functions ), /* todo_flags_finish */ 5088 }; 5089 5090 class pass_ipa_cp : public ipa_opt_pass_d 5091 { 5092 public: 5093 pass_ipa_cp (gcc::context *ctxt) 5094 : ipa_opt_pass_d (pass_data_ipa_cp, ctxt, 5095 ipcp_generate_summary, /* generate_summary */ 5096 ipcp_write_summary, /* write_summary */ 5097 ipcp_read_summary, /* read_summary */ 5098 ipcp_write_transformation_summaries, /* 5099 write_optimization_summary */ 5100 ipcp_read_transformation_summaries, /* 5101 read_optimization_summary */ 5102 NULL, /* stmt_fixup */ 5103 0, /* function_transform_todo_flags_start */ 5104 ipcp_transform_function, /* function_transform */ 5105 NULL) /* variable_transform */ 5106 {} 5107 5108 /* opt_pass methods: */ 5109 virtual bool gate (function *) 5110 { 5111 /* FIXME: We should remove the optimize check after we ensure we never run 5112 IPA passes when not optimizing. */ 5113 return (flag_ipa_cp && optimize) || in_lto_p; 5114 } 5115 5116 virtual unsigned int execute (function *) { return ipcp_driver (); } 5117 5118 }; // class pass_ipa_cp 5119 5120 } // anon namespace 5121 5122 ipa_opt_pass_d * 5123 make_pass_ipa_cp (gcc::context *ctxt) 5124 { 5125 return new pass_ipa_cp (ctxt); 5126 } 5127 5128 /* Reset all state within ipa-cp.c so that we can rerun the compiler 5129 within the same process. For use by toplev::finalize. */ 5130 5131 void 5132 ipa_cp_c_finalize (void) 5133 { 5134 max_count = 0; 5135 overall_size = 0; 5136 max_new_size = 0; 5137 } 5138