Branch data Line data Source code
1 : : // Access-related utilities 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 : : namespace rtl_ssa {
21 : :
22 : : // Return a referene to the whole of register REGNO.
23 : : inline resource_info
24 : 20299154 : full_register (unsigned int regno)
25 : : {
26 : 20299154 : return { GET_MODE (regno_reg_rtx[regno]), regno };
27 : : }
28 : :
29 : : // Return true if sorted array ACCESSES includes an access to hard registers.
30 : : inline bool
31 : 5065 : accesses_include_hard_registers (const access_array &accesses)
32 : : {
33 : 5065 : return accesses.size () && HARD_REGISTER_NUM_P (accesses.front ()->regno ());
34 : : }
35 : :
36 : : // Return true if ACCESSES includes a reference to a non-fixed hard register.
37 : : inline bool
38 : 50888661 : accesses_include_nonfixed_hard_registers (access_array accesses)
39 : : {
40 : 62275287 : for (access_info *access : accesses)
41 : : {
42 : 53025647 : if (!HARD_REGISTER_NUM_P (access->regno ()))
43 : : break;
44 : 18523269 : if (!fixed_regs[access->regno ()])
45 : : return true;
46 : : }
47 : : return false;
48 : : }
49 : :
50 : : // Return true if sorted array ACCESSES includes an access to memory.
51 : : inline bool
52 : : accesses_include_memory (const access_array &accesses)
53 : : {
54 : : return accesses.size () && accesses.back ()->is_mem ();
55 : : }
56 : :
57 : : // If sorted array ACCESSES includes an access to memory, return the access,
58 : : // otherwise return null.
59 : : template<typename T>
60 : : inline auto
61 : 105900662 : memory_access (T accesses) -> decltype (accesses[0])
62 : : {
63 : 204105681 : if (accesses.size () && accesses.back ()->is_mem ())
64 : : return accesses.back ();
65 : : return nullptr;
66 : : }
67 : :
68 : : // If ACCESSES has a memory access, drop it. Otherwise, return ACCESSES
69 : : // unchanged.
70 : : template<typename T>
71 : : inline T
72 : : drop_memory_access (T accesses)
73 : : {
74 : : if (!memory_access (accesses))
75 : : return accesses;
76 : :
77 : : access_array arr (accesses);
78 : : return T (arr.begin (), accesses.size () - 1);
79 : : }
80 : :
81 : : // Filter ACCESSES to return an access_array of only those accesses that
82 : : // satisfy PREDICATE. Alocate the new array above WATERMARK.
83 : : template<typename T, typename FilterPredicate>
84 : : inline T
85 : 751641 : filter_accesses (obstack_watermark &watermark,
86 : : T accesses,
87 : : FilterPredicate predicate)
88 : : {
89 : 751641 : access_array_builder builder (watermark);
90 : 751641 : builder.reserve (accesses.size ());
91 : 2830013 : for (auto access : accesses)
92 : 2078372 : if (predicate (access))
93 : 910594 : builder.quick_push (access);
94 : 751641 : return T (builder.finish ());
95 : 751641 : }
96 : :
97 : : // Given an array of ACCESSES, remove any access with regno REGNO.
98 : : // Allocate the new access array above WM.
99 : : template<typename T>
100 : : inline T
101 : : remove_regno_access (obstack_watermark &watermark,
102 : : T accesses, unsigned int regno)
103 : : {
104 : : using Access = decltype (accesses[0]);
105 : : auto pred = [regno](Access a) { return a->regno () != regno; };
106 : : return filter_accesses (watermark, accesses, pred);
107 : : }
108 : :
109 : : // As above, but additionally check that we actually did remove an access.
110 : : template<typename T>
111 : : inline T
112 : : check_remove_regno_access (obstack_watermark &watermark,
113 : : T accesses, unsigned regno)
114 : : {
115 : : auto orig_size = accesses.size ();
116 : : auto result = remove_regno_access (watermark, accesses, regno);
117 : : gcc_assert (result.size () < orig_size);
118 : : return result;
119 : : }
120 : :
121 : : // If sorted array ACCESSES includes a reference to REGNO, return the
122 : : // access, otherwise return null.
123 : : template<typename T>
124 : : inline auto
125 : 27626352 : find_access (T accesses, unsigned int regno) -> decltype (accesses[0])
126 : : {
127 : 27626352 : unsigned int start = 0;
128 : 27626352 : unsigned int end = accesses.size ();
129 : 65486113 : while (start < end)
130 : : {
131 : 36016135 : unsigned int mid = (start + end) / 2;
132 : 72032270 : unsigned int found = accesses[mid]->regno ();
133 : 36016135 : if (found == regno)
134 : : return accesses[mid];
135 : 10233409 : if (found < regno)
136 : 3261067 : start = mid + 1;
137 : : else
138 : : end = mid;
139 : : }
140 : : return nullptr;
141 : : }
142 : :
143 : : // If sorted array ACCESSES includes a reference to REGNO, return the
144 : : // index of the access, otherwise return -1.
145 : : inline int
146 : 6213191 : find_access_index (access_array accesses, unsigned int regno)
147 : : {
148 : 6213191 : unsigned int start = 0;
149 : 6213191 : unsigned int end = accesses.size ();
150 : 12606260 : while (start < end)
151 : : {
152 : 6393069 : unsigned int mid = (start + end) / 2;
153 : 6393069 : unsigned int found = accesses[mid]->regno ();
154 : 6393069 : if (found == regno)
155 : 6213191 : return mid;
156 : 179878 : if (found < regno)
157 : 558 : start = mid + 1;
158 : : else
159 : : end = mid;
160 : : }
161 : : return -1;
162 : : }
163 : :
164 : : // If ACCESS is a set whose result is used by at least one instruction,
165 : : // return the access as a set_info, otherwise return null.
166 : : inline const set_info *
167 : 123610162 : set_with_nondebug_insn_uses (const access_info *access)
168 : : {
169 : 123610162 : if (access->is_set_with_nondebug_insn_uses ())
170 : : // No need for as_a; this test is just as definitive.
171 : 82270354 : return static_cast<const set_info *> (access);
172 : : return nullptr;
173 : : }
174 : :
175 : : // A non-const version of the above.
176 : : inline set_info *
177 : : set_with_nondebug_insn_uses (access_info *access)
178 : : {
179 : : if (access->is_set_with_nondebug_insn_uses ())
180 : : return static_cast<set_info *> (access);
181 : : return nullptr;
182 : : }
183 : :
184 : : // ACCESS is known to be associated with an instruction rather than
185 : : // a phi node. Return which instruction that is.
186 : : inline insn_info *
187 : 154999920 : access_insn (const access_info *access)
188 : : {
189 : : // In release builds this function reduces to a single pointer reference.
190 : 154999920 : if (auto *def = dyn_cast<const def_info *> (access))
191 : 82080097 : return def->insn ();
192 : 72919823 : return as_a<const use_info *> (access)->insn ();
193 : : }
194 : :
195 : : // If ACCESS records a use, return the value that it uses. If ACCESS records
196 : : // a set, return that set. If ACCESS records a clobber, return null.
197 : : inline const set_info *
198 : : access_value (const access_info *access)
199 : : {
200 : : if (!access)
201 : : return nullptr;
202 : :
203 : : if (auto *use = dyn_cast<const use_info *> (access))
204 : : return use->def ();
205 : :
206 : : return dyn_cast<const set_info *> (access);
207 : : }
208 : :
209 : : // A non-const version of the above.
210 : : inline set_info *
211 : : access_value (access_info *access)
212 : : {
213 : : auto *const_access = const_cast<const access_info *> (access);
214 : : return const_cast<set_info *> (access_value (const_access));
215 : : }
216 : :
217 : : // If ACCESS is a degenerate phi, return the set_info that defines its input,
218 : : // otherwise return ACCESS itself.
219 : : template<typename T>
220 : : inline const T *
221 : 185128443 : look_through_degenerate_phi (const T *access)
222 : : {
223 : 25299938 : if (auto *phi = dyn_cast<const phi_info *> (access))
224 : 25299938 : if (phi->is_degenerate ())
225 : 11633212 : return phi->input_value (0);
226 : : return access;
227 : : }
228 : :
229 : : // A non-const version of the above.
230 : : template<typename T>
231 : : inline T *
232 : 185128443 : look_through_degenerate_phi (T *access)
233 : : {
234 : 185128443 : auto *const_access = const_cast<const T *> (access);
235 : 185128443 : return const_cast<T *> (look_through_degenerate_phi (const_access));
236 : : }
237 : :
238 : : // If CLOBBER is in a group, return the first clobber in the group,
239 : : // otherwise return CLOBBER itself.
240 : : inline clobber_info *
241 : 10718714 : first_clobber_in_group (clobber_info *clobber)
242 : : {
243 : 10718714 : if (clobber->is_in_group ())
244 : 10655656 : return clobber->group ()->first_clobber ();
245 : : return clobber;
246 : : }
247 : :
248 : : // If CLOBBER is in a group, return the last clobber in the group,
249 : : // otherwise return CLOBBER itself.
250 : : inline clobber_info *
251 : 11262497 : last_clobber_in_group (clobber_info *clobber)
252 : : {
253 : 11262497 : if (clobber->is_in_group ())
254 : 11259130 : return clobber->group ()->last_clobber ();
255 : : return clobber;
256 : : }
257 : :
258 : : // If DEF is a clobber in a group, return the containing group,
259 : : // otherwise return DEF.
260 : : inline def_mux
261 : 4140299 : clobber_group_or_single_def (def_info *def)
262 : : {
263 : 4140299 : if (auto *clobber = dyn_cast<clobber_info *> (def))
264 : 2403996 : if (clobber->is_in_group ())
265 : 2195593 : return clobber->group ();
266 : 1944706 : return def;
267 : : }
268 : :
269 : : // Return the first definition associated with NODE. If NODE holds
270 : : // a single set, the result is that set. If NODE holds a clobber_group,
271 : : // the result is the first clobber in the group.
272 : : inline def_info *
273 : 46090917 : first_def (def_node *node)
274 : : {
275 : 80768899 : return node->first_def ();
276 : : }
277 : :
278 : : // Likewise for something that is either a node or a single definition.
279 : : inline def_info *
280 : 1976327 : first_def (def_mux mux)
281 : : {
282 : 3017657 : return mux.first_def ();
283 : : }
284 : :
285 : : // Return the last definition associated with NODE. If NODE holds
286 : : // a single set, the result is that set. If NODE holds a clobber_group,
287 : : // the result is the last clobber in the group.
288 : : inline def_info *
289 : 5899465 : last_def (def_node *node)
290 : : {
291 : 5899465 : if (auto *group = dyn_cast<clobber_group *> (node))
292 : 2944136 : return group->last_clobber ();
293 : 2955329 : return node->first_def ();
294 : : }
295 : :
296 : : // Likewise for something that is either a node or a single definition.
297 : : inline def_info *
298 : 2163972 : last_def (def_mux mux)
299 : : {
300 : 2163972 : return mux.last_def ();
301 : : }
302 : :
303 : : // If INSN's definitions contain a single set, return that set, otherwise
304 : : // return null.
305 : : inline set_info *
306 : 102271840 : single_set_info (insn_info *insn)
307 : : {
308 : 102271840 : set_info *set = nullptr;
309 : 231678546 : for (auto def : insn->defs ())
310 : 266112616 : if (auto this_set = dyn_cast<set_info *> (def))
311 : : {
312 : 97556601 : if (set)
313 : 7299204 : return nullptr;
314 : : set = this_set;
315 : : }
316 : 94972636 : return set;
317 : : }
318 : :
319 : : int lookup_use (splay_tree<use_info *> &, insn_info *);
320 : : int lookup_def (def_splay_tree &, insn_info *);
321 : : int lookup_clobber (clobber_tree &, insn_info *);
322 : : int lookup_call_clobbers (insn_call_clobbers_tree &, insn_info *);
323 : :
324 : : // Search backwards from immediately before INSN for the first "relevant"
325 : : // instruction recorded in TREE. IGNORE is an object that provides the same
326 : : // interface as ignore_nothing; it defines which insns are "relevant"
327 : : // and which should be ignored.
328 : : //
329 : : // Return null if no such relevant instruction exists.
330 : : template<typename IgnorePredicates>
331 : : insn_info *
332 : 12085675 : prev_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn,
333 : : IgnorePredicates ignore)
334 : : {
335 : 12085675 : if (!tree)
336 : : return nullptr;
337 : :
338 : 12085675 : int comparison = lookup_call_clobbers (tree, insn);
339 : 14521229 : while (comparison <= 0 || ignore.should_ignore_insn (tree->insn ()))
340 : : {
341 : 8596466 : if (!tree.splay_prev_node ())
342 : : return nullptr;
343 : :
344 : : comparison = 1;
345 : : }
346 : : return tree->insn ();
347 : : }
348 : :
349 : : // Search forwards from immediately after INSN for the first "relevant"
350 : : // instruction recorded in TREE. IGNORE is an object that provides the
351 : : // same interface as ignore_nothing; it defines which insns are "relevant"
352 : : // and which should be ignored.
353 : : //
354 : : // Return null if no such relevant instruction exists.
355 : : template<typename IgnorePredicates>
356 : : insn_info *
357 : 30781949 : next_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn,
358 : : IgnorePredicates ignore)
359 : : {
360 : 30781949 : if (!tree)
361 : : return nullptr;
362 : :
363 : 30781949 : int comparison = lookup_call_clobbers (tree, insn);
364 : 41223625 : while (comparison >= 0 || ignore.should_ignore_insn (tree->insn ()))
365 : : {
366 : 21712964 : if (!tree.splay_next_node ())
367 : : return nullptr;
368 : :
369 : : comparison = -1;
370 : : }
371 : 56364 : return tree->insn ();
372 : : }
373 : :
374 : : // Search forwards from immediately after INSN for the first instruction
375 : : // recorded in TREE. Return null if no such instruction exists.
376 : : inline insn_info *
377 : 62917 : next_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn)
378 : : {
379 : 62917 : return next_call_clobbers (tree, insn, ignore_nothing ());
380 : : }
381 : :
382 : : // If ACCESS is a set, return the first "relevant" use of ACCESS by a
383 : : // nondebug insn. IGNORE is an object that provides the same interface
384 : : // as ignore_nothing; it defines which accesses and insns are "relevant"
385 : : // and which should be ignored.
386 : : //
387 : : // Return null if ACCESS is not a set or if no such relevant use exists.
388 : : template<typename IgnorePredicates>
389 : : inline use_info *
390 : 80788558 : first_nondebug_insn_use (const access_info *access, IgnorePredicates ignore)
391 : : {
392 : 48191948 : if (const set_info *set = set_with_nondebug_insn_uses (access))
393 : : {
394 : : // Written this way to emphasize to the compiler that first_use
395 : : // must be nonnull in this situation.
396 : 48191948 : use_info *use = set->first_use ();
397 : : do
398 : : {
399 : 48191948 : if (!ignore.should_ignore_insn (use->insn ()))
400 : : return use;
401 : 0 : use = use->next_nondebug_insn_use ();
402 : : }
403 : 0 : while (use);
404 : : }
405 : : return nullptr;
406 : : }
407 : :
408 : : // If ACCESS is a set, return the last "relevant" use of ACCESS by a
409 : : // nondebug insn. IGNORE is an object that provides the same interface
410 : : // as ignore_nothing; it defines which accesses and insns are "relevant"
411 : : // and which should be ignored.
412 : : //
413 : : // Return null if ACCESS is not a set or if no such relevant use exists.
414 : : template<typename IgnorePredicates>
415 : : inline use_info *
416 : 42821604 : last_nondebug_insn_use (const access_info *access, IgnorePredicates ignore)
417 : : {
418 : 34078406 : if (const set_info *set = set_with_nondebug_insn_uses (access))
419 : : {
420 : : // Written this way to emphasize to the compiler that
421 : : // last_nondebug_insn_use must be nonnull in this situation.
422 : 34078406 : use_info *use = set->last_nondebug_insn_use ();
423 : : do
424 : : {
425 : 39284944 : if (!ignore.should_ignore_insn (use->insn ()))
426 : : return use;
427 : 12101635 : use = use->prev_use ();
428 : : }
429 : 12101635 : while (use);
430 : : }
431 : : return nullptr;
432 : : }
433 : :
434 : : // If DEF is null, return null.
435 : : //
436 : : // Otherwise, search backwards for an access to DEF->resource (), starting at
437 : : // the end of DEF's live range. Ignore clobbers if IGNORE_CLOBBERS_SETTING
438 : : // is YES, otherwise treat them like any other access. Also ignore any
439 : : // accesses and insns that IGNORE says should be ignored, where IGNORE
440 : : // is an object that provides the same interface as ignore_nothing.
441 : : //
442 : : // Thus if DEF is a set that is used by nondebug insns, the first access
443 : : // that the function considers is the last such use of the set. Otherwise,
444 : : // the first access that the function considers is DEF itself.
445 : : //
446 : : // Return the access found, or null if there is no access that meets
447 : : // the criteria.
448 : : //
449 : : // Note that this function does not consider separately-recorded call clobbers,
450 : : // although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
451 : : template<typename IgnorePredicates>
452 : : access_info *
453 : 67735395 : last_access (def_info *def, ignore_clobbers ignore_clobbers_setting,
454 : : IgnorePredicates ignore)
455 : : {
456 : 67735395 : while (def)
457 : : {
458 : 56350440 : auto *clobber = dyn_cast<clobber_info *> (def);
459 : 56350440 : if (clobber && ignore_clobbers_setting == ignore_clobbers::YES)
460 : 10718714 : def = first_clobber_in_group (clobber);
461 : 22550938 : else if (!ignore.should_ignore_def (def))
462 : : {
463 : 42821604 : if (use_info *use = last_nondebug_insn_use (def, ignore))
464 : : return use;
465 : 23885467 : if (!ignore.should_ignore_insn (def->insn ()))
466 : : return def;
467 : : }
468 : 81797822 : def = def->prev_def ();
469 : : }
470 : : return nullptr;
471 : : }
472 : :
473 : : // Search backwards for an access to DEF->resource (), starting
474 : : // immediately before the point at which DEF occurs. Ignore clobbers
475 : : // if IGNORE_CLOBBERS_SETTING is YES, otherwise treat them like any other
476 : : // access. Also ignore any accesses and insns that IGNORE says should be
477 : : // ignored, where IGNORE is an object that provides the same interface as
478 : : // ignore_nothing.
479 : : //
480 : : // Thus if DEF->insn () uses DEF->resource (), that use is the first access
481 : : // that the function considers, since an instruction's uses occur strictly
482 : : // before its definitions.
483 : : //
484 : : // Note that this function does not consider separately-recorded call clobbers,
485 : : // although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
486 : : template<typename IgnorePredicates>
487 : : inline access_info *
488 : 66638792 : prev_access (def_info *def, ignore_clobbers ignore_clobbers_setting,
489 : : IgnorePredicates ignore)
490 : : {
491 : 66638792 : return last_access (def->prev_def (), ignore_clobbers_setting, ignore);
492 : : }
493 : :
494 : : // If DEF is null, return null.
495 : : //
496 : : // Otherwise, search forwards for an access to DEF->resource (),
497 : : // starting at DEF itself. Ignore clobbers if IGNORE_CLOBBERS_SETTING
498 : : // is YES, otherwise treat them like any other access. Also ignore any
499 : : // accesses and insns that IGNORE says should be ignored, where IGNORE
500 : : // is an object that provides the same interface as ignore_nothing.
501 : : //
502 : : // Return the definition found, or null if there is no access that meets
503 : : // the criteria.
504 : : //
505 : : // Note that this function does not consider separately-recorded call clobbers,
506 : : // although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
507 : : template<typename IgnorePredicates>
508 : : access_info *
509 : 164907784 : first_access (def_info *def, ignore_clobbers ignore_clobbers_setting,
510 : : IgnorePredicates ignore)
511 : : {
512 : 164907784 : while (def)
513 : : {
514 : 92342229 : auto *clobber = dyn_cast<clobber_info *> (def);
515 : 92342229 : if (clobber && ignore_clobbers_setting == ignore_clobbers::YES)
516 : 11262497 : def = last_clobber_in_group (clobber);
517 : 36583023 : else if (!ignore.should_ignore_def (def))
518 : : {
519 : 78669725 : if (!ignore.should_ignore_insn (def->insn ()))
520 : : return def;
521 : 14149766 : if (use_info *use = first_nondebug_insn_use (def, ignore))
522 : : return use;
523 : : }
524 : 183777154 : def = def->next_def ();
525 : : }
526 : : return nullptr;
527 : : }
528 : :
529 : : // Search forwards for the next access to DEF->resource (),
530 : : // starting immediately after DEF's instruction. Ignore clobbers if
531 : : // IGNORE_CLOBBERS_SETTING is YES, otherwise treat them like any other access.
532 : : // Also ignore any accesses and insns that IGNORE says should be ignored,
533 : : // where IGNORE is an object that provides the same interface as
534 : : // ignore_nothing.
535 : : //
536 : : // Thus if DEF is a set with uses by nondebug insns, the first access that the
537 : : // function considers is the first such use of the set. Otherwise, the first
538 : : // access that the function considers is the definition after DEF.
539 : : //
540 : : // Return the access found, or null if there is no access that meets the
541 : : // criteria.
542 : : //
543 : : // Note that this function does not consider separately-recorded call clobbers,
544 : : // although such clobbers are only relevant if IGNORE_CLOBBERS_SETTING is NO.
545 : : template<typename IgnorePredicates>
546 : : access_info *
547 : 66638792 : next_access (def_info *def, ignore_clobbers ignore_clobbers_setting,
548 : : IgnorePredicates ignore)
549 : : {
550 : 24514207 : if (!ignore.should_ignore_def (def))
551 : 66638792 : if (use_info *use = first_nondebug_insn_use (def, ignore))
552 : : return use;
553 : :
554 : 27399744 : return first_access (def->next_def (), ignore_clobbers_setting, ignore);
555 : : }
556 : :
557 : : // Return true if ACCESS1 should before ACCESS2 in an access_array.
558 : : inline bool
559 : 637196817 : compare_access_infos (const access_info *access1, const access_info *access2)
560 : : {
561 : 637196817 : gcc_checking_assert (access1 == access2
562 : : || access1->regno () != access2->regno ());
563 : 637196817 : return access1->regno () < access2->regno ();
564 : : }
565 : :
566 : : // Sort [BEGIN, END) into ascending regno order. The sequence must have
567 : : // at most one access to a given a regno.
568 : : inline void
569 : 486099389 : sort_accesses (access_info **begin, access_info **end)
570 : : {
571 : 486099389 : auto count = end - begin;
572 : 486099389 : if (count <= 1)
573 : : return;
574 : :
575 : 176421458 : if (count == 2)
576 : : {
577 : 120060622 : gcc_checking_assert (begin[0]->regno () != begin[1]->regno ());
578 : 120060622 : if (begin[0]->regno () > begin[1]->regno ())
579 : 78016746 : std::swap (begin[0], begin[1]);
580 : 120060622 : return;
581 : : }
582 : :
583 : 56360836 : std::sort (begin, end, compare_access_infos);
584 : : }
585 : :
586 : : // Sort the accesses in CONTAINER, which contains pointers to access_infos.
587 : : template<typename T>
588 : : inline void
589 : 486099389 : sort_accesses (T &container)
590 : : {
591 : 972198778 : return sort_accesses (container.begin (), container.end ());
592 : : }
593 : :
594 : : // The underlying non-template implementation of merge_access_arrays.
595 : : access_array merge_access_arrays_base (obstack_watermark &, access_array,
596 : : access_array);
597 : : // Merge access arrays ACCESSES1 and ACCESSES2, including the allocation
598 : : // in the area governed by WATERMARK. Return an invalid access_array if
599 : : // ACCESSES1 and ACCESSES2 contain conflicting accesses to the same resource.
600 : : //
601 : : // T can be an access_array, a def_array or a use_array.
602 : : template<typename T>
603 : : inline T
604 : 56618088 : merge_access_arrays (obstack_watermark &watermark, T accesses1, T accesses2)
605 : : {
606 : 56618088 : return T (merge_access_arrays_base (watermark, accesses1, accesses2));
607 : : }
608 : :
609 : : // The underlying non-template implementation of insert_access.
610 : : access_array insert_access_base (obstack_watermark &, access_info *,
611 : : access_array);
612 : :
613 : : // Return a new access_array that contains the result of inserting ACCESS1
614 : : // into sorted access array ACCESSES2. Allocate the returned array in the
615 : : // area governed by WATERMARK. Return an invalid access_array if ACCESSES2
616 : : // contains a conflicting access to the same resource as ACCESS1.
617 : : //
618 : : // T can be an access_array, a def_array or a use_array.
619 : : template<typename T>
620 : : inline T
621 : 1843626 : insert_access (obstack_watermark &watermark,
622 : : typename T::value_type access1, T accesses2)
623 : : {
624 : 1843626 : return T (insert_access_base (watermark, access1, accesses2));
625 : : }
626 : :
627 : : // Return a copy of USES that drops any use of DEF.
628 : : use_array remove_uses_of_def (obstack_watermark &, use_array uses,
629 : : def_info *def);
630 : :
631 : : // The underlying non-template implementation of remove_note_accesses.
632 : : access_array remove_note_accesses_base (obstack_watermark &, access_array);
633 : :
634 : : // If ACCESSES contains accesses that only occur in notes, return a new
635 : : // array without such accesses, allocating it in the area governed by
636 : : // WATERMARK. Return ACCESSES itself otherwise.
637 : : //
638 : : // T can be an access_array, a def_array or a use_array.
639 : : template<typename T>
640 : : inline T
641 : 42577407 : remove_note_accesses (obstack_watermark &watermark, T accesses)
642 : : {
643 : 42577407 : return T (remove_note_accesses_base (watermark, accesses));
644 : : }
645 : :
646 : : // Return true if ACCESSES1 and ACCESSES2 have at least one resource in common.
647 : : bool accesses_reference_same_resource (access_array accesses1,
648 : : access_array accesses2);
649 : :
650 : : // Return true if INSN clobbers the value of any resources in ACCESSES.
651 : : bool insn_clobbers_resources (insn_info *insn, access_array accesses);
652 : :
653 : : }
|