movement.h revision 1.1.1.1 1 1.1 mrg // RTL SSA utilities relating to instruction movement -*- C++ -*-
2 1.1 mrg // Copyright (C) 2020-2022 Free Software Foundation, Inc.
3 1.1 mrg //
4 1.1 mrg // This file is part of GCC.
5 1.1 mrg //
6 1.1 mrg // GCC is free software; you can redistribute it and/or modify it under
7 1.1 mrg // the terms of the GNU General Public License as published by the Free
8 1.1 mrg // Software Foundation; either version 3, or (at your option) any later
9 1.1 mrg // version.
10 1.1 mrg //
11 1.1 mrg // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 1.1 mrg // WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 1.1 mrg // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 1.1 mrg // for more details.
15 1.1 mrg //
16 1.1 mrg // You should have received a copy of the GNU General Public License
17 1.1 mrg // along with GCC; see the file COPYING3. If not see
18 1.1 mrg // <http://www.gnu.org/licenses/>.
19 1.1 mrg
20 1.1 mrg namespace rtl_ssa {
21 1.1 mrg
22 1.1 mrg // Restrict movement range RANGE so that the instruction is placed later
23 1.1 mrg // than INSN. (The movement range is the range of instructions after which
24 1.1 mrg // an instruction can be placed.)
25 1.1 mrg inline insn_range_info
26 1.1 mrg move_later_than (insn_range_info range, insn_info *insn)
27 1.1 mrg {
28 1.1 mrg return { later_insn (range.first, insn), range.last };
29 1.1 mrg }
30 1.1 mrg
31 1.1 mrg // Restrict movement range RANGE so that the instruction is placed no earlier
32 1.1 mrg // than INSN. (The movement range is the range of instructions after which
33 1.1 mrg // an instruction can be placed.)
34 1.1 mrg inline insn_range_info
35 1.1 mrg move_no_earlier_than (insn_range_info range, insn_info *insn)
36 1.1 mrg {
37 1.1 mrg insn_info *first = later_insn (range.first, insn->prev_nondebug_insn ());
38 1.1 mrg return { first, range.last };
39 1.1 mrg }
40 1.1 mrg
41 1.1 mrg // Restrict movement range RANGE so that the instruction is placed no later
42 1.1 mrg // than INSN. (The movement range is the range of instructions after which
43 1.1 mrg // an instruction can be placed.)
44 1.1 mrg inline insn_range_info
45 1.1 mrg move_no_later_than (insn_range_info range, insn_info *insn)
46 1.1 mrg {
47 1.1 mrg return { range.first, earlier_insn (range.last, insn) };
48 1.1 mrg }
49 1.1 mrg
50 1.1 mrg // Restrict movement range RANGE so that the instruction is placed earlier
51 1.1 mrg // than INSN. (The movement range is the range of instructions after which
52 1.1 mrg // an instruction can be placed.)
53 1.1 mrg inline insn_range_info
54 1.1 mrg move_earlier_than (insn_range_info range, insn_info *insn)
55 1.1 mrg {
56 1.1 mrg insn_info *last = earlier_insn (range.last, insn->prev_nondebug_insn ());
57 1.1 mrg return { range.first, last };
58 1.1 mrg }
59 1.1 mrg
60 1.1 mrg // Return true if it is possible to insert a new instruction after INSN.
61 1.1 mrg inline bool
62 1.1 mrg can_insert_after (insn_info *insn)
63 1.1 mrg {
64 1.1 mrg return insn->is_bb_head () || (insn->is_real () && !insn->is_jump ());
65 1.1 mrg }
66 1.1 mrg
67 1.1 mrg // Try to restrict move range MOVE_RANGE so that it is possible to
68 1.1 mrg // insert INSN after both of the end points. Return true on success,
69 1.1 mrg // otherwise leave MOVE_RANGE in an invalid state.
70 1.1 mrg inline bool
71 1.1 mrg canonicalize_move_range (insn_range_info &move_range, insn_info *insn)
72 1.1 mrg {
73 1.1 mrg while (move_range.first != insn && !can_insert_after (move_range.first))
74 1.1 mrg move_range.first = move_range.first->next_nondebug_insn ();
75 1.1 mrg while (move_range.last != insn && !can_insert_after (move_range.last))
76 1.1 mrg move_range.last = move_range.last->prev_nondebug_insn ();
77 1.1 mrg return bool (move_range);
78 1.1 mrg }
79 1.1 mrg
80 1.1 mrg // Try to restrict movement range MOVE_RANGE of INSN so that it can set
81 1.1 mrg // or clobber REGNO. Assume that if:
82 1.1 mrg //
83 1.1 mrg // - an instruction I2 contains another access A to REGNO; and
84 1.1 mrg // - IGNORE (I2) is true
85 1.1 mrg //
86 1.1 mrg // then either:
87 1.1 mrg //
88 1.1 mrg // - A will be removed; or
89 1.1 mrg // - something will ensure that the new definition of REGNO does not
90 1.1 mrg // interfere with A, without this having to be enforced by I1's move range.
91 1.1 mrg //
92 1.1 mrg // Return true on success, otherwise leave MOVE_RANGE in an invalid state.
93 1.1 mrg //
94 1.1 mrg // This function only works correctly for instructions that remain within
95 1.1 mrg // the same extended basic block.
96 1.1 mrg template<typename IgnorePredicate>
97 1.1 mrg bool
98 1.1 mrg restrict_movement_for_dead_range (insn_range_info &move_range,
99 1.1 mrg unsigned int regno, insn_info *insn,
100 1.1 mrg IgnorePredicate ignore)
101 1.1 mrg {
102 1.1 mrg // Find a definition at or neighboring INSN.
103 1.1 mrg resource_info resource = full_register (regno);
104 1.1 mrg def_lookup dl = crtl->ssa->find_def (resource, insn);
105 1.1 mrg
106 1.1 mrg def_info *prev = dl.last_def_of_prev_group ();
107 1.1 mrg ebb_info *ebb = insn->ebb ();
108 1.1 mrg if (!prev || prev->ebb () != ebb)
109 1.1 mrg {
110 1.1 mrg // REGNO is not defined or used in EBB before INSN, but it
111 1.1 mrg // might be live on entry. To keep complexity under control,
112 1.1 mrg // handle only these cases:
113 1.1 mrg //
114 1.1 mrg // - If the register is not live on entry to EBB, the register is
115 1.1 mrg // free from the start of EBB to the first definition in EBB.
116 1.1 mrg //
117 1.1 mrg // - Otherwise, if the register is live on entry to BB, refuse
118 1.1 mrg // to allocate the register. We could in principle try to move
119 1.1 mrg // the instruction to later blocks in the EBB, but it's rarely
120 1.1 mrg // worth the effort, and could lead to linear complexity.
121 1.1 mrg //
122 1.1 mrg // - Otherwise, don't allow INSN to move earlier than its current
123 1.1 mrg // block. Again, we could in principle look backwards to find where
124 1.1 mrg // REGNO dies, but it's rarely worth the effort.
125 1.1 mrg bb_info *bb = insn->bb ();
126 1.1 mrg insn_info *limit;
127 1.1 mrg if (!bitmap_bit_p (DF_LR_IN (ebb->first_bb ()->cfg_bb ()), regno))
128 1.1 mrg limit = ebb->phi_insn ();
129 1.1 mrg else if (bitmap_bit_p (DF_LR_IN (bb->cfg_bb ()), regno))
130 1.1 mrg return false;
131 1.1 mrg else
132 1.1 mrg limit = bb->head_insn ();
133 1.1 mrg move_range = move_later_than (move_range, limit);
134 1.1 mrg }
135 1.1 mrg else
136 1.1 mrg {
137 1.1 mrg // Stop the instruction moving beyond the previous relevant access
138 1.1 mrg // to REGNO.
139 1.1 mrg access_info *prev_access
140 1.1 mrg = last_access_ignoring (prev, ignore_clobbers::YES, ignore);
141 1.1 mrg if (prev_access)
142 1.1 mrg move_range = move_later_than (move_range, access_insn (prev_access));
143 1.1 mrg }
144 1.1 mrg
145 1.1 mrg // Stop the instruction moving beyond the next relevant definition of REGNO.
146 1.1 mrg def_info *next = dl.matching_set_or_first_def_of_next_group ();
147 1.1 mrg next = first_def_ignoring (next, ignore_clobbers::YES, ignore);
148 1.1 mrg if (next)
149 1.1 mrg move_range = move_earlier_than (move_range, next->insn ());
150 1.1 mrg
151 1.1 mrg return canonicalize_move_range (move_range, insn);
152 1.1 mrg }
153 1.1 mrg
154 1.1 mrg // Try to restrict movement range MOVE_RANGE so that it is possible for the
155 1.1 mrg // instruction being moved ("instruction I1") to perform all the definitions
156 1.1 mrg // in DEFS while still preserving dependencies between those definitions
157 1.1 mrg // and surrounding instructions. Assume that if:
158 1.1 mrg //
159 1.1 mrg // - DEFS contains a definition D of resource R;
160 1.1 mrg // - an instruction I2 contains another access A to R; and
161 1.1 mrg // - IGNORE (I2) is true
162 1.1 mrg //
163 1.1 mrg // then either:
164 1.1 mrg //
165 1.1 mrg // - A will be removed; or
166 1.1 mrg // - something will ensure that D and A maintain their current order,
167 1.1 mrg // without this having to be enforced by I1's move range.
168 1.1 mrg //
169 1.1 mrg // Return true on success, otherwise leave MOVE_RANGE in an invalid state.
170 1.1 mrg //
171 1.1 mrg // This function only works correctly for instructions that remain within
172 1.1 mrg // the same extended basic block.
173 1.1 mrg template<typename IgnorePredicate>
174 1.1 mrg bool
175 1.1 mrg restrict_movement_for_defs_ignoring (insn_range_info &move_range,
176 1.1 mrg def_array defs, IgnorePredicate ignore)
177 1.1 mrg {
178 1.1 mrg for (def_info *def : defs)
179 1.1 mrg {
180 1.1 mrg // If the definition is a clobber, we can move it with respect
181 1.1 mrg // to other clobbers.
182 1.1 mrg //
183 1.1 mrg // ??? We could also do this if a definition and all its uses
184 1.1 mrg // are being moved at once.
185 1.1 mrg bool is_clobber = is_a<clobber_info *> (def);
186 1.1 mrg
187 1.1 mrg // Search back for the first unfiltered use or definition of the
188 1.1 mrg // same resource.
189 1.1 mrg access_info *access;
190 1.1 mrg access = prev_access_ignoring (def, ignore_clobbers (is_clobber),
191 1.1 mrg ignore);
192 1.1 mrg if (access)
193 1.1 mrg move_range = move_later_than (move_range, access_insn (access));
194 1.1 mrg
195 1.1 mrg // Search forward for the first unfiltered use of DEF,
196 1.1 mrg // or the first unfiltered definition that follows DEF.
197 1.1 mrg //
198 1.1 mrg // We don't need to consider uses of following definitions, since
199 1.1 mrg // if IGNORE (D->insn ()) is true for some definition D, the caller
200 1.1 mrg // is guarantees that either
201 1.1 mrg //
202 1.1 mrg // - D will be removed, and thus its uses will be removed; or
203 1.1 mrg // - D will occur after DEF, and thus D's uses will also occur
204 1.1 mrg // after DEF.
205 1.1 mrg //
206 1.1 mrg // This is purely a simplification: we could also process D's uses,
207 1.1 mrg // but we don't need to.
208 1.1 mrg access = next_access_ignoring (def, ignore_clobbers (is_clobber),
209 1.1 mrg ignore);
210 1.1 mrg if (access)
211 1.1 mrg move_range = move_earlier_than (move_range, access_insn (access));
212 1.1 mrg
213 1.1 mrg // If DEF sets a hard register, take any call clobbers
214 1.1 mrg // into account.
215 1.1 mrg unsigned int regno = def->regno ();
216 1.1 mrg if (!HARD_REGISTER_NUM_P (regno) || is_clobber)
217 1.1 mrg continue;
218 1.1 mrg
219 1.1 mrg ebb_info *ebb = def->ebb ();
220 1.1 mrg for (ebb_call_clobbers_info *call_group : ebb->call_clobbers ())
221 1.1 mrg {
222 1.1 mrg if (!call_group->clobbers (def->resource ()))
223 1.1 mrg continue;
224 1.1 mrg
225 1.1 mrg // Exit now if we've already failed, and if the splay accesses
226 1.1 mrg // below would be wasted work.
227 1.1 mrg if (!move_range)
228 1.1 mrg return false;
229 1.1 mrg
230 1.1 mrg insn_info *insn;
231 1.1 mrg insn = prev_call_clobbers_ignoring (*call_group, def->insn (),
232 1.1 mrg ignore);
233 1.1 mrg if (insn)
234 1.1 mrg move_range = move_later_than (move_range, insn);
235 1.1 mrg
236 1.1 mrg insn = next_call_clobbers_ignoring (*call_group, def->insn (),
237 1.1 mrg ignore);
238 1.1 mrg if (insn)
239 1.1 mrg move_range = move_earlier_than (move_range, insn);
240 1.1 mrg }
241 1.1 mrg }
242 1.1 mrg
243 1.1 mrg // Make sure that we don't move stores between basic blocks, since we
244 1.1 mrg // don't have enough information to tell whether it's safe.
245 1.1 mrg if (def_info *def = memory_access (defs))
246 1.1 mrg {
247 1.1 mrg move_range = move_later_than (move_range, def->bb ()->head_insn ());
248 1.1 mrg move_range = move_earlier_than (move_range, def->bb ()->end_insn ());
249 1.1 mrg }
250 1.1 mrg
251 1.1 mrg return bool (move_range);
252 1.1 mrg }
253 1.1 mrg
254 1.1 mrg // Like restrict_movement_for_defs_ignoring, but for the uses in USES.
255 1.1 mrg template<typename IgnorePredicate>
256 1.1 mrg bool
257 1.1 mrg restrict_movement_for_uses_ignoring (insn_range_info &move_range,
258 1.1 mrg use_array uses, IgnorePredicate ignore)
259 1.1 mrg {
260 1.1 mrg for (const use_info *use : uses)
261 1.1 mrg {
262 1.1 mrg // Ignore uses of undefined values.
263 1.1 mrg set_info *set = use->def ();
264 1.1 mrg if (!set)
265 1.1 mrg continue;
266 1.1 mrg
267 1.1 mrg // Ignore uses by debug instructions. Debug instructions are
268 1.1 mrg // never supposed to move, and uses by debug instructions are
269 1.1 mrg // never supposed to be transferred elsewhere, so we know that
270 1.1 mrg // the caller must be changing the uses on the debug instruction
271 1.1 mrg // and checking whether all new uses are available at the debug
272 1.1 mrg // instruction's original location.
273 1.1 mrg if (use->is_in_debug_insn ())
274 1.1 mrg continue;
275 1.1 mrg
276 1.1 mrg // If the used value is defined by an instruction I2 for which
277 1.1 mrg // IGNORE (I2) is true, the caller guarantees that I2 will occur
278 1.1 mrg // before change.insn (). Otherwise, make sure that the use occurs
279 1.1 mrg // after the definition.
280 1.1 mrg insn_info *insn = set->insn ();
281 1.1 mrg if (!ignore (insn))
282 1.1 mrg move_range = move_later_than (move_range, insn);
283 1.1 mrg
284 1.1 mrg // Search forward for the first unfiltered definition that follows SET.
285 1.1 mrg //
286 1.1 mrg // We don't need to consider the uses of these definitions, since
287 1.1 mrg // if IGNORE (D->insn ()) is true for some definition D, the caller
288 1.1 mrg // is guarantees that either
289 1.1 mrg //
290 1.1 mrg // - D will be removed, and thus its uses will be removed; or
291 1.1 mrg // - D will occur after USE, and thus D's uses will also occur
292 1.1 mrg // after USE.
293 1.1 mrg //
294 1.1 mrg // This is purely a simplification: we could also process D's uses,
295 1.1 mrg // but we don't need to.
296 1.1 mrg def_info *def;
297 1.1 mrg def = first_def_ignoring (set->next_def (), ignore_clobbers::NO,
298 1.1 mrg ignore);
299 1.1 mrg if (def)
300 1.1 mrg move_range = move_earlier_than (move_range, def->insn ());
301 1.1 mrg
302 1.1 mrg // If USE uses a hard register, take any call clobbers into account too.
303 1.1 mrg // SET will necessarily occur after any previous call clobber, so we
304 1.1 mrg // only need to check for later clobbers.
305 1.1 mrg unsigned int regno = use->regno ();
306 1.1 mrg if (!HARD_REGISTER_NUM_P (regno))
307 1.1 mrg continue;
308 1.1 mrg
309 1.1 mrg ebb_info *ebb = use->ebb ();
310 1.1 mrg for (ebb_call_clobbers_info *call_group : ebb->call_clobbers ())
311 1.1 mrg {
312 1.1 mrg if (!call_group->clobbers (use->resource ()))
313 1.1 mrg continue;
314 1.1 mrg
315 1.1 mrg if (!move_range)
316 1.1 mrg return false;
317 1.1 mrg
318 1.1 mrg insn_info *insn = next_call_clobbers_ignoring (*call_group,
319 1.1 mrg use->insn (), ignore);
320 1.1 mrg if (insn)
321 1.1 mrg move_range = move_earlier_than (move_range, insn);
322 1.1 mrg }
323 1.1 mrg }
324 1.1 mrg
325 1.1 mrg // Make sure that we don't move loads into an earlier basic block.
326 1.1 mrg //
327 1.1 mrg // ??? It would be good to relax this for loads that can be safely
328 1.1 mrg // speculated.
329 1.1 mrg if (use_info *use = memory_access (uses))
330 1.1 mrg move_range = move_later_than (move_range, use->bb ()->head_insn ());
331 1.1 mrg
332 1.1 mrg return bool (move_range);
333 1.1 mrg }
334 1.1 mrg
335 1.1 mrg }
336