1 | // Implementation of instruction-related RTL SSA functions -*- C++ -*- |
2 | // Copyright (C) 2020-2023 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 | #define INCLUDE_ALGORITHM |
21 | #define INCLUDE_FUNCTIONAL |
22 | #include "config.h" |
23 | #include "system.h" |
24 | #include "coretypes.h" |
25 | #include "backend.h" |
26 | #include "rtl.h" |
27 | #include "df.h" |
28 | #include "rtl-ssa.h" |
29 | #include "rtl-ssa/internals.h" |
30 | #include "rtl-ssa/internals.inl" |
31 | #include "predict.h" |
32 | #include "print-rtl.h" |
33 | #include "rtl-iter.h" |
34 | |
35 | using namespace rtl_ssa; |
36 | |
37 | // The gap to leave between program points when building up the list |
38 | // of instructions for the first time. Using 2 allows an instruction |
39 | // to be inserted between two others without resorting to splay tree |
40 | // ordering. Using 0 is useful as a debugging aid to stress the |
41 | // splay tree code. |
42 | static const unsigned int POINT_INCREASE = 2; |
43 | |
44 | // Calculate and record the cost of the instruction, based on the |
45 | // form it had before any in-progress changes were made. |
46 | void |
47 | insn_info::calculate_cost () const |
48 | { |
49 | basic_block cfg_bb = BLOCK_FOR_INSN (insn: m_rtl); |
50 | temporarily_undo_changes (0); |
51 | m_cost_or_uid = insn_cost (m_rtl, optimize_bb_for_speed_p (cfg_bb)); |
52 | redo_changes (0); |
53 | } |
54 | |
55 | // Add NOTE to the instruction's notes. |
56 | void |
57 | insn_info::add_note (insn_note *note) |
58 | { |
59 | insn_note **ptr = &m_first_note; |
60 | // Always put the order node first, since it's the one that's likely |
61 | // to be used most often. |
62 | if (*ptr && (*ptr)->kind () == insn_note_kind::ORDER_NODE) |
63 | ptr = &(*ptr)->m_next_note; |
64 | note->m_next_note = *ptr; |
65 | *ptr = note; |
66 | } |
67 | |
68 | // Implement compare_with for the case in which this insn and OTHER |
69 | // have the same program point. |
70 | int |
71 | insn_info::slow_compare_with (const insn_info &other) const |
72 | { |
73 | return order_splay_tree::compare_nodes (node1: get_known_order_node (), |
74 | node2: other.get_known_order_node ()); |
75 | } |
76 | |
77 | // Print insn uid UID to PP, where UID has the same form as insn_info::uid. |
78 | void |
79 | insn_info::print_uid (pretty_printer *pp, int uid) |
80 | { |
81 | char tmp[3 * sizeof (uid) + 2]; |
82 | if (uid < 0) |
83 | // An artificial instruction. |
84 | snprintf (s: tmp, maxlen: sizeof (tmp), format: "a%d" , -uid); |
85 | else |
86 | // A real RTL instruction. |
87 | snprintf (s: tmp, maxlen: sizeof (tmp), format: "i%d" , uid); |
88 | pp_string (pp, tmp); |
89 | } |
90 | |
91 | // See comment above declaration. |
92 | void |
93 | insn_info::print_identifier (pretty_printer *pp) const |
94 | { |
95 | print_uid (pp, uid: uid ()); |
96 | } |
97 | |
98 | // See comment above declaration. |
99 | void |
100 | insn_info::print_location (pretty_printer *pp) const |
101 | { |
102 | if (bb_info *bb = this->bb ()) |
103 | { |
104 | ebb_info *ebb = bb->ebb (); |
105 | if (ebb && is_phi ()) |
106 | ebb->print_identifier (pp); |
107 | else |
108 | bb->print_identifier (pp); |
109 | pp_string (pp, " at point " ); |
110 | pp_decimal_int (pp, m_point); |
111 | } |
112 | else |
113 | pp_string (pp, "<unknown location>" ); |
114 | } |
115 | |
116 | // See comment above declaration. |
117 | void |
118 | insn_info::print_identifier_and_location (pretty_printer *pp) const |
119 | { |
120 | if (m_is_asm) |
121 | pp_string (pp, "asm " ); |
122 | if (m_is_debug_insn) |
123 | pp_string (pp, "debug " ); |
124 | pp_string (pp, "insn " ); |
125 | print_identifier (pp); |
126 | pp_string (pp, " in " ); |
127 | print_location (pp); |
128 | } |
129 | |
130 | // See comment above declaration. |
131 | void |
132 | insn_info::print_full (pretty_printer *pp) const |
133 | { |
134 | print_identifier_and_location (pp); |
135 | pp_colon (pp); |
136 | if (is_real ()) |
137 | { |
138 | pp_newline_and_indent (pp, 2); |
139 | if (has_been_deleted ()) |
140 | pp_string (pp, "deleted" ); |
141 | else |
142 | { |
143 | // Print the insn pattern to a temporary printer. |
144 | pretty_printer sub_pp; |
145 | print_insn_with_notes (&sub_pp, rtl ()); |
146 | const char *text = pp_formatted_text (&sub_pp); |
147 | |
148 | // Calculate the length of the maximum line in the pattern. |
149 | unsigned int max_len = 0; |
150 | const char *start = text; |
151 | while (const char *end = strchr (s: start, c: '\n')) |
152 | { |
153 | max_len = MAX (max_len, (unsigned int) (end - start)); |
154 | start = end + 1; |
155 | } |
156 | |
157 | // Print a separator before or after the pattern. |
158 | auto print_top_bottom = [&]() |
159 | { |
160 | pp_character (pp, '+'); |
161 | for (unsigned int i = 0; i < max_len + 2; ++i) |
162 | pp_character (pp, '-'); |
163 | }; |
164 | |
165 | print_top_bottom (); |
166 | start = text; |
167 | while (const char *end = strchr (s: start, c: '\n')) |
168 | { |
169 | pp_newline_and_indent (pp, 0); |
170 | pp_character (pp, '|'); |
171 | // Each line of the pattern already starts with a space. |
172 | // so we don't need to add another one here. |
173 | pp_append_text (pp, start, end); |
174 | start = end + 1; |
175 | } |
176 | pp_newline_and_indent (pp, 0); |
177 | print_top_bottom (); |
178 | |
179 | if (m_cost_or_uid != UNKNOWN_COST) |
180 | { |
181 | pp_newline_and_indent (pp, 0); |
182 | pp_string (pp, "cost: " ); |
183 | pp_decimal_int (pp, m_cost_or_uid); |
184 | } |
185 | if (m_has_pre_post_modify) |
186 | { |
187 | pp_newline_and_indent (pp, 0); |
188 | pp_string (pp, "has pre/post-modify operations" ); |
189 | } |
190 | if (m_has_volatile_refs) |
191 | { |
192 | pp_newline_and_indent (pp, 0); |
193 | pp_string (pp, "has volatile refs" ); |
194 | } |
195 | } |
196 | pp_indentation (pp) -= 2; |
197 | } |
198 | |
199 | auto print_accesses = [&](const char *heading, access_array accesses, |
200 | unsigned int flags) |
201 | { |
202 | if (!accesses.empty ()) |
203 | { |
204 | pp_newline_and_indent (pp, 2); |
205 | pp_string (pp, heading); |
206 | pp_newline_and_indent (pp, 2); |
207 | pp_accesses (pp, accesses, flags); |
208 | pp_indentation (pp) -= 4; |
209 | } |
210 | }; |
211 | |
212 | print_accesses ("uses:" , uses (), PP_ACCESS_USER); |
213 | auto *call_clobbers_note = find_note<insn_call_clobbers_note> (); |
214 | if (call_clobbers_note) |
215 | { |
216 | pp_newline_and_indent (pp, 2); |
217 | pp_string (pp, "has call clobbers for ABI " ); |
218 | pp_decimal_int (pp, call_clobbers_note->abi_id ()); |
219 | pp_indentation (pp) -= 2; |
220 | } |
221 | print_accesses ("defines:" , defs (), PP_ACCESS_SETTER); |
222 | if (num_uses () == 0 && !call_clobbers_note && num_defs () == 0) |
223 | { |
224 | pp_newline_and_indent (pp, 2); |
225 | pp_string (pp, "has no uses or defs" ); |
226 | pp_indentation (pp) -= 2; |
227 | } |
228 | |
229 | if (order_node *node = get_order_node ()) |
230 | { |
231 | while (node->m_parent) |
232 | node = node->m_parent; |
233 | |
234 | pp_newline_and_indent (pp, 2); |
235 | pp_string (pp, "insn order: " ); |
236 | pp_newline_and_indent (pp, 2); |
237 | auto print_order = [](pretty_printer *pp, order_node *node) |
238 | { |
239 | print_uid (pp, uid: node->uid ()); |
240 | }; |
241 | order_splay_tree::print (pp, node, printer: print_order); |
242 | pp_indentation (pp) -= 4; |
243 | } |
244 | } |
245 | |
246 | // Return an insn_info::order_node for INSN, creating one if necessary. |
247 | insn_info::order_node * |
248 | function_info::need_order_node (insn_info *insn) |
249 | { |
250 | insn_info::order_node *order = insn->get_order_node (); |
251 | if (!order) |
252 | { |
253 | order = allocate<insn_info::order_node> (args: insn->uid ()); |
254 | insn->add_note (note: order); |
255 | } |
256 | return order; |
257 | } |
258 | |
259 | // Add instruction INSN immediately after AFTER in the reverse postorder list. |
260 | // INSN is not currently in the list. |
261 | void |
262 | function_info::add_insn_after (insn_info *insn, insn_info *after) |
263 | { |
264 | gcc_checking_assert (!insn->has_insn_links ()); |
265 | |
266 | insn->copy_next_from (other: after); |
267 | after->set_next_any_insn (insn); |
268 | |
269 | // The prev link is easy if AFTER and INSN are the same type. |
270 | // Handle the other cases below. |
271 | if (after->is_debug_insn () == insn->is_debug_insn ()) |
272 | insn->set_prev_sametype_insn (after); |
273 | |
274 | if (insn_info *next = insn->next_any_insn ()) |
275 | { |
276 | if (insn->is_debug_insn () == next->is_debug_insn ()) |
277 | { |
278 | // INSN might now be the start of the subsequence of debug insns, |
279 | // and so its prev pointer might point to the end of the subsequence |
280 | // instead of AFTER. |
281 | insn->copy_prev_from (other: next); |
282 | next->set_prev_sametype_insn (insn); |
283 | } |
284 | else if (insn->is_debug_insn ()) // && !next->is_debug_insn () |
285 | { |
286 | // INSN ends a subsequence of debug instructions. Find the |
287 | // first debug instruction in the subsequence, which might |
288 | // be INSN itself. (If it isn't, then AFTER is also a debug |
289 | // instruction and we updated INSN's prev link above.) |
290 | insn_info *first = next->prev_nondebug_insn ()->next_any_insn (); |
291 | first->set_last_debug_insn (insn); |
292 | } |
293 | else // !insn->is_debug_insn () && next->is_debug_insn () |
294 | { |
295 | // At present we don't (need to) support inserting a nondebug |
296 | // instruction between two existing debug instructions. |
297 | gcc_assert (!after->is_debug_insn ()); |
298 | |
299 | // Find the next nondebug insn and update its previous pointer |
300 | // to point to INSN. |
301 | auto next_nondebug = next->last_debug_insn ()->next_any_insn (); |
302 | gcc_checking_assert (!next_nondebug->is_debug_insn ()); |
303 | next_nondebug->set_prev_sametype_insn (insn); |
304 | } |
305 | |
306 | // If AFTER and NEXT are separated by at least two points, we can |
307 | // use a unique point number for INSN. Otherwise INSN will have |
308 | // the same point number as AFTER. |
309 | insn->set_point ((next->point () + after->point ()) / 2); |
310 | } |
311 | else |
312 | { |
313 | if (!insn->is_debug_insn ()) |
314 | { |
315 | insn->set_prev_sametype_insn (m_last_nondebug_insn); |
316 | m_last_nondebug_insn = insn; |
317 | } |
318 | else |
319 | // There is now at least one debug instruction after |
320 | // m_last_nondebug_insn: either INSN itself, or the start of |
321 | // a longer subsequence of debug insns that now ends with AFTER |
322 | // followed by INSN. |
323 | m_last_nondebug_insn->next_any_insn ()->set_last_debug_insn (insn); |
324 | m_last_insn = insn; |
325 | |
326 | insn->set_point (after->point () + POINT_INCREASE); |
327 | } |
328 | |
329 | // If INSN's program point is the same as AFTER's, we need to use the |
330 | // splay tree to record their relative order. |
331 | if (insn->point () == after->point ()) |
332 | { |
333 | insn_info::order_node *after_node = need_order_node (insn: after); |
334 | insn_info::order_node *insn_node = need_order_node (insn); |
335 | insn_info::order_splay_tree::insert_child (node: after_node, index: 1, child: insn_node); |
336 | } |
337 | } |
338 | |
339 | // Remove INSN from the function's list of instructions. |
340 | void |
341 | function_info::remove_insn (insn_info *insn) |
342 | { |
343 | if (insn_info::order_node *order = insn->get_order_node ()) |
344 | insn_info::order_splay_tree::remove_node (node: order); |
345 | |
346 | if (auto *note = insn->find_note<insn_call_clobbers_note> ()) |
347 | { |
348 | ebb_call_clobbers_info *ecc = insn->ebb ()->first_call_clobbers (); |
349 | while (ecc->abi ()->id () != note->abi_id ()) |
350 | ecc = ecc->next (); |
351 | int comparison = lookup_call_clobbers (*ecc, insn); |
352 | gcc_assert (comparison == 0); |
353 | ecc->remove_root (); |
354 | } |
355 | |
356 | insn_info *prev = insn->prev_any_insn (); |
357 | insn_info *next = insn->next_any_insn (); |
358 | insn_info *prev_nondebug = insn->prev_nondebug_insn (); |
359 | insn_info *next_nondebug = insn->next_nondebug_insn (); |
360 | |
361 | // We should never remove the entry or exit block's instructions. |
362 | // At present we also don't remove entire blocks, so should never |
363 | // remove debug instructions. |
364 | gcc_checking_assert (prev_nondebug |
365 | && next_nondebug |
366 | && !insn->is_debug_insn ()); |
367 | |
368 | if (prev->is_debug_insn () && next->is_debug_insn ()) |
369 | { |
370 | // We need to stitch together two subsequences of debug insns. |
371 | insn_info *last = next->last_debug_insn (); |
372 | next->set_prev_sametype_insn (prev); |
373 | prev_nondebug->next_any_insn ()->set_last_debug_insn (last); |
374 | } |
375 | prev->set_next_any_insn (next); |
376 | next_nondebug->set_prev_sametype_insn (prev_nondebug); |
377 | |
378 | insn->clear_insn_links (); |
379 | } |
380 | |
381 | // Create an artificial instruction for BB, associating it with RTL (which can |
382 | // be null). Add the new instruction to the end of the function's list and |
383 | // return the new instruction. |
384 | insn_info * |
385 | function_info::append_artificial_insn (bb_info *bb, rtx_insn *rtl) |
386 | { |
387 | insn_info *insn = allocate<insn_info> (args: bb, args: rtl, args: m_next_artificial_uid); |
388 | m_next_artificial_uid -= 1; |
389 | append_insn (insn); |
390 | return insn; |
391 | } |
392 | |
393 | // Finish building a new list of uses and definitions for instruction INSN. |
394 | void |
395 | function_info::finish_insn_accesses (insn_info *insn) |
396 | { |
397 | unsigned int num_defs = m_temp_defs.length (); |
398 | unsigned int num_uses = m_temp_uses.length (); |
399 | obstack_make_room (&m_obstack, num_defs + num_uses); |
400 | if (num_defs) |
401 | { |
402 | sort_accesses (container&: m_temp_defs); |
403 | obstack_grow (&m_obstack, m_temp_defs.address (), |
404 | num_defs * sizeof (access_info *)); |
405 | m_temp_defs.truncate (size: 0); |
406 | } |
407 | if (num_uses) |
408 | { |
409 | sort_accesses (container&: m_temp_uses); |
410 | obstack_grow (&m_obstack, m_temp_uses.address (), |
411 | num_uses * sizeof (access_info *)); |
412 | m_temp_uses.truncate (size: 0); |
413 | } |
414 | void *addr = obstack_finish (&m_obstack); |
415 | insn->set_accesses (accesses: static_cast<access_info **> (addr), num_defs, num_uses); |
416 | } |
417 | |
418 | // Called while building SSA form using BI. Create and return a use of |
419 | // register RESOURCE in INSN. Create a degenerate phi where necessary. |
420 | use_info * |
421 | function_info::create_reg_use (build_info &bi, insn_info *insn, |
422 | resource_info resource) |
423 | { |
424 | set_info *value = bi.current_reg_value (regno: resource.regno); |
425 | if (value && value->ebb () != bi.current_ebb) |
426 | { |
427 | if (insn->is_debug_insn ()) |
428 | value = look_through_degenerate_phi (access: value); |
429 | else if (bitmap_bit_p (map: bi.potential_phi_regs, bitno: resource.regno)) |
430 | { |
431 | // VALUE is defined by a previous EBB and RESOURCE has multiple |
432 | // definitions. Create a degenerate phi in the current EBB |
433 | // so that all definitions and uses follow a linear RPO view; |
434 | // see rtl.texi for details. |
435 | access_info *inputs[] = { look_through_degenerate_phi (access: value) }; |
436 | value = create_phi (bi.current_ebb, value->resource (), inputs, 1); |
437 | bi.record_reg_def (def: value); |
438 | } |
439 | } |
440 | auto *use = allocate<use_info> (args: insn, args: resource, args: value); |
441 | add_use (use); |
442 | return use; |
443 | } |
444 | |
445 | // Called while building SSA form using BI. Record that INSN contains |
446 | // read reference REF. If this requires new entries to be added to |
447 | // INSN->uses (), add those entries to the list we're building in |
448 | // m_temp_uses. |
449 | void |
450 | function_info::record_use (build_info &bi, insn_info *insn, |
451 | rtx_obj_reference ref) |
452 | { |
453 | unsigned int regno = ref.regno; |
454 | machine_mode mode = ref.is_reg () ? ref.mode : BLKmode; |
455 | access_info *access = bi.last_access[ref.regno + 1]; |
456 | use_info *use = safe_dyn_cast<use_info *> (p: access); |
457 | if (!use) |
458 | { |
459 | set_info *value = safe_dyn_cast<set_info *> (p: access); |
460 | // In order to ensure that -g doesn't affect codegen, uses in debug |
461 | // instructions do not affect liveness, either in DF or here. |
462 | // This means that there might be no correct definition of the resource |
463 | // available (e.g. if it would require a phi node that the nondebug |
464 | // code doesn't need). Perhaps we could have "debug phi nodes" as |
465 | // well as "debug instructions", but that would require a method |
466 | // of building phi nodes that didn't depend on DF liveness information, |
467 | // and so might be significantly more expensive. |
468 | // |
469 | // Therefore, the only value we try to attach to a use by a debug |
470 | // instruction is VALUE itself (as we would for nondebug instructions). |
471 | // We then need to make a conservative check for whether VALUE is |
472 | // actually correct. |
473 | auto value_is_valid = [&]() |
474 | { |
475 | // Memmory always has a valid definition. |
476 | if (ref.is_mem ()) |
477 | return true; |
478 | |
479 | // If VALUE would lead to an uninitialized use anyway, there's |
480 | // nothing to check. |
481 | if (!value) |
482 | return false; |
483 | |
484 | // If the previous definition occurs in the same EBB then it |
485 | // is certainly correct. |
486 | if (value->ebb () == bi.current_ebb) |
487 | return true; |
488 | |
489 | // Check if VALUE is the function's only definition of REGNO. |
490 | // (We already know that it dominates the use.) |
491 | if (!bitmap_bit_p (map: bi.potential_phi_regs, bitno: regno)) |
492 | return true; |
493 | |
494 | // If the register is live on entry to the EBB but not used |
495 | // within it, VALUE is the correct live-in value. |
496 | if (!bi.ebb_live_in_for_debug) |
497 | calculate_ebb_live_in_for_debug (bi); |
498 | if (bitmap_bit_p (bi.ebb_live_in_for_debug, regno)) |
499 | return true; |
500 | |
501 | // Punt for other cases. |
502 | return false; |
503 | }; |
504 | if (insn->is_debug_insn () && !value_is_valid ()) |
505 | value = nullptr; |
506 | |
507 | use = create_reg_use (bi, insn, resource: { .mode: mode, .regno: regno }); |
508 | m_temp_uses.safe_push (obj: use); |
509 | bi.last_access[ref.regno + 1] = use; |
510 | use->record_reference (ref, is_first: true); |
511 | } |
512 | else |
513 | { |
514 | // Record the mode of the largest use. The choice is arbitrary if |
515 | // the instruction (unusually) references the same register in two |
516 | // different but equal-sized modes. |
517 | gcc_checking_assert (use->insn () == insn); |
518 | if (HARD_REGISTER_NUM_P (regno) |
519 | && partial_subreg_p (outermode: use->mode (), innermode: mode)) |
520 | use->set_mode (mode); |
521 | use->record_reference (ref, is_first: false); |
522 | } |
523 | } |
524 | |
525 | // Called while building SSA form for INSN using BI. Record the effect |
526 | // of call clobbers in RTL. We have already added the explicit sets and |
527 | // clobbers for RTL, which have priority over any call clobbers. |
528 | void |
529 | function_info::record_call_clobbers (build_info &bi, insn_info *insn, |
530 | rtx_call_insn *rtl) |
531 | { |
532 | // See whether we should record this call in the EBB's list of |
533 | // call clobbers. Three things affect this choice: |
534 | // |
535 | // (1) The list is the only way we have of recording partial clobbers. |
536 | // All calls that only partially clobber registers must therefore |
537 | // be in the list. |
538 | // |
539 | // (2) Adding calls to the list is much more memory-efficient than |
540 | // creating a long list of clobber_infos. |
541 | // |
542 | // (3) Adding calls to the list limits the ability to move definitions |
543 | // of registers that are normally fully or partially clobbered |
544 | // by the associated predefined ABI. So adding calls to the list |
545 | // can hamper optimization if (thanks to -fipa-ra) the number of |
546 | // clobbers is much smaller than the usual set. |
547 | // |
548 | // The trade-off that we currently take is to use the list if there |
549 | // are some registers that the call only partially clobbers or if |
550 | // the set of clobbers is the standard set. |
551 | function_abi abi = insn_callee_abi (rtl); |
552 | if (abi.base_abi ().full_reg_clobbers () == abi.full_reg_clobbers () |
553 | || abi.full_and_partial_reg_clobbers () != abi.full_reg_clobbers ()) |
554 | { |
555 | // Find an entry for this predefined ABI, creating one if necessary. |
556 | ebb_call_clobbers_info *ecc = bi.current_ebb->first_call_clobbers (); |
557 | while (ecc && ecc->abi () != &abi.base_abi ()) |
558 | ecc = ecc->next (); |
559 | if (!ecc) |
560 | { |
561 | ecc = allocate<ebb_call_clobbers_info> (args: &abi.base_abi ()); |
562 | ecc->m_next = bi.current_ebb->first_call_clobbers (); |
563 | bi.current_ebb->set_first_call_clobbers (ecc); |
564 | } |
565 | |
566 | auto abi_id = abi.base_abi ().id (); |
567 | auto *insn_clobbers = allocate<insn_call_clobbers_note> (args: abi_id, args: insn); |
568 | insn->add_note (note: insn_clobbers); |
569 | |
570 | ecc->insert_max_node (new_node: insn_clobbers); |
571 | |
572 | m_clobbered_by_calls |= abi.full_and_partial_reg_clobbers (); |
573 | } |
574 | else |
575 | for (unsigned int regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno) |
576 | if (TEST_HARD_REG_BIT (set: abi.full_reg_clobbers (), bit: regno)) |
577 | { |
578 | def_info *def = m_defs[regno + 1]; |
579 | if (!def || def->last_def ()->insn () != insn) |
580 | { |
581 | def = allocate<clobber_info> (args: insn, args: regno); |
582 | def->m_is_call_clobber = true; |
583 | append_def (def); |
584 | m_temp_defs.safe_push (obj: def); |
585 | bi.record_reg_def (def); |
586 | } |
587 | } |
588 | } |
589 | |
590 | // Called while building SSA form using BI. Record that INSN contains |
591 | // write reference REF. Add associated def_infos to the list of accesses |
592 | // that we're building in m_temp_defs. Record the register's new live |
593 | // value in BI. |
594 | void |
595 | function_info::record_def (build_info &bi, insn_info *insn, |
596 | rtx_obj_reference ref) |
597 | { |
598 | // Punt if we see multiple definitions of the same resource. |
599 | // This can happen for several reasons: |
600 | // |
601 | // - An instruction might store two values to memory at once, giving two |
602 | // distinct memory references. |
603 | // |
604 | // - An instruction might assign to multiple pieces of a wide pseudo |
605 | // register. For example, on 32-bit targets, an instruction might |
606 | // assign to both the upper and lower halves of a 64-bit pseudo register. |
607 | // |
608 | // - It's possible for the same register to be clobbered by the |
609 | // CALL_INSN_FUNCTION_USAGE and to be set by the main instruction |
610 | // pattern as well. In that case, the clobber conceptually happens |
611 | // before the set and can essentially be ignored. |
612 | // |
613 | // - Similarly, global registers are implicitly set by a call but can |
614 | // be explicitly set or clobbered as well. In that situation, the sets |
615 | // are listed first and should win over a clobber. |
616 | unsigned int regno = ref.regno; |
617 | machine_mode mode = ref.is_reg () ? ref.mode : BLKmode; |
618 | def_info *def = safe_dyn_cast<def_info *> (p: bi.last_access[ref.regno + 1]); |
619 | if (def && def->insn () == insn) |
620 | { |
621 | if (!ref.is_clobber ()) |
622 | { |
623 | gcc_checking_assert (!is_a<clobber_info *> (def)); |
624 | def->record_reference (ref, is_first: false); |
625 | } |
626 | return; |
627 | } |
628 | |
629 | // Memory is always well-defined, so only use clobber_infos for registers. |
630 | if (ref.is_reg () && ref.is_clobber ()) |
631 | def = allocate<clobber_info> (args: insn, args: regno); |
632 | else |
633 | def = allocate<set_info> (args: insn, args: resource_info { .mode: mode, .regno: regno }); |
634 | def->record_reference (ref, is_first: true); |
635 | append_def (def); |
636 | m_temp_defs.safe_push (obj: def); |
637 | bi.record_reg_def (def); |
638 | } |
639 | |
640 | // Called while building SSA form using BI. Add an insn_info for RTL |
641 | // to the block that we're current building. |
642 | void |
643 | function_info::add_insn_to_block (build_info &bi, rtx_insn *rtl) |
644 | { |
645 | insn_info *insn = allocate<insn_info> (args: bi.current_bb, args: rtl, args: UNKNOWN_COST); |
646 | append_insn (insn); |
647 | |
648 | vec_rtx_properties properties; |
649 | properties.add_insn (insn: rtl, include_notes: true); |
650 | insn->set_properties (properties); |
651 | |
652 | start_insn_accesses (); |
653 | |
654 | // Record the uses. |
655 | for (rtx_obj_reference ref : properties.refs ()) |
656 | if (ref.is_read ()) |
657 | record_use (bi, insn, ref); |
658 | |
659 | // Restore the contents of bi.last_access, which we used as a cache |
660 | // when assembling the uses. |
661 | for (access_info *access : m_temp_uses) |
662 | { |
663 | unsigned int regno = access->regno (); |
664 | gcc_checking_assert (bi.last_access[regno + 1] == access); |
665 | bi.last_access[regno + 1] = as_a<use_info *> (p: access)->def (); |
666 | } |
667 | |
668 | // Record the definitions. |
669 | for (rtx_obj_reference ref : properties.refs ()) |
670 | if (ref.is_write ()) |
671 | record_def (bi, insn, ref); |
672 | |
673 | // Logically these happen before the explicit definitions, but if the |
674 | // explicit definitions and call clobbers reference the same register, |
675 | // the explicit definition should win. |
676 | if (auto *call_rtl = dyn_cast<rtx_call_insn *> (p: rtl)) |
677 | record_call_clobbers (bi, insn, rtl: call_rtl); |
678 | |
679 | finish_insn_accesses (insn); |
680 | } |
681 | |
682 | // Check whether INSN sets any registers that are never subsequently used. |
683 | // If so, add REG_UNUSED notes for them. The caller has already removed |
684 | // any previous REG_UNUSED notes. |
685 | void |
686 | function_info::add_reg_unused_notes (insn_info *insn) |
687 | { |
688 | rtx_insn *rtl = insn->rtl (); |
689 | |
690 | auto handle_potential_set = [&](rtx pattern) |
691 | { |
692 | if (GET_CODE (pattern) != SET) |
693 | return; |
694 | |
695 | rtx dest = SET_DEST (pattern); |
696 | if (!REG_P (dest)) |
697 | return; |
698 | |
699 | def_array defs = insn->defs (); |
700 | unsigned int index = find_access_index (accesses: defs, REGNO (dest)); |
701 | for (unsigned int i = 0; i < REG_NREGS (dest); ++i) |
702 | { |
703 | def_info *def = defs[index + i]; |
704 | gcc_checking_assert (def->regno () == REGNO (dest) + i); |
705 | set_info *set = dyn_cast<set_info *> (p: def); |
706 | if (set && set->has_nondebug_uses ()) |
707 | return; |
708 | } |
709 | add_reg_note (rtl, REG_UNUSED, dest); |
710 | }; |
711 | |
712 | rtx pattern = PATTERN (insn: rtl); |
713 | if (GET_CODE (pattern) == PARALLEL) |
714 | for (int i = 0; i < XVECLEN (pattern, 0); ++i) |
715 | handle_potential_set (XVECEXP (pattern, 0, i)); |
716 | else |
717 | handle_potential_set (pattern); |
718 | } |
719 | |
720 | // Search TREE for call clobbers at INSN. Return: |
721 | // |
722 | // - less than zero if INSN occurs before the root of TREE |
723 | // - 0 if INSN is the root of TREE |
724 | // - greater than zero if INSN occurs after the root of TREE |
725 | int |
726 | rtl_ssa::lookup_call_clobbers (insn_call_clobbers_tree &tree, insn_info *insn) |
727 | { |
728 | auto compare = [&](insn_call_clobbers_note *clobbers) |
729 | { |
730 | return insn->compare_with (other: clobbers->insn ()); |
731 | }; |
732 | return tree.lookup (compare); |
733 | } |
734 | |
735 | // Print a description of INSN to PP. |
736 | void |
737 | rtl_ssa::pp_insn (pretty_printer *pp, const insn_info *insn) |
738 | { |
739 | if (!insn) |
740 | pp_string (pp, "<null>" ); |
741 | else |
742 | insn->print_full (pp); |
743 | } |
744 | |
745 | // Print a description of INSN to FILE. |
746 | void |
747 | dump (FILE *file, const insn_info *insn) |
748 | { |
749 | dump_using (file, printer: pp_insn, args: insn); |
750 | } |
751 | |
752 | // Debug interface to the dump routine above. |
753 | void debug (const insn_info *x) { dump (stderr, insn: x); } |
754 | |