hppa: Fix REG+D address support before reload
[official-gcc.git] / gcc / rtl-ssa / member-fns.inl
blobe4825ad2a184d3df715306f0f643897f16445c70
1 // Implementation of public 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 // This file contains inline implementations of public member functions that
21 // are too large to be written in the class definition.  It also contains
22 // some non-inline template definitions of public member functions.
23 // See the comments above the function declarations for details.
25 // The file also contains the bare minimum of private and protected inline
26 // member functions that are needed to make the public functions compile.
27 namespace rtl_ssa {
29 inline void
30 access_array_builder::reserve (unsigned int num_accesses)
32   obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
35 inline void
36 access_array_builder::quick_push (access_info *access)
38   obstack_ptr_grow_fast (m_obstack, access);
41 inline array_slice<access_info *>
42 access_array_builder::finish ()
44   auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
45   if (num_accesses == 0)
46     return {};
48   auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
49   keep ();
50   return { base, num_accesses };
53 inline bool
54 access_info::is_set_with_nondebug_insn_uses () const
56   return m_is_set_with_nondebug_insn_uses;
59 inline bool
60 use_info::is_in_debug_insn () const
62   return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
65 inline bb_info *
66 use_info::bb () const
68   if (m_insn_or_phi.is_first ())
69     return m_insn_or_phi.known_first ()->bb ();
70   return m_insn_or_phi.known_second ()->bb ();
73 inline ebb_info *
74 use_info::ebb () const
76   return bb ()->ebb ();
79 inline use_info *
80 use_info::prev_use () const
82   return m_last_use_or_prev_use.second_or_null ();
85 inline use_info *
86 use_info::next_use () const
88   return m_last_nondebug_insn_use_or_next_use.second_or_null ();
91 inline bool
92 use_info::is_first_use () const
94   return m_last_use_or_prev_use.is_first ();
97 inline bool
98 use_info::is_last_use () const
100   return m_last_nondebug_insn_use_or_next_use.is_first ();
103 inline use_info *
104 use_info::next_nondebug_insn_use () const
106   if (m_is_last_nondebug_insn_use)
107     return nullptr;
108   return m_last_nondebug_insn_use_or_next_use.known_second ();
111 inline use_info *
112 use_info::next_any_insn_use () const
114   // This is used less often than next_nondebug_insn_use, so it doesn't
115   // seem worth having an m_is_last_nondebug_insn_use-style end marker.
116   if (use_info *use = next_use ())
117     if (use->is_in_any_insn ())
118       return use;
119   return nullptr;
122 inline use_info *
123 use_info::next_debug_insn_use () const
125   if (auto use = next_use ())
126     if (use->is_in_debug_insn ())
127       return use;
128   return nullptr;
131 inline use_info *
132 use_info::prev_phi_use () const
134   // This is used less often than next_nondebug_insn_use, so it doesn't
135   // seem worth having an m_is_last_nondebug_insn_use-style end marker.
136   if (use_info *use = prev_use ())
137     if (use->is_in_phi ())
138       return use;
139   return nullptr;
142 // Return the last use of any kind in the list.  Only valid when is_first ()
143 // is true.
144 inline use_info *
145 use_info::last_use () const
147   return m_last_use_or_prev_use.known_first ();
150 // Return the last nondebug insn use in the list, or null if none.  Only valid
151 // when is_last_use () is true.
152 inline use_info *
153 use_info::last_nondebug_insn_use () const
155   return m_last_nondebug_insn_use_or_next_use.known_first ();
158 inline def_info *
159 def_info::prev_def () const
161   return m_last_def_or_prev_def.second_or_null ();
164 inline def_info *
165 def_info::next_def () const
167   return m_splay_root_or_next_def.second_or_null ();
170 inline bool
171 def_info::is_first_def () const
173   return m_last_def_or_prev_def.is_first ();
176 inline bool
177 def_info::is_last_def () const
179   return m_splay_root_or_next_def.is_first ();
182 inline bb_info *
183 def_info::bb () const
185   return m_insn->bb ();
188 inline ebb_info *
189 def_info::ebb () const
191   return m_insn->ebb ();
194 inline clobber_group *
195 clobber_info::group () const
197   if (!m_group || !m_group->has_been_superceded ())
198     return m_group;
199   return const_cast<clobber_info *> (this)->recompute_group ();
202 inline use_info *
203 set_info::last_use () const
205   return m_first_use ? m_first_use->last_use () : nullptr;
208 inline use_info *
209 set_info::first_nondebug_insn_use () const
211   if (m_is_set_with_nondebug_insn_uses)
212     return m_first_use;
213   return nullptr;
216 inline use_info *
217 set_info::last_nondebug_insn_use () const
219   if (m_is_set_with_nondebug_insn_uses)
220     return m_first_use->last_use ()->last_nondebug_insn_use ();
221   return nullptr;
224 inline use_info *
225 set_info::first_debug_insn_use () const
227   use_info *use;
228   if (has_nondebug_insn_uses ())
229     use = last_nondebug_insn_use ()->next_use ();
230   else
231     use = first_use ();
233   if (use && use->is_in_debug_insn ())
234     return use;
235   return nullptr;
238 inline use_info *
239 set_info::first_any_insn_use () const
241   if (m_first_use && m_first_use->is_in_any_insn ())
242     return m_first_use;
243   return nullptr;
246 inline use_info *
247 set_info::last_phi_use () const
249   if (m_first_use)
250     {
251       use_info *last = m_first_use->last_use ();
252       if (last->is_in_phi ())
253         return last;
254     }
255   return nullptr;
258 inline bool
259 set_info::has_nondebug_uses () const
261   return has_nondebug_insn_uses () || has_phi_uses ();
264 inline bool
265 set_info::has_nondebug_insn_uses () const
267   return m_is_set_with_nondebug_insn_uses;
270 inline bool
271 set_info::has_phi_uses () const
273   return m_first_use && m_first_use->last_use ()->is_in_phi ();
276 inline use_info *
277 set_info::single_nondebug_use () const
279   if (!has_phi_uses ())
280     return single_nondebug_insn_use ();
281   if (!has_nondebug_insn_uses ())
282     return single_phi_use ();
283   return nullptr;
286 inline use_info *
287 set_info::single_nondebug_insn_use () const
289   use_info *first = first_nondebug_insn_use ();
290   if (first && !first->next_nondebug_insn_use ())
291     return first;
292   return nullptr;
295 inline use_info *
296 set_info::single_phi_use () const
298   use_info *last = last_phi_use ();
299   if (last && !last->prev_phi_use ())
300     return last;
301   return nullptr;
304 inline bool
305 set_info::is_local_to_ebb () const
307   if (!m_first_use)
308     return true;
310   use_info *last = m_first_use->last_use ();
311   if (last->is_in_phi ())
312     return false;
314   last = last->last_nondebug_insn_use ();
315   return !last || last->ebb () == ebb ();
318 inline iterator_range<use_iterator>
319 set_info::all_uses () const
321   return { m_first_use, nullptr };
324 inline iterator_range<reverse_use_iterator>
325 set_info::reverse_all_uses () const
327   return { last_use (), nullptr };
330 inline iterator_range<nondebug_insn_use_iterator>
331 set_info::nondebug_insn_uses () const
333   return { first_nondebug_insn_use (), nullptr };
336 inline iterator_range<debug_insn_use_iterator>
337 set_info::debug_insn_uses () const
339   return { first_debug_insn_use (), nullptr };
342 inline iterator_range<reverse_use_iterator>
343 set_info::reverse_nondebug_insn_uses () const
345   return { last_nondebug_insn_use (), nullptr };
348 inline iterator_range<any_insn_use_iterator>
349 set_info::all_insn_uses () const
351   return { first_any_insn_use (), nullptr };
354 inline iterator_range<phi_use_iterator>
355 set_info::phi_uses () const
357   return { last_phi_use (), nullptr };
360 inline use_array
361 phi_info::inputs () const
363   if (m_num_inputs == 1)
364     return use_array (&m_single_input, 1);
365   return use_array (m_inputs, m_num_inputs);
368 inline use_info *
369 phi_info::input_use (unsigned int i) const
371   if (m_num_inputs == 1)
372     return as_a<use_info *> (m_single_input);
373   return as_a<use_info *> (m_inputs[i]);
376 inline set_info *
377 phi_info::input_value (unsigned int i) const
379   return input_use (i)->def ();
382 inline def_info *
383 def_node::first_def () const
385   // This should get optimized into an AND with -2.
386   if (m_clobber_or_set.is_first ())
387     return m_clobber_or_set.known_first ();
388   return m_clobber_or_set.known_second ();
391 inline clobber_info *
392 clobber_group::first_clobber () const
394   return m_clobber_or_set.known_first ();
397 inline iterator_range<def_iterator>
398 clobber_group::clobbers () const
400   return { first_clobber (), m_last_clobber->next_def () };
403 inline def_info *
404 def_mux::first_def () const
406   if (is_first ())
407     return known_first ();
408   return known_second ()->first_def ();
411 inline def_info *
412 def_mux::last_def () const
414   if (is_first ())
415     return known_first ();
417   def_node *node = known_second ();
418   if (auto *clobber = ::dyn_cast<clobber_group *> (node))
419     return clobber->last_clobber ();
421   return node->first_def ();
424 inline set_info *
425 def_mux::set () const
427   if (is_first ())
428     return ::safe_dyn_cast<set_info *> (known_first ());
429   return ::dyn_cast<set_info *> (known_second ()->first_def ());
432 inline def_info *
433 def_lookup::last_def_of_prev_group () const
435   if (!mux)
436     return nullptr;
438   if (comparison > 0)
439     return mux.last_def ();
441   return mux.first_def ()->prev_def ();
444 inline def_info *
445 def_lookup::first_def_of_next_group () const
447   if (!mux)
448     return nullptr;
450   if (comparison < 0)
451     return mux.first_def ();
453   return mux.last_def ()->next_def ();
456 inline set_info *
457 def_lookup::matching_set () const
459   if (comparison == 0)
460     return mux.set ();
461   return nullptr;
464 inline def_info *
465 def_lookup::matching_set_or_last_def_of_prev_group () const
467   if (set_info *set = matching_set ())
468     return set;
469   return last_def_of_prev_group ();
472 inline def_info *
473 def_lookup::matching_set_or_first_def_of_next_group () const
475   if (set_info *set = matching_set ())
476     return set;
477   return first_def_of_next_group ();
480 inline insn_note::insn_note (insn_note_kind kind)
481   : m_next_note (nullptr),
482     m_kind (kind),
483     m_data8 (0),
484     m_data16 (0),
485     m_data32 (0)
489 template<typename T>
490 inline T
491 insn_note::as_a ()
493   using deref_type = decltype (*std::declval<T> ());
494   using derived = typename std::remove_reference<deref_type>::type;
495   gcc_checking_assert (m_kind == derived::kind);
496   return static_cast<T> (this);
499 template<typename T>
500 inline T
501 insn_note::dyn_cast ()
503   using deref_type = decltype (*std::declval<T> ());
504   using derived = typename std::remove_reference<deref_type>::type;
505   if (m_kind == derived::kind)
506     return static_cast<T> (this);
507   return nullptr;
510 inline bool
511 insn_info::operator< (const insn_info &other) const
513   if (this == &other)
514     return false;
516   if (LIKELY (m_point != other.m_point))
517     return m_point < other.m_point;
519   return slow_compare_with (other) < 0;
522 inline bool
523 insn_info::operator> (const insn_info &other) const
525   return other < *this;
528 inline bool
529 insn_info::operator<= (const insn_info &other) const
531   return !(other < *this);
534 inline bool
535 insn_info::operator>= (const insn_info &other) const
537   return !(*this < other);
540 inline int
541 insn_info::compare_with (const insn_info *other) const
543   if (this == other)
544     return 0;
546   if (LIKELY (m_point != other->m_point))
547     // Assume that points remain in [0, INT_MAX].
548     return m_point - other->m_point;
550   return slow_compare_with (*other);
553 inline insn_info *
554 insn_info::prev_nondebug_insn () const
556   gcc_checking_assert (!is_debug_insn ());
557   return m_prev_insn_or_last_debug_insn.known_first ();
560 inline insn_info *
561 insn_info::next_nondebug_insn () const
563   gcc_checking_assert (!is_debug_insn ());
564   const insn_info *from = this;
565   if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
566     from = first_debug->last_debug_insn ();
567   return from->m_next_nondebug_or_debug_insn.known_first ();
570 inline insn_info *
571 insn_info::prev_any_insn () const
573   const insn_info *from = this;
574   if (insn_info *last_debug = m_prev_insn_or_last_debug_insn.second_or_null ())
575     // This instruction is the first in a subsequence of debug instructions.
576     // Move to the following nondebug instruction.
577     from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
578   return from->m_prev_insn_or_last_debug_insn.known_first ();
581 inline insn_info *
582 insn_info::next_any_insn () const
584   // This should get optimized into an AND with -2.
585   if (m_next_nondebug_or_debug_insn.is_first ())
586     return m_next_nondebug_or_debug_insn.known_first ();
587   return m_next_nondebug_or_debug_insn.known_second ();
590 inline bool
591 insn_info::is_phi () const
593   return this == ebb ()->phi_insn ();
596 inline bool
597 insn_info::is_bb_head () const
599   return this == m_bb->head_insn ();
602 inline bool
603 insn_info::is_bb_end () const
605   return this == m_bb->end_insn ();
608 inline ebb_info *
609 insn_info::ebb () const
611   return m_bb->ebb ();
614 inline int
615 insn_info::uid () const
617   return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
620 inline use_array
621 insn_info::uses () const
623   return use_array (m_accesses + m_num_defs, m_num_uses);
626 inline bool
627 insn_info::has_call_clobbers () const
629   return find_note<insn_call_clobbers_note> ();
632 inline def_array
633 insn_info::defs () const
635   return def_array (m_accesses, m_num_defs);
638 inline unsigned int
639 insn_info::cost () const
641   if (m_cost_or_uid < 0)
642     return 0;
643   if (m_cost_or_uid == UNKNOWN_COST)
644     calculate_cost ();
645   return m_cost_or_uid;
648 template<typename T>
649 inline const T *
650 insn_info::find_note () const
652   // We could break if the note kind is > T::kind, but since the number
653   // of notes should be very small, the check is unlikely to pay for itself.
654   for (const insn_note *note = first_note (); note; note = note->next_note ())
655     if (note->kind () == T::kind)
656       return static_cast<const T *> (note);
657   return nullptr;
660 // Only valid for debug instructions that come after a nondebug instruction,
661 // and so start a subsequence of debug instructions.  Return the last debug
662 // instruction in the subsequence.
663 inline insn_info *
664 insn_info::last_debug_insn () const
666   return m_prev_insn_or_last_debug_insn.known_second ();
669 inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
670   : first (first), last (last)
674 inline bool
675 insn_range_info::operator== (const insn_range_info &other) const
677   return first == other.first && last == other.last;
680 inline bool
681 insn_range_info::operator!= (const insn_range_info &other) const
683   return first != other.first || last != other.last;
686 inline insn_info *
687 insn_range_info::singleton () const
689   return first == last ? last : nullptr;
692 inline bool
693 insn_range_info::includes (insn_info *insn) const
695   return *insn >= *first && *insn <= *last;
698 inline insn_info *
699 insn_range_info::clamp_insn_to_range (insn_info *insn) const
701   if (*first > *insn)
702     return first;
703   if (*last < *insn)
704     return last;
705   return insn;
708 inline bool
709 insn_range_info::is_subrange_of (const insn_range_info &other) const
711   return *first >= *other.first && *last <= *other.last;
714 inline iterator_range<any_insn_iterator>
715 bb_info::all_insns () const
717   return { m_head_insn, m_end_insn->next_any_insn () };
720 inline iterator_range<reverse_any_insn_iterator>
721 bb_info::reverse_all_insns () const
723   return { m_end_insn, m_head_insn->prev_any_insn () };
726 inline iterator_range<nondebug_insn_iterator>
727 bb_info::nondebug_insns () const
729   return { m_head_insn, m_end_insn->next_nondebug_insn () };
732 inline iterator_range<reverse_nondebug_insn_iterator>
733 bb_info::reverse_nondebug_insns () const
735   return { m_end_insn, m_head_insn->prev_nondebug_insn () };
738 inline iterator_range<any_insn_iterator>
739 bb_info::real_insns () const
741   return { m_head_insn->next_any_insn (), m_end_insn };
744 inline iterator_range<reverse_any_insn_iterator>
745 bb_info::reverse_real_insns () const
747   return { m_end_insn->prev_any_insn (), m_head_insn };
750 inline iterator_range<nondebug_insn_iterator>
751 bb_info::real_nondebug_insns () const
753   return { m_head_insn->next_nondebug_insn (), m_end_insn };
756 inline iterator_range<reverse_nondebug_insn_iterator>
757 bb_info::reverse_real_nondebug_insns () const
759   return { m_end_insn->prev_nondebug_insn (), m_head_insn };
762 inline bool
763 ebb_call_clobbers_info::clobbers (resource_info resource) const
765   // Only register clobbers are tracked this way.  Other clobbers are
766   // recorded explicitly.
767   return (resource.is_reg ()
768           && m_abi->clobbers_reg_p (resource.mode, resource.regno));
771 inline ebb_info *
772 ebb_info::prev_ebb () const
774   if (bb_info *prev_bb = m_first_bb->prev_bb ())
775     return prev_bb->ebb ();
776   return nullptr;
779 inline ebb_info *
780 ebb_info::next_ebb () const
782   if (bb_info *next_bb = m_last_bb->next_bb ())
783     return next_bb->ebb ();
784   return nullptr;
787 inline iterator_range<phi_iterator>
788 ebb_info::phis () const
790   return { m_first_phi, nullptr };
793 inline iterator_range<bb_iterator>
794 ebb_info::bbs () const
796   return { m_first_bb, m_last_bb->next_bb () };
799 inline iterator_range<reverse_bb_iterator>
800 ebb_info::reverse_bbs () const
802   return { m_last_bb, m_first_bb->prev_bb () };
805 inline iterator_range<any_insn_iterator>
806 ebb_info::all_insns () const
808   return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
811 inline iterator_range<reverse_any_insn_iterator>
812 ebb_info::reverse_all_insns () const
814   return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
817 inline iterator_range<nondebug_insn_iterator>
818 ebb_info::nondebug_insns () const
820   return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
823 inline iterator_range<reverse_nondebug_insn_iterator>
824 ebb_info::reverse_nondebug_insns () const
826   return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
829 inline insn_range_info
830 ebb_info::insn_range () const
832   return { m_phi_insn, m_last_bb->end_insn () };
835 inline void
836 ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
838   m_first_call_clobbers = call_clobbers;
841 inline ebb_call_clobbers_info *
842 ebb_info::first_call_clobbers () const
844   return m_first_call_clobbers;
847 inline iterator_range<ebb_call_clobbers_iterator>
848 ebb_info::call_clobbers () const
850   return { m_first_call_clobbers, nullptr };
853 inline insn_change::insn_change (insn_info *insn)
854   : m_insn (insn),
855     new_defs (insn->defs ()),
856     new_uses (insn->uses ()),
857     move_range (insn),
858     new_cost (UNKNOWN_COST),
859     m_is_deletion (false)
863 inline insn_change::insn_change (insn_info *insn, delete_action)
864   : m_insn (insn),
865     new_defs (),
866     new_uses (),
867     move_range (insn),
868     new_cost (0),
869     m_is_deletion (true)
873 inline insn_is_changing_closure::
874 insn_is_changing_closure (array_slice<insn_change *const> changes)
875   : m_changes (changes)
879 inline bool
880 insn_is_changing_closure::operator() (const insn_info *insn) const
882   for (const insn_change *change : m_changes)
883     if (change->insn () == insn)
884       return true;
885   return false;
888 inline iterator_range<bb_iterator>
889 function_info::bbs () const
891   return { m_first_bb, nullptr };
894 inline iterator_range<reverse_bb_iterator>
895 function_info::reverse_bbs () const
897   return { m_last_bb, nullptr };
900 inline iterator_range<ebb_iterator>
901 function_info::ebbs () const
903   return { m_first_bb->ebb (), nullptr };
906 inline iterator_range<reverse_ebb_iterator>
907 function_info::reverse_ebbs () const
909   return { m_last_bb->ebb (), nullptr };
912 inline iterator_range<any_insn_iterator>
913 function_info::all_insns () const
915   return { m_first_insn, nullptr };
918 inline iterator_range<reverse_any_insn_iterator>
919 function_info::reverse_all_insns () const
921   return { m_last_insn, nullptr };
924 inline iterator_range<nondebug_insn_iterator>
925 function_info::nondebug_insns () const
927   return { m_first_insn, nullptr };
930 inline iterator_range<reverse_nondebug_insn_iterator>
931 function_info::reverse_nondebug_insns () const
933   return { m_last_insn, nullptr };
936 inline iterator_range<def_iterator>
937 function_info::mem_defs () const
939   return { m_defs[0], nullptr };
942 inline iterator_range<def_iterator>
943 function_info::reg_defs (unsigned int regno) const
945   return { m_defs[regno + 1], nullptr };
948 inline bool
949 function_info::is_single_dominating_def (const set_info *set) const
951   return (set->is_first_def ()
952           && set->is_last_def ()
953           && (!HARD_REGISTER_NUM_P (set->regno ())
954               || !TEST_HARD_REG_BIT (m_clobbered_by_calls, set->regno ())));
957 inline set_info *
958 function_info::single_dominating_def (unsigned int regno) const
960   if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
961     if (is_single_dominating_def (set))
962       return set;
963   return nullptr;
966 template<typename IgnorePredicate>
967 bool
968 function_info::add_regno_clobber (obstack_watermark &watermark,
969                                   insn_change &change, unsigned int regno,
970                                   IgnorePredicate ignore)
972   // Check whether CHANGE already clobbers REGNO.
973   if (find_access (change.new_defs, regno))
974     return true;
976   // Get the closest position to INSN at which the new instruction
977   // could be placed.
978   insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
979   def_array new_defs = insert_temp_clobber (watermark, insn, regno,
980                                             change.new_defs);
981   if (!new_defs.is_valid ())
982     return false;
984   // Find a definition at or neighboring INSN.
985   insn_range_info move_range = change.move_range;
986   if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
987     return false;
989   change.new_defs = new_defs;
990   change.move_range = move_range;
991   return true;
994 template<typename T, typename... Ts>
995 inline T *
996 function_info::change_alloc (obstack_watermark &wm, Ts... args)
998   static_assert (std::is_trivially_destructible<T>::value,
999                  "destructor won't be called");
1000   static_assert (alignof (T) <= obstack_alignment,
1001                  "too much alignment required");
1002   void *addr = XOBNEW (wm, T);
1003   return new (addr) T (std::forward<Ts> (args)...);