Branch data Line data Source code
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.
27 : : namespace rtl_ssa {
28 : :
29 : : inline void
30 : 28525016 : access_array_builder::reserve (unsigned int num_accesses)
31 : : {
32 : 28525016 : obstack_make_room (m_obstack, num_accesses * sizeof (access_info *));
33 : 28525016 : }
34 : :
35 : : inline void
36 : 83931307 : access_array_builder::quick_push (access_info *access)
37 : : {
38 : 82537914 : obstack_ptr_grow_fast (m_obstack, access);
39 : 2290166 : }
40 : :
41 : : inline array_slice<access_info *>
42 : 26938653 : access_array_builder::finish ()
43 : : {
44 : 26938653 : auto num_accesses = obstack_object_size (m_obstack) / sizeof (access_info *);
45 : 26938653 : if (num_accesses == 0)
46 : 170 : return {};
47 : :
48 : 26938483 : auto **base = static_cast<access_info **> (obstack_finish (m_obstack));
49 : 26938483 : keep ();
50 : 26938483 : return { base, num_accesses };
51 : : }
52 : :
53 : : inline bool
54 : 64041587 : access_info::is_set_with_nondebug_insn_uses () const
55 : : {
56 : 64041587 : return m_is_set_with_nondebug_insn_uses;
57 : : }
58 : :
59 : : inline bool
60 : 423147290 : use_info::is_in_debug_insn () const
61 : : {
62 : 423147290 : return m_insn_or_phi.is_first () && m_is_in_debug_insn_or_phi;
63 : : }
64 : :
65 : : inline bb_info *
66 : 133769007 : use_info::bb () const
67 : : {
68 : 112081643 : if (m_insn_or_phi.is_first ())
69 : 133769007 : return m_insn_or_phi.known_first ()->bb ();
70 : 0 : return m_insn_or_phi.known_second ()->bb ();
71 : : }
72 : :
73 : : inline ebb_info *
74 : 21687364 : use_info::ebb () const
75 : : {
76 : 43374728 : return bb ()->ebb ();
77 : : }
78 : :
79 : : inline use_info *
80 : 535618072 : use_info::prev_use () const
81 : : {
82 : 891925023 : return m_last_use_or_prev_use.second_or_null ();
83 : : }
84 : :
85 : : inline use_info *
86 : 1748726008 : use_info::next_use () const
87 : : {
88 : 2690007371 : return m_last_nondebug_insn_use_or_next_use.second_or_null ();
89 : : }
90 : :
91 : : inline bool
92 : : use_info::is_first_use () const
93 : : {
94 : : return m_last_use_or_prev_use.is_first ();
95 : : }
96 : :
97 : : inline bool
98 : : use_info::is_last_use () const
99 : : {
100 : : return m_last_nondebug_insn_use_or_next_use.is_first ();
101 : : }
102 : :
103 : : inline use_info *
104 : 29062109 : use_info::next_nondebug_insn_use () const
105 : : {
106 : 29062109 : if (m_is_last_nondebug_insn_use)
107 : : return nullptr;
108 : 0 : return m_last_nondebug_insn_use_or_next_use.known_second ();
109 : : }
110 : :
111 : : inline use_info *
112 : 9247292 : use_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 : 9247292 : if (use_info *use = next_use ())
117 : 8972900 : if (use->is_in_any_insn ())
118 : 8765811 : return use;
119 : : return nullptr;
120 : : }
121 : :
122 : : inline use_info *
123 : : use_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 : :
131 : : inline use_info *
132 : 12435742 : use_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 : 12435742 : if (use_info *use = prev_use ())
137 : 11436077 : 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.
144 : : inline use_info *
145 : 321620706 : use_info::last_use () const
146 : : {
147 : 466282258 : 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.
152 : : inline use_info *
153 : 185888522 : use_info::last_nondebug_insn_use () const
154 : : {
155 : 492808028 : return m_last_nondebug_insn_use_or_next_use.known_first ();
156 : : }
157 : :
158 : : inline def_info *
159 : 68836070 : def_info::prev_def () const
160 : : {
161 : 148665572 : return m_last_def_or_prev_def.second_or_null ();
162 : : }
163 : :
164 : : inline def_info *
165 : 164096003 : def_info::next_def () const
166 : : {
167 : 336207618 : return m_splay_root_or_next_def.second_or_null ();
168 : : }
169 : :
170 : : inline bool
171 : 62880572 : def_info::is_first_def () const
172 : : {
173 : 62880572 : return m_last_def_or_prev_def.is_first ();
174 : : }
175 : :
176 : : inline bool
177 : 62453930 : def_info::is_last_def () const
178 : : {
179 : 56140265 : return m_splay_root_or_next_def.is_first ();
180 : : }
181 : :
182 : : inline bb_info *
183 : 240729162 : def_info::bb () const
184 : : {
185 : 233718986 : return m_insn->bb ();
186 : : }
187 : :
188 : : inline ebb_info *
189 : 359990001 : def_info::ebb () const
190 : : {
191 : 359990001 : return m_insn->ebb ();
192 : : }
193 : :
194 : : inline clobber_group *
195 : 43861916 : clobber_info::group () const
196 : : {
197 : 43861916 : if (!m_group || !m_group->has_been_superceded ())
198 : : return m_group;
199 : 0 : return const_cast<clobber_info *> (this)->recompute_group ();
200 : : }
201 : :
202 : : inline use_info *
203 : 35049507 : set_info::last_use () const
204 : : {
205 : 35049507 : return m_first_use ? m_first_use->last_use () : nullptr;
206 : : }
207 : :
208 : : inline use_info *
209 : 46996064 : set_info::first_nondebug_insn_use () const
210 : : {
211 : 46996064 : if (m_is_set_with_nondebug_insn_uses)
212 : 43628132 : return m_first_use;
213 : : return nullptr;
214 : : }
215 : :
216 : : inline use_info *
217 : 44824638 : set_info::last_nondebug_insn_use () const
218 : : {
219 : 44824638 : if (m_is_set_with_nondebug_insn_uses)
220 : 33543928 : return m_first_use->last_use ()->last_nondebug_insn_use ();
221 : : return nullptr;
222 : : }
223 : :
224 : : inline use_info *
225 : : set_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 : :
238 : : inline use_info *
239 : 481481 : set_info::first_any_insn_use () const
240 : : {
241 : 481481 : if (m_first_use && m_first_use->is_in_any_insn ())
242 : : return m_first_use;
243 : : return nullptr;
244 : : }
245 : :
246 : : inline use_info *
247 : 27433385 : set_info::last_phi_use () const
248 : : {
249 : 27433385 : if (m_first_use)
250 : : {
251 : 25293431 : use_info *last = m_first_use->last_use ();
252 : 25293431 : if (last->is_in_phi ())
253 : 682429 : return last;
254 : : }
255 : : return nullptr;
256 : : }
257 : :
258 : : inline bool
259 : 2036291 : set_info::has_nondebug_uses () const
260 : : {
261 : 3355617 : return has_nondebug_insn_uses () || has_phi_uses ();
262 : : }
263 : :
264 : : inline bool
265 : 3629511 : set_info::has_nondebug_insn_uses () const
266 : : {
267 : 3629511 : return m_is_set_with_nondebug_insn_uses;
268 : : }
269 : :
270 : : inline bool
271 : 30797846 : set_info::has_phi_uses () const
272 : : {
273 : 30797846 : return m_first_use && m_first_use->last_use ()->is_in_phi ();
274 : : }
275 : :
276 : : inline use_info *
277 : 30663734 : set_info::single_nondebug_use () const
278 : : {
279 : 30663734 : if (!has_phi_uses ())
280 : 29070514 : return single_nondebug_insn_use ();
281 : 1593220 : if (!has_nondebug_insn_uses ())
282 : 0 : return single_phi_use ();
283 : : return nullptr;
284 : : }
285 : :
286 : : inline use_info *
287 : 29070514 : set_info::single_nondebug_insn_use () const
288 : : {
289 : 29070514 : use_info *first = first_nondebug_insn_use ();
290 : 29062109 : if (first && !first->next_nondebug_insn_use ())
291 : 16358682 : return first;
292 : : return nullptr;
293 : : }
294 : :
295 : : inline use_info *
296 : 0 : set_info::single_phi_use () const
297 : : {
298 : 0 : use_info *last = last_phi_use ();
299 : 0 : if (last && !last->prev_phi_use ())
300 : 0 : return last;
301 : : return nullptr;
302 : : }
303 : :
304 : : inline bool
305 : : set_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 : :
318 : : inline iterator_range<use_iterator>
319 : 5262470 : set_info::all_uses () const
320 : : {
321 : 5262470 : return { m_first_use, nullptr };
322 : : }
323 : :
324 : : inline iterator_range<reverse_use_iterator>
325 : : set_info::reverse_all_uses () const
326 : : {
327 : : return { last_use (), nullptr };
328 : : }
329 : :
330 : : inline iterator_range<nondebug_insn_use_iterator>
331 : 17925550 : set_info::nondebug_insn_uses () const
332 : : {
333 : 35851100 : return { first_nondebug_insn_use (), nullptr };
334 : : }
335 : :
336 : : inline iterator_range<debug_insn_use_iterator>
337 : : set_info::debug_insn_uses () const
338 : : {
339 : : return { first_debug_insn_use (), nullptr };
340 : : }
341 : :
342 : : inline iterator_range<reverse_use_iterator>
343 : : set_info::reverse_nondebug_insn_uses () const
344 : : {
345 : : return { last_nondebug_insn_use (), nullptr };
346 : : }
347 : :
348 : : inline iterator_range<any_insn_use_iterator>
349 : 481481 : set_info::all_insn_uses () const
350 : : {
351 : 10210254 : return { first_any_insn_use (), nullptr };
352 : : }
353 : :
354 : : inline iterator_range<phi_use_iterator>
355 : 26407611 : set_info::phi_uses () const
356 : : {
357 : 52815222 : return { last_phi_use (), nullptr };
358 : : }
359 : :
360 : : inline use_array
361 : 28810768 : phi_info::inputs () const
362 : : {
363 : 28810768 : if (m_num_inputs == 1)
364 : 19103678 : return use_array (&m_single_input, 1);
365 : 9707090 : return use_array (m_inputs, m_num_inputs);
366 : : }
367 : :
368 : : inline use_info *
369 : 58537841 : phi_info::input_use (unsigned int i) const
370 : : {
371 : 58537841 : if (m_num_inputs == 1)
372 : 31064026 : return as_a<use_info *> (m_single_input);
373 : 27473815 : return as_a<use_info *> (m_inputs[i]);
374 : : }
375 : :
376 : : inline set_info *
377 : 16841348 : phi_info::input_value (unsigned int i) const
378 : : {
379 : 16841348 : return input_use (i)->def ();
380 : : }
381 : :
382 : : inline def_info *
383 : 31822598 : def_node::first_def () const
384 : : {
385 : : // This should get optimized into an AND with -2.
386 : 29705182 : if (m_clobber_or_set.is_first ())
387 : : return m_clobber_or_set.known_first ();
388 : 22304304 : return m_clobber_or_set.known_second ();
389 : : }
390 : :
391 : : inline clobber_info *
392 : 8875469 : clobber_group::first_clobber () const
393 : : {
394 : 8875469 : return m_clobber_or_set.known_first ();
395 : : }
396 : :
397 : : inline iterator_range<def_iterator>
398 : 0 : clobber_group::clobbers () const
399 : : {
400 : 0 : return { first_clobber (), m_last_clobber->next_def () };
401 : : }
402 : :
403 : : inline def_info *
404 : 3231761 : def_mux::first_def () const
405 : : {
406 : 3173469 : if (is_first ())
407 : : return known_first ();
408 : 3231751 : return known_second ()->first_def ();
409 : : }
410 : :
411 : : inline def_info *
412 : 3946024 : def_mux::last_def () const
413 : : {
414 : 3946024 : if (is_first ())
415 : : return known_first ();
416 : :
417 : 2919594 : def_node *node = known_second ();
418 : 2919594 : if (auto *clobber = ::dyn_cast<clobber_group *> (node))
419 : 2639266 : return clobber->last_clobber ();
420 : :
421 : 280328 : return node->first_def ();
422 : : }
423 : :
424 : : inline set_info *
425 : 1032539 : def_mux::set () const
426 : : {
427 : 1032539 : if (is_first ())
428 : 2574 : return ::safe_dyn_cast<set_info *> (known_first ());
429 : 1146452 : return ::dyn_cast<set_info *> (known_second ()->first_def ());
430 : : }
431 : :
432 : : inline def_info *
433 : 1772587 : def_lookup::last_def_of_prev_group () const
434 : : {
435 : 1772587 : if (!mux)
436 : : return nullptr;
437 : :
438 : 1772110 : if (comparison > 0)
439 : 568637 : return mux.last_def ();
440 : :
441 : 2406941 : return mux.first_def ()->prev_def ();
442 : : }
443 : :
444 : : inline def_info *
445 : 1772587 : def_lookup::first_def_of_next_group () const
446 : : {
447 : 1772587 : if (!mux)
448 : : return nullptr;
449 : :
450 : 1772110 : if (comparison < 0)
451 : 290003 : return mux.first_def ();
452 : :
453 : 1482107 : return mux.last_def ()->next_def ();
454 : : }
455 : :
456 : : inline set_info *
457 : 1895757 : def_lookup::matching_set () const
458 : : {
459 : 1895757 : if (comparison == 0)
460 : 1032539 : return mux.set ();
461 : : return nullptr;
462 : : }
463 : :
464 : : inline def_info *
465 : : def_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 : :
472 : : inline def_info *
473 : 1650641 : def_lookup::matching_set_or_first_def_of_next_group () const
474 : : {
475 : 1650641 : if (set_info *set = matching_set ())
476 : : return set;
477 : 1650641 : return first_def_of_next_group ();
478 : : }
479 : :
480 : 8324577 : inline insn_note::insn_note (insn_note_kind kind)
481 : 8324577 : : m_next_note (nullptr),
482 : 8324577 : m_kind (kind),
483 : 8324577 : m_data8 (0),
484 : 8324577 : m_data16 (0),
485 : : m_data32 (0)
486 : : {
487 : : }
488 : :
489 : : template<typename T>
490 : : inline T
491 : 0 : insn_note::as_a ()
492 : : {
493 : : using deref_type = decltype (*std::declval<T> ());
494 : : using derived = typename std::remove_reference<deref_type>::type;
495 : 0 : gcc_checking_assert (m_kind == derived::kind);
496 : 0 : return static_cast<T> (this);
497 : : }
498 : :
499 : : template<typename T>
500 : : inline T
501 : 0 : insn_note::dyn_cast ()
502 : : {
503 : : using deref_type = decltype (*std::declval<T> ());
504 : : using derived = typename std::remove_reference<deref_type>::type;
505 : 0 : if (m_kind == derived::kind)
506 : : return static_cast<T> (this);
507 : : return nullptr;
508 : : }
509 : :
510 : : inline bool
511 : 419713259 : insn_info::operator< (const insn_info &other) const
512 : : {
513 : 419713259 : if (this == &other)
514 : : return false;
515 : :
516 : 282614254 : if (LIKELY (m_point != other.m_point))
517 : 282614254 : return m_point < other.m_point;
518 : :
519 : 0 : return slow_compare_with (other) < 0;
520 : : }
521 : :
522 : : inline bool
523 : 33905642 : insn_info::operator> (const insn_info &other) const
524 : : {
525 : 33905642 : return other < *this;
526 : : }
527 : :
528 : : inline bool
529 : 114003121 : insn_info::operator<= (const insn_info &other) const
530 : : {
531 : 114003121 : return !(other < *this);
532 : : }
533 : :
534 : : inline bool
535 : 1895280 : insn_info::operator>= (const insn_info &other) const
536 : : {
537 : 1895280 : return !(*this < other);
538 : : }
539 : :
540 : : inline int
541 : 353155749 : insn_info::compare_with (const insn_info *other) const
542 : : {
543 : 353155749 : if (this == other)
544 : : return 0;
545 : :
546 : 332208658 : if (LIKELY (m_point != other->m_point))
547 : : // Assume that points remain in [0, INT_MAX].
548 : 332208658 : return m_point - other->m_point;
549 : :
550 : 0 : return slow_compare_with (*other);
551 : : }
552 : :
553 : : inline insn_info *
554 : 80820101 : insn_info::prev_nondebug_insn () const
555 : : {
556 : 80820101 : gcc_checking_assert (!is_debug_insn ());
557 : 80820101 : return m_prev_insn_or_last_debug_insn.known_first ();
558 : : }
559 : :
560 : : inline insn_info *
561 : 4 : insn_info::next_nondebug_insn () const
562 : : {
563 : 4 : gcc_checking_assert (!is_debug_insn ());
564 : 4 : const insn_info *from = this;
565 : 4 : if (insn_info *first_debug = m_next_nondebug_or_debug_insn.second_or_null ())
566 : 0 : from = first_debug->last_debug_insn ();
567 : 4 : return from->m_next_nondebug_or_debug_insn.known_first ();
568 : : }
569 : :
570 : : inline insn_info *
571 : 0 : insn_info::prev_any_insn () const
572 : : {
573 : 0 : const insn_info *from = this;
574 : 0 : 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 : 0 : from = last_debug->m_next_nondebug_or_debug_insn.known_first ();
578 : 0 : return from->m_prev_insn_or_last_debug_insn.known_first ();
579 : : }
580 : :
581 : : inline insn_info *
582 : 576901463 : insn_info::next_any_insn () const
583 : : {
584 : : // This should get optimized into an AND with -2.
585 : 576901463 : if (m_next_nondebug_or_debug_insn.is_first ())
586 : : return m_next_nondebug_or_debug_insn.known_first ();
587 : 152812210 : return m_next_nondebug_or_debug_insn.known_second ();
588 : : }
589 : :
590 : : inline bool
591 : 0 : insn_info::is_phi () const
592 : : {
593 : 0 : return this == ebb ()->phi_insn ();
594 : : }
595 : :
596 : : inline bool
597 : 6 : insn_info::is_bb_head () const
598 : : {
599 : 6 : return this == m_bb->head_insn ();
600 : : }
601 : :
602 : : inline bool
603 : : insn_info::is_bb_end () const
604 : : {
605 : : return this == m_bb->end_insn ();
606 : : }
607 : :
608 : : inline ebb_info *
609 : 361640642 : insn_info::ebb () const
610 : : {
611 : 329483739 : return m_bb->ebb ();
612 : : }
613 : :
614 : : inline int
615 : 65 : insn_info::uid () const
616 : : {
617 : 65 : return m_cost_or_uid < 0 ? m_cost_or_uid : INSN_UID (m_rtl);
618 : : }
619 : :
620 : : inline use_array
621 : 267670875 : insn_info::uses () const
622 : : {
623 : 237470308 : return use_array (m_accesses + m_num_defs, m_num_uses);
624 : : }
625 : :
626 : : inline bool
627 : : insn_info::has_call_clobbers () const
628 : : {
629 : : return find_note<insn_call_clobbers_note> ();
630 : : }
631 : :
632 : : inline def_array
633 : 38197844 : insn_info::defs () const
634 : : {
635 : 38197844 : return def_array (m_accesses, m_num_defs);
636 : : }
637 : :
638 : : inline unsigned int
639 : 0 : insn_info::cost () const
640 : : {
641 : 0 : if (m_cost_or_uid < 0)
642 : : return 0;
643 : 0 : if (m_cost_or_uid == UNKNOWN_COST)
644 : 0 : calculate_cost ();
645 : 0 : return m_cost_or_uid;
646 : : }
647 : :
648 : : template<typename T>
649 : : inline const T *
650 : 0 : insn_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 : 0 : for (const insn_note *note = first_note (); note; note = note->next_note ())
655 : 0 : 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.
663 : : inline insn_info *
664 : 0 : insn_info::last_debug_insn () const
665 : : {
666 : 0 : return m_prev_insn_or_last_debug_insn.known_second ();
667 : : }
668 : :
669 : 219335643 : inline insn_range_info::insn_range_info (insn_info *first, insn_info *last)
670 : : : first (first), last (last)
671 : : {
672 : : }
673 : :
674 : : inline bool
675 : : insn_range_info::operator== (const insn_range_info &other) const
676 : : {
677 : : return first == other.first && last == other.last;
678 : : }
679 : :
680 : : inline bool
681 : : insn_range_info::operator!= (const insn_range_info &other) const
682 : : {
683 : : return first != other.first || last != other.last;
684 : : }
685 : :
686 : : inline insn_info *
687 : : insn_range_info::singleton () const
688 : : {
689 : : return first == last ? last : nullptr;
690 : : }
691 : :
692 : : inline bool
693 : : insn_range_info::includes (insn_info *insn) const
694 : : {
695 : : return *insn >= *first && *insn <= *last;
696 : : }
697 : :
698 : : inline insn_info *
699 : 1650641 : insn_range_info::clamp_insn_to_range (insn_info *insn) const
700 : : {
701 : 1650641 : if (*first > *insn)
702 : 0 : return first;
703 : 1650641 : if (*last < *insn)
704 : 0 : return last;
705 : : return insn;
706 : : }
707 : :
708 : : inline bool
709 : : insn_range_info::is_subrange_of (const insn_range_info &other) const
710 : : {
711 : : return *first >= *other.first && *last <= *other.last;
712 : : }
713 : :
714 : : inline iterator_range<any_insn_iterator>
715 : : bb_info::all_insns () const
716 : : {
717 : : return { m_head_insn, m_end_insn->next_any_insn () };
718 : : }
719 : :
720 : : inline iterator_range<reverse_any_insn_iterator>
721 : : bb_info::reverse_all_insns () const
722 : : {
723 : : return { m_end_insn, m_head_insn->prev_any_insn () };
724 : : }
725 : :
726 : : inline iterator_range<nondebug_insn_iterator>
727 : : bb_info::nondebug_insns () const
728 : : {
729 : : return { m_head_insn, m_end_insn->next_nondebug_insn () };
730 : : }
731 : :
732 : : inline iterator_range<reverse_nondebug_insn_iterator>
733 : : bb_info::reverse_nondebug_insns () const
734 : : {
735 : : return { m_end_insn, m_head_insn->prev_nondebug_insn () };
736 : : }
737 : :
738 : : inline iterator_range<any_insn_iterator>
739 : 0 : bb_info::real_insns () const
740 : : {
741 : 0 : return { m_head_insn->next_any_insn (), m_end_insn };
742 : : }
743 : :
744 : : inline iterator_range<reverse_any_insn_iterator>
745 : : bb_info::reverse_real_insns () const
746 : : {
747 : : return { m_end_insn->prev_any_insn (), m_head_insn };
748 : : }
749 : :
750 : : inline iterator_range<nondebug_insn_iterator>
751 : : bb_info::real_nondebug_insns () const
752 : : {
753 : : return { m_head_insn->next_nondebug_insn (), m_end_insn };
754 : : }
755 : :
756 : : inline iterator_range<reverse_nondebug_insn_iterator>
757 : : bb_info::reverse_real_nondebug_insns () const
758 : : {
759 : : return { m_end_insn->prev_nondebug_insn (), m_head_insn };
760 : : }
761 : :
762 : : inline bool
763 : 27876796 : ebb_call_clobbers_info::clobbers (resource_info resource) const
764 : : {
765 : : // Only register clobbers are tracked this way. Other clobbers are
766 : : // recorded explicitly.
767 : 27876796 : return (resource.is_reg ()
768 : 27876796 : && m_abi->clobbers_reg_p (resource.mode, resource.regno));
769 : : }
770 : :
771 : : inline ebb_info *
772 : : ebb_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 : :
779 : : inline ebb_info *
780 : 29239098 : ebb_info::next_ebb () const
781 : : {
782 : 29239098 : if (bb_info *next_bb = m_last_bb->next_bb ())
783 : 25288570 : return next_bb->ebb ();
784 : : return nullptr;
785 : : }
786 : :
787 : : inline iterator_range<phi_iterator>
788 : 26049725 : ebb_info::phis () const
789 : : {
790 : 26049725 : return { m_first_phi, nullptr };
791 : : }
792 : :
793 : : inline iterator_range<bb_iterator>
794 : 3222 : ebb_info::bbs () const
795 : : {
796 : 3222 : return { m_first_bb, m_last_bb->next_bb () };
797 : : }
798 : :
799 : : inline iterator_range<reverse_bb_iterator>
800 : : ebb_info::reverse_bbs () const
801 : : {
802 : : return { m_last_bb, m_first_bb->prev_bb () };
803 : : }
804 : :
805 : : inline iterator_range<any_insn_iterator>
806 : : ebb_info::all_insns () const
807 : : {
808 : : return { m_phi_insn, m_last_bb->end_insn ()->next_any_insn () };
809 : : }
810 : :
811 : : inline iterator_range<reverse_any_insn_iterator>
812 : : ebb_info::reverse_all_insns () const
813 : : {
814 : : return { m_last_bb->end_insn (), m_phi_insn->prev_any_insn () };
815 : : }
816 : :
817 : : inline iterator_range<nondebug_insn_iterator>
818 : : ebb_info::nondebug_insns () const
819 : : {
820 : : return { m_phi_insn, m_last_bb->end_insn ()->next_nondebug_insn () };
821 : : }
822 : :
823 : : inline iterator_range<reverse_nondebug_insn_iterator>
824 : : ebb_info::reverse_nondebug_insns () const
825 : : {
826 : : return { m_last_bb->end_insn (), m_phi_insn->prev_nondebug_insn () };
827 : : }
828 : :
829 : : inline insn_range_info
830 : : ebb_info::insn_range () const
831 : : {
832 : : return { m_phi_insn, m_last_bb->end_insn () };
833 : : }
834 : :
835 : : inline void
836 : 4741776 : ebb_info::set_first_call_clobbers (ebb_call_clobbers_info *call_clobbers)
837 : : {
838 : 4741776 : m_first_call_clobbers = call_clobbers;
839 : 4741776 : }
840 : :
841 : : inline ebb_call_clobbers_info *
842 : 13066353 : ebb_info::first_call_clobbers () const
843 : : {
844 : 13066353 : return m_first_call_clobbers;
845 : : }
846 : :
847 : : inline iterator_range<ebb_call_clobbers_iterator>
848 : 32126274 : ebb_info::call_clobbers () const
849 : : {
850 : 32126274 : return { m_first_call_clobbers, nullptr };
851 : : }
852 : :
853 : 30200567 : inline insn_change::insn_change (insn_info *insn)
854 : 30200567 : : m_insn (insn),
855 : 30200567 : new_defs (insn->defs ()),
856 : 30200567 : new_uses (insn->uses ()),
857 : 30200567 : move_range (insn),
858 : 30200567 : new_cost (UNKNOWN_COST),
859 : 30200567 : m_is_deletion (false)
860 : : {
861 : : }
862 : :
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)
870 : : {
871 : : }
872 : :
873 : : inline insn_is_changing_closure::
874 : : insn_is_changing_closure (array_slice<insn_change *const> changes)
875 : : : m_changes (changes)
876 : : {
877 : : }
878 : :
879 : : inline bool
880 : : insn_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 : :
888 : : inline iterator_range<bb_iterator>
889 : : function_info::bbs () const
890 : : {
891 : : return { m_first_bb, nullptr };
892 : : }
893 : :
894 : : inline iterator_range<reverse_bb_iterator>
895 : : function_info::reverse_bbs () const
896 : : {
897 : : return { m_last_bb, nullptr };
898 : : }
899 : :
900 : : inline iterator_range<ebb_iterator>
901 : 3950528 : function_info::ebbs () const
902 : : {
903 : 3950528 : return { m_first_bb->ebb (), nullptr };
904 : : }
905 : :
906 : : inline iterator_range<reverse_ebb_iterator>
907 : : function_info::reverse_ebbs () const
908 : : {
909 : : return { m_last_bb->ebb (), nullptr };
910 : : }
911 : :
912 : : inline iterator_range<any_insn_iterator>
913 : : function_info::all_insns () const
914 : : {
915 : : return { m_first_insn, nullptr };
916 : : }
917 : :
918 : : inline iterator_range<reverse_any_insn_iterator>
919 : : function_info::reverse_all_insns () const
920 : : {
921 : : return { m_last_insn, nullptr };
922 : : }
923 : :
924 : : inline iterator_range<nondebug_insn_iterator>
925 : : function_info::nondebug_insns () const
926 : : {
927 : : return { m_first_insn, nullptr };
928 : : }
929 : :
930 : : inline iterator_range<reverse_nondebug_insn_iterator>
931 : : function_info::reverse_nondebug_insns () const
932 : : {
933 : : return { m_last_insn, nullptr };
934 : : }
935 : :
936 : : inline iterator_range<def_iterator>
937 : : function_info::mem_defs () const
938 : : {
939 : : return { m_defs[0], nullptr };
940 : : }
941 : :
942 : : inline iterator_range<def_iterator>
943 : : function_info::reg_defs (unsigned int regno) const
944 : : {
945 : : return { m_defs[regno + 1], nullptr };
946 : : }
947 : :
948 : : inline bool
949 : 62880572 : function_info::is_single_dominating_def (const set_info *set) const
950 : : {
951 : 62880572 : return (set->is_first_def ()
952 : 58389427 : && set->is_last_def ()
953 : 100370828 : && (!HARD_REGISTER_NUM_P (set->regno ())
954 : 3218143 : || !TEST_HARD_REG_BIT (m_clobbered_by_calls, set->regno ())));
955 : : }
956 : :
957 : : inline set_info *
958 : 54251570 : function_info::single_dominating_def (unsigned int regno) const
959 : : {
960 : 54251570 : if (set_info *set = safe_dyn_cast<set_info *> (m_defs[regno + 1]))
961 : 52075762 : if (is_single_dominating_def (set))
962 : 30716078 : return set;
963 : : return nullptr;
964 : : }
965 : :
966 : : template<typename IgnorePredicate>
967 : : bool
968 : 1650942 : function_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 : 1650942 : if (find_access (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 : 1650641 : insn_info *insn = change.move_range.clamp_insn_to_range (change.insn ());
979 : 1650641 : def_array new_defs = insert_temp_clobber (watermark, insn, regno,
980 : : change.new_defs);
981 : 2 : if (!new_defs.is_valid ())
982 : : return false;
983 : :
984 : : // Find a definition at or neighboring INSN.
985 : 1650641 : insn_range_info move_range = change.move_range;
986 : 1650641 : if (!restrict_movement_for_dead_range (move_range, regno, insn, ignore))
987 : : return false;
988 : :
989 : 1650639 : change.new_defs = new_defs;
990 : 1650639 : change.move_range = move_range;
991 : 1650639 : return true;
992 : : }
993 : :
994 : : template<typename T, typename... Ts>
995 : : inline T *
996 : 0 : function_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 : 0 : void *addr = XOBNEW (wm, T);
1003 : 0 : return new (addr) T (std::forward<Ts> (args)...);
1004 : : }
1005 : :
1006 : : }
|