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.
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
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.
24//
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.
27namespace rtl_ssa {
28
29inline void
30access_array_builder::reserve (unsigned int num_accesses)
31{
32 obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
33}
34
35inline void
36access_array_builder::quick_push (access_info *access)
37{
38 obstack_ptr_grow_fast (m_obstack, access);
39}
40
41inline array_slice<access_info *>
42access_array_builder::finish ()
43{
44 auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
45 if (num_accesses == 0)
46 return {};
47
48 auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
49 keep ();
50 return { base, num_accesses };
51}
52
53inline bool
54access_info::is_set_with_nondebug_insn_uses () const
55{
56 return m_is_set_with_nondebug_insn_uses;
57}
58
59inline bool
60use_info::is_in_debug_insn () const
61{
62 return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
63}
64
65inline bb_info *
66use_info::bb () const
67{
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 ();
71}
72
73inline ebb_info *
74use_info::ebb () const
75{
76 return bb ()->ebb ();
77}
78
79inline use_info *
80use_info::prev_use () const
81{
82 return m_last_use_or_prev_use.second_or_null ();
83}
84
85inline use_info *
86use_info::next_use () const
87{
88 return m_last_nondebug_insn_use_or_next_use.second_or_null ();
89}
90
91inline bool
92use_info::is_first_use () const
93{
94 return m_last_use_or_prev_use.is_first ();
95}
96
97inline bool
98use_info::is_last_use () const
99{
100 return m_last_nondebug_insn_use_or_next_use.is_first ();
101}
102
103inline use_info *
104use_info::next_nondebug_insn_use () const
105{
106 if (m_is_last_nondebug_insn_use)
107 return nullptr;
108 return m_last_nondebug_insn_use_or_next_use.known_second ();
109}
110
111inline use_info *
112use_info::next_any_insn_use () const
113{
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;
120}
121
122inline use_info *
123use_info::next_debug_insn_use () const
124{
125 if (auto use = next_use ())
126 if (use->is_in_debug_insn ())
127 return use;
128 return nullptr;
129}
130
131inline use_info *
132use_info::prev_phi_use () const
133{
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;
140}
141
142// Return the last use of any kind in the list. Only valid when is_first ()
143// is true.
144inline use_info *
145use_info::last_use () const
146{
147 return m_last_use_or_prev_use.known_first ();
148}
149
150// Return the last nondebug insn use in the list, or null if none. Only valid
151// when is_last_use () is true.
152inline use_info *
153use_info::last_nondebug_insn_use () const
154{
155 return m_last_nondebug_insn_use_or_next_use.known_first ();
156}
157
158inline def_info *
159def_info::prev_def () const
160{
161 return m_last_def_or_prev_def.second_or_null ();
162}
163
164inline def_info *
165def_info::next_def () const
166{
167 return m_splay_root_or_next_def.second_or_null ();
168}
169
170inline bool
171def_info::is_first_def () const
172{
173 return m_last_def_or_prev_def.is_first ();
174}
175
176inline bool
177def_info::is_last_def () const
178{
179 return m_splay_root_or_next_def.is_first ();
180}
181
182inline bb_info *
183def_info::bb () const
184{
185 return m_insn->bb ();
186}
187
188inline ebb_info *
189def_info::ebb () const
190{
191 return m_insn->ebb ();
192}
193
194inline clobber_group *
195clobber_info::group () const
196{
197 if (!m_group || !m_group->has_been_superceded ())
198 return m_group;
199 return const_cast<clobber_info *> (this)->recompute_group ();
200}
201
202inline use_info *
203set_info::last_use () const
204{
205 return m_first_use ? m_first_use->last_use () : nullptr;
206}
207
208inline use_info *
209set_info::first_nondebug_insn_use () const
210{
211 if (m_is_set_with_nondebug_insn_uses)
212 return m_first_use;
213 return nullptr;
214}
215
216inline use_info *
217set_info::last_nondebug_insn_use () const
218{
219 if (m_is_set_with_nondebug_insn_uses)
220 return m_first_use->last_use ()->last_nondebug_insn_use ();
221 return nullptr;
222}
223
224inline use_info *
225set_info::first_debug_insn_use () const
226{
227 use_info *use;
228 if (has_nondebug_insn_uses ())
229 use = last_nondebug_insn_use ()->next_use ();
230 else
231 use = first_use ();
232
233 if (use && use->is_in_debug_insn ())
234 return use;
235 return nullptr;
236}
237
238inline use_info *
239set_info::first_any_insn_use () const
240{
241 if (m_first_use && m_first_use->is_in_any_insn ())
242 return m_first_use;
243 return nullptr;
244}
245
246inline use_info *
247set_info::last_phi_use () const
248{
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;
256}
257
258inline bool
259set_info::has_nondebug_uses () const
260{
261 return has_nondebug_insn_uses () || has_phi_uses ();
262}
263
264inline bool
265set_info::has_nondebug_insn_uses () const
266{
267 return m_is_set_with_nondebug_insn_uses;
268}
269
270inline bool
271set_info::has_phi_uses () const
272{
273 return m_first_use && m_first_use->last_use ()->is_in_phi ();
274}
275
276inline use_info *
277set_info::single_nondebug_use () const
278{
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;
284}
285
286inline use_info *
287set_info::single_nondebug_insn_use () const
288{
289 use_info *first = first_nondebug_insn_use ();
290 if (first && !first->next_nondebug_insn_use ())
291 return first;
292 return nullptr;
293}
294
295inline use_info *
296set_info::single_phi_use () const
297{
298 use_info *last = last_phi_use ();
299 if (last && !last->prev_phi_use ())
300 return last;
301 return nullptr;
302}
303
304inline bool
305set_info::is_local_to_ebb () const
306{
307 if (!m_first_use)
308 return true;
309
310 use_info *last = m_first_use->last_use ();
311 if (last->is_in_phi ())
312 return false;
313
314 last = last->last_nondebug_insn_use ();
315 return !last || last->ebb () == ebb ();
316}
317
318inline iterator_range<use_iterator>
319set_info::all_uses () const
320{
321 return { m_first_use, nullptr };
322}
323
324inline iterator_range<reverse_use_iterator>
325set_info::reverse_all_uses () const
326{
327 return { last_use (), nullptr };
328}
329
330inline iterator_range<nondebug_insn_use_iterator>
331set_info::nondebug_insn_uses () const
332{
333 return { first_nondebug_insn_use (), nullptr };
334}
335
336inline iterator_range<debug_insn_use_iterator>
337set_info::debug_insn_uses () const
338{
339 return { first_debug_insn_use (), nullptr };
340}
341
342inline iterator_range<reverse_use_iterator>
343set_info::reverse_nondebug_insn_uses () const
344{
345 return { last_nondebug_insn_use (), nullptr };
346}
347
348inline iterator_range<any_insn_use_iterator>
349set_info::all_insn_uses () const
350{
351 return { first_any_insn_use (), nullptr };
352}
353
354inline iterator_range<phi_use_iterator>
355set_info::phi_uses () const
356{
357 return { last_phi_use (), nullptr };
358}
359
360inline use_array
361phi_info::inputs () const
362{
363 if (m_num_inputs == 1)
364 return use_array (&m_single_input, 1);
365 return use_array (m_inputs, m_num_inputs);
366}
367
368inline use_info *
369phi_info::input_use (unsigned int i) const
370{
371 if (m_num_inputs == 1)
372 return as_a<use_info *> (p: m_single_input);
373 return as_a<use_info *> (p: m_inputs[i]);
374}
375
376inline set_info *
377phi_info::input_value (unsigned int i) const
378{
379 return input_use (i)->def ();
380}
381
382inline def_info *
383def_node::first_def () const
384{
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 ();
389}
390
391inline clobber_info *
392clobber_group::first_clobber () const
393{
394 return m_clobber_or_set.known_first ();
395}
396
397inline iterator_range<def_iterator>
398clobber_group::clobbers () const
399{
400 return { first_clobber (), m_last_clobber->next_def () };
401}
402
403inline def_info *
404def_mux::first_def () const
405{
406 if (is_first ())
407 return known_first ();
408 return known_second ()->first_def ();
409}
410
411inline def_info *
412def_mux::last_def () const
413{
414 if (is_first ())
415 return known_first ();
416
417 def_node *node = known_second ();
418 if (auto *clobber = ::dyn_cast<clobber_group *> (p: node))
419 return clobber->last_clobber ();
420
421 return node->first_def ();
422}
423
424inline set_info *
425def_mux::set () const
426{
427 if (is_first ())
428 return ::safe_dyn_cast<set_info *> (p: known_first ());
429 return ::dyn_cast<set_info *> (p: known_second ()->first_def ());
430}
431
432inline def_info *
433def_lookup::last_def_of_prev_group () const
434{
435 if (!mux)
436 return nullptr;
437
438 if (comparison > 0)
439 return mux.last_def ();
440
441 return mux.first_def ()->prev_def ();
442}
443
444inline def_info *
445def_lookup::first_def_of_next_group () const
446{
447 if (!mux)
448 return nullptr;
449
450 if (comparison < 0)
451 return mux.first_def ();
452
453 return mux.last_def ()->next_def ();
454}
455
456inline set_info *
457def_lookup::matching_set () const
458{
459 if (comparison == 0)
460 return mux.set ();
461 return nullptr;
462}
463
464inline def_info *
465def_lookup::matching_set_or_last_def_of_prev_group () const
466{
467 if (set_info *set = matching_set ())
468 return set;
469 return last_def_of_prev_group ();
470}
471
472inline def_info *
473def_lookup::matching_set_or_first_def_of_next_group () const
474{
475 if (set_info *set = matching_set ())
476 return set;
477 return first_def_of_next_group ();
478}
479
480inline 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)
486{
487}
488
489template<typename T>
490inline T
491insn_note::as_a ()
492{
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);
497}
498
499template<typename T>
500inline T
501insn_note::dyn_cast ()
502{
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;
508}
509
510inline bool
511insn_info::operator< (const insn_info &other) const
512{
513 if (this == &other)
514 return false;
515
516 if (LIKELY (m_point != other.m_point))
517 return m_point < other.m_point;
518
519 return slow_compare_with (other) < 0;
520}
521
522inline bool
523insn_info::operator> (const insn_info &other) const
524{
525 return other < *this;
526}
527
528inline bool
529insn_info::operator<= (const insn_info &other) const
530{
531 return !(other < *this);
532}
533
534inline bool
535insn_info::operator>= (const insn_info &other) const
536{
537 return !(*this < other);
538}
539
540inline int
541insn_info::compare_with (const insn_info *other) const
542{
543 if (this == other)
544 return 0;
545
546 if (LIKELY (m_point != other->m_point))
547 // Assume that points remain in [0, INT_MAX].
548 return m_point - other->m_point;
549
550 return slow_compare_with (*other);
551}
552
553inline insn_info *
554insn_info::prev_nondebug_insn () const
555{
556 gcc_checking_assert (!is_debug_insn ());
557 return m_prev_insn_or_last_debug_insn.known_first ();
558}
559
560inline insn_info *
561insn_info::next_nondebug_insn () const
562{
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 ();
568}
569
570inline insn_info *
571insn_info::prev_any_insn () const
572{
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 ();
579}
580
581inline insn_info *
582insn_info::next_any_insn () const
583{
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 ();
588}
589
590inline bool
591insn_info::is_phi () const
592{
593 return this == ebb ()->phi_insn ();
594}
595
596inline bool
597insn_info::is_bb_head () const
598{
599 return this == m_bb->head_insn ();
600}
601
602inline bool
603insn_info::is_bb_end () const
604{
605 return this == m_bb->end_insn ();
606}
607
608inline ebb_info *
609insn_info::ebb () const
610{
611 return m_bb->ebb ();
612}
613
614inline int
615insn_info::uid () const
616{
617 return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (insn: m_rtl);
618}
619
620inline use_array
621insn_info::uses () const
622{
623 return use_array (m_accesses + m_num_defs, m_num_uses);
624}
625
626inline bool
627insn_info::has_call_clobbers () const
628{
629 return find_note<insn_call_clobbers_note> ();
630}
631
632inline def_array
633insn_info::defs () const
634{
635 return def_array (m_accesses, m_num_defs);
636}
637
638inline unsigned int
639insn_info::cost () const
640{
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;
646}
647
648template<typename T>
649inline const T *
650insn_info::find_note () const
651{
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;
658}
659
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.
663inline insn_info *
664insn_info::last_debug_insn () const
665{
666 return m_prev_insn_or_last_debug_insn.known_second ();
667}
668
669inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
670 : first (first), last (last)
671{
672}
673
674inline bool
675insn_range_info::operator== (const insn_range_info &other) const
676{
677 return first == other.first && last == other.last;
678}
679
680inline bool
681insn_range_info::operator!= (const insn_range_info &other) const
682{
683 return first != other.first || last != other.last;
684}
685
686inline insn_info *
687insn_range_info::singleton () const
688{
689 return first == last ? last : nullptr;
690}
691
692inline bool
693insn_range_info::includes (insn_info *insn) const
694{
695 return *insn >= *first && *insn <= *last;
696}
697
698inline insn_info *
699insn_range_info::clamp_insn_to_range (insn_info *insn) const
700{
701 if (*first > *insn)
702 return first;
703 if (*last < *insn)
704 return last;
705 return insn;
706}
707
708inline bool
709insn_range_info::is_subrange_of (const insn_range_info &other) const
710{
711 return *first >= *other.first && *last <= *other.last;
712}
713
714inline iterator_range<any_insn_iterator>
715bb_info::all_insns () const
716{
717 return { m_head_insn, m_end_insn->next_any_insn () };
718}
719
720inline iterator_range<reverse_any_insn_iterator>
721bb_info::reverse_all_insns () const
722{
723 return { m_end_insn, m_head_insn->prev_any_insn () };
724}
725
726inline iterator_range<nondebug_insn_iterator>
727bb_info::nondebug_insns () const
728{
729 return { m_head_insn, m_end_insn->next_nondebug_insn () };
730}
731
732inline iterator_range<reverse_nondebug_insn_iterator>
733bb_info::reverse_nondebug_insns () const
734{
735 return { m_end_insn, m_head_insn->prev_nondebug_insn () };
736}
737
738inline iterator_range<any_insn_iterator>
739bb_info::real_insns () const
740{
741 return { m_head_insn->next_any_insn (), m_end_insn };
742}
743
744inline iterator_range<reverse_any_insn_iterator>
745bb_info::reverse_real_insns () const
746{
747 return { m_end_insn->prev_any_insn (), m_head_insn };
748}
749
750inline iterator_range<nondebug_insn_iterator>
751bb_info::real_nondebug_insns () const
752{
753 return { m_head_insn->next_nondebug_insn (), m_end_insn };
754}
755
756inline iterator_range<reverse_nondebug_insn_iterator>
757bb_info::reverse_real_nondebug_insns () const
758{
759 return { m_end_insn->prev_nondebug_insn (), m_head_insn };
760}
761
762inline bool
763ebb_call_clobbers_info::clobbers (resource_info resource) const
764{
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 (mode: resource.mode, regno: resource.regno));
769}
770
771inline ebb_info *
772ebb_info::prev_ebb () const
773{
774 if (bb_info *prev_bb = m_first_bb->prev_bb ())
775 return prev_bb->ebb ();
776 return nullptr;
777}
778
779inline ebb_info *
780ebb_info::next_ebb () const
781{
782 if (bb_info *next_bb = m_last_bb->next_bb ())
783 return next_bb->ebb ();
784 return nullptr;
785}
786
787inline iterator_range<phi_iterator>
788ebb_info::phis () const
789{
790 return { m_first_phi, nullptr };
791}
792
793inline iterator_range<bb_iterator>
794ebb_info::bbs () const
795{
796 return { m_first_bb, m_last_bb->next_bb () };
797}
798
799inline iterator_range<reverse_bb_iterator>
800ebb_info::reverse_bbs () const
801{
802 return { m_last_bb, m_first_bb->prev_bb () };
803}
804
805inline iterator_range<any_insn_iterator>
806ebb_info::all_insns () const
807{
808 return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
809}
810
811inline iterator_range<reverse_any_insn_iterator>
812ebb_info::reverse_all_insns () const
813{
814 return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
815}
816
817inline iterator_range<nondebug_insn_iterator>
818ebb_info::nondebug_insns () const
819{
820 return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
821}
822
823inline iterator_range<reverse_nondebug_insn_iterator>
824ebb_info::reverse_nondebug_insns () const
825{
826 return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
827}
828
829inline insn_range_info
830ebb_info::insn_range () const
831{
832 return { m_phi_insn, m_last_bb->end_insn () };
833}
834
835inline void
836ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
837{
838 m_first_call_clobbers = call_clobbers;
839}
840
841inline ebb_call_clobbers_info *
842ebb_info::first_call_clobbers () const
843{
844 return m_first_call_clobbers;
845}
846
847inline iterator_range<ebb_call_clobbers_iterator>
848ebb_info::call_clobbers () const
849{
850 return { m_first_call_clobbers, nullptr };
851}
852
853inline 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)
860{
861}
862
863inline 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)
870{
871}
872
873inline insn_is_changing_closure::
874insn_is_changing_closure (array_slice<insn_change *const> changes)
875 : m_changes (changes)
876{
877}
878
879inline bool
880insn_is_changing_closure::operator() (const insn_info *insn) const
881{
882 for (const insn_change *change : m_changes)
883 if (change->insn () == insn)
884 return true;
885 return false;
886}
887
888inline iterator_range<bb_iterator>
889function_info::bbs () const
890{
891 return { m_first_bb, nullptr };
892}
893
894inline iterator_range<reverse_bb_iterator>
895function_info::reverse_bbs () const
896{
897 return { m_last_bb, nullptr };
898}
899
900inline iterator_range<ebb_iterator>
901function_info::ebbs () const
902{
903 return { m_first_bb->ebb (), nullptr };
904}
905
906inline iterator_range<reverse_ebb_iterator>
907function_info::reverse_ebbs () const
908{
909 return { m_last_bb->ebb (), nullptr };
910}
911
912inline iterator_range<any_insn_iterator>
913function_info::all_insns () const
914{
915 return { m_first_insn, nullptr };
916}
917
918inline iterator_range<reverse_any_insn_iterator>
919function_info::reverse_all_insns () const
920{
921 return { m_last_insn, nullptr };
922}
923
924inline iterator_range<nondebug_insn_iterator>
925function_info::nondebug_insns () const
926{
927 return { m_first_insn, nullptr };
928}
929
930inline iterator_range<reverse_nondebug_insn_iterator>
931function_info::reverse_nondebug_insns () const
932{
933 return { m_last_insn, nullptr };
934}
935
936inline iterator_range<def_iterator>
937function_info::mem_defs () const
938{
939 return { m_defs[0], nullptr };
940}
941
942inline iterator_range<def_iterator>
943function_info::reg_defs (unsigned int regno) const
944{
945 return { m_defs[regno + 1], nullptr };
946}
947
948inline bool
949function_info::is_single_dominating_def (const set_info *set) const
950{
951 return (set->is_first_def ()
952 && set->is_last_def ()
953 && (!HARD_REGISTER_NUM_P (set->regno ())
954 || !TEST_HARD_REG_BIT (set: m_clobbered_by_calls, bit: set->regno ())));
955}
956
957inline set_info *
958function_info::single_dominating_def (unsigned int regno) const
959{
960 if (set_info *set = safe_dyn_cast<set_info *> (p: m_defs[regno + 1]))
961 if (is_single_dominating_def (set))
962 return set;
963 return nullptr;
964}
965
966template<typename IgnorePredicate>
967bool
968function_info::add_regno_clobber (obstack_watermark &watermark,
969 insn_change &change, unsigned int regno,
970 IgnorePredicate ignore)
971{
972 // Check whether CHANGE already clobbers REGNO.
973 if (find_access (accesses: change.new_defs, regno))
974 return true;
975
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 (insn: 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;
983
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;
988
989 change.new_defs = new_defs;
990 change.move_range = move_range;
991 return true;
992}
993
994template<typename T, typename... Ts>
995inline T *
996function_info::change_alloc (obstack_watermark &wm, Ts... args)
997{
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)...);
1004}
1005
1006}
1007

source code of gcc/rtl-ssa/member-fns.inl