c++: inherited CTAD fixes [PR116276]
[official-gcc.git] / gcc / rtl-ssa / change-utils.h
blobfa27d1ad0472b8f165a52c49dcea9e7afa8d4203
1 // RTL SSA utility functions for changing instructions -*- C++ -*-
2 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 //
4 // This file is part of GCC.
5 //
6 // GCC is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU General Public License as published by the Free
8 // Software Foundation; either version 3, or (at your option) any later
9 // version.
11 // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 // for more details.
16 // You should have received a copy of the GNU General Public License
17 // along with GCC; see the file COPYING3. If not see
18 // <http://www.gnu.org/licenses/>.
20 namespace rtl_ssa {
22 // Return true if INSN is one of the instructions being changed by CHANGES.
23 inline bool
24 insn_is_changing (array_slice<insn_change *const> changes,
25 const insn_info *insn)
27 for (const insn_change *change : changes)
28 if (change->insn () == insn)
29 return true;
30 return false;
33 // Restrict CHANGE.move_range so that the changed instruction can perform
34 // all its definitions and uses.
36 // IGNORE is an object that provides the same interface as ignore_nothing.
37 // Assume that if:
39 // - CHANGE contains an access A1 of resource R;
40 // - an instruction I2 contains another access A2 to R; and
41 // - IGNORE says that I2 should be ignored
43 // then either:
45 // - A2 will be removed; or
46 // - something will ensure that A1 and A2 maintain their current order,
47 // without this having to be enforced by CHANGE's move range.
49 // Assume the same thing about a definition D of R, and about all uses of D,
50 // if IGNORE says that D should be ignored.
52 // IGNORE should ignore CHANGE.insn ().
54 // Return true on success, otherwise leave CHANGE.move_range in an invalid
55 // state.
57 // This function only works correctly for instructions that remain within
58 // the same extended basic block.
59 template<typename IgnorePredicates>
60 bool
61 restrict_movement (insn_change &change, IgnorePredicates ignore)
63 // Uses generally lead to failure quicker, so test those first.
64 return (restrict_movement_for_uses (change.move_range,
65 change.new_uses, ignore)
66 && restrict_movement_for_defs (change.move_range,
67 change.new_defs, ignore)
68 && canonicalize_move_range (change.move_range, change.insn ()));
71 // As above, but ignore only the instruction that is being changed.
72 inline bool
73 restrict_movement (insn_change &change)
75 return restrict_movement (change, ignore_insn (change.insn ()));
78 using add_regno_clobber_fn = std::function<bool (insn_change &,
79 unsigned int)>;
80 bool recog_internal (insn_change &, add_regno_clobber_fn);
82 // Try to recognize the new instruction pattern for CHANGE, potentially
83 // tweaking the pattern or adding extra clobbers in order to make it match.
85 // When adding an extra clobber for register R, restrict CHANGE.move_range
86 // to a range of instructions for which R is not live. Use IGNORE to guide
87 // this process, where IGNORE is an object that provides the same interface
88 // as ignore_nothing. When determining whether R is live, ignore accesses
89 // made by an instruction I if IGNORE says that I should be ignored.
90 // The caller then assumes the responsibility of ensuring that CHANGE
91 // and I are placed in a valid order. Similarly, ignore live ranges
92 // associated with a definition of R if IGNORE says that that definition
93 // should be ignored.
95 // IGNORE should ignore CHANGE.insn ().
97 // Return true on success. Leave CHANGE unmodified on failure.
98 template<typename IgnorePredicates>
99 inline bool
100 recog (obstack_watermark &watermark, insn_change &change,
101 IgnorePredicates ignore)
103 auto add_regno_clobber = [&](insn_change &change, unsigned int regno)
105 return crtl->ssa->add_regno_clobber (watermark, change, regno, ignore);
107 return recog_internal (change, add_regno_clobber);
110 // As above, but ignore only the instruction that is being changed.
111 inline bool
112 recog (obstack_watermark &watermark, insn_change &change)
114 return recog (watermark, change, ignore_insn (change.insn ()));
117 // Check whether insn costs indicate that the net effect of the changes
118 // in CHANGES is worthwhile. Require a strict improvement if STRICT_P,
119 // otherwise allow the new instructions to be the same cost as the old
120 // instructions.
121 bool changes_are_worthwhile (array_slice<insn_change *const> changes,
122 bool strict_p = false);
124 // Like changes_are_worthwhile, but for a single change.
125 inline bool
126 change_is_worthwhile (insn_change &change, bool strict_p = false)
128 insn_change *changes[] = { &change };
129 return changes_are_worthwhile (changes, strict_p);