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