hppa: Fix REG+D address support before reload
[official-gcc.git] / gcc / rtl-ssa / internals.inl
blob73581a02bad841d7dca6289c0ecf693f96bfabb0
1 // Implementation of private inline member functions for RTL SSA    -*- C++ -*-
2 // Copyright (C) 2020-2024 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.
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.
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/>.
20 namespace rtl_ssa {
22 // Construct a new access with the given resource () and kind () values.
23 inline access_info::access_info (resource_info resource, access_kind kind)
24   : m_regno (resource.regno),
25     m_mode (resource.mode),
26     m_kind (kind),
27     m_is_artificial (false),
28     m_is_set_with_nondebug_insn_uses (false),
29     m_is_pre_post_modify (false),
30     m_is_call_clobber (false),
31     m_is_live_out_use (false),
32     m_includes_address_uses (false),
33     m_includes_read_writes (false),
34     m_includes_subregs (false),
35     m_includes_multiregs (false),
36     m_only_occurs_in_notes (false),
37     m_is_last_nondebug_insn_use (false),
38     m_is_in_debug_insn_or_phi (false),
39     m_has_been_superceded (false),
40     m_is_temp (false)
44 // Construct a use of RESOURCE in LOCATION.  The resource's value is provided
45 // by DEF, or is completely undefined if DEF is null.
46 inline use_info::use_info (insn_or_phi location, resource_info resource,
47                            set_info *definition)
48   : access_info (resource, access_kind::USE),
49     m_insn_or_phi (location),
50     m_last_use_or_prev_use (nullptr),
51     m_last_nondebug_insn_use_or_next_use (nullptr),
52     m_def (definition)
54   if (m_insn_or_phi.is_second ())
55     {
56       m_is_in_debug_insn_or_phi = true;
57       m_is_artificial = true;
58     }
59   else
60     {
61       insn_info *insn = m_insn_or_phi.known_first ();
62       m_is_in_debug_insn_or_phi = insn->is_debug_insn ();
63       m_is_artificial = insn->is_artificial ();
64     }
67 // Return the correct (uncached) value of m_is_last_nondebug_insn_use.
68 inline bool
69 use_info::calculate_is_last_nondebug_insn_use () const
71   use_info *next = next_use ();
72   return is_in_nondebug_insn () && (!next || next->is_in_debug_insn_or_phi ());
75 // Accumulate any properties about REF that are also stored in use_infos.
76 // IS_FIRST is true if REF is the first access to resource () that we have
77 // recorded in this way, false if we have already recorded previous
78 // references.
79 inline void
80 use_info::record_reference (rtx_obj_reference ref, bool is_first)
82   if (is_first)
83     {
84       m_includes_address_uses = ref.in_address ();
85       m_includes_read_writes = ref.is_write ();
86       m_includes_subregs = ref.in_subreg ();
87       m_includes_multiregs = ref.is_multireg ();
88       m_only_occurs_in_notes = ref.in_note ();
89     }
90   else
91     {
92       m_includes_address_uses |= ref.in_address ();
93       m_includes_read_writes |= ref.is_write ();
94       m_includes_subregs |= ref.in_subreg ();
95       m_includes_multiregs |= ref.is_multireg ();
96       m_only_occurs_in_notes &= ref.in_note ();
97     }
100 // Change the value of insn () to INSN.
101 inline void
102 use_info::set_insn (insn_info *insn)
104   m_insn_or_phi = insn;
105   m_is_artificial = insn->is_artificial ();
108 // Copy the overloaded prev link from OTHER.
109 inline void
110 use_info::copy_prev_from (use_info *other)
112   m_last_use_or_prev_use = other->m_last_use_or_prev_use;
115 // Copy the overloaded next link from OTHER.
116 inline void
117 use_info::copy_next_from (use_info *other)
119   m_last_nondebug_insn_use_or_next_use
120     = other->m_last_nondebug_insn_use_or_next_use;
121   m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use ();
124 // Record that this use is the first in the list and that the last use is LAST.
125 inline void
126 use_info::set_last_use (use_info *last_use)
128   m_last_use_or_prev_use.set_first (last_use);
131 // Record that this use is not the first in the list and that the previous
132 // use is PREV.
133 inline void
134 use_info::set_prev_use (use_info *prev_use)
136   m_last_use_or_prev_use.set_second (prev_use);
139 // Record that this use is the last use in the list.  If USE is nonnull,
140 // record that USE is the last use in the list by a nondebug instruction,
141 // otherwise record that there are no uses by nondebug instructions
142 // in the list.
143 inline void
144 use_info::set_last_nondebug_insn_use (use_info *use)
146   m_last_nondebug_insn_use_or_next_use.set_first (use);
147   m_is_last_nondebug_insn_use = (use == this);
150 // Record that this use is not the last in the list and that the next
151 // use is NEXT_USE.
152 inline void
153 use_info::set_next_use (use_info *next_use)
155   m_last_nondebug_insn_use_or_next_use.set_second (next_use);
156   m_is_last_nondebug_insn_use = calculate_is_last_nondebug_insn_use ();
159 // Clear any information relating to the position of the use in its
160 // definition's list.
161 inline void
162 use_info::clear_use_links ()
164   m_last_use_or_prev_use = nullptr;
165   m_last_nondebug_insn_use_or_next_use = nullptr;
166   m_is_last_nondebug_insn_use = false;
169 // Return true if the use has any links to other uses.  This is mostly
170 // for assert checking.
171 inline bool
172 use_info::has_use_links ()
174   return (m_last_use_or_prev_use
175           || m_last_nondebug_insn_use_or_next_use
176           || m_is_last_nondebug_insn_use);
179 // Construct a definition of RESOURCE in INSN, giving it kind KIND.
180 inline def_info::def_info (insn_info *insn, resource_info resource,
181                            access_kind kind)
182   : access_info (resource, kind),
183     m_insn (insn),
184     m_last_def_or_prev_def (nullptr),
185     m_splay_root_or_next_def (nullptr)
187   m_is_artificial = insn->is_artificial ();
190 // Record any properties about REF that are also stored in def_infos.
191 // IS_FIRST is true if REF is the first access to resource () that we have
192 // recorded in this way, false if we have already recorded previous
193 // references.
194 inline void
195 def_info::record_reference (rtx_obj_reference ref, bool is_first)
197   if (is_first)
198     {
199       m_is_pre_post_modify = ref.is_pre_post_modify ();
200       m_includes_read_writes = ref.is_read ();
201       m_includes_subregs = ref.in_subreg ();
202       m_includes_multiregs = ref.is_multireg ();
203     }
204   else
205     {
206       m_is_pre_post_modify |= ref.is_pre_post_modify ();
207       m_includes_read_writes |= ref.is_read ();
208       m_includes_subregs |= ref.in_subreg ();
209       m_includes_multiregs |= ref.is_multireg ();
210     }
213 // Return the last definition in the list.  Only valid when is_first ()
214 // is true.
215 inline def_info *
216 def_info::last_def () const
218   return m_last_def_or_prev_def.known_first ();
221 // Return the root of the splay tree of definitions of resource (),
222 // or null if no splay tree has been created for this resource.
223 // Only valid when is_last () is true.
224 inline def_node *
225 def_info::splay_root () const
227   return m_splay_root_or_next_def.known_first ();
230 // Copy the overloaded prev link from OTHER.
231 inline void
232 def_info::copy_prev_from (def_info *other)
234   m_last_def_or_prev_def
235     = other->m_last_def_or_prev_def;
238 // Copy the overloaded next link from OTHER.
239 inline void
240 def_info::copy_next_from (def_info *other)
242   m_splay_root_or_next_def = other->m_splay_root_or_next_def;
245 // Record that this definition is the first in the list and that the last
246 // definition is LAST.
247 inline void
248 def_info::set_last_def (def_info *last_def)
250   m_last_def_or_prev_def.set_first (last_def);
253 // Record that this definition is not the first in the list and that the
254 // previous definition is PREV.
255 inline void
256 def_info::set_prev_def (def_info *prev_def)
258   m_last_def_or_prev_def.set_second (prev_def);
261 // Record that this definition is the last in the list and that the root
262 // of the splay tree associated with resource () is ROOT.
263 inline void
264 def_info::set_splay_root (def_node *root)
266   m_splay_root_or_next_def = root;
269 // Record that this definition is not the last in the list and that the
270 // next definition is NEXT.
271 inline void
272 def_info::set_next_def (def_info *next_def)
274   m_splay_root_or_next_def = next_def;
277 // Clear the prev and next links
278 inline void
279 def_info::clear_def_links ()
281   m_last_def_or_prev_def = nullptr;
282   m_splay_root_or_next_def = nullptr;
285 // Return true if the definition has any links to other definitions.
286 // This is mostly for assert checking.
287 inline bool
288 def_info::has_def_links ()
290   return m_last_def_or_prev_def || m_splay_root_or_next_def;
293 // Construct a clobber of register REGNO in insn INSN.
294 inline clobber_info::clobber_info (insn_info *insn, unsigned int regno)
295   : def_info (insn, { E_BLKmode, regno }, access_kind::CLOBBER),
296     m_children (),
297     m_parent (nullptr),
298     m_group (nullptr)
302 // Set the containing group to GROUP, if it isn't already.  The main
303 // use of this function is to update the new root of GROUP's splay tree.
304 inline void
305 clobber_info::update_group (clobber_group *group)
307   if (UNLIKELY (m_group != group))
308     m_group = group;
311 // Cconstruct a set_info for a store to RESOURCE in INSN, giving it
312 // kind KIND.
313 inline set_info::set_info (insn_info *insn, resource_info resource,
314                            access_kind kind)
315   : def_info (insn, resource, kind),
316     m_first_use (nullptr)
320 // Cconstruct a set_info for a store to RESOURCE in INSN.
321 inline set_info::set_info (insn_info *insn, resource_info resource)
322   : set_info (insn, resource, access_kind::SET)
326 // Record that USE is the first use of this definition.
327 inline void
328 set_info::set_first_use (use_info *first_use)
330   m_first_use = first_use;
331   m_is_set_with_nondebug_insn_uses
332     = (first_use && first_use->is_in_nondebug_insn ());
335 // Construct a phi for RESOURCE in INSN, giving it identifier UID.
336 inline phi_info::phi_info (insn_info *insn, resource_info resource,
337                            unsigned int uid)
338   : set_info (insn, resource, access_kind::PHI),
339     m_uid (uid),
340     m_num_inputs (0),
341     m_prev_phi (nullptr),
342     m_next_phi (nullptr)
346 // Turn the phi into a degenerate phi, with INPUT representing the
347 // value of the resource on all incoming edges.
348 inline void
349 phi_info::make_degenerate (use_info *input)
351   m_num_inputs = 1;
352   m_single_input = input;
355 // Set the inputs of the phi to INPUTS.
356 inline void
357 phi_info::set_inputs (use_array inputs)
359   m_num_inputs = inputs.size ();
360   if (inputs.size () == 1)
361     m_single_input = inputs[0];
362   else
363     m_inputs = access_array (inputs).begin ();
366 // Construct a definition splay tree node for FIRST_DEF, which is either
367 // the first clobber_info in a group or a standalone set_info.
368 inline def_node::def_node (clobber_or_set first_def)
369   : m_clobber_or_set (first_def),
370     m_children ()
374 // Construct a new group of clobber_infos that initially contains just CLOBBER.
375 inline clobber_group::clobber_group (clobber_info *clobber)
376   : def_node (clobber),
377     m_last_clobber (clobber),
378     m_clobber_tree (clobber)
380   clobber->m_group = this;
383 // Construct a node for the instruction with uid UID.
384 inline insn_info::order_node::order_node (int uid)
385   : insn_note (kind),
386     m_children (),
387     m_parent (nullptr)
389   m_data32 = uid;
392 // Construct a note for instruction INSN, giving it abi_id () value ABI_ID.
393 inline insn_call_clobbers_note::insn_call_clobbers_note (unsigned int abi_id,
394                                                          insn_info *insn)
395   : insn_note (kind),
396     m_children (),
397     m_insn (insn)
399   m_data32 = abi_id;
402 // Construct an instruction with the given bb () and rtl () values.
403 // If the instruction is real, COST_OR_UID is the value of cost (),
404 // otherwise it is the value of uid ().
405 inline insn_info::insn_info (bb_info *bb, rtx_insn *rtl, int cost_or_uid)
406   : m_prev_insn_or_last_debug_insn (nullptr),
407     m_next_nondebug_or_debug_insn (nullptr),
408     m_bb (bb),
409     m_rtl (rtl),
410     m_accesses (nullptr),
411     m_num_uses (0),
412     m_num_defs (0),
413     m_is_debug_insn (rtl && DEBUG_INSN_P (rtl)),
414     m_can_be_optimized (false),
415     m_is_asm (false),
416     m_has_pre_post_modify (false),
417     m_has_volatile_refs (false),
418     m_is_temp (false),
419     m_spare (0),
420     m_point (0),
421     m_cost_or_uid (cost_or_uid),
422     m_first_note (nullptr)
426 // Copy any insn properties from PROPERTIES that are also stored in an
427 // insn_info.
428 inline void
429 insn_info::set_properties (const rtx_properties &properties)
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));
441 // Change the list of instruction accesses to ACCESSES, which contains
442 // NUM_DEFS definitions followed by NUM_USES uses.
443 inline void
444 insn_info::set_accesses (access_info **accesses,
445                          unsigned int num_defs, unsigned int num_uses)
447   m_accesses = accesses;
448   m_num_defs = num_defs;
449   gcc_assert (num_defs == m_num_defs);
450   m_num_uses = num_uses;
453 // Change defs () and uses () to DEFS and USES respectively, given that
454 // the existing m_accesses array has enough room for them.
455 inline void
456 insn_info::copy_accesses (access_array defs, access_array uses)
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 ();
466 // If the instruction has an insn_info::order_node, return the node,
467 // otherwise return null.
468 inline insn_info::order_node *
469 insn_info::get_order_node () const
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;
477 // Like get_order_node (), but the node is known to exist.
478 inline insn_info::order_node *
479 insn_info::get_known_order_node () const
481   // The order_node always comes first.
482   return first_note ()->as_a<insn_info::order_node *> ();
485 // Copy the overloaded prev link from OTHER.
486 inline void
487 insn_info::copy_prev_from (insn_info *other)
489   m_prev_insn_or_last_debug_insn = other->m_prev_insn_or_last_debug_insn;
492 // Copy the overloaded next link from OTHER.
493 inline void
494 insn_info::copy_next_from (insn_info *other)
496   m_next_nondebug_or_debug_insn = other->m_next_nondebug_or_debug_insn;
499 // If this is a nondebug instruction, record that the previous nondebug
500 // instruction is PREV.  (There might be intervening debug instructions.)
502 // If this is a debug instruction, record that the previous instruction
503 // is debug instruction PREV.
504 inline void
505 insn_info::set_prev_sametype_insn (insn_info *prev)
507   m_prev_insn_or_last_debug_insn.set_first (prev);
510 // Only valid for debug instructions.  Record that this instruction starts
511 // a subsequence of debug instructions that ends with LAST.
512 inline void
513 insn_info::set_last_debug_insn (insn_info *last)
515   m_prev_insn_or_last_debug_insn.set_second (last);
518 // Record that the next instruction of any kind is NEXT.
519 inline void
520 insn_info::set_next_any_insn (insn_info *next)
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);
528 // Clear the list links and point number for this instruction.
529 inline void
530 insn_info::clear_insn_links ()
532   m_prev_insn_or_last_debug_insn = nullptr;
533   m_next_nondebug_or_debug_insn = nullptr;
534   m_point = 0;
537 // Return true if the instruction contains any list information.
538 // This is used by assert checking.
539 inline bool
540 insn_info::has_insn_links ()
542   return (m_prev_insn_or_last_debug_insn
543           || m_next_nondebug_or_debug_insn
544           || m_point);
547 // Construct a representation of basic block CFG_BB.
548 inline 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)
558 // Construct a tree of call clobbers for the given ABI.
559 inline ebb_call_clobbers_info::
560 ebb_call_clobbers_info (const predefined_function_abi *abi)
561   : m_next (nullptr),
562     m_abi (abi)
566 // Construct an EBB whose first block is FIRST_BB and whose last block
567 // is LAST_BB.
568 inline 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)
577 // Record register definition DEF in last_access, pushing a definition
578 // to def_stack where appropriate.
579 inline void
580 function_info::build_info::record_reg_def (def_info *def)
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;
594 // Set the contents of last_access for memory to DEF.
595 inline void
596 function_info::build_info::record_mem_def (def_info *def)
598   last_access[0] = def;
601 // Return the current value of live register REGNO, or null if the register's
602 // value is completedly undefined.
603 inline set_info *
604 function_info::build_info::current_reg_value (unsigned int regno) const
606   return safe_dyn_cast<set_info *> (last_access[regno + 1]);
609 // Return the current value of memory.
610 inline set_info *
611 function_info::build_info::current_mem_value () const
613   return as_a<set_info *> (last_access[0]);
616 // Allocate a T on the function's main obstack, passing ARGS
617 // to its constructor.
618 template<typename T, typename... Ts>
619 inline T *
620 function_info::allocate (Ts... args)
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)...);
630 // Allocate a T on the function's temporary obstack, passing ARGS
631 // to its constructor.
632 template<typename T, typename... Ts>
633 inline T *
634 function_info::allocate_temp (Ts... args)
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)...);
644 // Add INSN to the end of the function's list of instructions.
645 inline void
646 function_info::append_insn (insn_info *insn)
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;
657 // Start building a new list of uses and definitions for an instruction.
658 inline void
659 function_info::start_insn_accesses ()
661   gcc_checking_assert (m_temp_defs.is_empty ()
662                        && m_temp_uses.is_empty ());
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.
668 inline machine_mode
669 combine_modes (machine_mode mode1, machine_mode mode2)
671   if (mode1 == E_BLKmode)
672     return mode2;
674   if (mode2 == E_BLKmode)
675     return mode1;
677   if (!ordered_p (GET_MODE_SIZE (mode1), GET_MODE_SIZE (mode2)))
678     return BLKmode;
680   return wider_subreg_mode (mode1, mode2);
683 // PRINTER (PP, ARGS...) prints ARGS... to a pretty_printer PP.  Use it
684 // to print ARGS... to FILE.
685 template<typename Printer, typename... Args>
686 inline void
687 dump_using (FILE *file, Printer printer, Args... args)
689   pretty_printer pp;
690   printer (&pp, args...);
691   pp_newline (&pp);
692   fprintf (file, "%s", pp_formatted_text (&pp));