1// Implementation of private inline member functions for RTL SSA -*- C++ -*- 2// Copyright (C) 2020-2022 Free Software Foundation, Inc. 3// 4// This file is part of GCC. 5// 6// GCC is free software; you can redistribute it and/or modify it under 7// the terms of the GNU General Public License as published by the Free 8// Software Foundation; either version 3, or (at your option) any later 9// version. 10// 11// GCC is distributed in the hope that it will be useful, but WITHOUT ANY 12// WARRANTY; without even the implied warranty of MERCHANTABILITY or 13// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14// for more details. 15// 16// You should have received a copy of the GNU General Public License 17// along with GCC; see the file COPYING3. If not see 18// <http://www.gnu.org/licenses/>. 19 20namespace rtl_ssa { 21 22// Construct a new access with the given resource () and kind () values. 23inline access_info::access_info (resource_info resource, access_kind kind) 24 : m_regno (resource.regno), 25 m_kind (kind), 26 m_is_artificial (false), 27 m_is_set_with_nondebug_insn_uses (false), 28 m_is_pre_post_modify (false), 29 m_is_call_clobber (false), 30 m_is_live_out_use (false), 31 m_includes_address_uses (false), 32 m_includes_read_writes (false), 33 m_includes_subregs (false), 34 m_includes_multiregs (false), 35 m_only_occurs_in_notes (false), 36 m_is_last_nondebug_insn_use (false), 37 m_is_in_debug_insn_or_phi (false), 38 m_has_been_superceded (false), 39 m_is_temp (false), 40 m_spare (0), 41 m_mode (resource.mode) 42{ 43} 44 45// Construct a use of RESOURCE in LOCATION. The resource's value is provided 46// by DEF, or is completely undefined if DEF is null. 47inline use_info::use_info (insn_or_phi location, resource_info resource, 48 set_info *definition) 49 : access_info (resource, access_kind::USE), 50 m_insn_or_phi (location), 51 m_last_use_or_prev_use (nullptr), 52 m_last_nondebug_insn_use_or_next_use (nullptr), 53 m_def (definition) 54{ 55 if (m_insn_or_phi.is_second ()) 56 { 57 m_is_in_debug_insn_or_phi = true; 58 m_is_artificial = true; 59 } 60 else 61 { 62 insn_info *insn = m_insn_or_phi.known_first (); 63 m_is_in_debug_insn_or_phi = insn->is_debug_insn (); 64 m_is_artificial = insn->is_artificial (); 65 } 66} 67 68// Return the correct (uncached) value of m_is_last_nondebug_insn_use. 69inline bool 70use_info::calculate_is_last_nondebug_insn_use () const 71{ 72 use_info *next = next_use (); 73 return is_in_nondebug_insn () && (!next || next->is_in_debug_insn_or_phi ()); 74} 75 76// Accumulate any properties about REF that are also stored in use_infos. 77// IS_FIRST is true if REF is the first access to resource () that we have 78// recorded in this way, false if we have already recorded previous 79// references. 80inline void 81use_info::record_reference (rtx_obj_reference ref, bool is_first) 82{ 83 if (is_first) 84 { 85 m_includes_address_uses = ref.in_address (); 86 m_includes_read_writes = ref.is_write (); 87 m_includes_subregs = ref.in_subreg (); 88 m_includes_multiregs = ref.is_multireg (); 89 m_only_occurs_in_notes = ref.in_note (); 90 } 91 else 92 { 93 m_includes_address_uses |= ref.in_address (); 94 m_includes_read_writes |= ref.is_write (); 95 m_includes_subregs |= ref.in_subreg (); 96 m_includes_multiregs |= ref.is_multireg (); 97 m_only_occurs_in_notes &= ref.in_note (); 98 } 99} 100 101// Change the value of insn () to INSN. 102inline void 103use_info::set_insn (insn_info *insn) 104{ 105 m_insn_or_phi = insn; 106 m_is_artificial = insn->is_artificial (); 107} 108 109// Copy the overloaded prev link from OTHER. 110inline void 111use_info::copy_prev_from (use_info *other) 112{ 113 m_last_use_or_prev_use = other->m_last_use_or_prev_use; 114} 115 116// Copy the overloaded next link from OTHER. 117inline void 118use_info::copy_next_from (use_info *other) 119{ 120 m_last_nondebug_insn_use_or_next_use 121 = other->m_last_nondebug_insn_use_or_next_use; 122 m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use (); 123} 124 125// Record that this use is the first in the list and that the last use is LAST. 126inline void 127use_info::set_last_use (use_info *last_use) 128{ 129 m_last_use_or_prev_use.set_first (last_use); 130} 131 132// Record that this use is not the first in the list and that the previous 133// use is PREV. 134inline void 135use_info::set_prev_use (use_info *prev_use) 136{ 137 m_last_use_or_prev_use.set_second (prev_use); 138} 139 140// Record that this use is the last use in the list. If USE is nonnull, 141// record that USE is the last use in the list by a nondebug instruction, 142// otherwise record that there are no uses by nondebug instructions 143// in the list. 144inline void 145use_info::set_last_nondebug_insn_use (use_info *use) 146{ 147 m_last_nondebug_insn_use_or_next_use.set_first (use); 148 m_is_last_nondebug_insn_use = (use == this); 149} 150 151// Record that this use is not the last in the list and that the next 152// use is NEXT_USE. 153inline void 154use_info::set_next_use (use_info *next_use) 155{ 156 m_last_nondebug_insn_use_or_next_use.set_second (next_use); 157 m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use (); 158} 159 160// Clear any information relating to the position of the use in its 161// definition's list. 162inline void 163use_info::clear_use_links () 164{ 165 m_last_use_or_prev_use = nullptr; 166 m_last_nondebug_insn_use_or_next_use = nullptr; 167 m_is_last_nondebug_insn_use = false; 168} 169 170// Return true if the use has any links to other uses. This is mostly 171// for assert checking. 172inline bool 173use_info::has_use_links () 174{ 175 return (m_last_use_or_prev_use 176 || m_last_nondebug_insn_use_or_next_use 177 || m_is_last_nondebug_insn_use); 178} 179 180// Construct a definition of RESOURCE in INSN, giving it kind KIND. 181inline def_info::def_info (insn_info *insn, resource_info resource, 182 access_kind kind) 183 : access_info (resource, kind), 184 m_insn (insn), 185 m_last_def_or_prev_def (nullptr), 186 m_splay_root_or_next_def (nullptr) 187{ 188 m_is_artificial = insn->is_artificial (); 189} 190 191// Record any properties about REF that are also stored in def_infos. 192// IS_FIRST is true if REF is the first access to resource () that we have 193// recorded in this way, false if we have already recorded previous 194// references. 195inline void 196def_info::record_reference (rtx_obj_reference ref, bool is_first) 197{ 198 if (is_first) 199 { 200 m_is_pre_post_modify = ref.is_pre_post_modify (); 201 m_includes_read_writes = ref.is_read (); 202 m_includes_subregs = ref.in_subreg (); 203 m_includes_multiregs = ref.is_multireg (); 204 } 205 else 206 { 207 m_is_pre_post_modify |= ref.is_pre_post_modify (); 208 m_includes_read_writes |= ref.is_read (); 209 m_includes_subregs |= ref.in_subreg (); 210 m_includes_multiregs |= ref.is_multireg (); 211 } 212} 213 214// Return the last definition in the list. Only valid when is_first () 215// is true. 216inline def_info * 217def_info::last_def () const 218{ 219 return m_last_def_or_prev_def.known_first (); 220} 221 222// Return the root of the splay tree of definitions of resource (), 223// or null if no splay tree has been created for this resource. 224// Only valid when is_last () is true. 225inline def_node * 226def_info::splay_root () const 227{ 228 return m_splay_root_or_next_def.known_first (); 229} 230 231// Copy the overloaded prev link from OTHER. 232inline void 233def_info::copy_prev_from (def_info *other) 234{ 235 m_last_def_or_prev_def 236 = other->m_last_def_or_prev_def; 237} 238 239// Copy the overloaded next link from OTHER. 240inline void 241def_info::copy_next_from (def_info *other) 242{ 243 m_splay_root_or_next_def = other->m_splay_root_or_next_def; 244} 245 246// Record that this definition is the first in the list and that the last 247// definition is LAST. 248inline void 249def_info::set_last_def (def_info *last_def) 250{ 251 m_last_def_or_prev_def.set_first (last_def); 252} 253 254// Record that this definition is not the first in the list and that the 255// previous definition is PREV. 256inline void 257def_info::set_prev_def (def_info *prev_def) 258{ 259 m_last_def_or_prev_def.set_second (prev_def); 260} 261 262// Record that this definition is the last in the list and that the root 263// of the splay tree associated with resource () is ROOT. 264inline void 265def_info::set_splay_root (def_node *root) 266{ 267 m_splay_root_or_next_def = root; 268} 269 270// Record that this definition is not the last in the list and that the 271// next definition is NEXT. 272inline void 273def_info::set_next_def (def_info *next_def) 274{ 275 m_splay_root_or_next_def = next_def; 276} 277 278// Clear the prev and next links 279inline void 280def_info::clear_def_links () 281{ 282 m_last_def_or_prev_def = nullptr; 283 m_splay_root_or_next_def = nullptr; 284} 285 286// Return true if the definition has any links to other definitions. 287// This is mostly for assert checking. 288inline bool 289def_info::has_def_links () 290{ 291 return m_last_def_or_prev_def || m_splay_root_or_next_def; 292} 293 294// Construct a clobber of register REGNO in insn INSN. 295inline clobber_info::clobber_info (insn_info *insn, unsigned int regno) 296 : def_info (insn, { E_BLKmode, regno }, access_kind::CLOBBER), 297 m_children (), 298 m_parent (nullptr), 299 m_group (nullptr) 300{ 301} 302 303// Set the containing group to GROUP, if it isn't already. The main 304// use of this function is to update the new root of GROUP's splay tree. 305inline void 306clobber_info::update_group (clobber_group *group) 307{ 308 if (__builtin_expect (m_group != group, 0)) 309 m_group = group; 310} 311 312// Cconstruct a set_info for a store to RESOURCE in INSN, giving it 313// kind KIND. 314inline set_info::set_info (insn_info *insn, resource_info resource, 315 access_kind kind) 316 : def_info (insn, resource, kind), 317 m_first_use (nullptr) 318{ 319} 320 321// Cconstruct a set_info for a store to RESOURCE in INSN. 322inline set_info::set_info (insn_info *insn, resource_info resource) 323 : set_info (insn, resource, access_kind::SET) 324{ 325} 326 327// Record that USE is the first use of this definition. 328inline void 329set_info::set_first_use (use_info *first_use) 330{ 331 m_first_use = first_use; 332 m_is_set_with_nondebug_insn_uses 333 = (first_use && first_use->is_in_nondebug_insn ()); 334} 335 336// Construct a phi for RESOURCE in INSN, giving it identifier UID. 337inline phi_info::phi_info (insn_info *insn, resource_info resource, 338 unsigned int uid) 339 : set_info (insn, resource, access_kind::PHI), 340 m_uid (uid), 341 m_num_inputs (0), 342 m_prev_phi (nullptr), 343 m_next_phi (nullptr) 344{ 345} 346 347// Turn the phi into a degenerate phi, with INPUT representing the 348// value of the resource on all incoming edges. 349inline void 350phi_info::make_degenerate (use_info *input) 351{ 352 m_num_inputs = 1; 353 m_single_input = input; 354} 355 356// Set the inputs of the phi to INPUTS. 357inline void 358phi_info::set_inputs (use_array inputs) 359{ 360 m_num_inputs = inputs.size (); 361 if (inputs.size () == 1) 362 m_single_input = inputs[0]; 363 else 364 m_inputs = access_array (inputs).begin (); 365} 366 367// Construct a definition splay tree node for FIRST_DEF, which is either 368// the first clobber_info in a group or a standalone set_info. 369inline def_node::def_node (clobber_or_set first_def) 370 : m_clobber_or_set (first_def), 371 m_children () 372{ 373} 374 375// Construct a new group of clobber_infos that initially contains just CLOBBER. 376inline clobber_group::clobber_group (clobber_info *clobber) 377 : def_node (clobber), 378 m_last_clobber (clobber), 379 m_clobber_tree (clobber) 380{ 381 clobber->m_group = this; 382} 383 384// Construct a node for the instruction with uid UID. 385inline insn_info::order_node::order_node (int uid) 386 : insn_note (kind), 387 m_children (), 388 m_parent (nullptr) 389{ 390 m_data32 = uid; 391} 392 393// Construct a note for instruction INSN, giving it abi_id () value ABI_ID. 394inline insn_call_clobbers_note::insn_call_clobbers_note (unsigned int abi_id, 395 insn_info *insn) 396 : insn_note (kind), 397 m_children (), 398 m_insn (insn) 399{ 400 m_data32 = abi_id; 401} 402 403// Construct an instruction with the given bb () and rtl () values. 404// If the instruction is real, COST_OR_UID is the value of cost (), 405// otherwise it is the value of uid (). 406inline insn_info::insn_info (bb_info *bb, rtx_insn *rtl, int cost_or_uid) 407 : m_prev_insn_or_last_debug_insn (nullptr), 408 m_next_nondebug_or_debug_insn (nullptr), 409 m_bb (bb), 410 m_rtl (rtl), 411 m_accesses (nullptr), 412 m_num_uses (0), 413 m_num_defs (0), 414 m_is_debug_insn (rtl && DEBUG_INSN_P (rtl)), 415 m_can_be_optimized (false), 416 m_is_asm (false), 417 m_has_pre_post_modify (false), 418 m_has_volatile_refs (false), 419 m_spare (0), 420 m_point (0), 421 m_cost_or_uid (cost_or_uid), 422 m_first_note (nullptr) 423{ 424} 425 426// Copy any insn properties from PROPERTIES that are also stored in an 427// insn_info. 428inline void 429insn_info::set_properties (const rtx_properties &properties) 430{ 431 m_is_asm = properties.has_asm; 432 m_has_pre_post_modify = properties.has_pre_post_modify; 433 m_has_volatile_refs = properties.has_volatile_refs; 434 // Not strictly related to the properties we've been given, but it's 435 // a convenient location to do this. 436 m_can_be_optimized = (NONDEBUG_INSN_P (m_rtl) 437 & (GET_CODE (PATTERN (m_rtl)) != USE) 438 & (GET_CODE (PATTERN (m_rtl)) != CLOBBER)); 439} 440 441// Change the list of instruction accesses to ACCESSES, which contains 442// NUM_DEFS definitions followed by NUM_USES uses. 443inline void 444insn_info::set_accesses (access_info **accesses, 445 unsigned int num_defs, unsigned int num_uses) 446{ 447 m_accesses = accesses; 448 m_num_defs = num_defs; 449 gcc_assert (num_defs == m_num_defs); 450 m_num_uses = num_uses; 451} 452 453// Change defs () and uses () to DEFS and USES respectively, given that 454// the existing m_accesses array has enough room for them. 455inline void 456insn_info::copy_accesses (access_array defs, access_array uses) 457{ 458 gcc_assert (defs.size () + uses.size () <= m_num_defs + m_num_uses); 459 memcpy (m_accesses, defs.begin (), defs.size_bytes ()); 460 memcpy (m_accesses + defs.size (), uses.begin (), uses.size_bytes ()); 461 m_num_defs = defs.size (); 462 gcc_assert (m_num_defs == defs.size ()); 463 m_num_uses = uses.size (); 464} 465 466// If the instruction has an insn_info::order_node, return the node, 467// otherwise return null. 468inline insn_info::order_node * 469insn_info::get_order_node () const 470{ 471 // The order_node always comes first. 472 if (insn_note *note = first_note ()) 473 return note->dyn_cast<insn_info::order_node *> (); 474 return nullptr; 475} 476 477// Like get_order_node (), but the node is known to exist. 478inline insn_info::order_node * 479insn_info::get_known_order_node () const 480{ 481 // The order_node always comes first. 482 return first_note ()->as_a<insn_info::order_node *> (); 483} 484 485// Copy the overloaded prev link from OTHER. 486inline void 487insn_info::copy_prev_from (insn_info *other) 488{ 489 m_prev_insn_or_last_debug_insn = other->m_prev_insn_or_last_debug_insn; 490} 491 492// Copy the overloaded next link from OTHER. 493inline void 494insn_info::copy_next_from (insn_info *other) 495{ 496 m_next_nondebug_or_debug_insn = other->m_next_nondebug_or_debug_insn; 497} 498 499// If this is a nondebug instruction, record that the previous nondebug 500// instruction is PREV. (There might be intervening debug instructions.) 501// 502// If this is a debug instruction, record that the previous instruction 503// is debug instruction PREV. 504inline void 505insn_info::set_prev_sametype_insn (insn_info *prev) 506{ 507 m_prev_insn_or_last_debug_insn.set_first (prev); 508} 509 510// Only valid for debug instructions. Record that this instruction starts 511// a subsequence of debug instructions that ends with LAST. 512inline void 513insn_info::set_last_debug_insn (insn_info *last) 514{ 515 m_prev_insn_or_last_debug_insn.set_second (last); 516} 517 518// Record that the next instruction of any kind is NEXT. 519inline void 520insn_info::set_next_any_insn (insn_info *next) 521{ 522 if (next && next->is_debug_insn ()) 523 m_next_nondebug_or_debug_insn.set_second (next); 524 else 525 m_next_nondebug_or_debug_insn.set_first (next); 526} 527 528// Clear the list links and point number for this instruction. 529inline void 530insn_info::clear_insn_links () 531{ 532 m_prev_insn_or_last_debug_insn = nullptr; 533 m_next_nondebug_or_debug_insn = nullptr; 534 m_point = 0; 535} 536 537// Return true if the instruction contains any list information. 538// This is used by assert checking. 539inline bool 540insn_info::has_insn_links () 541{ 542 return (m_prev_insn_or_last_debug_insn 543 || m_next_nondebug_or_debug_insn 544 || m_point); 545} 546 547// Construct a representation of basic block CFG_BB. 548inline bb_info::bb_info (basic_block cfg_bb) 549 : m_prev_bb (nullptr), 550 m_next_bb (nullptr), 551 m_cfg_bb (cfg_bb), 552 m_ebb (nullptr), 553 m_head_insn (nullptr), 554 m_end_insn (nullptr) 555{ 556} 557 558// Construct a tree of call clobbers for the given ABI. 559inline ebb_call_clobbers_info:: 560ebb_call_clobbers_info (const predefined_function_abi *abi) 561 : m_next (nullptr), 562 m_abi (abi) 563{ 564} 565 566// Construct an EBB whose first block is FIRST_BB and whose last block 567// is LAST_BB. 568inline ebb_info::ebb_info (bb_info *first_bb, bb_info *last_bb) 569 : m_first_phi (nullptr), 570 m_phi_insn (nullptr), 571 m_first_bb (first_bb), 572 m_last_bb (last_bb), 573 m_first_call_clobbers (nullptr) 574{ 575} 576 577// Record register definition DEF in last_access, pushing a definition 578// to def_stack where appropriate. 579inline void 580function_info::build_info::record_reg_def (def_info *def) 581{ 582 unsigned int regno = def->regno (); 583 auto *prev_dominating_def = safe_as_a<def_info *> (last_access[regno + 1]); 584 if (!prev_dominating_def) 585 // Indicate that DEF is the first dominating definition of REGNO. 586 def_stack.safe_push (def); 587 else if (prev_dominating_def->bb () != def->bb ()) 588 // Record that PREV_DOMINATING_DEF was the dominating definition 589 // of REGNO on entry to the current block. 590 def_stack.safe_push (prev_dominating_def); 591 last_access[regno + 1] = def; 592} 593 594// Set the contents of last_access for memory to DEF. 595inline void 596function_info::build_info::record_mem_def (def_info *def) 597{ 598 last_access[0] = def; 599} 600 601// Return the current value of live register REGNO, or null if the register's 602// value is completedly undefined. 603inline set_info * 604function_info::build_info::current_reg_value (unsigned int regno) const 605{ 606 return safe_dyn_cast<set_info *> (last_access[regno + 1]); 607} 608 609// Return the current value of memory. 610inline set_info * 611function_info::build_info::current_mem_value () const 612{ 613 return as_a<set_info *> (last_access[0]); 614} 615 616// Allocate a T on the function's main obstack, passing ARGS 617// to its constructor. 618template<typename T, typename... Ts> 619inline T * 620function_info::allocate (Ts... args) 621{ 622 static_assert (std::is_trivially_destructible<T>::value, 623 "destructor won't be called"); 624 static_assert (alignof (T) <= obstack_alignment, 625 "too much alignment required"); 626 void *addr = obstack_alloc (&m_obstack, sizeof (T)); 627 return new (addr) T (std::forward<Ts> (args)...); 628} 629 630// Allocate a T on the function's temporary obstack, passing ARGS 631// to its constructor. 632template<typename T, typename... Ts> 633inline T * 634function_info::allocate_temp (Ts... args) 635{ 636 static_assert (std::is_trivially_destructible<T>::value, 637 "destructor won't be called"); 638 static_assert (alignof (T) <= obstack_alignment, 639 "too much alignment required"); 640 void *addr = obstack_alloc (&m_temp_obstack, sizeof (T)); 641 return new (addr) T (std::forward<Ts> (args)...); 642} 643 644// Add INSN to the end of the function's list of instructions. 645inline void 646function_info::append_insn (insn_info *insn) 647{ 648 gcc_checking_assert (!insn->has_insn_links ()); 649 if (insn_info *after = m_last_insn) 650 add_insn_after (insn, after); 651 else 652 // The first instruction is for the entry block and is always a nondebug 653 // insn 654 m_first_insn = m_last_insn = m_last_nondebug_insn = insn; 655} 656 657// Start building a new list of uses and definitions for an instruction. 658inline void 659function_info::start_insn_accesses () 660{ 661 gcc_checking_assert (m_temp_defs.is_empty () 662 && m_temp_uses.is_empty ()); 663} 664 665// Return a mode that encapsulates two distinct references to a register, 666// one with mode MODE1 and one with mode MODE2. Treat BLKmode as a 667// "don't know" wildcard. 668inline machine_mode 669combine_modes (machine_mode mode1, machine_mode mode2) 670{ 671 if (mode1 == E_BLKmode) 672 return mode2; 673 674 if (mode2 == E_BLKmode) 675 return mode1; 676 677 return wider_subreg_mode (mode1, mode2); 678} 679 680// PRINTER (PP, ARGS...) prints ARGS... to a pretty_printer PP. Use it 681// to print ARGS... to FILE. 682template<typename Printer, typename... Args> 683inline void 684dump_using (FILE *file, Printer printer, Args... args) 685{ 686 pretty_printer pp; 687 printer (&pp, args...); 688 pp_newline (&pp); 689 fprintf (file, "%s", pp_formatted_text (&pp)); 690} 691 692} 693