Fix gnat.dg/opt39.adb on hppa.
[official-gcc.git] / gcc / rtl-ssa / member-fns.inl
blobc127fab8b981a88a2f161f711e215c3f8ad65b60
1 // Implementation of public inline member functions for RTL SSA     -*- C++ -*-
2 // Copyright (C) 2020-2023 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::prev_phi_use () const
125   // This is used less often than next_nondebug_insn_use, so it doesn't
126   // seem worth having an m_is_last_nondebug_insn_use-style end marker.
127   if (use_info *use = prev_use ())
128     if (use->is_in_phi ())
129       return use;
130   return nullptr;
133 // Return the last use of any kind in the list.  Only valid when is_first ()
134 // is true.
135 inline use_info *
136 use_info::last_use () const
138   return m_last_use_or_prev_use.known_first ();
141 // Return the last nondebug insn use in the list, or null if none.  Only valid
142 // when is_last_use () is true.
143 inline use_info *
144 use_info::last_nondebug_insn_use () const
146   return m_last_nondebug_insn_use_or_next_use.known_first ();
149 inline def_info *
150 def_info::prev_def () const
152   return m_last_def_or_prev_def.second_or_null ();
155 inline def_info *
156 def_info::next_def () const
158   return m_splay_root_or_next_def.second_or_null ();
161 inline bool
162 def_info::is_first_def () const
164   return m_last_def_or_prev_def.is_first ();
167 inline bool
168 def_info::is_last_def () const
170   return m_splay_root_or_next_def.is_first ();
173 inline bb_info *
174 def_info::bb () const
176   return m_insn->bb ();
179 inline ebb_info *
180 def_info::ebb () const
182   return m_insn->ebb ();
185 inline clobber_group *
186 clobber_info::group () const
188   if (!m_group || !m_group->has_been_superceded ())
189     return m_group;
190   return const_cast<clobber_info *> (this)->recompute_group ();
193 inline use_info *
194 set_info::last_use () const
196   return m_first_use ? m_first_use->last_use () : nullptr;
199 inline use_info *
200 set_info::first_nondebug_insn_use () const
202   if (m_is_set_with_nondebug_insn_uses)
203     return m_first_use;
204   return nullptr;
207 inline use_info *
208 set_info::last_nondebug_insn_use () const
210   if (m_is_set_with_nondebug_insn_uses)
211     return m_first_use->last_use ()->last_nondebug_insn_use ();
212   return nullptr;
215 inline use_info *
216 set_info::first_any_insn_use () const
218   if (m_first_use->is_in_any_insn ())
219     return m_first_use;
220   return nullptr;
223 inline use_info *
224 set_info::last_phi_use () const
226   if (m_first_use)
227     {
228       use_info *last = m_first_use->last_use ();
229       if (last->is_in_phi ())
230         return last;
231     }
232   return nullptr;
235 inline bool
236 set_info::has_nondebug_uses () const
238   return has_nondebug_insn_uses () || has_phi_uses ();
241 inline bool
242 set_info::has_nondebug_insn_uses () const
244   return m_is_set_with_nondebug_insn_uses;
247 inline bool
248 set_info::has_phi_uses () const
250   return m_first_use && m_first_use->last_use ()->is_in_phi ();
253 inline use_info *
254 set_info::single_nondebug_use () const
256   if (!has_phi_uses ())
257     return single_nondebug_insn_use ();
258   if (!has_nondebug_insn_uses ())
259     return single_phi_use ();
260   return nullptr;
263 inline use_info *
264 set_info::single_nondebug_insn_use () const
266   use_info *first = first_nondebug_insn_use ();
267   if (first && !first->next_nondebug_insn_use ())
268     return first;
269   return nullptr;
272 inline use_info *
273 set_info::single_phi_use () const
275   use_info *last = last_phi_use ();
276   if (last && !last->prev_phi_use ())
277     return last;
278   return nullptr;
281 inline bool
282 set_info::is_local_to_ebb () const
284   if (!m_first_use)
285     return true;
287   use_info *last = m_first_use->last_use ();
288   if (last->is_in_phi ())
289     return false;
291   last = last->last_nondebug_insn_use ();
292   return !last || last->ebb () == ebb ();
295 inline iterator_range<use_iterator>
296 set_info::all_uses () const
298   return { m_first_use, nullptr };
301 inline iterator_range<reverse_use_iterator>
302 set_info::reverse_all_uses () const
304   return { last_use (), nullptr };
307 inline iterator_range<nondebug_insn_use_iterator>
308 set_info::nondebug_insn_uses () const
310   return { first_nondebug_insn_use (), nullptr };
313 inline iterator_range<reverse_use_iterator>
314 set_info::reverse_nondebug_insn_uses () const
316   return { last_nondebug_insn_use (), nullptr };
319 inline iterator_range<any_insn_use_iterator>
320 set_info::all_insn_uses () const
322   return { first_any_insn_use (), nullptr };
325 inline iterator_range<phi_use_iterator>
326 set_info::phi_uses () const
328   return { last_phi_use (), nullptr };
331 inline use_array
332 phi_info::inputs () const
334   if (m_num_inputs == 1)
335     return use_array (&m_single_input, 1);
336   return use_array (m_inputs, m_num_inputs);
339 inline use_info *
340 phi_info::input_use (unsigned int i) const
342   if (m_num_inputs == 1)
343     return as_a<use_info *> (m_single_input);
344   return as_a<use_info *> (m_inputs[i]);
347 inline set_info *
348 phi_info::input_value (unsigned int i) const
350   return input_use (i)->def ();
353 inline def_info *
354 def_node::first_def () const
356   // This should get optimized into an AND with -2.
357   if (m_clobber_or_set.is_first ())
358     return m_clobber_or_set.known_first ();
359   return m_clobber_or_set.known_second ();
362 inline clobber_info *
363 clobber_group::first_clobber () const
365   return m_clobber_or_set.known_first ();
368 inline iterator_range<def_iterator>
369 clobber_group::clobbers () const
371   return { first_clobber (), m_last_clobber->next_def () };
374 inline def_info *
375 def_mux::first_def () const
377   if (is_first ())
378     return known_first ();
379   return known_second ()->first_def ();
382 inline def_info *
383 def_mux::last_def () const
385   if (is_first ())
386     return known_first ();
388   def_node *node = known_second ();
389   if (auto *clobber = ::dyn_cast<clobber_group *> (node))
390     return clobber->last_clobber ();
392   return node->first_def ();
395 inline set_info *
396 def_mux::set () const
398   if (is_first ())
399     return ::safe_dyn_cast<set_info *> (known_first ());
400   return ::dyn_cast<set_info *> (known_second ()->first_def ());
403 inline def_info *
404 def_lookup::last_def_of_prev_group () const
406   if (!mux)
407     return nullptr;
409   if (comparison > 0)
410     return mux.last_def ();
412   return mux.first_def ()->prev_def ();
415 inline def_info *
416 def_lookup::first_def_of_next_group () const
418   if (!mux)
419     return nullptr;
421   if (comparison < 0)
422     return mux.first_def ();
424   return mux.last_def ()->next_def ();
427 inline set_info *
428 def_lookup::matching_set () const
430   if (comparison == 0)
431     return mux.set ();
432   return nullptr;
435 inline def_info *
436 def_lookup::matching_set_or_last_def_of_prev_group () const
438   if (set_info *set = matching_set ())
439     return set;
440   return last_def_of_prev_group ();
443 inline def_info *
444 def_lookup::matching_set_or_first_def_of_next_group () const
446   if (set_info *set = matching_set ())
447     return set;
448   return first_def_of_next_group ();
451 inline insn_note::insn_note (insn_note_kind kind)
452   : m_next_note (nullptr),
453     m_kind (kind),
454     m_data8 (0),
455     m_data16 (0),
456     m_data32 (0)
460 template<typename T>
461 inline T
462 insn_note::as_a ()
464   using deref_type = decltype (*std::declval<T> ());
465   using derived = typename std::remove_reference<deref_type>::type;
466   gcc_checking_assert (m_kind == derived::kind);
467   return static_cast<T> (this);
470 template<typename T>
471 inline T
472 insn_note::dyn_cast ()
474   using deref_type = decltype (*std::declval<T> ());
475   using derived = typename std::remove_reference<deref_type>::type;
476   if (m_kind == derived::kind)
477     return static_cast<T> (this);
478   return nullptr;
481 inline bool
482 insn_info::operator< (const insn_info &other) const
484   if (this == &other)
485     return false;
487   if (LIKELY (m_point != other.m_point))
488     return m_point < other.m_point;
490   return slow_compare_with (other) < 0;
493 inline bool
494 insn_info::operator> (const insn_info &other) const
496   return other < *this;
499 inline bool
500 insn_info::operator<= (const insn_info &other) const
502   return !(other < *this);
505 inline bool
506 insn_info::operator>= (const insn_info &other) const
508   return !(*this < other);
511 inline int
512 insn_info::compare_with (const insn_info *other) const
514   if (this == other)
515     return 0;
517   if (LIKELY (m_point != other->m_point))
518     // Assume that points remain in [0, INT_MAX].
519     return m_point - other->m_point;
521   return slow_compare_with (*other);
524 inline insn_info *
525 insn_info::prev_nondebug_insn () const
527   gcc_checking_assert (!is_debug_insn ());
528   return m_prev_insn_or_last_debug_insn.known_first ();
531 inline insn_info *
532 insn_info::next_nondebug_insn () const
534   gcc_checking_assert (!is_debug_insn ());
535   const insn_info *from = this;
536   if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
537     from = first_debug->last_debug_insn ();
538   return from->m_next_nondebug_or_debug_insn.known_first ();
541 inline insn_info *
542 insn_info::prev_any_insn () const
544   const insn_info *from = this;
545   if (insn_info *last_debug = m_prev_insn_or_last_debug_insn.second_or_null ())
546     // This instruction is the first in a subsequence of debug instructions.
547     // Move to the following nondebug instruction.
548     from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
549   return from->m_prev_insn_or_last_debug_insn.known_first ();
552 inline insn_info *
553 insn_info::next_any_insn () const
555   // This should get optimized into an AND with -2.
556   if (m_next_nondebug_or_debug_insn.is_first ())
557     return m_next_nondebug_or_debug_insn.known_first ();
558   return m_next_nondebug_or_debug_insn.known_second ();
561 inline bool
562 insn_info::is_phi () const
564   return this == ebb ()->phi_insn ();
567 inline bool
568 insn_info::is_bb_head () const
570   return this == m_bb->head_insn ();
573 inline bool
574 insn_info::is_bb_end () const
576   return this == m_bb->end_insn ();
579 inline ebb_info *
580 insn_info::ebb () const
582   return m_bb->ebb ();
585 inline int
586 insn_info::uid () const
588   return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
591 inline use_array
592 insn_info::uses () const
594   return use_array (m_accesses + m_num_defs, m_num_uses);
597 inline bool
598 insn_info::has_call_clobbers () const
600   return find_note<insn_call_clobbers_note> ();
603 inline def_array
604 insn_info::defs () const
606   return def_array (m_accesses, m_num_defs);
609 inline unsigned int
610 insn_info::cost () const
612   if (m_cost_or_uid < 0)
613     return 0;
614   if (m_cost_or_uid == UNKNOWN_COST)
615     calculate_cost ();
616   return m_cost_or_uid;
619 template<typename T>
620 inline const T *
621 insn_info::find_note () const
623   // We could break if the note kind is > T::kind, but since the number
624   // of notes should be very small, the check is unlikely to pay for itself.
625   for (const insn_note *note = first_note (); note; note = note->next_note ())
626     if (note->kind () == T::kind)
627       return static_cast<const T *> (note);
628   return nullptr;
631 // Only valid for debug instructions that come after a nondebug instruction,
632 // and so start a subsequence of debug instructions.  Return the last debug
633 // instruction in the subsequence.
634 inline insn_info *
635 insn_info::last_debug_insn () const
637   return m_prev_insn_or_last_debug_insn.known_second ();
640 inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
641   : first (first), last (last)
645 inline bool
646 insn_range_info::operator== (const insn_range_info &other) const
648   return first == other.first && last == other.last;
651 inline bool
652 insn_range_info::operator!= (const insn_range_info &other) const
654   return first != other.first || last != other.last;
657 inline insn_info *
658 insn_range_info::singleton () const
660   return first == last ? last : nullptr;
663 inline bool
664 insn_range_info::includes (insn_info *insn) const
666   return *insn >= *first && *insn <= *last;
669 inline insn_info *
670 insn_range_info::clamp_insn_to_range (insn_info *insn) const
672   if (*first > *insn)
673     return first;
674   if (*last < *insn)
675     return last;
676   return insn;
679 inline bool
680 insn_range_info::is_subrange_of (const insn_range_info &other) const
682   return *first >= *other.first && *last <= *other.last;
685 inline iterator_range<any_insn_iterator>
686 bb_info::all_insns () const
688   return { m_head_insn, m_end_insn->next_any_insn () };
691 inline iterator_range<reverse_any_insn_iterator>
692 bb_info::reverse_all_insns () const
694   return { m_end_insn, m_head_insn->prev_any_insn () };
697 inline iterator_range<nondebug_insn_iterator>
698 bb_info::nondebug_insns () const
700   return { m_head_insn, m_end_insn->next_nondebug_insn () };
703 inline iterator_range<reverse_nondebug_insn_iterator>
704 bb_info::reverse_nondebug_insns () const
706   return { m_end_insn, m_head_insn->prev_nondebug_insn () };
709 inline iterator_range<any_insn_iterator>
710 bb_info::real_insns () const
712   return { m_head_insn->next_any_insn (), m_end_insn };
715 inline iterator_range<reverse_any_insn_iterator>
716 bb_info::reverse_real_insns () const
718   return { m_end_insn->prev_any_insn (), m_head_insn };
721 inline iterator_range<nondebug_insn_iterator>
722 bb_info::real_nondebug_insns () const
724   return { m_head_insn->next_nondebug_insn (), m_end_insn };
727 inline iterator_range<reverse_nondebug_insn_iterator>
728 bb_info::reverse_real_nondebug_insns () const
730   return { m_end_insn->prev_nondebug_insn (), m_head_insn };
733 inline bool
734 ebb_call_clobbers_info::clobbers (resource_info resource) const
736   // Only register clobbers are tracked this way.  Other clobbers are
737   // recorded explicitly.
738   return (resource.is_reg ()
739           && m_abi->clobbers_reg_p (resource.mode, resource.regno));
742 inline ebb_info *
743 ebb_info::prev_ebb () const
745   if (bb_info *prev_bb = m_first_bb->prev_bb ())
746     return prev_bb->ebb ();
747   return nullptr;
750 inline ebb_info *
751 ebb_info::next_ebb () const
753   if (bb_info *next_bb = m_last_bb->next_bb ())
754     return next_bb->ebb ();
755   return nullptr;
758 inline iterator_range<phi_iterator>
759 ebb_info::phis () const
761   return { m_first_phi, nullptr };
764 inline iterator_range<bb_iterator>
765 ebb_info::bbs () const
767   return { m_first_bb, m_last_bb->next_bb () };
770 inline iterator_range<reverse_bb_iterator>
771 ebb_info::reverse_bbs () const
773   return { m_last_bb, m_first_bb->prev_bb () };
776 inline iterator_range<any_insn_iterator>
777 ebb_info::all_insns () const
779   return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
782 inline iterator_range<reverse_any_insn_iterator>
783 ebb_info::reverse_all_insns () const
785   return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
788 inline iterator_range<nondebug_insn_iterator>
789 ebb_info::nondebug_insns () const
791   return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
794 inline iterator_range<reverse_nondebug_insn_iterator>
795 ebb_info::reverse_nondebug_insns () const
797   return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
800 inline insn_range_info
801 ebb_info::insn_range () const
803   return { m_phi_insn, m_last_bb->end_insn () };
806 inline void
807 ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
809   m_first_call_clobbers = call_clobbers;
812 inline ebb_call_clobbers_info *
813 ebb_info::first_call_clobbers () const
815   return m_first_call_clobbers;
818 inline iterator_range<ebb_call_clobbers_iterator>
819 ebb_info::call_clobbers () const
821   return { m_first_call_clobbers, nullptr };
824 inline insn_change::insn_change (insn_info *insn)
825   : m_insn (insn),
826     new_defs (insn->defs ()),
827     new_uses (insn->uses ()),
828     move_range (insn),
829     new_cost (UNKNOWN_COST),
830     m_is_deletion (false)
834 inline insn_change::insn_change (insn_info *insn, delete_action)
835   : m_insn (insn),
836     new_defs (),
837     new_uses (),
838     move_range (insn),
839     new_cost (0),
840     m_is_deletion (true)
844 inline insn_is_changing_closure::
845 insn_is_changing_closure (array_slice<insn_change *const> changes)
846   : m_changes (changes)
850 inline bool
851 insn_is_changing_closure::operator() (const insn_info *insn) const
853   for (const insn_change *change : m_changes)
854     if (change->insn () == insn)
855       return true;
856   return false;
859 inline iterator_range<bb_iterator>
860 function_info::bbs () const
862   return { m_first_bb, nullptr };
865 inline iterator_range<reverse_bb_iterator>
866 function_info::reverse_bbs () const
868   return { m_last_bb, nullptr };
871 inline iterator_range<ebb_iterator>
872 function_info::ebbs () const
874   return { m_first_bb->ebb (), nullptr };
877 inline iterator_range<reverse_ebb_iterator>
878 function_info::reverse_ebbs () const
880   return { m_last_bb->ebb (), nullptr };
883 inline iterator_range<any_insn_iterator>
884 function_info::all_insns () const
886   return { m_first_insn, nullptr };
889 inline iterator_range<reverse_any_insn_iterator>
890 function_info::reverse_all_insns () const
892   return { m_last_insn, nullptr };
895 inline iterator_range<nondebug_insn_iterator>
896 function_info::nondebug_insns () const
898   return { m_first_insn, nullptr };
901 inline iterator_range<reverse_nondebug_insn_iterator>
902 function_info::reverse_nondebug_insns () const
904   return { m_last_insn, nullptr };
907 inline iterator_range<def_iterator>
908 function_info::mem_defs () const
910   return { m_defs[0], nullptr };
913 inline iterator_range<def_iterator>
914 function_info::reg_defs (unsigned int regno) const
916   return { m_defs[regno + 1], nullptr };
919 inline set_info *
920 function_info::single_dominating_def (unsigned int regno) const
922   if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
923     if (is_single_dominating_def (set))
924       return set;
925   return nullptr;
928 template<typename IgnorePredicate>
929 bool
930 function_info::add_regno_clobber (obstack_watermark &watermark,
931                                   insn_change &change, unsigned int regno,
932                                   IgnorePredicate ignore)
934   // Check whether CHANGE already clobbers REGNO.
935   if (find_access (change.new_defs, regno))
936     return true;
938   // Get the closest position to INSN at which the new instruction
939   // could be placed.
940   insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
941   def_array new_defs = insert_temp_clobber (watermark, insn, regno,
942                                             change.new_defs);
943   if (!new_defs.is_valid ())
944     return false;
946   // Find a definition at or neighboring INSN.
947   insn_range_info move_range = change.move_range;
948   if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
949     return false;
951   change.new_defs = new_defs;
952   change.move_range = move_range;
953   return true;