Line data Source code
1 : /* Subroutines used by or related to instruction recognition.
2 : Copyright (C) 1987-2026 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 :
21 : #include "config.h"
22 : #include "system.h"
23 : #include "coretypes.h"
24 : #include "backend.h"
25 : #include "target.h"
26 : #include "rtl.h"
27 : #include "tree.h"
28 : #include "stmt.h"
29 : #include "cfghooks.h"
30 : #include "df.h"
31 : #include "memmodel.h"
32 : #include "tm_p.h"
33 : #include "insn-config.h"
34 : #include "regs.h"
35 : #include "emit-rtl.h"
36 : #include "recog.h"
37 : #include "insn-attr.h"
38 : #include "addresses.h"
39 : #include "cfgrtl.h"
40 : #include "cfgbuild.h"
41 : #include "cfgcleanup.h"
42 : #include "reload.h"
43 : #include "tree-pass.h"
44 : #include "function-abi.h"
45 : #include "rtl-iter.h"
46 :
47 : #ifndef STACK_POP_CODE
48 : #if STACK_GROWS_DOWNWARD
49 : #define STACK_POP_CODE POST_INC
50 : #else
51 : #define STACK_POP_CODE POST_DEC
52 : #endif
53 : #endif
54 :
55 : static void validate_replace_rtx_1 (rtx *, rtx, rtx, rtx_insn *, bool);
56 : static void validate_replace_src_1 (rtx *, void *);
57 : static rtx_insn *split_insn (rtx_insn *);
58 :
59 : struct target_recog default_target_recog;
60 : #if SWITCHABLE_TARGET
61 : struct target_recog *this_target_recog = &default_target_recog;
62 : #endif
63 :
64 : /* Nonzero means allow operands to be volatile.
65 : This should be 0 if you are generating rtl, such as if you are calling
66 : the functions in optabs.cc and expmed.cc (most of the time).
67 : This should be 1 if all valid insns need to be recognized,
68 : such as in reginfo.cc and final.cc and reload.cc.
69 :
70 : init_recog and init_recog_no_volatile are responsible for setting this. */
71 :
72 : int volatile_ok;
73 :
74 : struct recog_data_d recog_data;
75 :
76 : /* Contains a vector of operand_alternative structures, such that
77 : operand OP of alternative A is at index A * n_operands + OP.
78 : Set up by preprocess_constraints. */
79 : const operand_alternative *recog_op_alt;
80 :
81 : /* Used to provide recog_op_alt for asms. */
82 : static operand_alternative asm_op_alt[MAX_RECOG_OPERANDS
83 : * MAX_RECOG_ALTERNATIVES];
84 :
85 : /* On return from `constrain_operands', indicate which alternative
86 : was satisfied. */
87 :
88 : int which_alternative;
89 :
90 : /* True for inline asm operands with - constraint modifier. */
91 : bool raw_constraint_p;
92 :
93 : /* Nonzero after end of reload pass.
94 : Set to 1 or 0 by toplev.cc.
95 : Controls the significance of (SUBREG (MEM)). */
96 :
97 : int reload_completed;
98 :
99 : bool post_ra_split_completed;
100 :
101 : /* Nonzero after thread_prologue_and_epilogue_insns has run. */
102 : int epilogue_completed;
103 :
104 : /* Initialize data used by the function `recog'.
105 : This must be called once in the compilation of a function
106 : before any insn recognition may be done in the function. */
107 :
108 : void
109 7929758 : init_recog_no_volatile (void)
110 : {
111 7929758 : volatile_ok = 0;
112 7929758 : }
113 :
114 : void
115 11792466 : init_recog (void)
116 : {
117 11792466 : volatile_ok = 1;
118 11792466 : }
119 :
120 :
121 : /* Return true if labels in asm operands BODY are LABEL_REFs. */
122 :
123 : static bool
124 106408638 : asm_labels_ok (rtx body)
125 : {
126 106408638 : rtx asmop;
127 106408638 : int i;
128 :
129 106408638 : asmop = extract_asm_operands (body);
130 106408638 : if (asmop == NULL_RTX)
131 : return true;
132 :
133 834469 : for (i = 0; i < ASM_OPERANDS_LABEL_LENGTH (asmop); i++)
134 7559 : if (GET_CODE (ASM_OPERANDS_LABEL (asmop, i)) != LABEL_REF)
135 : return false;
136 :
137 : return true;
138 : }
139 :
140 : /* Check that X is an insn-body for an `asm' with operands
141 : and that the operands mentioned in it are legitimate. */
142 :
143 : bool
144 106408638 : check_asm_operands (rtx x)
145 : {
146 106408638 : int noperands;
147 106408638 : rtx *operands;
148 106408638 : const char **constraints;
149 106408638 : int i;
150 :
151 106408638 : if (!asm_labels_ok (x))
152 : return false;
153 :
154 : /* Post-reload, be more strict with things. */
155 106408638 : if (reload_completed)
156 : {
157 : /* ??? Doh! We've not got the wrapping insn. Cook one up. */
158 28969 : rtx_insn *insn = make_insn_raw (x);
159 28969 : extract_insn (insn);
160 28969 : constrain_operands (1, get_enabled_alternatives (insn));
161 28969 : return which_alternative >= 0;
162 : }
163 :
164 106379669 : noperands = asm_noperands (x);
165 106379669 : if (noperands < 0)
166 : return false;
167 782172 : if (noperands == 0)
168 : return true;
169 :
170 668941 : operands = XALLOCAVEC (rtx, noperands);
171 668941 : constraints = XALLOCAVEC (const char *, noperands);
172 :
173 668941 : decode_asm_operands (x, operands, NULL, constraints, NULL, NULL);
174 :
175 3234605 : for (i = 0; i < noperands; i++)
176 : {
177 2851710 : const char *c = constraints[i];
178 2851710 : if (c[0] == '%')
179 12321 : c++;
180 2851710 : if (! asm_operand_ok (operands[i], c, constraints))
181 : return false;
182 : }
183 :
184 : return true;
185 : }
186 :
187 : /* Static data for the next two routines. */
188 :
189 : struct change_t
190 : {
191 : rtx object;
192 : int old_code;
193 : int old_len;
194 : bool unshare;
195 : rtx *loc;
196 : rtx old;
197 : };
198 :
199 : static change_t *changes;
200 : static int changes_allocated;
201 :
202 : static int num_changes = 0;
203 : int undo_recog_changes::s_num_changes = 0;
204 :
205 : /* Validate a proposed change to OBJECT. LOC is the location in the rtl
206 : at which NEW_RTX will be placed. If NEW_LEN is >= 0, XVECLEN (NEW_RTX, 0)
207 : will also be changed to NEW_LEN, which is no greater than the current
208 : XVECLEN. If OBJECT is zero, no validation is done, the change is
209 : simply made.
210 :
211 : Two types of objects are supported: If OBJECT is a MEM, memory_address_p
212 : will be called with the address and mode as parameters. If OBJECT is
213 : an INSN, CALL_INSN, or JUMP_INSN, the insn will be re-recognized with
214 : the change in place.
215 :
216 : IN_GROUP is nonzero if this is part of a group of changes that must be
217 : performed as a group. In that case, the changes will be stored. The
218 : function `apply_change_group' will validate and apply the changes.
219 :
220 : If IN_GROUP is zero, this is a single change. Try to recognize the insn
221 : or validate the memory reference with the change applied. If the result
222 : is not valid for the machine, suppress the change and return false.
223 : Otherwise, perform the change and return true. */
224 :
225 : static bool
226 1819333892 : validate_change_1 (rtx object, rtx *loc, rtx new_rtx, bool in_group,
227 : bool unshare, int new_len = -1)
228 : {
229 1819333892 : gcc_assert (!undo_recog_changes::is_active ());
230 1819333892 : rtx old = *loc;
231 :
232 : /* Single-element parallels aren't valid and won't match anything.
233 : Replace them with the single element. */
234 1819333892 : if (new_len == 1 && GET_CODE (new_rtx) == PARALLEL)
235 : {
236 6470248 : new_rtx = XVECEXP (new_rtx, 0, 0);
237 6470248 : new_len = -1;
238 : }
239 :
240 : /* When a change is part of a group, callers expect to be able to change
241 : INSN_CODE after making the change and have the code reset to its old
242 : value by a later cancel_changes. We therefore need to register group
243 : changes even if they're no-ops. */
244 1819333892 : if (!in_group
245 211659476 : && (old == new_rtx || rtx_equal_p (old, new_rtx))
246 2012647363 : && (new_len < 0 || XVECLEN (new_rtx, 0) == new_len))
247 : return true;
248 :
249 1626020421 : gcc_assert ((in_group != 0 || num_changes == 0)
250 : && (new_len < 0 || new_rtx == *loc));
251 :
252 1626020421 : *loc = new_rtx;
253 :
254 : /* Save the information describing this change. */
255 1626020421 : if (num_changes >= changes_allocated)
256 : {
257 174323 : if (changes_allocated == 0)
258 : /* This value allows for repeated substitutions inside complex
259 : indexed addresses, or changes in up to 5 insns. */
260 173067 : changes_allocated = MAX_RECOG_OPERANDS * 5;
261 : else
262 1256 : changes_allocated *= 2;
263 :
264 174323 : changes = XRESIZEVEC (change_t, changes, changes_allocated);
265 : }
266 :
267 1626020421 : changes[num_changes].object = object;
268 1626020421 : changes[num_changes].loc = loc;
269 1626020421 : changes[num_changes].old = old;
270 1626020421 : changes[num_changes].old_len = (new_len >= 0 ? XVECLEN (new_rtx, 0) : -1);
271 1626020421 : changes[num_changes].unshare = unshare;
272 :
273 1626020421 : if (new_len >= 0)
274 11617659 : XVECLEN (new_rtx, 0) = new_len;
275 :
276 1626020421 : if (object && !MEM_P (object))
277 : {
278 : /* Set INSN_CODE to force rerecognition of insn. Save old code in
279 : case invalid. */
280 1601447928 : changes[num_changes].old_code = INSN_CODE (object);
281 1601447928 : INSN_CODE (object) = -1;
282 : }
283 :
284 1626020421 : num_changes++;
285 :
286 : /* If we are making a group of changes, return 1. Otherwise, validate the
287 : change group we made. */
288 :
289 1626020421 : if (in_group)
290 : return true;
291 : else
292 18346005 : return apply_change_group ();
293 : }
294 :
295 : /* Wrapper for validate_change_1 without the UNSHARE argument defaulting
296 : UNSHARE to false. */
297 :
298 : bool
299 1511779582 : validate_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
300 : {
301 1511779582 : return validate_change_1 (object, loc, new_rtx, in_group, false);
302 : }
303 :
304 : /* Wrapper for validate_change_1 without the UNSHARE argument defaulting
305 : UNSHARE to true. */
306 :
307 : bool
308 289466403 : validate_unshare_change (rtx object, rtx *loc, rtx new_rtx, bool in_group)
309 : {
310 289466403 : return validate_change_1 (object, loc, new_rtx, in_group, true);
311 : }
312 :
313 : /* Change XVECLEN (*LOC, 0) to NEW_LEN. OBJECT, IN_GROUP and the return
314 : value are as for validate_change_1. */
315 :
316 : bool
317 18087907 : validate_change_xveclen (rtx object, rtx *loc, int new_len, bool in_group)
318 : {
319 18087907 : return validate_change_1 (object, loc, *loc, in_group, false, new_len);
320 : }
321 :
322 : /* Keep X canonicalized if some changes have made it non-canonical; only
323 : modifies the operands of X, not (for example) its code. Simplifications
324 : are not the job of this routine.
325 :
326 : Return true if anything was changed. */
327 : bool
328 1871151 : canonicalize_change_group (rtx_insn *insn, rtx x)
329 : {
330 1871151 : if (COMMUTATIVE_P (x)
331 1871151 : && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
332 : {
333 : /* Oops, the caller has made X no longer canonical.
334 : Let's redo the changes in the correct order. */
335 105510 : rtx tem = XEXP (x, 0);
336 105510 : validate_unshare_change (insn, &XEXP (x, 0), XEXP (x, 1), 1);
337 105510 : validate_unshare_change (insn, &XEXP (x, 1), tem, 1);
338 105510 : return true;
339 : }
340 : else
341 1765641 : return false;
342 : }
343 :
344 : /* Check if REG_INC argument in *data overlaps a stored REG. */
345 :
346 : static void
347 0 : check_invalid_inc_dec (rtx reg, const_rtx, void *data)
348 : {
349 0 : rtx *pinc = (rtx *) data;
350 0 : if (*pinc == NULL_RTX || MEM_P (reg))
351 : return;
352 0 : if (reg_overlap_mentioned_p (reg, *pinc))
353 0 : *pinc = NULL_RTX;
354 : }
355 :
356 : /* This subroutine of apply_change_group verifies whether the changes to INSN
357 : were valid; i.e. whether INSN can still be recognized.
358 :
359 : If IN_GROUP is true clobbers which have to be added in order to
360 : match the instructions will be added to the current change group.
361 : Otherwise the changes will take effect immediately. */
362 :
363 : bool
364 471822013 : insn_invalid_p (rtx_insn *insn, bool in_group)
365 : {
366 471822013 : rtx pat = PATTERN (insn);
367 471822013 : int num_clobbers = 0;
368 : /* If we are before reload and the pattern is a SET, see if we can add
369 : clobbers. */
370 471822013 : int icode = recog (pat, insn,
371 471822013 : (GET_CODE (pat) == SET
372 390029017 : && ! reload_completed
373 370226145 : && ! reload_in_progress)
374 : ? &num_clobbers : 0);
375 471822013 : bool is_asm = icode < 0 && asm_noperands (PATTERN (insn)) >= 0;
376 :
377 :
378 : /* If this is an asm and the operand aren't legal, then fail. Likewise if
379 : this is not an asm and the insn wasn't recognized. */
380 577920 : if ((is_asm && ! check_asm_operands (PATTERN (insn)))
381 471620115 : || (!is_asm && icode < 0))
382 17859275 : return true;
383 :
384 : /* If we have to add CLOBBERs, fail if we have to add ones that reference
385 : hard registers since our callers can't know if they are live or not.
386 : Otherwise, add them. */
387 453962738 : if (num_clobbers > 0)
388 : {
389 1984 : rtx newpat;
390 :
391 1984 : if (added_clobbers_hard_reg_p (icode))
392 : return true;
393 :
394 678 : newpat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (num_clobbers + 1));
395 678 : XVECEXP (newpat, 0, 0) = pat;
396 678 : add_clobbers (newpat, icode);
397 678 : if (in_group)
398 677 : validate_change (insn, &PATTERN (insn), newpat, 1);
399 : else
400 1 : PATTERN (insn) = pat = newpat;
401 : }
402 :
403 : /* After reload, verify that all constraints are satisfied. */
404 453961432 : if (reload_completed)
405 : {
406 19745528 : extract_insn (insn);
407 :
408 19745528 : if (! constrain_operands (1, get_preferred_alternatives (insn)))
409 : return true;
410 : }
411 :
412 : /* Punt if REG_INC argument overlaps some stored REG. */
413 453937169 : for (rtx link = FIND_REG_INC_NOTE (insn, NULL_RTX);
414 453937169 : link; link = XEXP (link, 1))
415 : if (REG_NOTE_KIND (link) == REG_INC)
416 : {
417 : rtx reg = XEXP (link, 0);
418 : note_stores (insn, check_invalid_inc_dec, ®);
419 : if (reg == NULL_RTX)
420 : return true;
421 : }
422 :
423 453937169 : INSN_CODE (insn) = icode;
424 453937169 : return false;
425 : }
426 :
427 : /* Return number of changes made and not validated yet. */
428 : int
429 4813965 : num_changes_pending (void)
430 : {
431 4813965 : return num_changes;
432 : }
433 :
434 : /* Tentatively apply the changes numbered NUM and up.
435 : Return true if all changes are valid, false otherwise. */
436 :
437 : bool
438 774373255 : verify_changes (int num)
439 : {
440 774373255 : int i;
441 774373255 : rtx last_validated = NULL_RTX;
442 :
443 : /* The changes have been applied and all INSN_CODEs have been reset to force
444 : rerecognition.
445 :
446 : The changes are valid if we aren't given an object, or if we are
447 : given a MEM and it still is a valid address, or if this is in insn
448 : and it is recognized. In the latter case, if reload has completed,
449 : we also require that the operands meet the constraints for
450 : the insn. */
451 :
452 2262629542 : for (i = num; i < num_changes; i++)
453 : {
454 1502899295 : rtx object = changes[i].object;
455 :
456 : /* If there is no object to test or if it is the same as the one we
457 : already tested, ignore it. */
458 1502899295 : if (object == 0 || object == last_validated)
459 768944505 : continue;
460 :
461 733954790 : if (MEM_P (object))
462 : {
463 35844 : if (! memory_address_addr_space_p (GET_MODE (object),
464 : XEXP (object, 0),
465 17922 : MEM_ADDR_SPACE (object)))
466 : break;
467 : }
468 733936868 : else if (/* changes[i].old might be zero, e.g. when putting a
469 : REG_FRAME_RELATED_EXPR into a previously empty list. */
470 733936868 : changes[i].old
471 733936868 : && REG_P (changes[i].old)
472 234852760 : && asm_noperands (PATTERN (object)) > 0
473 734135811 : && register_asm_p (changes[i].old))
474 : {
475 : /* Don't allow changes of hard register operands to inline
476 : assemblies if they have been defined as register asm ("x"). */
477 : break;
478 : }
479 733936867 : else if (DEBUG_INSN_P (object))
480 263059494 : continue;
481 470877373 : else if (insn_invalid_p (as_a <rtx_insn *> (object), true))
482 : {
483 17316996 : rtx pat = PATTERN (object);
484 :
485 : /* Perhaps we couldn't recognize the insn because there were
486 : extra CLOBBERs at the end. If so, try to re-recognize
487 : without the last CLOBBER (later iterations will cause each of
488 : them to be eliminated, in turn). But don't do this if we
489 : have an ASM_OPERAND. */
490 17316996 : if (GET_CODE (pat) == PARALLEL
491 4108016 : && GET_CODE (XVECEXP (pat, 0, XVECLEN (pat, 0) - 1)) == CLOBBER
492 20178242 : && asm_noperands (PATTERN (object)) < 0)
493 : {
494 2661005 : rtx newpat;
495 :
496 2661005 : if (XVECLEN (pat, 0) == 2)
497 2254706 : newpat = XVECEXP (pat, 0, 0);
498 : else
499 : {
500 406299 : int j;
501 :
502 406299 : newpat
503 406299 : = gen_rtx_PARALLEL (VOIDmode,
504 : rtvec_alloc (XVECLEN (pat, 0) - 1));
505 1253129 : for (j = 0; j < XVECLEN (newpat, 0); j++)
506 846830 : XVECEXP (newpat, 0, j) = XVECEXP (pat, 0, j);
507 : }
508 :
509 : /* Add a new change to this group to replace the pattern
510 : with this new pattern. Then consider this change
511 : as having succeeded. The change we added will
512 : cause the entire call to fail if things remain invalid.
513 :
514 : Note that this can lose if a later change than the one
515 : we are processing specified &XVECEXP (PATTERN (object), 0, X)
516 : but this shouldn't occur. */
517 :
518 2661005 : validate_change (object, &PATTERN (object), newpat, 1);
519 2661005 : continue;
520 2661005 : }
521 14655991 : else if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
522 14642937 : || GET_CODE (pat) == VAR_LOCATION)
523 : /* If this insn is a CLOBBER or USE, it is always valid, but is
524 : never recognized. */
525 13054 : continue;
526 : else
527 : break;
528 : }
529 : last_validated = object;
530 : }
531 :
532 774373255 : return (i == num_changes);
533 : }
534 :
535 : /* A group of changes has previously been issued with validate_change
536 : and verified with verify_changes. Call df_insn_rescan for each of
537 : the insn changed and clear num_changes. */
538 :
539 : void
540 770845204 : confirm_change_group (void)
541 : {
542 770845204 : int i;
543 770845204 : rtx last_object = NULL;
544 :
545 770845204 : gcc_assert (!undo_recog_changes::is_active ());
546 2268681843 : for (i = 0; i < num_changes; i++)
547 : {
548 1497836639 : rtx object = changes[i].object;
549 :
550 1497836639 : if (changes[i].unshare)
551 19866354 : *changes[i].loc = copy_rtx (*changes[i].loc);
552 :
553 : /* Avoid unnecessary rescanning when multiple changes to same instruction
554 : are made. */
555 1497836639 : if (object)
556 : {
557 1495474259 : if (object != last_object && last_object && INSN_P (last_object))
558 7689985 : df_insn_rescan (as_a <rtx_insn *> (last_object));
559 : last_object = object;
560 : }
561 : }
562 :
563 770845204 : if (last_object && INSN_P (last_object))
564 605059387 : df_insn_rescan (as_a <rtx_insn *> (last_object));
565 770845204 : num_changes = 0;
566 770845204 : }
567 :
568 : /* Apply a group of changes previously issued with `validate_change'.
569 : If all changes are valid, call confirm_change_group and return true,
570 : otherwise, call cancel_changes and return false. */
571 :
572 : bool
573 767235539 : apply_change_group (void)
574 : {
575 767235539 : if (verify_changes (0))
576 : {
577 755352527 : confirm_change_group ();
578 755352527 : return true;
579 : }
580 : else
581 : {
582 11883012 : cancel_changes (0);
583 11883012 : return false;
584 : }
585 : }
586 :
587 :
588 : /* Return the number of changes so far in the current group. */
589 :
590 : int
591 743168368 : num_validated_changes (void)
592 : {
593 743168368 : return num_changes;
594 : }
595 :
596 : /* Retract the changes numbered NUM and up. */
597 :
598 : void
599 169955676 : cancel_changes (int num)
600 : {
601 169955676 : gcc_assert (!undo_recog_changes::is_active ());
602 169955676 : int i;
603 :
604 : /* Back out all the changes. Do this in the opposite order in which
605 : they were made. */
606 298139458 : for (i = num_changes - 1; i >= num; i--)
607 : {
608 128183782 : if (changes[i].old_len >= 0)
609 10763658 : XVECLEN (*changes[i].loc, 0) = changes[i].old_len;
610 : else
611 117420124 : *changes[i].loc = changes[i].old;
612 128183782 : if (changes[i].object && !MEM_P (changes[i].object))
613 : {
614 105991521 : INSN_CODE (changes[i].object) = changes[i].old_code;
615 105991521 : if (recog_data.insn == changes[i].object)
616 184 : recog_data.insn = nullptr;
617 : }
618 : }
619 169955676 : num_changes = num;
620 169955676 : }
621 :
622 : /* Swap the status of change NUM from being applied to not being applied,
623 : or vice versa. */
624 :
625 : static void
626 47445604 : swap_change (int num)
627 : {
628 47445604 : if (changes[num].old_len >= 0)
629 2136712 : std::swap (XVECLEN (*changes[num].loc, 0), changes[num].old_len);
630 : else
631 45308892 : std::swap (*changes[num].loc, changes[num].old);
632 47445604 : if (changes[num].object && !MEM_P (changes[num].object))
633 : {
634 47445604 : std::swap (INSN_CODE (changes[num].object), changes[num].old_code);
635 47445604 : if (recog_data.insn == changes[num].object)
636 8 : recog_data.insn = nullptr;
637 : }
638 47445604 : }
639 :
640 27568697 : undo_recog_changes::undo_recog_changes (int num)
641 27568697 : : m_old_num_changes (s_num_changes)
642 : {
643 27568697 : gcc_assert (num <= num_changes - s_num_changes);
644 51291499 : for (int i = num_changes - s_num_changes - 1; i >= num; i--)
645 23722802 : swap_change (i);
646 27568697 : s_num_changes = num_changes - num;
647 27568697 : }
648 :
649 27568697 : undo_recog_changes::~undo_recog_changes ()
650 : {
651 51291499 : for (int i = num_changes - s_num_changes;
652 51291499 : i < num_changes - m_old_num_changes; ++i)
653 23722802 : swap_change (i);
654 27568697 : s_num_changes = m_old_num_changes;
655 27568697 : }
656 :
657 : /* Reduce conditional compilation elsewhere. */
658 : /* A subroutine of validate_replace_rtx_1 that tries to simplify the resulting
659 : rtx. */
660 :
661 : static void
662 12346887 : simplify_while_replacing (rtx *loc, rtx to, rtx_insn *object,
663 : machine_mode op0_mode)
664 : {
665 12346887 : rtx x = *loc;
666 12346887 : enum rtx_code code = GET_CODE (x);
667 12346887 : rtx new_rtx = NULL_RTX;
668 12346887 : scalar_int_mode is_mode;
669 :
670 12346887 : if (SWAPPABLE_OPERANDS_P (x)
671 12346887 : && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
672 : {
673 447341 : validate_unshare_change (object, loc,
674 447341 : gen_rtx_fmt_ee (COMMUTATIVE_ARITH_P (x) ? code
675 : : swap_condition (code),
676 : GET_MODE (x), XEXP (x, 1),
677 : XEXP (x, 0)), 1);
678 447341 : x = *loc;
679 447341 : code = GET_CODE (x);
680 : }
681 :
682 : /* Canonicalize arithmetics with all constant operands. */
683 12346887 : switch (GET_RTX_CLASS (code))
684 : {
685 806623 : case RTX_UNARY:
686 806623 : if (CONSTANT_P (XEXP (x, 0)))
687 561463 : new_rtx = simplify_unary_operation (code, GET_MODE (x), XEXP (x, 0),
688 : op0_mode);
689 : break;
690 6370795 : case RTX_COMM_ARITH:
691 6370795 : case RTX_BIN_ARITH:
692 6370795 : if (CONSTANT_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
693 255279 : new_rtx = simplify_binary_operation (code, GET_MODE (x), XEXP (x, 0),
694 : XEXP (x, 1));
695 : break;
696 114328 : case RTX_COMPARE:
697 114328 : case RTX_COMM_COMPARE:
698 114328 : if (CONSTANT_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
699 3207 : new_rtx = simplify_relational_operation (code, GET_MODE (x), op0_mode,
700 : XEXP (x, 0), XEXP (x, 1));
701 : break;
702 : default:
703 : break;
704 : }
705 819949 : if (new_rtx)
706 : {
707 788805 : validate_change (object, loc, new_rtx, 1);
708 788805 : return;
709 : }
710 :
711 11558082 : switch (code)
712 : {
713 2169124 : case PLUS:
714 : /* If we have a PLUS whose second operand is now a CONST_INT, use
715 : simplify_gen_binary to try to simplify it.
716 : ??? We may want later to remove this, once simplification is
717 : separated from this function. */
718 2169124 : if (CONST_INT_P (XEXP (x, 1)) && XEXP (x, 1) == to)
719 193437 : validate_change (object, loc,
720 : simplify_gen_binary
721 193437 : (PLUS, GET_MODE (x), XEXP (x, 0), XEXP (x, 1)), 1);
722 : break;
723 486110 : case MINUS:
724 486110 : if (CONST_SCALAR_INT_P (XEXP (x, 1)))
725 22845 : validate_change (object, loc,
726 : simplify_gen_binary
727 22845 : (PLUS, GET_MODE (x), XEXP (x, 0),
728 : simplify_gen_unary (NEG,
729 : GET_MODE (x), XEXP (x, 1),
730 22845 : GET_MODE (x))), 1);
731 : break;
732 182148 : case ZERO_EXTEND:
733 182148 : case SIGN_EXTEND:
734 182148 : if (GET_MODE (XEXP (x, 0)) == VOIDmode)
735 : {
736 0 : new_rtx = simplify_gen_unary (code, GET_MODE (x), XEXP (x, 0),
737 : op0_mode);
738 : /* If any of the above failed, substitute in something that
739 : we know won't be recognized. */
740 0 : if (!new_rtx)
741 0 : new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
742 0 : validate_change (object, loc, new_rtx, 1);
743 : }
744 : break;
745 151660 : case SUBREG:
746 : /* All subregs possible to simplify should be simplified. */
747 303320 : new_rtx = simplify_subreg (GET_MODE (x), SUBREG_REG (x), op0_mode,
748 151660 : SUBREG_BYTE (x));
749 :
750 : /* Subregs of VOIDmode operands are incorrect. */
751 151660 : if (!new_rtx && GET_MODE (SUBREG_REG (x)) == VOIDmode)
752 2 : new_rtx = gen_rtx_CLOBBER (GET_MODE (x), const0_rtx);
753 2 : if (new_rtx)
754 133537 : validate_change (object, loc, new_rtx, 1);
755 : break;
756 5315 : case ZERO_EXTRACT:
757 5315 : case SIGN_EXTRACT:
758 : /* If we are replacing a register with memory, try to change the memory
759 : to be the mode required for memory in extract operations (this isn't
760 : likely to be an insertion operation; if it was, nothing bad will
761 : happen, we might just fail in some cases). */
762 :
763 5315 : if (MEM_P (XEXP (x, 0))
764 396 : && is_a <scalar_int_mode> (GET_MODE (XEXP (x, 0)), &is_mode)
765 396 : && CONST_INT_P (XEXP (x, 1))
766 396 : && CONST_INT_P (XEXP (x, 2))
767 289 : && !mode_dependent_address_p (XEXP (XEXP (x, 0), 0),
768 307 : MEM_ADDR_SPACE (XEXP (x, 0)))
769 5604 : && !MEM_VOLATILE_P (XEXP (x, 0)))
770 : {
771 285 : int pos = INTVAL (XEXP (x, 2));
772 285 : machine_mode new_mode = is_mode;
773 285 : if (GET_CODE (x) == ZERO_EXTRACT && targetm.have_extzv ())
774 0 : new_mode = insn_data[targetm.code_for_extzv].operand[1].mode;
775 285 : else if (GET_CODE (x) == SIGN_EXTRACT && targetm.have_extv ())
776 0 : new_mode = insn_data[targetm.code_for_extv].operand[1].mode;
777 285 : scalar_int_mode wanted_mode = (new_mode == VOIDmode
778 285 : ? word_mode
779 285 : : as_a <scalar_int_mode> (new_mode));
780 :
781 : /* If we have a narrower mode, we can do something. */
782 855 : if (GET_MODE_SIZE (wanted_mode) < GET_MODE_SIZE (is_mode))
783 : {
784 0 : int offset = pos / BITS_PER_UNIT;
785 0 : rtx newmem;
786 :
787 : /* If the bytes and bits are counted differently, we
788 : must adjust the offset. */
789 0 : if (BYTES_BIG_ENDIAN != BITS_BIG_ENDIAN)
790 : offset =
791 : (GET_MODE_SIZE (is_mode) - GET_MODE_SIZE (wanted_mode) -
792 : offset);
793 :
794 0 : gcc_assert (GET_MODE_PRECISION (wanted_mode)
795 : == GET_MODE_BITSIZE (wanted_mode));
796 0 : pos %= GET_MODE_BITSIZE (wanted_mode);
797 :
798 0 : newmem = adjust_address_nv (XEXP (x, 0), wanted_mode, offset);
799 :
800 0 : validate_change (object, &XEXP (x, 2), GEN_INT (pos), 1);
801 0 : validate_change (object, &XEXP (x, 0), newmem, 1);
802 : }
803 : }
804 :
805 : break;
806 :
807 : default:
808 : break;
809 : }
810 : }
811 :
812 : /* Replace every occurrence of FROM in X with TO. Mark each change with
813 : validate_change passing OBJECT. */
814 :
815 : static void
816 69515126 : validate_replace_rtx_1 (rtx *loc, rtx from, rtx to, rtx_insn *object,
817 : bool simplify)
818 : {
819 69515126 : int i, j;
820 69515126 : const char *fmt;
821 69515126 : rtx x = *loc;
822 69515126 : enum rtx_code code;
823 69515126 : machine_mode op0_mode = VOIDmode;
824 69515126 : int prev_changes = num_changes;
825 :
826 69515126 : if (!x)
827 : return;
828 :
829 69515126 : code = GET_CODE (x);
830 69515126 : fmt = GET_RTX_FORMAT (code);
831 69515126 : if (fmt[0] == 'e')
832 23854017 : op0_mode = GET_MODE (XEXP (x, 0));
833 :
834 : /* X matches FROM if it is the same rtx or they are both referring to the
835 : same register in the same mode. Avoid calling rtx_equal_p unless the
836 : operands look similar. */
837 :
838 69515126 : if (x == from
839 53733952 : || (REG_P (x) && REG_P (from)
840 15524193 : && GET_MODE (x) == GET_MODE (from)
841 9137741 : && REGNO (x) == REGNO (from))
842 123249075 : || (GET_CODE (x) == GET_CODE (from) && GET_MODE (x) == GET_MODE (from)
843 9137738 : && rtx_equal_p (x, from)))
844 : {
845 15781177 : validate_unshare_change (object, loc, to, 1);
846 15781177 : return;
847 : }
848 :
849 : /* Call ourself recursively to perform the replacements.
850 : We must not replace inside already replaced expression, otherwise we
851 : get infinite recursion for replacements like (reg X)->(subreg (reg X))
852 : so we must special case shared ASM_OPERANDS. */
853 :
854 53733949 : if (GET_CODE (x) == PARALLEL)
855 : {
856 1400779 : for (j = XVECLEN (x, 0) - 1; j >= 0; j--)
857 : {
858 1033804 : if (j && GET_CODE (XVECEXP (x, 0, j)) == SET
859 30626 : && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == ASM_OPERANDS)
860 : {
861 : /* Verify that operands are really shared. */
862 275 : gcc_assert (ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP (x, 0, 0)))
863 : == ASM_OPERANDS_INPUT_VEC (SET_SRC (XVECEXP
864 : (x, 0, j))));
865 275 : validate_replace_rtx_1 (&SET_DEST (XVECEXP (x, 0, j)),
866 : from, to, object, simplify);
867 : }
868 : else
869 1033529 : validate_replace_rtx_1 (&XVECEXP (x, 0, j), from, to, object,
870 : simplify);
871 : }
872 : }
873 : else
874 136196850 : for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
875 : {
876 82829876 : if (fmt[i] == 'e')
877 40754958 : validate_replace_rtx_1 (&XEXP (x, i), from, to, object, simplify);
878 42074918 : else if (fmt[i] == 'E')
879 6381545 : for (j = XVECLEN (x, i) - 1; j >= 0; j--)
880 3475807 : validate_replace_rtx_1 (&XVECEXP (x, i, j), from, to, object,
881 : simplify);
882 : }
883 :
884 : /* If we didn't substitute, there is nothing more to do. */
885 53733949 : if (num_changes == prev_changes)
886 : return;
887 :
888 : /* ??? The regmove is no more, so is this aberration still necessary? */
889 : /* Allow substituted expression to have different mode. This is used by
890 : regmove to change mode of pseudo register. */
891 12346958 : if (fmt[0] == 'e' && GET_MODE (XEXP (x, 0)) != VOIDmode)
892 9348125 : op0_mode = GET_MODE (XEXP (x, 0));
893 :
894 : /* Do changes needed to keep rtx consistent. Don't do any other
895 : simplifications, as it is not our job. */
896 12346958 : if (simplify)
897 12346887 : simplify_while_replacing (loc, to, object, op0_mode);
898 : }
899 :
900 : /* Try replacing every occurrence of FROM in subexpression LOC of INSN
901 : with TO. After all changes have been made, validate by seeing
902 : if INSN is still valid. */
903 :
904 : bool
905 0 : validate_replace_rtx_subexp (rtx from, rtx to, rtx_insn *insn, rtx *loc)
906 : {
907 0 : validate_replace_rtx_1 (loc, from, to, insn, true);
908 0 : return apply_change_group ();
909 : }
910 :
911 : /* Try replacing every occurrence of FROM in INSN with TO. After all
912 : changes have been made, validate by seeing if INSN is still valid. */
913 :
914 : bool
915 2051760 : validate_replace_rtx (rtx from, rtx to, rtx_insn *insn)
916 : {
917 2051760 : validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
918 2051760 : return apply_change_group ();
919 : }
920 :
921 : /* Try replacing every occurrence of FROM in WHERE with TO. Assume that WHERE
922 : is a part of INSN. After all changes have been made, validate by seeing if
923 : INSN is still valid.
924 : validate_replace_rtx (from, to, insn) is equivalent to
925 : validate_replace_rtx_part (from, to, &PATTERN (insn), insn). */
926 :
927 : bool
928 0 : validate_replace_rtx_part (rtx from, rtx to, rtx *where, rtx_insn *insn)
929 : {
930 0 : validate_replace_rtx_1 (where, from, to, insn, true);
931 0 : return apply_change_group ();
932 : }
933 :
934 : /* Same as above, but do not simplify rtx afterwards. */
935 : bool
936 89 : validate_replace_rtx_part_nosimplify (rtx from, rtx to, rtx *where,
937 : rtx_insn *insn)
938 : {
939 89 : validate_replace_rtx_1 (where, from, to, insn, false);
940 89 : return apply_change_group ();
941 :
942 : }
943 :
944 : /* Try replacing every occurrence of FROM in INSN with TO. This also
945 : will replace in REG_EQUAL and REG_EQUIV notes. */
946 :
947 : void
948 21 : validate_replace_rtx_group (rtx from, rtx to, rtx_insn *insn)
949 : {
950 21 : rtx note;
951 21 : validate_replace_rtx_1 (&PATTERN (insn), from, to, insn, true);
952 28 : for (note = REG_NOTES (insn); note; note = XEXP (note, 1))
953 7 : if (REG_NOTE_KIND (note) == REG_EQUAL
954 7 : || REG_NOTE_KIND (note) == REG_EQUIV)
955 0 : validate_replace_rtx_1 (&XEXP (note, 0), from, to, insn, true);
956 21 : }
957 :
958 : /* Function called by note_uses to replace used subexpressions. */
959 : struct validate_replace_src_data
960 : {
961 : rtx from; /* Old RTX */
962 : rtx to; /* New RTX */
963 : rtx_insn *insn; /* Insn in which substitution is occurring. */
964 : };
965 :
966 : static void
967 22198687 : validate_replace_src_1 (rtx *x, void *data)
968 : {
969 22198687 : struct validate_replace_src_data *d
970 : = (struct validate_replace_src_data *) data;
971 :
972 22198687 : validate_replace_rtx_1 (x, d->from, d->to, d->insn, true);
973 22198687 : }
974 :
975 : /* Try replacing every occurrence of FROM in INSN with TO, avoiding
976 : SET_DESTs. */
977 :
978 : void
979 15843661 : validate_replace_src_group (rtx from, rtx to, rtx_insn *insn)
980 : {
981 15843661 : struct validate_replace_src_data d;
982 :
983 15843661 : d.from = from;
984 15843661 : d.to = to;
985 15843661 : d.insn = insn;
986 15843661 : note_uses (&PATTERN (insn), validate_replace_src_1, &d);
987 15843661 : }
988 :
989 : /* Try simplify INSN.
990 : Invoke simplify_rtx () on every SET_SRC and SET_DEST inside the INSN's
991 : pattern and return true if something was simplified. */
992 :
993 : bool
994 0 : validate_simplify_insn (rtx_insn *insn)
995 : {
996 0 : int i;
997 0 : rtx pat = NULL;
998 0 : rtx newpat = NULL;
999 :
1000 0 : pat = PATTERN (insn);
1001 :
1002 0 : if (GET_CODE (pat) == SET)
1003 : {
1004 0 : newpat = simplify_rtx (SET_SRC (pat));
1005 0 : if (newpat && !rtx_equal_p (SET_SRC (pat), newpat))
1006 0 : validate_change (insn, &SET_SRC (pat), newpat, 1);
1007 0 : newpat = simplify_rtx (SET_DEST (pat));
1008 0 : if (newpat && !rtx_equal_p (SET_DEST (pat), newpat))
1009 0 : validate_change (insn, &SET_DEST (pat), newpat, 1);
1010 : }
1011 0 : else if (GET_CODE (pat) == PARALLEL)
1012 0 : for (i = 0; i < XVECLEN (pat, 0); i++)
1013 : {
1014 0 : rtx s = XVECEXP (pat, 0, i);
1015 :
1016 0 : if (GET_CODE (XVECEXP (pat, 0, i)) == SET)
1017 : {
1018 0 : newpat = simplify_rtx (SET_SRC (s));
1019 0 : if (newpat && !rtx_equal_p (SET_SRC (s), newpat))
1020 0 : validate_change (insn, &SET_SRC (s), newpat, 1);
1021 0 : newpat = simplify_rtx (SET_DEST (s));
1022 0 : if (newpat && !rtx_equal_p (SET_DEST (s), newpat))
1023 0 : validate_change (insn, &SET_DEST (s), newpat, 1);
1024 : }
1025 : }
1026 0 : return ((num_changes_pending () > 0) && (apply_change_group () > 0));
1027 : }
1028 :
1029 : /* Try to process the address of memory expression MEM. Return true on
1030 : success; leave the caller to clean up on failure. */
1031 :
1032 : bool
1033 24345657 : insn_propagation::apply_to_mem_1 (rtx mem)
1034 : {
1035 24345657 : auto old_num_changes = num_validated_changes ();
1036 24345657 : mem_depth += 1;
1037 24345657 : bool res = apply_to_rvalue_1 (&XEXP (mem, 0));
1038 24345657 : mem_depth -= 1;
1039 24345657 : if (!res)
1040 : return false;
1041 :
1042 24345024 : if (old_num_changes != num_validated_changes ()
1043 7834930 : && should_check_mems
1044 27662293 : && !check_mem (old_num_changes, mem))
1045 : return false;
1046 :
1047 : return true;
1048 : }
1049 :
1050 : /* Try to process the rvalue expression at *LOC. Return true on success;
1051 : leave the caller to clean up on failure. */
1052 :
1053 : bool
1054 237441302 : insn_propagation::apply_to_rvalue_1 (rtx *loc)
1055 : {
1056 237441302 : rtx x = *loc;
1057 237441302 : enum rtx_code code = GET_CODE (x);
1058 237441302 : machine_mode mode = GET_MODE (x);
1059 :
1060 237441302 : auto old_num_changes = num_validated_changes ();
1061 237441302 : if (from
1062 226286240 : && GET_CODE (x) == GET_CODE (from)
1063 330664718 : && (REG_P (x)
1064 93223416 : ? REGNO (x) == REGNO (from)
1065 24093 : : rtx_equal_p (x, from)))
1066 : {
1067 : /* Don't replace register asms in asm statements; we mustn't
1068 : change the user's register allocation. */
1069 59945828 : if (REG_P (x)
1070 59922633 : && HARD_REGISTER_P (x)
1071 18311702 : && register_asm_p (x)
1072 59947825 : && asm_noperands (PATTERN (insn)) > 0)
1073 : return false;
1074 :
1075 59944000 : rtx newval = to;
1076 59944000 : if (GET_MODE (x) != GET_MODE (from))
1077 : {
1078 699081 : gcc_assert (REG_P (x) && HARD_REGISTER_P (x));
1079 699081 : if (REG_NREGS (x) != REG_NREGS (from)
1080 699081 : || !REG_CAN_CHANGE_MODE_P (REGNO (x), GET_MODE (from),
1081 : GET_MODE (x)))
1082 356398 : return false;
1083 :
1084 : /* If the reference is paradoxical and the replacement
1085 : value contains registers, we would need to check that the
1086 : simplification below does not increase REG_NREGS for those
1087 : registers either. It seems simpler to punt on nonconstant
1088 : values instead. */
1089 615243 : if (paradoxical_subreg_p (GET_MODE (x), GET_MODE (from))
1090 615243 : && !CONSTANT_P (to))
1091 : return false;
1092 :
1093 595993 : newval = simplify_subreg (GET_MODE (x), to, GET_MODE (from),
1094 : subreg_lowpart_offset (GET_MODE (x),
1095 : GET_MODE (from)));
1096 595993 : if (!newval)
1097 : return false;
1098 :
1099 : /* Check that the simplification didn't just push an explicit
1100 : subreg down into subexpressions. In particular, for a register
1101 : R that has a fixed mode, such as the stack pointer, a subreg of:
1102 :
1103 : (plus:M (reg:M R) (const_int C))
1104 :
1105 : would be:
1106 :
1107 : (plus:N (subreg:N (reg:M R) ...) (const_int C'))
1108 :
1109 : But targets can legitimately assume that subregs of hard registers
1110 : will not be created after RA (except in special circumstances,
1111 : such as strict_low_part). */
1112 345538 : subrtx_iterator::array_type array;
1113 1322400 : FOR_EACH_SUBRTX (iter, array, newval, NONCONST)
1114 979717 : if (GET_CODE (*iter) == SUBREG)
1115 2855 : return false;
1116 345538 : }
1117 :
1118 59587602 : if (should_unshare)
1119 59587602 : validate_unshare_change (insn, loc, newval, 1);
1120 : else
1121 0 : validate_change (insn, loc, newval, 1);
1122 59587602 : if (mem_depth && !REG_P (newval) && !CONSTANT_P (newval))
1123 : {
1124 : /* We're substituting into an address, but TO will have the
1125 : form expected outside an address. Canonicalize it if
1126 : necessary. */
1127 3555461 : insn_propagation subprop (insn);
1128 3555461 : subprop.mem_depth += 1;
1129 3555461 : if (!subprop.apply_to_rvalue (loc))
1130 0 : gcc_unreachable ();
1131 3555461 : if (should_unshare
1132 3555461 : && num_validated_changes () != old_num_changes + 1)
1133 : {
1134 : /* TO is owned by someone else, so create a copy and
1135 : return TO to its original form. */
1136 297166 : newval = copy_rtx (*loc);
1137 297166 : cancel_changes (old_num_changes);
1138 297166 : validate_change (insn, loc, newval, 1);
1139 : }
1140 : }
1141 59587602 : num_replacements += 1;
1142 59587602 : should_unshare = true;
1143 59587602 : result_flags |= UNSIMPLIFIED;
1144 59587602 : return true;
1145 : }
1146 :
1147 : /* Recursively apply the substitution and see if we can simplify
1148 : the result. This specifically shouldn't use simplify_gen_* for
1149 : speculative simplifications, since we want to avoid generating new
1150 : expressions where possible. */
1151 177495474 : auto old_result_flags = result_flags;
1152 177495474 : rtx newx = NULL_RTX;
1153 177495474 : bool recurse_p = false;
1154 177495474 : switch (GET_RTX_CLASS (code))
1155 : {
1156 3024151 : case RTX_UNARY:
1157 3024151 : {
1158 3024151 : machine_mode op0_mode = GET_MODE (XEXP (x, 0));
1159 3024151 : if (!apply_to_rvalue_1 (&XEXP (x, 0)))
1160 : return false;
1161 2985382 : if (from && old_num_changes == num_validated_changes ())
1162 : return true;
1163 :
1164 2402486 : newx = simplify_unary_operation (code, mode, XEXP (x, 0), op0_mode);
1165 2402486 : break;
1166 : }
1167 :
1168 46019446 : case RTX_BIN_ARITH:
1169 46019446 : case RTX_COMM_ARITH:
1170 46019446 : {
1171 46019446 : if (!apply_to_rvalue_1 (&XEXP (x, 0))
1172 46019446 : || !apply_to_rvalue_1 (&XEXP (x, 1)))
1173 471327 : return false;
1174 45548119 : if (from && old_num_changes == num_validated_changes ())
1175 : return true;
1176 :
1177 34901010 : if (GET_RTX_CLASS (code) == RTX_COMM_ARITH
1178 34901010 : && swap_commutative_operands_p (XEXP (x, 0), XEXP (x, 1)))
1179 2700530 : newx = simplify_gen_binary (code, mode, XEXP (x, 1), XEXP (x, 0));
1180 : else
1181 32200480 : newx = simplify_binary_operation (code, mode,
1182 : XEXP (x, 0), XEXP (x, 1));
1183 : break;
1184 : }
1185 :
1186 6053429 : case RTX_COMPARE:
1187 6053429 : case RTX_COMM_COMPARE:
1188 6053429 : {
1189 12106985 : machine_mode op_mode = (GET_MODE (XEXP (x, 0)) != VOIDmode
1190 6053429 : ? GET_MODE (XEXP (x, 0))
1191 127 : : GET_MODE (XEXP (x, 1)));
1192 6053429 : if (!apply_to_rvalue_1 (&XEXP (x, 0))
1193 6053429 : || !apply_to_rvalue_1 (&XEXP (x, 1)))
1194 4373 : return false;
1195 6049056 : if (from && old_num_changes == num_validated_changes ())
1196 : return true;
1197 :
1198 5159822 : newx = simplify_relational_operation (code, mode, op_mode,
1199 : XEXP (x, 0), XEXP (x, 1));
1200 5159822 : break;
1201 : }
1202 :
1203 5451975 : case RTX_TERNARY:
1204 5451975 : case RTX_BITFIELD_OPS:
1205 5451975 : {
1206 5451975 : machine_mode op0_mode = GET_MODE (XEXP (x, 0));
1207 5451975 : if (!apply_to_rvalue_1 (&XEXP (x, 0))
1208 5444752 : || !apply_to_rvalue_1 (&XEXP (x, 1))
1209 10874220 : || !apply_to_rvalue_1 (&XEXP (x, 2)))
1210 32021 : return false;
1211 5419954 : if (from && old_num_changes == num_validated_changes ())
1212 : return true;
1213 :
1214 5352096 : newx = simplify_ternary_operation (code, mode, op0_mode,
1215 : XEXP (x, 0), XEXP (x, 1),
1216 : XEXP (x, 2));
1217 5352096 : break;
1218 : }
1219 :
1220 11244830 : case RTX_EXTRA:
1221 11244830 : if (code == SUBREG)
1222 : {
1223 2516895 : machine_mode inner_mode = GET_MODE (SUBREG_REG (x));
1224 2516895 : if (!apply_to_rvalue_1 (&SUBREG_REG (x)))
1225 : return false;
1226 2516879 : if (from && old_num_changes == num_validated_changes ())
1227 : return true;
1228 :
1229 1851331 : rtx inner = SUBREG_REG (x);
1230 1851331 : newx = simplify_subreg (mode, inner, inner_mode, SUBREG_BYTE (x));
1231 : /* Reject the same cases that simplify_gen_subreg would. */
1232 1851331 : if (!newx
1233 1851331 : && (GET_CODE (inner) == SUBREG
1234 1160145 : || GET_CODE (inner) == CONCAT
1235 1147516 : || GET_MODE (inner) == VOIDmode
1236 1147515 : || !validate_subreg (mode, inner_mode,
1237 1147515 : inner, SUBREG_BYTE (x))))
1238 : {
1239 12674 : failure_reason = "would create an invalid subreg";
1240 12674 : return false;
1241 : }
1242 : break;
1243 : }
1244 : else
1245 : recurse_p = true;
1246 : break;
1247 :
1248 54217089 : case RTX_OBJ:
1249 54217089 : if (code == LO_SUM)
1250 : {
1251 0 : if (!apply_to_rvalue_1 (&XEXP (x, 0))
1252 0 : || !apply_to_rvalue_1 (&XEXP (x, 1)))
1253 0 : return false;
1254 0 : if (from && old_num_changes == num_validated_changes ())
1255 : return true;
1256 :
1257 : /* (lo_sum (high x) y) -> y where x and y have the same base. */
1258 0 : rtx op0 = XEXP (x, 0);
1259 0 : rtx op1 = XEXP (x, 1);
1260 0 : if (GET_CODE (op0) == HIGH)
1261 : {
1262 0 : rtx base0, base1, offset0, offset1;
1263 0 : split_const (XEXP (op0, 0), &base0, &offset0);
1264 0 : split_const (op1, &base1, &offset1);
1265 0 : if (rtx_equal_p (base0, base1))
1266 0 : newx = op1;
1267 : }
1268 : }
1269 54217089 : else if (code == REG)
1270 : {
1271 37424575 : if (from && REG_P (from) && reg_overlap_mentioned_p (x, from))
1272 : {
1273 61823 : failure_reason = "inexact register overlap";
1274 61823 : return false;
1275 : }
1276 : }
1277 16792514 : else if (code == MEM)
1278 12690072 : return apply_to_mem_1 (x);
1279 : else
1280 : recurse_p = true;
1281 : break;
1282 :
1283 : case RTX_CONST_OBJ:
1284 : break;
1285 :
1286 1431656 : case RTX_AUTOINC:
1287 1431656 : if (from && reg_overlap_mentioned_p (XEXP (x, 0), from))
1288 : {
1289 0 : failure_reason = "is subject to autoinc";
1290 0 : return false;
1291 : }
1292 : recurse_p = true;
1293 : break;
1294 :
1295 0 : case RTX_MATCH:
1296 0 : case RTX_INSN:
1297 0 : gcc_unreachable ();
1298 : }
1299 :
1300 49654071 : if (recurse_p)
1301 : {
1302 14262033 : const char *fmt = GET_RTX_FORMAT (code);
1303 32518718 : for (int i = 0; fmt[i]; i++)
1304 18370804 : switch (fmt[i])
1305 : {
1306 : case 'E':
1307 6121067 : for (int j = 0; j < XVECLEN (x, i); j++)
1308 4354497 : if (!apply_to_rvalue_1 (&XVECEXP (x, i, j)))
1309 : return false;
1310 : break;
1311 :
1312 12507472 : case 'e':
1313 12507472 : if (XEXP (x, i) && !apply_to_rvalue_1 (&XEXP (x, i)))
1314 : return false;
1315 : break;
1316 : }
1317 : }
1318 137069721 : else if (newx && !rtx_equal_p (x, newx))
1319 : {
1320 : /* All substitutions made by OLD_NUM_CHANGES onwards have been
1321 : simplified. */
1322 10782448 : result_flags = ((result_flags & ~UNSIMPLIFIED)
1323 : | (old_result_flags & UNSIMPLIFIED));
1324 :
1325 10782448 : if (should_note_simplifications)
1326 3927126 : note_simplification (old_num_changes, old_result_flags, x, newx);
1327 :
1328 : /* There's no longer any point unsharing the substitutions made
1329 : for subexpressions, since we'll just copy this one instead. */
1330 : bool unshare = false;
1331 21535455 : for (int i = old_num_changes; i < num_changes; ++i)
1332 : {
1333 10753007 : unshare |= changes[i].unshare;
1334 10753007 : changes[i].unshare = false;
1335 : }
1336 10782448 : if (unshare)
1337 10360482 : validate_unshare_change (insn, loc, newx, 1);
1338 : else
1339 421966 : validate_change (insn, loc, newx, 1);
1340 : }
1341 :
1342 : return true;
1343 : }
1344 :
1345 : /* Try to process the lvalue expression at *LOC. Return true on success;
1346 : leave the caller to clean up on failure. */
1347 :
1348 : bool
1349 63664211 : insn_propagation::apply_to_lvalue_1 (rtx dest)
1350 : {
1351 63664211 : rtx old_dest = dest;
1352 63664211 : while (GET_CODE (dest) == SUBREG
1353 63868870 : || GET_CODE (dest) == ZERO_EXTRACT
1354 63868870 : || GET_CODE (dest) == STRICT_LOW_PART)
1355 : {
1356 204659 : if (GET_CODE (dest) == ZERO_EXTRACT
1357 204659 : && (!apply_to_rvalue_1 (&XEXP (dest, 1))
1358 2745 : || !apply_to_rvalue_1 (&XEXP (dest, 2))))
1359 0 : return false;
1360 204659 : dest = XEXP (dest, 0);
1361 : }
1362 :
1363 63664211 : if (MEM_P (dest))
1364 11655585 : return apply_to_mem_1 (dest);
1365 :
1366 : /* Check whether the substitution is safe in the presence of this lvalue. */
1367 52008626 : if (!from
1368 52008626 : || dest == old_dest
1369 200476 : || !REG_P (dest)
1370 52209102 : || !reg_overlap_mentioned_p (dest, from))
1371 51907937 : return true;
1372 :
1373 100689 : if (SUBREG_P (old_dest)
1374 96070 : && SUBREG_REG (old_dest) == dest
1375 196759 : && !read_modify_subreg_p (old_dest))
1376 : return true;
1377 :
1378 100418 : failure_reason = "is part of a read-write destination";
1379 100418 : return false;
1380 : }
1381 :
1382 : /* Try to process the instruction pattern at *LOC. Return true on success;
1383 : leave the caller to clean up on failure. */
1384 :
1385 : bool
1386 67408875 : insn_propagation::apply_to_pattern_1 (rtx *loc)
1387 : {
1388 67408875 : rtx body = *loc;
1389 67408875 : switch (GET_CODE (body))
1390 : {
1391 0 : case COND_EXEC:
1392 0 : return (apply_to_rvalue_1 (&COND_EXEC_TEST (body))
1393 0 : && apply_to_pattern_1 (&COND_EXEC_CODE (body)));
1394 :
1395 : case PARALLEL:
1396 14642516 : for (int i = 0; i < XVECLEN (body, 0); ++i)
1397 : {
1398 10008930 : rtx *subloc = &XVECEXP (body, 0, i);
1399 10008930 : if (GET_CODE (*subloc) == SET)
1400 : {
1401 5437481 : if (!apply_to_lvalue_1 (SET_DEST (*subloc)))
1402 : return false;
1403 : /* ASM_OPERANDS are shared between SETs in the same PARALLEL.
1404 : Only process them on the first iteration. */
1405 761421 : if ((i == 0 || GET_CODE (SET_SRC (*subloc)) != ASM_OPERANDS)
1406 6063162 : && !apply_to_rvalue_1 (&SET_SRC (*subloc)))
1407 : return false;
1408 : }
1409 : else
1410 : {
1411 4571449 : if (!apply_to_pattern_1 (subloc))
1412 : return false;
1413 : }
1414 : }
1415 : return true;
1416 :
1417 8600 : case ASM_OPERANDS:
1418 30454 : for (int i = 0, len = ASM_OPERANDS_INPUT_LENGTH (body); i < len; ++i)
1419 22074 : if (!apply_to_rvalue_1 (&ASM_OPERANDS_INPUT (body, i)))
1420 : return false;
1421 : return true;
1422 :
1423 4371738 : case CLOBBER:
1424 4371738 : return apply_to_lvalue_1 (XEXP (body, 0));
1425 :
1426 53854992 : case SET:
1427 53854992 : return (apply_to_lvalue_1 (SET_DEST (body))
1428 53854992 : && apply_to_rvalue_1 (&SET_SRC (body)));
1429 :
1430 4487135 : default:
1431 : /* All the other possibilities never store and can use a normal
1432 : rtx walk. This includes:
1433 :
1434 : - USE
1435 : - TRAP_IF
1436 : - PREFETCH
1437 : - UNSPEC
1438 : - UNSPEC_VOLATILE. */
1439 4487135 : return apply_to_rvalue_1 (loc);
1440 : }
1441 : }
1442 :
1443 : /* Apply this insn_propagation object's simplification or substitution
1444 : to the instruction pattern at LOC. */
1445 :
1446 : bool
1447 62837426 : insn_propagation::apply_to_pattern (rtx *loc)
1448 : {
1449 62837426 : unsigned int num_changes = num_validated_changes ();
1450 62837426 : bool res = apply_to_pattern_1 (loc);
1451 62837426 : if (!res)
1452 2289876 : cancel_changes (num_changes);
1453 62837426 : return res;
1454 : }
1455 :
1456 : /* Apply this insn_propagation object's simplification or substitution
1457 : to the rvalue expression at LOC. */
1458 :
1459 : bool
1460 7416715 : insn_propagation::apply_to_rvalue (rtx *loc)
1461 : {
1462 7416715 : unsigned int num_changes = num_validated_changes ();
1463 7416715 : bool res = apply_to_rvalue_1 (loc);
1464 7416715 : if (!res)
1465 20763 : cancel_changes (num_changes);
1466 7416715 : return res;
1467 : }
1468 :
1469 : /* Like apply_to_rvalue, but specifically for the case where *LOC is in
1470 : a note. This never changes the INSN_CODE. */
1471 :
1472 : bool
1473 184024 : insn_propagation::apply_to_note (rtx *loc)
1474 : {
1475 184024 : auto old_code = INSN_CODE (insn);
1476 184024 : bool res = apply_to_rvalue (loc);
1477 184024 : if (INSN_CODE (insn) != old_code)
1478 88693 : INSN_CODE (insn) = old_code;
1479 184024 : return res;
1480 : }
1481 :
1482 : /* Check whether INSN matches a specific alternative of an .md pattern. */
1483 :
1484 : bool
1485 0 : valid_insn_p (rtx_insn *insn)
1486 : {
1487 0 : recog_memoized (insn);
1488 0 : if (INSN_CODE (insn) < 0)
1489 : return false;
1490 0 : extract_insn (insn);
1491 : /* We don't know whether the insn will be in code that is optimized
1492 : for size or speed, so consider all enabled alternatives. */
1493 0 : if (!constrain_operands (1, get_enabled_alternatives (insn)))
1494 : return false;
1495 : return true;
1496 : }
1497 :
1498 : /* Return true if OP is a valid general operand for machine mode MODE.
1499 : This is either a register reference, a memory reference,
1500 : or a constant. In the case of a memory reference, the address
1501 : is checked for general validity for the target machine.
1502 :
1503 : Register and memory references must have mode MODE in order to be valid,
1504 : but some constants have no machine mode and are valid for any mode.
1505 :
1506 : If MODE is VOIDmode, OP is checked for validity for whatever mode
1507 : it has.
1508 :
1509 : The main use of this function is as a predicate in match_operand
1510 : expressions in the machine description. */
1511 :
1512 : bool
1513 4913989922 : general_operand (rtx op, machine_mode mode)
1514 : {
1515 4913989922 : enum rtx_code code = GET_CODE (op);
1516 :
1517 4913989922 : if (mode == VOIDmode)
1518 1293961884 : mode = GET_MODE (op);
1519 :
1520 : /* Don't accept CONST_INT or anything similar
1521 : if the caller wants something floating. */
1522 4913989922 : if (GET_MODE (op) == VOIDmode && mode != VOIDmode
1523 221925289 : && GET_MODE_CLASS (mode) != MODE_INT
1524 6389 : && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1525 : return false;
1526 :
1527 4913983533 : if (CONST_INT_P (op)
1528 271353465 : && mode != VOIDmode
1529 5132678759 : && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
1530 : return false;
1531 :
1532 4913983284 : if (CONSTANT_P (op))
1533 64032730 : return ((GET_MODE (op) == VOIDmode || GET_MODE (op) == mode
1534 7832 : || mode == VOIDmode)
1535 335948696 : && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
1536 724059216 : && targetm.legitimate_constant_p (mode == VOIDmode
1537 52733940 : ? GET_MODE (op)
1538 : : mode, op));
1539 :
1540 : /* Except for certain constants with VOIDmode, already checked for,
1541 : OP's mode must match MODE if MODE specifies a mode. */
1542 :
1543 4578026756 : if (GET_MODE (op) != mode)
1544 : return false;
1545 :
1546 4523943074 : if (code == SUBREG)
1547 : {
1548 35612560 : rtx sub = SUBREG_REG (op);
1549 :
1550 : #ifdef INSN_SCHEDULING
1551 : /* On machines that have insn scheduling, we want all memory
1552 : reference to be explicit, so outlaw paradoxical SUBREGs.
1553 : However, we must allow them after reload so that they can
1554 : get cleaned up by cleanup_subreg_operands. */
1555 35563896 : if (!reload_completed && MEM_P (sub)
1556 35681519 : && paradoxical_subreg_p (op))
1557 : return false;
1558 : #endif
1559 : /* Avoid memories with nonzero SUBREG_BYTE, as offsetting the memory
1560 : may result in incorrect reference. We should simplify all valid
1561 : subregs of MEM anyway. But allow this after reload because we
1562 : might be called from cleanup_subreg_operands.
1563 :
1564 : ??? This is a kludge. */
1565 35543819 : if (!reload_completed
1566 35495155 : && maybe_ne (SUBREG_BYTE (op), 0)
1567 40714025 : && MEM_P (sub))
1568 : return false;
1569 :
1570 35543819 : if (REG_P (sub)
1571 33836661 : && REGNO (sub) < FIRST_PSEUDO_REGISTER
1572 4690 : && !REG_CAN_CHANGE_MODE_P (REGNO (sub), GET_MODE (sub), mode)
1573 0 : && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_INT
1574 0 : && GET_MODE_CLASS (GET_MODE (sub)) != MODE_COMPLEX_FLOAT
1575 : /* LRA can generate some invalid SUBREGS just for matched
1576 : operand reload presentation. LRA needs to treat them as
1577 : valid. */
1578 35543819 : && ! LRA_SUBREG_P (op))
1579 : return false;
1580 :
1581 : /* FLOAT_MODE subregs can't be paradoxical. Combine will occasionally
1582 : create such rtl, and we must reject it. */
1583 35543819 : if (SCALAR_FLOAT_MODE_P (GET_MODE (op))
1584 : /* LRA can use subreg to store a floating point value in an
1585 : integer mode. Although the floating point and the
1586 : integer modes need the same number of hard registers, the
1587 : size of floating point mode can be less than the integer
1588 : mode. */
1589 322370 : && ! lra_in_progress
1590 35849318 : && paradoxical_subreg_p (op))
1591 : return false;
1592 :
1593 35543819 : op = sub;
1594 35543819 : code = GET_CODE (op);
1595 : }
1596 :
1597 4523874333 : if (code == REG)
1598 3711862445 : return (REGNO (op) >= FIRST_PSEUDO_REGISTER
1599 3711862445 : || in_hard_reg_set_p (operand_reg_set, GET_MODE (op), REGNO (op)));
1600 :
1601 812011888 : if (code == MEM)
1602 : {
1603 718268007 : rtx y = XEXP (op, 0);
1604 :
1605 : /* If -ffuse-ops-with-volatile-access is enabled, allow volatile
1606 : memory reference. */
1607 718268007 : if (!flag_fuse_ops_with_volatile_access
1608 152029 : && !volatile_ok
1609 718314846 : && MEM_VOLATILE_P (op))
1610 : return false;
1611 :
1612 : /* Use the mem's mode, since it will be reloaded thus. LRA can
1613 : generate move insn with invalid addresses which is made valid
1614 : and efficiently calculated by LRA through further numerous
1615 : transformations. */
1616 718261965 : if (lra_in_progress
1617 771734193 : || memory_address_addr_space_p (GET_MODE (op), y, MEM_ADDR_SPACE (op)))
1618 699965223 : return true;
1619 : }
1620 :
1621 : return false;
1622 : }
1623 :
1624 : /* Return true if OP is a valid memory address for a memory reference
1625 : of mode MODE.
1626 :
1627 : The main use of this function is as a predicate in match_operand
1628 : expressions in the machine description. */
1629 :
1630 : bool
1631 115115192 : address_operand (rtx op, machine_mode mode)
1632 : {
1633 : /* Wrong mode for an address expr. */
1634 115115192 : if (GET_MODE (op) != VOIDmode
1635 102738345 : && ! SCALAR_INT_MODE_P (GET_MODE (op)))
1636 : return false;
1637 :
1638 114224850 : return memory_address_p (mode, op);
1639 : }
1640 :
1641 : /* Return true if OP is a register reference of mode MODE.
1642 : If MODE is VOIDmode, accept a register in any mode.
1643 :
1644 : The main use of this function is as a predicate in match_operand
1645 : expressions in the machine description. */
1646 :
1647 : bool
1648 2671211663 : register_operand (rtx op, machine_mode mode)
1649 : {
1650 2671211663 : if (GET_CODE (op) == SUBREG)
1651 : {
1652 12120772 : rtx sub = SUBREG_REG (op);
1653 :
1654 : /* Before reload, we can allow (SUBREG (MEM...)) as a register operand
1655 : because it is guaranteed to be reloaded into one.
1656 : Just make sure the MEM is valid in itself.
1657 : (Ideally, (SUBREG (MEM)...) should not exist after reload,
1658 : but currently it does result from (SUBREG (REG)...) where the
1659 : reg went on the stack.) */
1660 12120772 : if (!REG_P (sub) && (reload_completed || !MEM_P (sub)))
1661 : return false;
1662 : }
1663 2659090891 : else if (!REG_P (op))
1664 : return false;
1665 1963951268 : return general_operand (op, mode);
1666 : }
1667 :
1668 : /* Return true for a register in Pmode; ignore the tested mode. */
1669 :
1670 : bool
1671 0 : pmode_register_operand (rtx op, machine_mode mode ATTRIBUTE_UNUSED)
1672 : {
1673 0 : return register_operand (op, Pmode);
1674 : }
1675 :
1676 : /* Return true if OP should match a MATCH_SCRATCH, i.e., if it is a SCRATCH
1677 : or a hard register. */
1678 :
1679 : bool
1680 705403 : scratch_operand (rtx op, machine_mode mode)
1681 : {
1682 705403 : if (GET_MODE (op) != mode && mode != VOIDmode)
1683 : return false;
1684 :
1685 666846 : return (GET_CODE (op) == SCRATCH
1686 666846 : || (REG_P (op)
1687 87944 : && (lra_in_progress
1688 70196 : || (REGNO (op) < FIRST_PSEUDO_REGISTER
1689 67916 : && REGNO_REG_CLASS (REGNO (op)) != NO_REGS))));
1690 : }
1691 :
1692 : /* Return true if OP is a valid immediate operand for mode MODE.
1693 :
1694 : The main use of this function is as a predicate in match_operand
1695 : expressions in the machine description. */
1696 :
1697 : bool
1698 509208626 : immediate_operand (rtx op, machine_mode mode)
1699 : {
1700 : /* Don't accept CONST_INT or anything similar
1701 : if the caller wants something floating. */
1702 509208626 : if (GET_MODE (op) == VOIDmode && mode != VOIDmode
1703 145197851 : && GET_MODE_CLASS (mode) != MODE_INT
1704 0 : && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1705 : return false;
1706 :
1707 509208626 : if (CONST_INT_P (op)
1708 327274185 : && mode != VOIDmode
1709 651313336 : && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
1710 : return false;
1711 :
1712 508983255 : return (CONSTANT_P (op)
1713 393671108 : && (GET_MODE (op) == mode || mode == VOIDmode
1714 146488817 : || GET_MODE (op) == VOIDmode)
1715 391131060 : && (! flag_pic || LEGITIMATE_PIC_OPERAND_P (op))
1716 1119028172 : && targetm.legitimate_constant_p (mode == VOIDmode
1717 223639923 : ? GET_MODE (op)
1718 : : mode, op));
1719 : }
1720 :
1721 : /* Return true if OP is an operand that is a CONST_INT of mode MODE. */
1722 :
1723 : bool
1724 39330830 : const_int_operand (rtx op, machine_mode mode)
1725 : {
1726 39330830 : if (!CONST_INT_P (op))
1727 : return false;
1728 :
1729 33151453 : if (mode != VOIDmode
1730 33151453 : && trunc_int_for_mode (INTVAL (op), mode) != INTVAL (op))
1731 : return false;
1732 :
1733 : return true;
1734 : }
1735 :
1736 : #if TARGET_SUPPORTS_WIDE_INT
1737 : /* Return true if OP is an operand that is a CONST_INT or CONST_WIDE_INT
1738 : of mode MODE. */
1739 : bool
1740 2360750 : const_scalar_int_operand (rtx op, machine_mode mode)
1741 : {
1742 2360750 : if (!CONST_SCALAR_INT_P (op))
1743 : return false;
1744 :
1745 1983023 : if (CONST_INT_P (op))
1746 157648 : return const_int_operand (op, mode);
1747 :
1748 1825375 : if (mode != VOIDmode)
1749 : {
1750 1825375 : scalar_int_mode int_mode = as_a <scalar_int_mode> (mode);
1751 1825375 : int prec = GET_MODE_PRECISION (int_mode);
1752 1825375 : int bitsize = GET_MODE_BITSIZE (int_mode);
1753 :
1754 1825375 : if (CONST_WIDE_INT_NUNITS (op) * HOST_BITS_PER_WIDE_INT > bitsize)
1755 : return false;
1756 :
1757 1825375 : if (prec == bitsize)
1758 : return true;
1759 : else
1760 : {
1761 : /* Multiword partial int. */
1762 5496 : HOST_WIDE_INT x
1763 5496 : = CONST_WIDE_INT_ELT (op, CONST_WIDE_INT_NUNITS (op) - 1);
1764 5496 : return (sext_hwi (x, prec & (HOST_BITS_PER_WIDE_INT - 1)) == x);
1765 : }
1766 : }
1767 : return true;
1768 : }
1769 :
1770 : /* Return true if OP is an operand that is a constant integer or constant
1771 : floating-point number of MODE. */
1772 :
1773 : bool
1774 0 : const_double_operand (rtx op, machine_mode mode)
1775 : {
1776 0 : return (GET_CODE (op) == CONST_DOUBLE)
1777 0 : && (GET_MODE (op) == mode || mode == VOIDmode);
1778 : }
1779 : #else
1780 : /* Return true if OP is an operand that is a constant integer or constant
1781 : floating-point number of MODE. */
1782 :
1783 : bool
1784 : const_double_operand (rtx op, machine_mode mode)
1785 : {
1786 : /* Don't accept CONST_INT or anything similar
1787 : if the caller wants something floating. */
1788 : if (GET_MODE (op) == VOIDmode && mode != VOIDmode
1789 : && GET_MODE_CLASS (mode) != MODE_INT
1790 : && GET_MODE_CLASS (mode) != MODE_PARTIAL_INT)
1791 : return false;
1792 :
1793 : return ((CONST_DOUBLE_P (op) || CONST_INT_P (op))
1794 : && (mode == VOIDmode || GET_MODE (op) == mode
1795 : || GET_MODE (op) == VOIDmode));
1796 : }
1797 : #endif
1798 : /* Return true if OP is a general operand that is not an immediate
1799 : operand of mode MODE. */
1800 :
1801 : bool
1802 1893904252 : nonimmediate_operand (rtx op, machine_mode mode)
1803 : {
1804 1893904252 : return (general_operand (op, mode) && ! CONSTANT_P (op));
1805 : }
1806 :
1807 : /* Return true if OP is a register reference or
1808 : immediate value of mode MODE. */
1809 :
1810 : bool
1811 526346966 : nonmemory_operand (rtx op, machine_mode mode)
1812 : {
1813 526346966 : if (CONSTANT_P (op))
1814 32544545 : return immediate_operand (op, mode);
1815 493802421 : return register_operand (op, mode);
1816 : }
1817 :
1818 : /* Return true if OP is a valid operand that stands for pushing a
1819 : value of mode MODE onto the stack.
1820 :
1821 : The main use of this function is as a predicate in match_operand
1822 : expressions in the machine description. */
1823 :
1824 : bool
1825 843636899 : push_operand (rtx op, machine_mode mode)
1826 : {
1827 843636899 : if (!MEM_P (op))
1828 : return false;
1829 :
1830 249088337 : if (mode != VOIDmode && GET_MODE (op) != mode)
1831 : return false;
1832 :
1833 471508702 : poly_int64 rounded_size = GET_MODE_SIZE (mode);
1834 :
1835 : #ifdef PUSH_ROUNDING
1836 235754351 : rounded_size = PUSH_ROUNDING (MACRO_INT (rounded_size));
1837 : #endif
1838 :
1839 235754351 : op = XEXP (op, 0);
1840 :
1841 471508702 : if (known_eq (rounded_size, GET_MODE_SIZE (mode)))
1842 : {
1843 200824714 : if (GET_CODE (op) != STACK_PUSH_CODE)
1844 : return false;
1845 : }
1846 : else
1847 : {
1848 34929637 : poly_int64 offset;
1849 34929637 : if (GET_CODE (op) != PRE_MODIFY
1850 1200059 : || GET_CODE (XEXP (op, 1)) != PLUS
1851 1200059 : || XEXP (XEXP (op, 1), 0) != XEXP (op, 0)
1852 1200059 : || !poly_int_rtx_p (XEXP (XEXP (op, 1), 1), &offset)
1853 34929637 : || (STACK_GROWS_DOWNWARD
1854 1200059 : ? maybe_ne (offset, -rounded_size)
1855 : : maybe_ne (offset, rounded_size)))
1856 799883347 : return false;
1857 : }
1858 :
1859 43753552 : return XEXP (op, 0) == stack_pointer_rtx;
1860 : }
1861 :
1862 : /* Return true if OP is a valid operand that stands for popping a
1863 : value of mode MODE off the stack.
1864 :
1865 : The main use of this function is as a predicate in match_operand
1866 : expressions in the machine description. */
1867 :
1868 : bool
1869 292902769 : pop_operand (rtx op, machine_mode mode)
1870 : {
1871 292902769 : if (!MEM_P (op))
1872 : return false;
1873 :
1874 67530518 : if (mode != VOIDmode && GET_MODE (op) != mode)
1875 : return false;
1876 :
1877 67530518 : op = XEXP (op, 0);
1878 :
1879 67530518 : if (GET_CODE (op) != STACK_POP_CODE)
1880 : return false;
1881 :
1882 1394286 : return XEXP (op, 0) == stack_pointer_rtx;
1883 : }
1884 :
1885 : /* Return true if ADDR is a valid memory address
1886 : for mode MODE in address space AS. */
1887 :
1888 : bool
1889 1433651500 : memory_address_addr_space_p (machine_mode mode ATTRIBUTE_UNUSED, rtx addr,
1890 : addr_space_t as, code_helper ch ATTRIBUTE_UNUSED)
1891 : {
1892 : #ifdef GO_IF_LEGITIMATE_ADDRESS
1893 : gcc_assert (ADDR_SPACE_GENERIC_P (as));
1894 : GO_IF_LEGITIMATE_ADDRESS (mode, addr, win);
1895 : return false;
1896 :
1897 : win:
1898 : return true;
1899 : #else
1900 1433651500 : return targetm.addr_space.legitimate_address_p (mode, addr, 0, as, ch);
1901 : #endif
1902 : }
1903 :
1904 : /* Return true if OP is a valid memory reference with mode MODE,
1905 : including a valid address.
1906 :
1907 : The main use of this function is as a predicate in match_operand
1908 : expressions in the machine description. */
1909 :
1910 : bool
1911 1238306802 : memory_operand (rtx op, machine_mode mode)
1912 : {
1913 1238306802 : rtx inner;
1914 :
1915 1238306802 : if (! reload_completed)
1916 : /* Note that no SUBREG is a memory operand before end of reload pass,
1917 : because (SUBREG (MEM...)) forces reloading into a register. */
1918 124015727 : return MEM_P (op) && general_operand (op, mode);
1919 :
1920 1114291075 : if (mode != VOIDmode && GET_MODE (op) != mode)
1921 : return false;
1922 :
1923 814378565 : inner = op;
1924 814378565 : if (GET_CODE (inner) == SUBREG)
1925 8098 : inner = SUBREG_REG (inner);
1926 :
1927 814378565 : return (MEM_P (inner) && general_operand (op, mode));
1928 : }
1929 :
1930 : /* Return true if OP is a valid indirect memory reference with mode MODE;
1931 : that is, a memory reference whose address is a general_operand. */
1932 :
1933 : bool
1934 0 : indirect_operand (rtx op, machine_mode mode)
1935 : {
1936 : /* Before reload, a SUBREG isn't in memory (see memory_operand, above). */
1937 0 : if (! reload_completed
1938 0 : && GET_CODE (op) == SUBREG && MEM_P (SUBREG_REG (op)))
1939 : {
1940 0 : if (mode != VOIDmode && GET_MODE (op) != mode)
1941 : return false;
1942 :
1943 : /* The only way that we can have a general_operand as the resulting
1944 : address is if OFFSET is zero and the address already is an operand
1945 : or if the address is (plus Y (const_int -OFFSET)) and Y is an
1946 : operand. */
1947 0 : poly_int64 offset;
1948 0 : rtx addr = strip_offset (XEXP (SUBREG_REG (op), 0), &offset);
1949 0 : return (known_eq (offset + SUBREG_BYTE (op), 0)
1950 0 : && general_operand (addr, Pmode));
1951 : }
1952 :
1953 0 : return (MEM_P (op)
1954 0 : && memory_operand (op, mode)
1955 0 : && general_operand (XEXP (op, 0), Pmode));
1956 : }
1957 :
1958 : /* Return true if this is an ordered comparison operator (not including
1959 : ORDERED and UNORDERED). */
1960 :
1961 : bool
1962 28773943 : ordered_comparison_operator (rtx op, machine_mode mode)
1963 : {
1964 28773943 : if (mode != VOIDmode && GET_MODE (op) != mode)
1965 : return false;
1966 28773943 : switch (GET_CODE (op))
1967 : {
1968 : case EQ:
1969 : case NE:
1970 : case LT:
1971 : case LTU:
1972 : case LE:
1973 : case LEU:
1974 : case GT:
1975 : case GTU:
1976 : case GE:
1977 : case GEU:
1978 : return true;
1979 : default:
1980 : return false;
1981 : }
1982 : }
1983 :
1984 : /* Return true if this is a comparison operator. This allows the use of
1985 : MATCH_OPERATOR to recognize all the branch insns. */
1986 :
1987 : bool
1988 116138959 : comparison_operator (rtx op, machine_mode mode)
1989 : {
1990 4905894 : return ((mode == VOIDmode || GET_MODE (op) == mode)
1991 120629402 : && COMPARISON_P (op));
1992 : }
1993 :
1994 : /* If BODY is an insn body that uses ASM_OPERANDS, return it. */
1995 :
1996 : rtx
1997 2089053944 : extract_asm_operands (rtx body)
1998 : {
1999 2089053944 : rtx tmp;
2000 2089053944 : switch (GET_CODE (body))
2001 : {
2002 : case ASM_OPERANDS:
2003 : return body;
2004 :
2005 1604471417 : case SET:
2006 : /* Single output operand: BODY is (set OUTPUT (asm_operands ...)). */
2007 1604471417 : tmp = SET_SRC (body);
2008 1604471417 : if (GET_CODE (tmp) == ASM_OPERANDS)
2009 : return tmp;
2010 : break;
2011 :
2012 348517671 : case PARALLEL:
2013 348517671 : tmp = XVECEXP (body, 0, 0);
2014 348517671 : if (GET_CODE (tmp) == ASM_OPERANDS)
2015 : return tmp;
2016 346249131 : if (GET_CODE (tmp) == SET)
2017 : {
2018 341907073 : tmp = SET_SRC (tmp);
2019 341907073 : if (GET_CODE (tmp) == ASM_OPERANDS)
2020 : return tmp;
2021 : }
2022 : break;
2023 :
2024 : default:
2025 : break;
2026 : }
2027 2083036045 : return NULL;
2028 : }
2029 :
2030 : /* If BODY is an insn body that uses ASM_OPERANDS,
2031 : return the number of operands (both input and output) in the insn.
2032 : If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL,
2033 : return 0.
2034 : Otherwise return -1. */
2035 :
2036 : int
2037 1618566041 : asm_noperands (const_rtx body)
2038 : {
2039 1618566041 : rtx asm_op = extract_asm_operands (const_cast<rtx> (body));
2040 1618566041 : int i, n_sets = 0;
2041 :
2042 1618566041 : if (asm_op == NULL)
2043 : {
2044 1613721349 : if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) >= 2
2045 255551261 : && GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
2046 : {
2047 : /* body is [(asm_input ...) (clobber (reg ...))...]. */
2048 59826 : for (i = XVECLEN (body, 0) - 1; i > 0; i--)
2049 39884 : if (GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
2050 : return -1;
2051 : return 0;
2052 : }
2053 : return -1;
2054 : }
2055 :
2056 4844692 : if (GET_CODE (body) == SET)
2057 : n_sets = 1;
2058 4836953 : else if (GET_CODE (body) == PARALLEL)
2059 : {
2060 4826786 : if (GET_CODE (XVECEXP (body, 0, 0)) == SET)
2061 : {
2062 : /* Multiple output operands, or 1 output plus some clobbers:
2063 : body is
2064 : [(set OUTPUT (asm_operands ...))...
2065 : (use (reg ...))...
2066 : (clobber (reg ...))...]. */
2067 : /* Count backwards through USEs and CLOBBERs to determine
2068 : number of SETs. */
2069 5930128 : for (i = XVECLEN (body, 0); i > 0; i--)
2070 : {
2071 5930128 : if (GET_CODE (XVECEXP (body, 0, i - 1)) == SET)
2072 : break;
2073 2986561 : if (GET_CODE (XVECEXP (body, 0, i - 1)) != USE
2074 2986561 : && GET_CODE (XVECEXP (body, 0, i - 1)) != CLOBBER)
2075 : return -1;
2076 : }
2077 :
2078 : /* N_SETS is now number of output operands. */
2079 11316227 : n_sets = i;
2080 :
2081 : /* Verify that all the SETs we have
2082 : came from a single original asm_operands insn
2083 : (so that invalid combinations are blocked). */
2084 11316227 : for (i = 0; i < n_sets; i++)
2085 : {
2086 8412649 : rtx elt = XVECEXP (body, 0, i);
2087 8412649 : if (GET_CODE (elt) != SET)
2088 : return -1;
2089 8407245 : if (GET_CODE (SET_SRC (elt)) != ASM_OPERANDS)
2090 : return -1;
2091 : /* If these ASM_OPERANDS rtx's came from different original insns
2092 : then they aren't allowed together. */
2093 8390789 : if (ASM_OPERANDS_INPUT_VEC (SET_SRC (elt))
2094 8390789 : != ASM_OPERANDS_INPUT_VEC (asm_op))
2095 : return -1;
2096 : }
2097 : }
2098 : else
2099 : {
2100 : /* 0 outputs, but some clobbers:
2101 : body is [(asm_operands ...)
2102 : (use (reg ...))...
2103 : (clobber (reg ...))...]. */
2104 : /* Make sure all the other parallel things really are clobbers. */
2105 5797854 : for (i = XVECLEN (body, 0) - 1; i > 0; i--)
2106 3917007 : if (GET_CODE (XVECEXP (body, 0, i)) != USE
2107 3917007 : && GET_CODE (XVECEXP (body, 0, i)) != CLOBBER)
2108 : return -1;
2109 : }
2110 : }
2111 :
2112 4802331 : return (ASM_OPERANDS_INPUT_LENGTH (asm_op)
2113 4802331 : + ASM_OPERANDS_LABEL_LENGTH (asm_op) + n_sets);
2114 : }
2115 :
2116 : /* Assuming BODY is an insn body that uses ASM_OPERANDS,
2117 : copy its operands (both input and output) into the vector OPERANDS,
2118 : the locations of the operands within the insn into the vector OPERAND_LOCS,
2119 : and the constraints for the operands into CONSTRAINTS.
2120 : Write the modes of the operands into MODES.
2121 : Write the location info into LOC.
2122 : Return the assembler-template.
2123 : If BODY is an insn body that uses ASM_INPUT with CLOBBERS in PARALLEL,
2124 : return the basic assembly string.
2125 :
2126 : If LOC, MODES, OPERAND_LOCS, CONSTRAINTS or OPERANDS is 0,
2127 : we don't store that info. */
2128 :
2129 : const char *
2130 2241859 : decode_asm_operands (rtx body, rtx *operands, rtx **operand_locs,
2131 : const char **constraints, machine_mode *modes,
2132 : location_t *loc)
2133 : {
2134 2241859 : int nbase = 0, n, i;
2135 2241859 : rtx asmop;
2136 :
2137 2241859 : switch (GET_CODE (body))
2138 : {
2139 : case ASM_OPERANDS:
2140 : /* Zero output asm: BODY is (asm_operands ...). */
2141 : asmop = body;
2142 : break;
2143 :
2144 3655 : case SET:
2145 : /* Single output asm: BODY is (set OUTPUT (asm_operands ...)). */
2146 3655 : asmop = SET_SRC (body);
2147 :
2148 : /* The output is in the SET.
2149 : Its constraint is in the ASM_OPERANDS itself. */
2150 3655 : if (operands)
2151 3545 : operands[0] = SET_DEST (body);
2152 3655 : if (operand_locs)
2153 455 : operand_locs[0] = &SET_DEST (body);
2154 3655 : if (constraints)
2155 3545 : constraints[0] = ASM_OPERANDS_OUTPUT_CONSTRAINT (asmop);
2156 3655 : if (modes)
2157 455 : modes[0] = GET_MODE (SET_DEST (body));
2158 : nbase = 1;
2159 : break;
2160 :
2161 2233920 : case PARALLEL:
2162 2233920 : {
2163 2233920 : int nparallel = XVECLEN (body, 0); /* Includes CLOBBERs. */
2164 :
2165 2233920 : asmop = XVECEXP (body, 0, 0);
2166 2233920 : if (GET_CODE (asmop) == SET)
2167 : {
2168 1219292 : asmop = SET_SRC (asmop);
2169 :
2170 : /* At least one output, plus some CLOBBERs. The outputs are in
2171 : the SETs. Their constraints are in the ASM_OPERANDS itself. */
2172 4493435 : for (i = 0; i < nparallel; i++)
2173 : {
2174 4472077 : if (GET_CODE (XVECEXP (body, 0, i)) == USE
2175 4472077 : || GET_CODE (XVECEXP (body, 0, i)) == CLOBBER)
2176 : break; /* Past last SET */
2177 3274143 : gcc_assert (GET_CODE (XVECEXP (body, 0, i)) == SET);
2178 3274143 : if (operands)
2179 3098642 : operands[i] = SET_DEST (XVECEXP (body, 0, i));
2180 3274143 : if (operand_locs)
2181 1196141 : operand_locs[i] = &SET_DEST (XVECEXP (body, 0, i));
2182 3274143 : if (constraints)
2183 3114574 : constraints[i] = XSTR (SET_SRC (XVECEXP (body, 0, i)), 1);
2184 3274143 : if (modes)
2185 1196141 : modes[i] = GET_MODE (SET_DEST (XVECEXP (body, 0, i)));
2186 : }
2187 : nbase = i;
2188 : }
2189 1014628 : else if (GET_CODE (asmop) == ASM_INPUT)
2190 : {
2191 10158 : if (loc)
2192 0 : *loc = ASM_INPUT_SOURCE_LOCATION (asmop);
2193 10158 : return XSTR (asmop, 0);
2194 : }
2195 : break;
2196 : }
2197 :
2198 0 : default:
2199 0 : gcc_unreachable ();
2200 : }
2201 :
2202 2231701 : n = ASM_OPERANDS_INPUT_LENGTH (asmop);
2203 4309975 : for (i = 0; i < n; i++)
2204 : {
2205 2078274 : if (operand_locs)
2206 889782 : operand_locs[nbase + i] = &ASM_OPERANDS_INPUT (asmop, i);
2207 2078274 : if (operands)
2208 1937934 : operands[nbase + i] = ASM_OPERANDS_INPUT (asmop, i);
2209 2078274 : if (constraints)
2210 1957350 : constraints[nbase + i] = ASM_OPERANDS_INPUT_CONSTRAINT (asmop, i);
2211 2078274 : if (modes)
2212 889782 : modes[nbase + i] = ASM_OPERANDS_INPUT_MODE (asmop, i);
2213 : }
2214 2231701 : nbase += n;
2215 :
2216 2231701 : n = ASM_OPERANDS_LABEL_LENGTH (asmop);
2217 2252300 : for (i = 0; i < n; i++)
2218 : {
2219 20599 : if (operand_locs)
2220 11478 : operand_locs[nbase + i] = &ASM_OPERANDS_LABEL (asmop, i);
2221 20599 : if (operands)
2222 18716 : operands[nbase + i] = ASM_OPERANDS_LABEL (asmop, i);
2223 20599 : if (constraints)
2224 18788 : constraints[nbase + i] = "";
2225 20599 : if (modes)
2226 11478 : modes[nbase + i] = Pmode;
2227 : }
2228 :
2229 2231701 : if (loc)
2230 108164 : *loc = ASM_OPERANDS_SOURCE_LOCATION (asmop);
2231 :
2232 2231701 : return ASM_OPERANDS_TEMPLATE (asmop);
2233 : }
2234 :
2235 : /* Parse inline assembly string STRING and determine which operands are
2236 : referenced by % markers. For the first NOPERANDS operands, set USED[I]
2237 : to true if operand I is referenced.
2238 :
2239 : This is intended to distinguish barrier-like asms such as:
2240 :
2241 : asm ("" : "=m" (...));
2242 :
2243 : from real references such as:
2244 :
2245 : asm ("sw\t$0, %0" : "=m" (...)); */
2246 :
2247 : void
2248 0 : get_referenced_operands (const char *string, bool *used,
2249 : unsigned int noperands)
2250 : {
2251 0 : memset (used, 0, sizeof (bool) * noperands);
2252 0 : const char *p = string;
2253 0 : while (*p)
2254 0 : switch (*p)
2255 : {
2256 0 : case '%':
2257 0 : p += 1;
2258 : /* A letter followed by a digit indicates an operand number. */
2259 0 : if (ISALPHA (p[0]) && ISDIGIT (p[1]))
2260 0 : p += 1;
2261 0 : if (ISDIGIT (*p))
2262 : {
2263 0 : char *endptr;
2264 0 : unsigned long opnum = strtoul (p, &endptr, 10);
2265 0 : if (endptr != p && opnum < noperands)
2266 0 : used[opnum] = true;
2267 0 : p = endptr;
2268 : }
2269 : else
2270 0 : p += 1;
2271 : break;
2272 :
2273 0 : default:
2274 0 : p++;
2275 0 : break;
2276 : }
2277 0 : }
2278 :
2279 : /* Check if an asm_operand matches its constraints.
2280 : Return > 0 if ok, = 0 if bad, < 0 if inconclusive. */
2281 :
2282 : int
2283 3580035 : asm_operand_ok (rtx op, const char *constraint, const char **constraints)
2284 : {
2285 3580035 : int result = 0;
2286 3580035 : bool incdec_ok = false;
2287 :
2288 : /* Use constrain_operands after reload. */
2289 3580035 : gcc_assert (!reload_completed);
2290 :
2291 : /* Empty constraint string is the same as "X,...,X", i.e. X for as
2292 : many alternatives as required to match the other operands. */
2293 3580035 : if (*constraint == '\0')
2294 3833 : result = 1;
2295 :
2296 9864448 : while (*constraint)
2297 : {
2298 6284415 : enum constraint_num cn;
2299 6284415 : char c = *constraint;
2300 6284415 : int len;
2301 6284415 : switch (c)
2302 : {
2303 11497 : case ',':
2304 11497 : raw_constraint_p = false;
2305 11497 : constraint++;
2306 11497 : continue;
2307 :
2308 669972 : case '0': case '1': case '2': case '3': case '4':
2309 669972 : case '5': case '6': case '7': case '8': case '9':
2310 : /* If caller provided constraints pointer, look up
2311 : the matching constraint. Otherwise, our caller should have
2312 : given us the proper matching constraint, but we can't
2313 : actually fail the check if they didn't. Indicate that
2314 : results are inconclusive. */
2315 669972 : if (constraints)
2316 : {
2317 669771 : char *end;
2318 669771 : unsigned long match;
2319 :
2320 669771 : match = strtoul (constraint, &end, 10);
2321 669771 : if (!result)
2322 669510 : result = asm_operand_ok (op, constraints[match], NULL);
2323 669771 : constraint = (const char *) end;
2324 : }
2325 : else
2326 : {
2327 225 : do
2328 225 : constraint++;
2329 225 : while (ISDIGIT (*constraint));
2330 201 : if (! result)
2331 174 : result = -1;
2332 : }
2333 669972 : continue;
2334 :
2335 : /* The rest of the compiler assumes that reloading the address
2336 : of a MEM into a register will make it fit an 'o' constraint.
2337 : That is, if it sees a MEM operand for an 'o' constraint,
2338 : it assumes that (mem (base-reg)) will fit.
2339 :
2340 : That assumption fails on targets that don't have offsettable
2341 : addresses at all. We therefore need to treat 'o' asm
2342 : constraints as a special case and only accept operands that
2343 : are already offsettable, thus proving that at least one
2344 : offsettable address exists. */
2345 36 : case 'o': /* offsettable */
2346 36 : if (offsettable_nonstrict_memref_p (op))
2347 2395544 : result = 1;
2348 : break;
2349 :
2350 161772 : case 'g':
2351 161772 : if (general_operand (op, VOIDmode))
2352 2395544 : result = 1;
2353 : break;
2354 :
2355 32 : case '-':
2356 32 : raw_constraint_p = true;
2357 32 : constraint++;
2358 32 : continue;
2359 :
2360 : case '<':
2361 : case '>':
2362 : /* ??? Before auto-inc-dec, auto inc/dec insns are not supposed
2363 : to exist, excepting those that expand_call created. Further,
2364 : on some machines which do not have generalized auto inc/dec,
2365 : an inc/dec is not a memory_operand.
2366 :
2367 : Match any memory and hope things are resolved after reload. */
2368 5441106 : incdec_ok = true;
2369 : /* FALLTHRU */
2370 5441106 : default:
2371 5441106 : cn = lookup_constraint (constraint);
2372 5441106 : rtx mem = NULL;
2373 5441106 : switch (get_constraint_type (cn))
2374 : {
2375 5216803 : case CT_REGISTER:
2376 5216803 : if (!result
2377 2549287 : && (reg_class_for_constraint (cn) != NO_REGS
2378 2665547 : || constraint[0] == '{')
2379 2549945 : && GET_MODE (op) != BLKmode
2380 7766713 : && register_operand (op, VOIDmode))
2381 : result = 1;
2382 : break;
2383 :
2384 4 : case CT_CONST_INT:
2385 4 : if (!result
2386 4 : && CONST_INT_P (op)
2387 6 : && insn_const_int_ok_for_constraint (INTVAL (op), cn))
2388 : result = 1;
2389 : break;
2390 :
2391 201267 : case CT_MEMORY:
2392 201267 : case CT_RELAXED_MEMORY:
2393 201267 : mem = op;
2394 : /* Fall through. */
2395 201267 : case CT_SPECIAL_MEMORY:
2396 : /* Every memory operand can be reloaded to fit. */
2397 201267 : if (!mem)
2398 0 : mem = extract_mem_from_operand (op);
2399 201267 : result = result || memory_operand (mem, VOIDmode);
2400 201267 : break;
2401 :
2402 143 : case CT_ADDRESS:
2403 : /* Every address operand can be reloaded to fit. */
2404 143 : result = result || address_operand (op, VOIDmode);
2405 143 : break;
2406 :
2407 22889 : case CT_FIXED_FORM:
2408 22889 : result = result || constraint_satisfied_p (op, cn);
2409 22889 : break;
2410 : }
2411 : break;
2412 681501 : }
2413 5602914 : len = CONSTRAINT_LEN (c, constraint);
2414 5606993 : do
2415 5606993 : constraint++;
2416 11209907 : while (--len && *constraint && *constraint != ',');
2417 5602914 : if (len)
2418 : {
2419 2 : raw_constraint_p = false;
2420 2 : return 0;
2421 : }
2422 : }
2423 3580033 : raw_constraint_p = false;
2424 :
2425 : /* For operands without < or > constraints reject side-effects. */
2426 3580033 : if (AUTO_INC_DEC && !incdec_ok && result && MEM_P (op))
2427 : switch (GET_CODE (XEXP (op, 0)))
2428 : {
2429 : case PRE_INC:
2430 : case POST_INC:
2431 : case PRE_DEC:
2432 : case POST_DEC:
2433 : case PRE_MODIFY:
2434 : case POST_MODIFY:
2435 : return 0;
2436 : default:
2437 : break;
2438 : }
2439 :
2440 3580033 : return result;
2441 : }
2442 :
2443 : /* Given an rtx *P, if it is a sum containing an integer constant term,
2444 : return the location (type rtx *) of the pointer to that constant term.
2445 : Otherwise, return a null pointer. */
2446 :
2447 : rtx *
2448 40286703 : find_constant_term_loc (rtx *p)
2449 : {
2450 40286703 : rtx *tem;
2451 40286703 : enum rtx_code code = GET_CODE (*p);
2452 :
2453 : /* If *P IS such a constant term, P is its location. */
2454 :
2455 40286703 : if (code == CONST_INT || code == SYMBOL_REF || code == LABEL_REF
2456 28678593 : || code == CONST)
2457 : return p;
2458 :
2459 : /* Otherwise, if not a sum, it has no constant term. */
2460 :
2461 28630794 : if (GET_CODE (*p) != PLUS)
2462 : return 0;
2463 :
2464 : /* If one of the summands is constant, return its location. */
2465 :
2466 13453872 : if (XEXP (*p, 0) && CONSTANT_P (XEXP (*p, 0))
2467 0 : && XEXP (*p, 1) && CONSTANT_P (XEXP (*p, 1)))
2468 : return p;
2469 :
2470 : /* Otherwise, check each summand for containing a constant term. */
2471 :
2472 13453872 : if (XEXP (*p, 0) != 0)
2473 : {
2474 13453872 : tem = find_constant_term_loc (&XEXP (*p, 0));
2475 13453872 : if (tem != 0)
2476 : return tem;
2477 : }
2478 :
2479 13453872 : if (XEXP (*p, 1) != 0)
2480 : {
2481 13453872 : tem = find_constant_term_loc (&XEXP (*p, 1));
2482 13453872 : if (tem != 0)
2483 : return tem;
2484 : }
2485 :
2486 : return 0;
2487 : }
2488 :
2489 : /* Return true if OP is a memory reference whose address contains
2490 : no side effects and remains valid after the addition of a positive
2491 : integer less than the size of the object being referenced.
2492 :
2493 : We assume that the original address is valid and do not check it.
2494 :
2495 : This uses strict_memory_address_p as a subroutine, so
2496 : don't use it before reload. */
2497 :
2498 : bool
2499 5580289 : offsettable_memref_p (rtx op)
2500 : {
2501 5580289 : return ((MEM_P (op))
2502 11155132 : && offsettable_address_addr_space_p (1, GET_MODE (op), XEXP (op, 0),
2503 5574843 : MEM_ADDR_SPACE (op)));
2504 : }
2505 :
2506 : /* Similar, but don't require a strictly valid mem ref:
2507 : consider pseudo-regs valid as index or base regs. */
2508 :
2509 : bool
2510 11817442 : offsettable_nonstrict_memref_p (rtx op)
2511 : {
2512 11817442 : return ((MEM_P (op))
2513 23634850 : && offsettable_address_addr_space_p (0, GET_MODE (op), XEXP (op, 0),
2514 11817408 : MEM_ADDR_SPACE (op)));
2515 : }
2516 :
2517 : /* Return true if Y is a memory address which contains no side effects
2518 : and would remain valid for address space AS after the addition of
2519 : a positive integer less than the size of that mode.
2520 :
2521 : We assume that the original address is valid and do not check it.
2522 : We do check that it is valid for narrower modes.
2523 :
2524 : If STRICTP is nonzero, we require a strictly valid address,
2525 : for the sake of use in reload.cc. */
2526 :
2527 : bool
2528 17392251 : offsettable_address_addr_space_p (int strictp, machine_mode mode, rtx y,
2529 : addr_space_t as)
2530 : {
2531 17392251 : enum rtx_code ycode = GET_CODE (y);
2532 17392251 : rtx z;
2533 17392251 : rtx y1 = y;
2534 17392251 : rtx *y2;
2535 11817408 : bool (*addressp) (machine_mode, rtx, addr_space_t, code_helper) =
2536 17392251 : (strictp ? strict_memory_address_addr_space_p
2537 : : memory_address_addr_space_p);
2538 34784502 : poly_int64 mode_sz = GET_MODE_SIZE (mode);
2539 :
2540 17392251 : if (CONSTANT_ADDRESS_P (y))
2541 : return true;
2542 :
2543 : /* Adjusting an offsettable address involves changing to a narrower mode.
2544 : Make sure that's OK. */
2545 :
2546 14721270 : if (mode_dependent_address_p (y, as))
2547 : return false;
2548 :
2549 14537161 : machine_mode address_mode = GET_MODE (y);
2550 14537161 : if (address_mode == VOIDmode)
2551 0 : address_mode = targetm.addr_space.address_mode (as);
2552 : #ifdef POINTERS_EXTEND_UNSIGNED
2553 14537161 : machine_mode pointer_mode = targetm.addr_space.pointer_mode (as);
2554 : #endif
2555 :
2556 : /* ??? How much offset does an offsettable BLKmode reference need?
2557 : Clearly that depends on the situation in which it's being used.
2558 : However, the current situation in which we test 0xffffffff is
2559 : less than ideal. Caveat user. */
2560 14537161 : if (known_eq (mode_sz, 0))
2561 0 : mode_sz = BIGGEST_ALIGNMENT / BITS_PER_UNIT;
2562 :
2563 : /* If the expression contains a constant term,
2564 : see if it remains valid when max possible offset is added. */
2565 :
2566 14537161 : if ((ycode == PLUS) && (y2 = find_constant_term_loc (&y1)))
2567 : {
2568 11655909 : bool good;
2569 :
2570 11655909 : y1 = *y2;
2571 11655909 : *y2 = plus_constant (address_mode, *y2, mode_sz - 1);
2572 : /* Use QImode because an odd displacement may be automatically invalid
2573 : for any wider mode. But it should be valid for a single byte. */
2574 11655909 : good = (*addressp) (QImode, y, as, ERROR_MARK);
2575 :
2576 : /* In any case, restore old contents of memory. */
2577 11655909 : *y2 = y1;
2578 11655909 : return good;
2579 : }
2580 :
2581 2881252 : if (GET_RTX_CLASS (ycode) == RTX_AUTOINC)
2582 : return false;
2583 :
2584 : /* The offset added here is chosen as the maximum offset that
2585 : any instruction could need to add when operating on something
2586 : of the specified mode. We assume that if Y and Y+c are
2587 : valid addresses then so is Y+d for all 0<d<c. adjust_address will
2588 : go inside a LO_SUM here, so we do so as well. */
2589 2881252 : if (GET_CODE (y) == LO_SUM
2590 0 : && mode != BLKmode
2591 2881252 : && known_le (mode_sz, GET_MODE_ALIGNMENT (mode) / BITS_PER_UNIT))
2592 0 : z = gen_rtx_LO_SUM (address_mode, XEXP (y, 0),
2593 : plus_constant (address_mode, XEXP (y, 1),
2594 : mode_sz - 1));
2595 : #ifdef POINTERS_EXTEND_UNSIGNED
2596 : /* Likewise for a ZERO_EXTEND from pointer_mode. */
2597 2881252 : else if (POINTERS_EXTEND_UNSIGNED > 0
2598 2881252 : && GET_CODE (y) == ZERO_EXTEND
2599 13 : && GET_MODE (XEXP (y, 0)) == pointer_mode)
2600 7 : z = gen_rtx_ZERO_EXTEND (address_mode,
2601 : plus_constant (pointer_mode, XEXP (y, 0),
2602 : mode_sz - 1));
2603 : #endif
2604 : else
2605 2881245 : z = plus_constant (address_mode, y, mode_sz - 1);
2606 :
2607 : /* Use QImode because an odd displacement may be automatically invalid
2608 : for any wider mode. But it should be valid for a single byte. */
2609 2881252 : return (*addressp) (QImode, z, as, ERROR_MARK);
2610 : }
2611 :
2612 : /* Return true if ADDR is an address-expression whose effect depends
2613 : on the mode of the memory reference it is used in.
2614 :
2615 : ADDRSPACE is the address space associated with the address.
2616 :
2617 : Autoincrement addressing is a typical example of mode-dependence
2618 : because the amount of the increment depends on the mode. */
2619 :
2620 : bool
2621 40317673 : mode_dependent_address_p (rtx addr, addr_space_t addrspace)
2622 : {
2623 : /* Auto-increment addressing with anything other than post_modify
2624 : or pre_modify always introduces a mode dependency. Catch such
2625 : cases now instead of deferring to the target. */
2626 40317673 : if (GET_CODE (addr) == PRE_INC
2627 40317673 : || GET_CODE (addr) == POST_INC
2628 40317667 : || GET_CODE (addr) == PRE_DEC
2629 36536802 : || GET_CODE (addr) == POST_DEC)
2630 : return true;
2631 :
2632 36536802 : return targetm.mode_dependent_address_p (addr, addrspace);
2633 : }
2634 :
2635 : /* Return true if boolean attribute ATTR is supported. */
2636 :
2637 : static bool
2638 1643234569 : have_bool_attr (bool_attr attr)
2639 : {
2640 1643234569 : switch (attr)
2641 : {
2642 : case BA_ENABLED:
2643 : return HAVE_ATTR_enabled;
2644 : case BA_PREFERRED_FOR_SIZE:
2645 : return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_size;
2646 : case BA_PREFERRED_FOR_SPEED:
2647 : return HAVE_ATTR_enabled || HAVE_ATTR_preferred_for_speed;
2648 : }
2649 0 : gcc_unreachable ();
2650 : }
2651 :
2652 : /* Return the value of ATTR for instruction INSN. */
2653 :
2654 : static bool
2655 1746310780 : get_bool_attr (rtx_insn *insn, bool_attr attr)
2656 : {
2657 1746310780 : switch (attr)
2658 : {
2659 739917040 : case BA_ENABLED:
2660 739917040 : return get_attr_enabled (insn);
2661 361384746 : case BA_PREFERRED_FOR_SIZE:
2662 361384746 : return get_attr_enabled (insn) && get_attr_preferred_for_size (insn);
2663 645008994 : case BA_PREFERRED_FOR_SPEED:
2664 645008994 : return get_attr_enabled (insn) && get_attr_preferred_for_speed (insn);
2665 : }
2666 0 : gcc_unreachable ();
2667 : }
2668 :
2669 : /* Like get_bool_attr_mask, but don't use the cache. */
2670 :
2671 : static alternative_mask
2672 104398130 : get_bool_attr_mask_uncached (rtx_insn *insn, bool_attr attr)
2673 : {
2674 : /* Temporarily install enough information for get_attr_<foo> to assume
2675 : that the insn operands are already cached. As above, the attribute
2676 : mustn't depend on the values of operands, so we don't provide their
2677 : real values here. */
2678 104398130 : rtx_insn *old_insn = recog_data.insn;
2679 104398130 : int old_alternative = which_alternative;
2680 :
2681 104398130 : recog_data.insn = insn;
2682 104398130 : alternative_mask mask = ALL_ALTERNATIVES;
2683 104398130 : int n_alternatives = insn_data[INSN_CODE (insn)].n_alternatives;
2684 1850708910 : for (int i = 0; i < n_alternatives; i++)
2685 : {
2686 1746310780 : which_alternative = i;
2687 1746310780 : if (!get_bool_attr (insn, attr))
2688 529847803 : mask &= ~ALTERNATIVE_BIT (i);
2689 : }
2690 :
2691 104398130 : recog_data.insn = old_insn;
2692 104398130 : which_alternative = old_alternative;
2693 104398130 : return mask;
2694 : }
2695 :
2696 : /* Return the mask of operand alternatives that are allowed for INSN
2697 : by boolean attribute ATTR. This mask depends only on INSN and on
2698 : the current target; it does not depend on things like the values of
2699 : operands. */
2700 :
2701 : static alternative_mask
2702 1645553212 : get_bool_attr_mask (rtx_insn *insn, bool_attr attr)
2703 : {
2704 : /* Quick exit for asms and for targets that don't use these attributes. */
2705 1645553212 : int code = INSN_CODE (insn);
2706 1645553212 : if (code < 0 || !have_bool_attr (attr))
2707 : return ALL_ALTERNATIVES;
2708 :
2709 : /* Calling get_attr_<foo> can be expensive, so cache the mask
2710 : for speed. */
2711 1643234569 : if (!this_target_recog->x_bool_attr_masks[code][attr])
2712 13066047 : this_target_recog->x_bool_attr_masks[code][attr]
2713 13066047 : = get_bool_attr_mask_uncached (insn, attr);
2714 1643234569 : return this_target_recog->x_bool_attr_masks[code][attr];
2715 : }
2716 :
2717 : /* Return the set of alternatives of INSN that are allowed by the current
2718 : target. */
2719 :
2720 : alternative_mask
2721 1187376095 : get_enabled_alternatives (rtx_insn *insn)
2722 : {
2723 1187376095 : return get_bool_attr_mask (insn, BA_ENABLED);
2724 : }
2725 :
2726 : /* Return the set of alternatives of INSN that are allowed by the current
2727 : target and are preferred for the current size/speed optimization
2728 : choice. */
2729 :
2730 : alternative_mask
2731 458092080 : get_preferred_alternatives (rtx_insn *insn)
2732 : {
2733 458092080 : if (optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)))
2734 401699622 : return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED);
2735 : else
2736 56392458 : return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
2737 : }
2738 :
2739 : /* Return the set of alternatives of INSN that are allowed by the current
2740 : target and are preferred for the size/speed optimization choice
2741 : associated with BB. Passing a separate BB is useful if INSN has not
2742 : been emitted yet or if we are considering moving it to a different
2743 : block. */
2744 :
2745 : alternative_mask
2746 85037 : get_preferred_alternatives (rtx_insn *insn, basic_block bb)
2747 : {
2748 85037 : if (optimize_bb_for_speed_p (bb))
2749 80046 : return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SPEED);
2750 : else
2751 4991 : return get_bool_attr_mask (insn, BA_PREFERRED_FOR_SIZE);
2752 : }
2753 :
2754 : /* Assert that the cached boolean attributes for INSN are still accurate.
2755 : The backend is required to define these attributes in a way that only
2756 : depends on the current target (rather than operands, compiler phase,
2757 : etc.). */
2758 :
2759 : bool
2760 36929752 : check_bool_attrs (rtx_insn *insn)
2761 : {
2762 36929752 : int code = INSN_CODE (insn);
2763 36929752 : if (code >= 0)
2764 147719008 : for (int i = 0; i <= BA_LAST; ++i)
2765 : {
2766 110789256 : enum bool_attr attr = (enum bool_attr) i;
2767 110789256 : if (this_target_recog->x_bool_attr_masks[code][attr])
2768 91332083 : gcc_assert (this_target_recog->x_bool_attr_masks[code][attr]
2769 : == get_bool_attr_mask_uncached (insn, attr));
2770 : }
2771 36929752 : return true;
2772 : }
2773 :
2774 : /* Like extract_insn, but save insn extracted and don't extract again, when
2775 : called again for the same insn expecting that recog_data still contain the
2776 : valid information. This is used primary by gen_attr infrastructure that
2777 : often does extract insn again and again. */
2778 : void
2779 10583396215 : extract_insn_cached (rtx_insn *insn)
2780 : {
2781 10583396215 : if (recog_data.insn == insn && INSN_CODE (insn) >= 0)
2782 : return;
2783 775241741 : extract_insn (insn);
2784 775241741 : recog_data.insn = insn;
2785 : }
2786 :
2787 : /* Do uncached extract_insn, constrain_operands and complain about failures.
2788 : This should be used when extracting a pre-existing constrained instruction
2789 : if the caller wants to know which alternative was chosen. */
2790 : void
2791 268017705 : extract_constrain_insn (rtx_insn *insn)
2792 : {
2793 268017705 : extract_insn (insn);
2794 268017705 : if (!constrain_operands (reload_completed, get_enabled_alternatives (insn)))
2795 0 : fatal_insn_not_found (insn);
2796 268017705 : }
2797 :
2798 : /* Do cached extract_insn, constrain_operands and complain about failures.
2799 : Used by insn_attrtab. */
2800 : void
2801 9362074631 : extract_constrain_insn_cached (rtx_insn *insn)
2802 : {
2803 9362074631 : extract_insn_cached (insn);
2804 9362074631 : if (which_alternative == -1
2805 9362074631 : && !constrain_operands (reload_completed,
2806 : get_enabled_alternatives (insn)))
2807 0 : fatal_insn_not_found (insn);
2808 9362074631 : }
2809 :
2810 : /* Do cached constrain_operands on INSN and complain about failures. */
2811 : bool
2812 340924675 : constrain_operands_cached (rtx_insn *insn, int strict)
2813 : {
2814 340924675 : if (which_alternative == -1)
2815 93815196 : return constrain_operands (strict, get_enabled_alternatives (insn));
2816 : else
2817 : return true;
2818 : }
2819 :
2820 : /* Analyze INSN and fill in recog_data. */
2821 :
2822 : void
2823 2483799888 : extract_insn (rtx_insn *insn)
2824 : {
2825 2483799888 : int i;
2826 2483799888 : int icode;
2827 2483799888 : int noperands;
2828 2483799888 : rtx body = PATTERN (insn);
2829 :
2830 2483799888 : recog_data.n_operands = 0;
2831 2483799888 : recog_data.n_alternatives = 0;
2832 2483799888 : recog_data.n_dups = 0;
2833 2483799888 : recog_data.is_asm = false;
2834 :
2835 2483799888 : switch (GET_CODE (body))
2836 : {
2837 : case USE:
2838 : case CLOBBER:
2839 : case ASM_INPUT:
2840 : case ADDR_VEC:
2841 : case ADDR_DIFF_VEC:
2842 : case VAR_LOCATION:
2843 : case DEBUG_MARKER:
2844 : return;
2845 :
2846 1828335767 : case SET:
2847 1828335767 : if (GET_CODE (SET_SRC (body)) == ASM_OPERANDS)
2848 400 : goto asm_insn;
2849 : else
2850 1828335367 : goto normal_insn;
2851 248955758 : case PARALLEL:
2852 248955758 : if ((GET_CODE (XVECEXP (body, 0, 0)) == SET
2853 244356155 : && GET_CODE (SET_SRC (XVECEXP (body, 0, 0))) == ASM_OPERANDS)
2854 248468766 : || GET_CODE (XVECEXP (body, 0, 0)) == ASM_OPERANDS
2855 247740916 : || GET_CODE (XVECEXP (body, 0, 0)) == ASM_INPUT)
2856 1223303 : goto asm_insn;
2857 : else
2858 247732455 : goto normal_insn;
2859 1223843 : case ASM_OPERANDS:
2860 1223843 : asm_insn:
2861 1223843 : recog_data.n_operands = noperands = asm_noperands (body);
2862 1223843 : if (noperands >= 0)
2863 : {
2864 : /* This insn is an `asm' with operands. */
2865 :
2866 : /* expand_asm_operands makes sure there aren't too many operands. */
2867 1223843 : gcc_assert (noperands <= MAX_RECOG_OPERANDS);
2868 :
2869 : /* Now get the operand values and constraints out of the insn. */
2870 1223843 : decode_asm_operands (body, recog_data.operand,
2871 : recog_data.operand_loc,
2872 : recog_data.constraints,
2873 : recog_data.operand_mode, NULL);
2874 1223843 : memset (recog_data.is_operator, 0, sizeof recog_data.is_operator);
2875 1223843 : if (noperands > 0)
2876 : {
2877 593021 : const char *p = recog_data.constraints[0];
2878 593021 : recog_data.n_alternatives = 1;
2879 1676825 : while (*p)
2880 1083804 : recog_data.n_alternatives += (*p++ == ',');
2881 : }
2882 1223843 : recog_data.is_asm = true;
2883 1223843 : break;
2884 : }
2885 0 : fatal_insn_not_found (insn);
2886 :
2887 2139456804 : default:
2888 2139456804 : normal_insn:
2889 : /* Ordinary insn: recognize it, get the operands via insn_extract
2890 : and get the constraints. */
2891 :
2892 2139456804 : icode = recog_memoized (insn);
2893 2139456804 : if (icode < 0)
2894 0 : fatal_insn_not_found (insn);
2895 :
2896 2139456804 : recog_data.n_operands = noperands = insn_data[icode].n_operands;
2897 2139456804 : recog_data.n_alternatives = insn_data[icode].n_alternatives;
2898 2139456804 : recog_data.n_dups = insn_data[icode].n_dups;
2899 :
2900 2139456804 : insn_extract (insn);
2901 :
2902 8861021872 : for (i = 0; i < noperands; i++)
2903 : {
2904 4582108264 : recog_data.constraints[i] = insn_data[icode].operand[i].constraint;
2905 4582108264 : recog_data.is_operator[i] = insn_data[icode].operand[i].is_operator;
2906 4582108264 : recog_data.operand_mode[i] = insn_data[icode].operand[i].mode;
2907 : /* VOIDmode match_operands gets mode from their real operand. */
2908 4582108264 : if (recog_data.operand_mode[i] == VOIDmode)
2909 469340908 : recog_data.operand_mode[i] = GET_MODE (recog_data.operand[i]);
2910 : }
2911 : }
2912 6724714099 : for (i = 0; i < noperands; i++)
2913 4584033452 : recog_data.operand_type[i]
2914 7452362397 : = (recog_data.constraints[i][0] == '=' ? OP_OUT
2915 2868328945 : : recog_data.constraints[i][0] == '+' ? OP_INOUT
2916 : : OP_IN);
2917 :
2918 2140680647 : gcc_assert (recog_data.n_alternatives <= MAX_RECOG_ALTERNATIVES);
2919 :
2920 2140680647 : recog_data.insn = NULL;
2921 2140680647 : which_alternative = -1;
2922 : }
2923 :
2924 : /* Fill in OP_ALT_BASE for an instruction that has N_OPERANDS
2925 : operands, N_ALTERNATIVES alternatives and constraint strings
2926 : CONSTRAINTS. OP_ALT_BASE has N_ALTERNATIVES * N_OPERANDS entries
2927 : and CONSTRAINTS has N_OPERANDS entries. OPLOC should be passed in
2928 : if the insn is an asm statement and preprocessing should take the
2929 : asm operands into account, e.g. to determine whether they could be
2930 : addresses in constraints that require addresses; it should then
2931 : point to an array of pointers to each operand. */
2932 :
2933 : void
2934 4801578 : preprocess_constraints (int n_operands, int n_alternatives,
2935 : const char **constraints,
2936 : operand_alternative *op_alt_base,
2937 : rtx **oploc)
2938 : {
2939 12388194 : for (int i = 0; i < n_operands; i++)
2940 : {
2941 7586616 : int j;
2942 7586616 : struct operand_alternative *op_alt;
2943 7586616 : const char *p = constraints[i];
2944 :
2945 7586616 : op_alt = op_alt_base;
2946 :
2947 49368724 : for (j = 0; j < n_alternatives; j++, op_alt += n_operands)
2948 : {
2949 41782108 : op_alt[i].cl = NO_REGS;
2950 41782108 : op_alt[i].register_filters = 0;
2951 41782108 : op_alt[i].dependent_filters = 0;
2952 41782108 : op_alt[i].constraint = p;
2953 41782108 : op_alt[i].matches = -1;
2954 41782108 : op_alt[i].matched = -1;
2955 :
2956 41782108 : if (*p == '\0' || *p == ',')
2957 : {
2958 1783246 : op_alt[i].anything_ok = 1;
2959 1783246 : continue;
2960 : }
2961 :
2962 104764016 : for (;;)
2963 : {
2964 104764016 : char c = *p;
2965 104764016 : if (c == '#')
2966 0 : do
2967 0 : c = *++p;
2968 0 : while (c != ',' && c != '\0');
2969 104764016 : if (c == ',' || c == '\0')
2970 : {
2971 39998862 : p++;
2972 39998862 : break;
2973 : }
2974 :
2975 64765154 : switch (c)
2976 : {
2977 5793533 : case '?':
2978 5793533 : op_alt[i].reject += 6;
2979 5793533 : break;
2980 406763 : case '!':
2981 406763 : op_alt[i].reject += 600;
2982 406763 : break;
2983 61135 : case '&':
2984 61135 : op_alt[i].earlyclobber = 1;
2985 61135 : break;
2986 :
2987 2062948 : case '0': case '1': case '2': case '3': case '4':
2988 2062948 : case '5': case '6': case '7': case '8': case '9':
2989 2062948 : {
2990 2062948 : char *end;
2991 2062948 : op_alt[i].matches = strtoul (p, &end, 10);
2992 2062948 : op_alt[op_alt[i].matches].matched = i;
2993 2062948 : p = end;
2994 : }
2995 2062948 : continue;
2996 :
2997 31385 : case 'X':
2998 31385 : op_alt[i].anything_ok = 1;
2999 31385 : break;
3000 :
3001 213660 : case 'g':
3002 213660 : op_alt[i].cl =
3003 213660 : reg_class_subunion[(int) op_alt[i].cl][(int) GENERAL_REGS];
3004 213660 : break;
3005 :
3006 56195730 : default:
3007 56195730 : enum constraint_num cn = lookup_constraint (p);
3008 56195730 : enum reg_class cl;
3009 56195730 : switch (get_constraint_type (cn))
3010 : {
3011 40162175 : case CT_REGISTER:
3012 40162175 : cl = reg_class_for_constraint (cn);
3013 29177074 : if (cl != NO_REGS)
3014 : {
3015 25564325 : op_alt[i].cl = reg_class_subunion[op_alt[i].cl][cl];
3016 25564325 : auto filter_id = get_register_filter_id (cn);
3017 25564325 : if (filter_id >= 0)
3018 : op_alt[i].register_filters |= 1U << filter_id;
3019 25564325 : auto dep_filter_id = get_dependent_filter_id (cn);
3020 25564325 : if (dep_filter_id >= 0)
3021 : op_alt[i].dependent_filters |= 1U << dep_filter_id;
3022 : }
3023 : break;
3024 :
3025 : case CT_CONST_INT:
3026 : break;
3027 :
3028 7952920 : case CT_MEMORY:
3029 7952920 : case CT_SPECIAL_MEMORY:
3030 7952920 : case CT_RELAXED_MEMORY:
3031 7952920 : op_alt[i].memory_ok = 1;
3032 7952920 : break;
3033 :
3034 87774 : case CT_ADDRESS:
3035 87774 : if (oploc && !address_operand (*oploc[i], VOIDmode))
3036 : break;
3037 :
3038 87755 : op_alt[i].is_address = 1;
3039 87755 : op_alt[i].cl
3040 87755 : = (reg_class_subunion
3041 87755 : [(int) op_alt[i].cl]
3042 87755 : [(int) base_reg_class (VOIDmode, ADDR_SPACE_GENERIC,
3043 87755 : ADDRESS, SCRATCH)]);
3044 87755 : break;
3045 :
3046 : case CT_FIXED_FORM:
3047 : break;
3048 : }
3049 : break;
3050 2062948 : }
3051 62702206 : p += CONSTRAINT_LEN (c, p);
3052 : }
3053 : }
3054 : }
3055 4801578 : }
3056 :
3057 : /* Return an array of operand_alternative instructions for
3058 : instruction ICODE. */
3059 :
3060 : const operand_alternative *
3061 295633481 : preprocess_insn_constraints (unsigned int icode)
3062 : {
3063 295633481 : gcc_checking_assert (IN_RANGE (icode, 0, NUM_INSN_CODES - 1));
3064 295633481 : if (this_target_recog->x_op_alt[icode])
3065 : return this_target_recog->x_op_alt[icode];
3066 :
3067 5515313 : int n_operands = insn_data[icode].n_operands;
3068 5515313 : if (n_operands == 0)
3069 : return 0;
3070 : /* Always provide at least one alternative so that which_op_alt ()
3071 : works correctly. If the instruction has 0 alternatives (i.e. all
3072 : constraint strings are empty) then each operand in this alternative
3073 : will have anything_ok set. */
3074 2978444 : int n_alternatives = MAX (insn_data[icode].n_alternatives, 1);
3075 2978444 : int n_entries = n_operands * n_alternatives;
3076 :
3077 2978444 : operand_alternative *op_alt = XCNEWVEC (operand_alternative, n_entries);
3078 2978444 : const char **constraints = XALLOCAVEC (const char *, n_operands);
3079 :
3080 10108175 : for (int i = 0; i < n_operands; ++i)
3081 7129731 : constraints[i] = insn_data[icode].operand[i].constraint;
3082 2978444 : preprocess_constraints (n_operands, n_alternatives, constraints, op_alt,
3083 : NULL);
3084 :
3085 2978444 : this_target_recog->x_op_alt[icode] = op_alt;
3086 2978444 : return op_alt;
3087 : }
3088 :
3089 : /* After calling extract_insn, you can use this function to extract some
3090 : information from the constraint strings into a more usable form.
3091 : The collected data is stored in recog_op_alt. */
3092 :
3093 : void
3094 201423225 : preprocess_constraints (rtx_insn *insn)
3095 : {
3096 201423225 : int icode = INSN_CODE (insn);
3097 201423225 : if (icode >= 0)
3098 199644207 : recog_op_alt = preprocess_insn_constraints (icode);
3099 : else
3100 : {
3101 1779018 : int n_operands = recog_data.n_operands;
3102 1779018 : int n_alternatives = recog_data.n_alternatives;
3103 1779018 : int n_entries = n_operands * n_alternatives;
3104 1779018 : memset (asm_op_alt, 0, n_entries * sizeof (operand_alternative));
3105 1779018 : preprocess_constraints (n_operands, n_alternatives,
3106 : recog_data.constraints, asm_op_alt,
3107 : NULL);
3108 1779018 : recog_op_alt = asm_op_alt;
3109 : }
3110 201423225 : }
3111 :
3112 : /* Check the operands of an insn against the insn's operand constraints
3113 : and return 1 if they match any of the alternatives in ALTERNATIVES.
3114 :
3115 : The information about the insn's operands, constraints, operand modes
3116 : etc. is obtained from the global variables set up by extract_insn.
3117 :
3118 : WHICH_ALTERNATIVE is set to a number which indicates which
3119 : alternative of constraints was matched: 0 for the first alternative,
3120 : 1 for the next, etc.
3121 :
3122 : In addition, when two operands are required to match
3123 : and it happens that the output operand is (reg) while the
3124 : input operand is --(reg) or ++(reg) (a pre-inc or pre-dec),
3125 : make the output operand look like the input.
3126 : This is because the output operand is the one the template will print.
3127 :
3128 : This is used in final, just before printing the assembler code and by
3129 : the routines that determine an insn's attribute.
3130 :
3131 : If STRICT is a positive nonzero value, it means that we have been
3132 : called after reload has been completed. In that case, we must
3133 : do all checks strictly. If it is zero, it means that we have been called
3134 : before reload has completed. In that case, we first try to see if we can
3135 : find an alternative that matches strictly. If not, we try again, this
3136 : time assuming that reload will fix up the insn. This provides a "best
3137 : guess" for the alternative and is used to compute attributes of insns prior
3138 : to reload. A negative value of STRICT is used for this internal call. */
3139 :
3140 : struct funny_match
3141 : {
3142 : int this_op, other;
3143 : };
3144 :
3145 : /* For a register constraint CN with a dependent filter, return true if
3146 : the respective filter allows REGNO (OP) + OFFSET given the ref-operand
3147 : in recog_data.operand or false if it doesn't.
3148 : If the filter cannot be evaluated, for example when no hard reg
3149 : has been chosen yet, return true. */
3150 :
3151 : static bool
3152 0 : test_dependent_filter (constraint_num cn, rtx op, int offset,
3153 : machine_mode mode)
3154 : {
3155 0 : int id = get_dependent_filter_id (cn);
3156 0 : if (id < 0 || !REG_P (op))
3157 0 : return true;
3158 : int ref_opno = get_dependent_filter_ref (id);
3159 : if (ref_opno < 0 || ref_opno >= recog_data.n_operands)
3160 : return true;
3161 : rtx ref_op = recog_data.operand[ref_opno];
3162 : if (!REG_P (ref_op))
3163 : return true;
3164 : return eval_dependent_filter (id, REGNO (op) + offset, mode,
3165 : REGNO (ref_op), GET_MODE (ref_op));
3166 : }
3167 :
3168 : bool
3169 1137374681 : constrain_operands (int strict, alternative_mask alternatives)
3170 : {
3171 1138288502 : const char *constraints[MAX_RECOG_OPERANDS];
3172 1138288502 : int matching_operands[MAX_RECOG_OPERANDS];
3173 1138288502 : int earlyclobber[MAX_RECOG_OPERANDS];
3174 1138288502 : int c;
3175 :
3176 1138288502 : struct funny_match funny_match[MAX_RECOG_OPERANDS];
3177 1138288502 : int funny_match_index;
3178 :
3179 1138288502 : which_alternative = 0;
3180 1138288502 : if (recog_data.n_operands == 0 || recog_data.n_alternatives == 0)
3181 : return true;
3182 :
3183 3381282389 : for (c = 0; c < recog_data.n_operands; c++)
3184 2303569707 : constraints[c] = recog_data.constraints[c];
3185 :
3186 4047510653 : do
3187 : {
3188 4047510653 : int seen_earlyclobber_at = -1;
3189 4047510653 : int opno;
3190 4047510653 : bool lose = false;
3191 4047510653 : funny_match_index = 0;
3192 :
3193 4047510653 : if (!TEST_BIT (alternatives, which_alternative))
3194 : {
3195 : int i;
3196 :
3197 2752035198 : for (i = 0; i < recog_data.n_operands; i++)
3198 3694243120 : constraints[i] = skip_alternative (constraints[i]);
3199 :
3200 904913638 : which_alternative++;
3201 904913638 : continue;
3202 904913638 : }
3203 :
3204 9662941992 : for (opno = 0; opno < recog_data.n_operands; opno++)
3205 6520344977 : matching_operands[opno] = -1;
3206 :
3207 9662941992 : for (opno = 0; opno < recog_data.n_operands; opno++)
3208 : {
3209 6520344977 : rtx op = recog_data.operand[opno];
3210 6520344977 : machine_mode mode = GET_MODE (op);
3211 6520344977 : const char *p = constraints[opno];
3212 6520344977 : int offset = 0;
3213 6520344977 : bool win = false;
3214 6520344977 : int val;
3215 6520344977 : int len;
3216 :
3217 6520344977 : earlyclobber[opno] = 0;
3218 :
3219 6520344977 : if (GET_CODE (op) == SUBREG)
3220 : {
3221 1518660 : if (REG_P (SUBREG_REG (op))
3222 1518660 : && REGNO (SUBREG_REG (op)) < FIRST_PSEUDO_REGISTER)
3223 360 : offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
3224 360 : GET_MODE (SUBREG_REG (op)),
3225 360 : SUBREG_BYTE (op),
3226 : GET_MODE (op));
3227 1518660 : op = SUBREG_REG (op);
3228 : }
3229 :
3230 : /* An empty constraint or empty alternative
3231 : allows anything which matched the pattern. */
3232 6520344977 : if (*p == 0 || *p == ',')
3233 96521640 : win = true;
3234 :
3235 16474448485 : do
3236 16474448485 : switch (c = *p, len = CONSTRAINT_LEN (c, p), c)
3237 : {
3238 : case '\0':
3239 : len = 0;
3240 : break;
3241 6172559749 : case ',':
3242 6172559749 : c = '\0';
3243 6172559749 : break;
3244 32 : case '-':
3245 32 : raw_constraint_p = true;
3246 32 : break;
3247 :
3248 0 : case '#':
3249 : /* Ignore rest of this alternative as far as
3250 : constraint checking is concerned. */
3251 0 : do
3252 0 : p++;
3253 0 : while (*p && *p != ',');
3254 : len = 0;
3255 : break;
3256 :
3257 463564 : case '&':
3258 463564 : earlyclobber[opno] = 1;
3259 463564 : if (seen_earlyclobber_at < 0)
3260 442251 : seen_earlyclobber_at = opno;
3261 : break;
3262 :
3263 190102004 : case '0': case '1': case '2': case '3': case '4':
3264 190102004 : case '5': case '6': case '7': case '8': case '9':
3265 190102004 : {
3266 : /* This operand must be the same as a previous one.
3267 : This kind of constraint is used for instructions such
3268 : as add when they take only two operands.
3269 :
3270 : Note that the lower-numbered operand is passed first.
3271 :
3272 : If we are not testing strictly, assume that this
3273 : constraint will be satisfied. */
3274 :
3275 190102004 : char *end;
3276 190102004 : int match;
3277 :
3278 190102004 : match = strtoul (p, &end, 10);
3279 190102004 : p = end;
3280 :
3281 190102004 : if (strict < 0)
3282 : val = 1;
3283 : else
3284 : {
3285 189167623 : rtx op1 = recog_data.operand[match];
3286 189167623 : rtx op2 = recog_data.operand[opno];
3287 189167623 : val = operands_match_p (op1, op2);
3288 : }
3289 :
3290 190102004 : matching_operands[opno] = match;
3291 190102004 : matching_operands[match] = opno;
3292 :
3293 190102004 : if (val != 0)
3294 156500020 : win = true;
3295 :
3296 : /* If output is *x and input is *--x, arrange later
3297 : to change the output to *--x as well, since the
3298 : output op is the one that will be printed. */
3299 190102004 : if (val == 2 && strict > 0)
3300 : {
3301 0 : funny_match[funny_match_index].this_op = opno;
3302 0 : funny_match[funny_match_index++].other = match;
3303 : }
3304 : }
3305 190102004 : len = 0;
3306 190102004 : break;
3307 :
3308 267470 : case 'p':
3309 : /* p is used for address_operands. When we are called by
3310 : gen_reload, no one will have checked that the address is
3311 : strictly valid, i.e., that all pseudos requiring hard regs
3312 : have gotten them. We also want to make sure we have a
3313 : valid mode. */
3314 267470 : {
3315 267383 : auto mem_mode = (recog_data.is_asm
3316 267470 : ? VOIDmode
3317 : : recog_data.operand_mode[opno]);
3318 267470 : if ((GET_MODE (op) == VOIDmode
3319 267470 : || SCALAR_INT_MODE_P (GET_MODE (op)))
3320 534914 : && (strict <= 0
3321 267470 : || strict_memory_address_p (mem_mode, op)))
3322 267404 : win = true;
3323 : break;
3324 : }
3325 :
3326 : /* No need to check general_operand again;
3327 : it was done in insn-recog.cc. Well, except that reload
3328 : doesn't check the validity of its replacements, but
3329 : that should only matter when there's a bug. */
3330 122716940 : case 'g':
3331 : /* Anything goes unless it is a REG and really has a hard reg
3332 : but the hard reg is not in the class GENERAL_REGS. */
3333 122716940 : if (REG_P (op))
3334 : {
3335 46528249 : if (strict < 0
3336 : || GENERAL_REGS == ALL_REGS
3337 46528197 : || (reload_in_progress
3338 0 : && REGNO (op) >= FIRST_PSEUDO_REGISTER)
3339 93056446 : || reg_fits_class_p (op, GENERAL_REGS, offset, mode))
3340 : win = true;
3341 : }
3342 76188691 : else if (strict < 0 || general_operand (op, mode))
3343 : win = true;
3344 : break;
3345 :
3346 255 : case '{':
3347 247 : if ((REG_P (op) && HARD_REGISTER_P (op)
3348 247 : && (int) REGNO (op) == decode_hard_reg_constraint (p))
3349 269 : || !reload_completed)
3350 : win = true;
3351 : break;
3352 :
3353 9640553243 : default:
3354 9640553243 : {
3355 9640553243 : enum constraint_num cn = lookup_constraint (p);
3356 9640553243 : enum reg_class cl = reg_class_for_constraint (cn);
3357 4463756986 : if (cl != NO_REGS)
3358 : {
3359 4286288639 : auto *filter = get_register_filter (cn);
3360 4286288639 : if (strict < 0
3361 4284590203 : || (strict == 0
3362 22638884 : && REG_P (op)
3363 16601204 : && REGNO (op) >= FIRST_PSEUDO_REGISTER)
3364 6116003 : || (strict == 0 && GET_CODE (op) == SCRATCH)
3365 8554337846 : || (REG_P (op)
3366 3082513737 : && reg_fits_class_p (op, cl, offset, mode)
3367 : && (!filter
3368 : || TEST_HARD_REG_BIT (*filter,
3369 : REGNO (op) + offset))
3370 : && (strict <= 0
3371 : || test_dependent_filter (cn, op, offset,
3372 : mode))))
3373 : win = true;
3374 : }
3375 :
3376 5354264604 : else if (constraint_satisfied_p (op, cn))
3377 : win = true;
3378 :
3379 4474621140 : else if ((insn_extra_memory_constraint (cn)
3380 : || insn_extra_relaxed_memory_constraint (cn))
3381 : /* Every memory operand can be reloaded to fit. */
3382 4474621140 : && ((strict < 0 && MEM_P (op))
3383 : /* Before reload, accept what reload can turn
3384 : into a mem. */
3385 702210 : || (strict < 0 && CONSTANT_P (op))
3386 : /* Before reload, accept a pseudo or hard register,
3387 : since LRA can turn it into a mem. */
3388 701848 : || (strict < 0 && targetm.lra_p () && REG_P (op))
3389 : /* During reload, accept a pseudo */
3390 942027460 : || (reload_in_progress && REG_P (op)
3391 0 : && REGNO (op) >= FIRST_PSEUDO_REGISTER)))
3392 : win = true;
3393 4473918930 : else if (insn_extra_address_constraint (cn)
3394 : /* Every address operand can be reloaded to fit. */
3395 4473918930 : && strict < 0)
3396 : win = true;
3397 : /* Cater to architectures like IA-64 that define extra memory
3398 : constraints without using define_memory_constraint. */
3399 4473918930 : else if (reload_in_progress
3400 0 : && REG_P (op)
3401 0 : && REGNO (op) >= FIRST_PSEUDO_REGISTER
3402 0 : && reg_renumber[REGNO (op)] < 0
3403 0 : && reg_equiv_mem (REGNO (op)) != 0
3404 4473918930 : && constraint_satisfied_p
3405 0 : (reg_equiv_mem (REGNO (op)), cn))
3406 : win = true;
3407 : break;
3408 : }
3409 : }
3410 16474448485 : while (p += len, c);
3411 :
3412 6520344977 : raw_constraint_p = false;
3413 6520344977 : constraints[opno] = p;
3414 : /* If this operand did not win somehow,
3415 : this alternative loses. */
3416 6520344977 : if (! win)
3417 3152904541 : lose = true;
3418 : }
3419 : /* This alternative won; the operands are ok.
3420 : Change whichever operands this alternative says to change. */
3421 3142597015 : if (! lose)
3422 : {
3423 1073347049 : int opno, eopno;
3424 :
3425 : /* See if any earlyclobber operand conflicts with some other
3426 : operand. */
3427 :
3428 1073347049 : if (strict > 0 && seen_earlyclobber_at >= 0)
3429 1125708 : for (eopno = seen_earlyclobber_at;
3430 1485292 : eopno < recog_data.n_operands;
3431 : eopno++)
3432 : /* Ignore earlyclobber operands now in memory,
3433 : because we would often report failure when we have
3434 : two memory operands, one of which was formerly a REG. */
3435 1125708 : if (earlyclobber[eopno]
3436 379019 : && REG_P (recog_data.operand[eopno]))
3437 1924498 : for (opno = 0; opno < recog_data.n_operands; opno++)
3438 1545479 : if ((MEM_P (recog_data.operand[opno])
3439 1406818 : || recog_data.operand_type[opno] != OP_OUT)
3440 902256 : && opno != eopno
3441 : /* Ignore things like match_operator operands. */
3442 901698 : && *recog_data.constraints[opno] != 0
3443 925970 : && ! (matching_operands[opno] == eopno
3444 99554 : && operands_match_p (recog_data.operand[opno],
3445 : recog_data.operand[eopno]))
3446 2274476 : && ! safe_from_earlyclobber (recog_data.operand[opno],
3447 : recog_data.operand[eopno]))
3448 : lose = true;
3449 :
3450 1073347049 : if (! lose)
3451 : {
3452 1073343081 : while (--funny_match_index >= 0)
3453 : {
3454 0 : recog_data.operand[funny_match[funny_match_index].other]
3455 0 : = recog_data.operand[funny_match[funny_match_index].this_op];
3456 : }
3457 :
3458 : /* For operands without < or > constraints reject side-effects. */
3459 : if (AUTO_INC_DEC && recog_data.is_asm)
3460 : {
3461 : for (opno = 0; opno < recog_data.n_operands; opno++)
3462 : if (MEM_P (recog_data.operand[opno]))
3463 : switch (GET_CODE (XEXP (recog_data.operand[opno], 0)))
3464 : {
3465 : case PRE_INC:
3466 : case POST_INC:
3467 : case PRE_DEC:
3468 : case POST_DEC:
3469 : case PRE_MODIFY:
3470 : case POST_MODIFY:
3471 : if (strchr (recog_data.constraints[opno], '<') == NULL
3472 : && strchr (recog_data.constraints[opno], '>')
3473 : == NULL)
3474 : return false;
3475 : break;
3476 : default:
3477 : break;
3478 : }
3479 : }
3480 :
3481 : return true;
3482 : }
3483 : }
3484 :
3485 2069253934 : which_alternative++;
3486 : }
3487 2974167572 : while (which_alternative < recog_data.n_alternatives);
3488 :
3489 4369601 : which_alternative = -1;
3490 : /* If we are about to reject this, but we are not to test strictly,
3491 : try a very loose test. Only return failure if it fails also. */
3492 4369601 : if (strict == 0)
3493 : return constrain_operands (-1, alternatives);
3494 : else
3495 : return false;
3496 : }
3497 :
3498 : /* Return true iff OPERAND (assumed to be a REG rtx)
3499 : is a hard reg in class CLASS when its regno is offset by OFFSET
3500 : and changed to mode MODE.
3501 : If REG occupies multiple hard regs, all of them must be in CLASS. */
3502 :
3503 : bool
3504 3379847505 : reg_fits_class_p (const_rtx operand, reg_class_t cl, int offset,
3505 : machine_mode mode)
3506 : {
3507 3379847505 : unsigned int regno = REGNO (operand);
3508 :
3509 3379847505 : if (cl == NO_REGS)
3510 : return false;
3511 :
3512 : /* Regno must not be a pseudo register. Offset may be negative. */
3513 3281199294 : return (HARD_REGISTER_NUM_P (regno)
3514 3281123292 : && HARD_REGISTER_NUM_P (regno + offset)
3515 6562322586 : && in_hard_reg_set_p (reg_class_contents[(int) cl], mode,
3516 : regno + offset));
3517 : }
3518 :
3519 : /* Split single instruction. Helper function for split_all_insns and
3520 : split_all_insns_noflow. Return last insn in the sequence if successful,
3521 : or NULL if unsuccessful. */
3522 :
3523 : static rtx_insn *
3524 390199719 : split_insn (rtx_insn *insn)
3525 : {
3526 : /* Split insns here to get max fine-grain parallelism. */
3527 390199719 : rtx_insn *first = PREV_INSN (insn);
3528 390199719 : rtx_insn *last = try_split (PATTERN (insn), insn, 1);
3529 390199719 : rtx insn_set, last_set, note;
3530 :
3531 390199719 : if (last == insn)
3532 : return NULL;
3533 :
3534 : /* If the original instruction was a single set that was known to be
3535 : equivalent to a constant, see if we can say the same about the last
3536 : instruction in the split sequence. The two instructions must set
3537 : the same destination. */
3538 6190861 : insn_set = single_set (insn);
3539 6190861 : if (insn_set)
3540 : {
3541 6073548 : last_set = single_set (last);
3542 6073548 : if (last_set && rtx_equal_p (SET_DEST (last_set), SET_DEST (insn_set)))
3543 : {
3544 2870425 : note = find_reg_equal_equiv_note (insn);
3545 2870425 : if (note && CONSTANT_P (XEXP (note, 0)))
3546 75983 : set_unique_reg_note (last, REG_EQUAL, XEXP (note, 0));
3547 2794442 : else if (CONSTANT_P (SET_SRC (insn_set)))
3548 34454 : set_unique_reg_note (last, REG_EQUAL,
3549 : copy_rtx (SET_SRC (insn_set)));
3550 : }
3551 : }
3552 :
3553 : /* try_split returns the NOTE that INSN became. */
3554 6190861 : SET_INSN_DELETED (insn);
3555 :
3556 : /* ??? Coddle to md files that generate subregs in post-reload
3557 : splitters instead of computing the proper hard register. */
3558 6190861 : if (reload_completed && first != last)
3559 : {
3560 5763745 : auto old_post_ra_split_completed = post_ra_split_completed;
3561 5763745 : post_ra_split_completed = true;
3562 5763745 : first = NEXT_INSN (first);
3563 2722849 : for (;;)
3564 : {
3565 8486594 : if (INSN_P (first))
3566 8482557 : cleanup_subreg_operands (first);
3567 8486594 : if (first == last)
3568 : break;
3569 2722849 : first = NEXT_INSN (first);
3570 : }
3571 5763745 : post_ra_split_completed = old_post_ra_split_completed;
3572 : }
3573 :
3574 : return last;
3575 : }
3576 :
3577 : /* Split all insns in the function. If UPD_LIFE, update life info after. */
3578 :
3579 : void
3580 4067045 : split_all_insns (void)
3581 : {
3582 4067045 : bool changed;
3583 4067045 : bool need_cfg_cleanup = false;
3584 4067045 : basic_block bb;
3585 :
3586 4067045 : auto_sbitmap blocks (last_basic_block_for_fn (cfun));
3587 4067045 : bitmap_clear (blocks);
3588 4067045 : changed = false;
3589 :
3590 44161738 : FOR_EACH_BB_REVERSE_FN (bb, cfun)
3591 : {
3592 40094693 : rtx_insn *insn, *next;
3593 40094693 : bool finish = false;
3594 :
3595 40094693 : rtl_profile_for_bb (bb);
3596 512209557 : for (insn = BB_HEAD (bb); !finish ; insn = next)
3597 : {
3598 : /* Can't use `next_real_insn' because that might go across
3599 : CODE_LABELS and short-out basic blocks. */
3600 472114864 : next = NEXT_INSN (insn);
3601 472114864 : finish = (insn == BB_END (bb));
3602 :
3603 : /* If INSN has a REG_EH_REGION note and we split INSN, the
3604 : resulting split may not have/need REG_EH_REGION notes.
3605 :
3606 : If that happens and INSN was the last reference to the
3607 : given EH region, then the EH region will become unreachable.
3608 : We cannot leave the unreachable blocks in the CFG as that
3609 : will trigger a checking failure.
3610 :
3611 : So track if INSN has a REG_EH_REGION note. If so and we
3612 : split INSN, then trigger a CFG cleanup. */
3613 472114864 : rtx note = find_reg_note (insn, REG_EH_REGION, NULL_RTX);
3614 472114864 : if (INSN_P (insn))
3615 : {
3616 390247596 : rtx set = single_set (insn);
3617 :
3618 : /* Don't split no-op move insns. These should silently
3619 : disappear later in final. Splitting such insns would
3620 : break the code that handles LIBCALL blocks. */
3621 390247596 : if (set && set_noop_p (set))
3622 : {
3623 : /* Nops get in the way while scheduling, so delete them
3624 : now if register allocation has already been done. It
3625 : is too risky to try to do this before register
3626 : allocation, and there are unlikely to be very many
3627 : nops then anyways. */
3628 47877 : if (reload_completed)
3629 47877 : delete_insn_and_edges (insn);
3630 47877 : if (note)
3631 472114864 : need_cfg_cleanup = true;
3632 : }
3633 : else
3634 : {
3635 390199719 : if (split_insn (insn))
3636 : {
3637 6190861 : bitmap_set_bit (blocks, bb->index);
3638 6190861 : changed = true;
3639 6190861 : if (note)
3640 2806 : need_cfg_cleanup = true;
3641 : }
3642 : }
3643 : }
3644 : }
3645 : }
3646 :
3647 4067045 : if (reload_completed)
3648 2562097 : post_ra_split_completed = true;
3649 :
3650 4067045 : default_rtl_profile ();
3651 4067045 : if (changed)
3652 : {
3653 762362 : find_many_sub_basic_blocks (blocks);
3654 :
3655 : /* Splitting could drop an REG_EH_REGION if it potentially
3656 : trapped in its original form, but does not in its split
3657 : form. Consider a FLOAT_TRUNCATE which splits into a memory
3658 : store/load pair and -fnon-call-exceptions. */
3659 762362 : if (need_cfg_cleanup)
3660 1340 : cleanup_cfg (0);
3661 : }
3662 :
3663 4067045 : checking_verify_flow_info ();
3664 4067045 : }
3665 :
3666 : /* Same as split_all_insns, but do not expect CFG to be available.
3667 : Used by machine dependent reorg passes. */
3668 :
3669 : void
3670 0 : split_all_insns_noflow (void)
3671 : {
3672 0 : rtx_insn *next, *insn;
3673 :
3674 0 : for (insn = get_insns (); insn; insn = next)
3675 : {
3676 0 : next = NEXT_INSN (insn);
3677 0 : if (INSN_P (insn))
3678 : {
3679 : /* Don't split no-op move insns. These should silently
3680 : disappear later in final. Splitting such insns would
3681 : break the code that handles LIBCALL blocks. */
3682 0 : rtx set = single_set (insn);
3683 0 : if (set && set_noop_p (set))
3684 : {
3685 : /* Nops get in the way while scheduling, so delete them
3686 : now if register allocation has already been done. It
3687 : is too risky to try to do this before register
3688 : allocation, and there are unlikely to be very many
3689 : nops then anyways.
3690 :
3691 : ??? Should we use delete_insn when the CFG isn't valid? */
3692 0 : if (reload_completed)
3693 0 : delete_insn_and_edges (insn);
3694 : }
3695 : else
3696 0 : split_insn (insn);
3697 : }
3698 : }
3699 :
3700 0 : if (reload_completed)
3701 0 : post_ra_split_completed = true;
3702 0 : }
3703 :
3704 : struct peep2_insn_data
3705 : {
3706 : rtx_insn *insn;
3707 : regset live_before;
3708 : };
3709 :
3710 : static struct peep2_insn_data peep2_insn_data[MAX_INSNS_PER_PEEP2 + 1];
3711 : static int peep2_current;
3712 :
3713 : static bool peep2_do_rebuild_jump_labels;
3714 : static bool peep2_do_cleanup_cfg;
3715 :
3716 : /* The number of instructions available to match a peep2. */
3717 : int peep2_current_count;
3718 :
3719 : /* A marker indicating the last insn of the block. The live_before regset
3720 : for this element is correct, indicating DF_LIVE_OUT for the block. */
3721 : #define PEEP2_EOB invalid_insn_rtx
3722 :
3723 : /* Wrap N to fit into the peep2_insn_data buffer. */
3724 :
3725 : static int
3726 429584322 : peep2_buf_position (int n)
3727 : {
3728 0 : if (n >= MAX_INSNS_PER_PEEP2 + 1)
3729 145074619 : n -= MAX_INSNS_PER_PEEP2 + 1;
3730 429566226 : return n;
3731 : }
3732 :
3733 : /* Return the Nth non-note insn after `current', or return NULL_RTX if it
3734 : does not exist. Used by the recognizer to find the next insn to match
3735 : in a multi-insn pattern. */
3736 :
3737 : rtx_insn *
3738 222552977 : peep2_next_insn (int n)
3739 : {
3740 222552977 : gcc_assert (n <= peep2_current_count);
3741 :
3742 222552977 : n = peep2_buf_position (peep2_current + n);
3743 :
3744 222552977 : return peep2_insn_data[n].insn;
3745 : }
3746 :
3747 : /* Return true if REGNO is dead before the Nth non-note insn
3748 : after `current'. */
3749 :
3750 : bool
3751 13233592 : peep2_regno_dead_p (int ofs, int regno)
3752 : {
3753 13233592 : gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3754 :
3755 13233592 : ofs = peep2_buf_position (peep2_current + ofs);
3756 :
3757 13233592 : gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3758 :
3759 13233592 : return ! REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno);
3760 : }
3761 :
3762 : /* Similarly for a REG. */
3763 :
3764 : bool
3765 281454 : peep2_reg_dead_p (int ofs, rtx reg)
3766 : {
3767 281454 : gcc_assert (ofs < MAX_INSNS_PER_PEEP2 + 1);
3768 :
3769 281454 : ofs = peep2_buf_position (peep2_current + ofs);
3770 :
3771 281454 : gcc_assert (peep2_insn_data[ofs].insn != NULL_RTX);
3772 :
3773 281454 : unsigned int end_regno = END_REGNO (reg);
3774 359309 : for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
3775 281454 : if (REGNO_REG_SET_P (peep2_insn_data[ofs].live_before, regno))
3776 : return false;
3777 : return true;
3778 : }
3779 :
3780 : /* Regno offset to be used in the register search. */
3781 : static int search_ofs;
3782 :
3783 : /* Try to find a hard register of mode MODE, matching the register class in
3784 : CLASS_STR, which is available at the beginning of insn CURRENT_INSN and
3785 : remains available until the end of LAST_INSN. LAST_INSN may be NULL_RTX,
3786 : in which case the only condition is that the register must be available
3787 : before CURRENT_INSN.
3788 : Registers that already have bits set in REG_SET will not be considered.
3789 :
3790 : If an appropriate register is available, it will be returned and the
3791 : corresponding bit(s) in REG_SET will be set; otherwise, NULL_RTX is
3792 : returned. */
3793 :
3794 : rtx
3795 601353 : peep2_find_free_register (int from, int to, const char *class_str,
3796 : machine_mode mode, HARD_REG_SET *reg_set)
3797 : {
3798 601353 : enum reg_class cl;
3799 601353 : HARD_REG_SET live;
3800 601353 : df_ref def;
3801 601353 : int i;
3802 :
3803 601353 : gcc_assert (from < MAX_INSNS_PER_PEEP2 + 1);
3804 601353 : gcc_assert (to < MAX_INSNS_PER_PEEP2 + 1);
3805 :
3806 601353 : from = peep2_buf_position (peep2_current + from);
3807 601353 : to = peep2_buf_position (peep2_current + to);
3808 :
3809 601353 : gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3810 601353 : REG_SET_TO_HARD_REG_SET (live, peep2_insn_data[from].live_before);
3811 :
3812 601353 : while (from != to)
3813 : {
3814 18096 : gcc_assert (peep2_insn_data[from].insn != NULL_RTX);
3815 :
3816 : /* Don't use registers set or clobbered by the insn. */
3817 72384 : FOR_EACH_INSN_DEF (def, peep2_insn_data[from].insn)
3818 54288 : SET_HARD_REG_BIT (live, DF_REF_REGNO (def));
3819 :
3820 637545 : from = peep2_buf_position (from + 1);
3821 : }
3822 :
3823 601353 : cl = reg_class_for_constraint (lookup_constraint (class_str));
3824 :
3825 5830105 : for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
3826 : {
3827 5825316 : int raw_regno, regno, j;
3828 5825316 : bool success;
3829 :
3830 : /* Distribute the free registers as much as possible. */
3831 5825316 : raw_regno = search_ofs + i;
3832 5825316 : if (raw_regno >= FIRST_PSEUDO_REGISTER)
3833 258365 : raw_regno -= FIRST_PSEUDO_REGISTER;
3834 : #ifdef REG_ALLOC_ORDER
3835 5825316 : regno = reg_alloc_order[raw_regno];
3836 : #else
3837 : regno = raw_regno;
3838 : #endif
3839 :
3840 : /* Can it support the mode we need? */
3841 5825316 : if (!targetm.hard_regno_mode_ok (regno, mode))
3842 1794136 : continue;
3843 :
3844 4627744 : success = true;
3845 4627744 : for (j = 0; success && j < hard_regno_nregs (regno, mode); j++)
3846 : {
3847 : /* Don't allocate fixed registers. */
3848 4031180 : if (fixed_regs[regno + j])
3849 : {
3850 : success = false;
3851 : break;
3852 : }
3853 : /* Don't allocate global registers. */
3854 2114818 : if (global_regs[regno + j])
3855 : {
3856 : success = false;
3857 : break;
3858 : }
3859 : /* Make sure the register is of the right class. */
3860 2114818 : if (! TEST_HARD_REG_BIT (reg_class_contents[cl], regno + j))
3861 : {
3862 : success = false;
3863 : break;
3864 : }
3865 : /* And that we don't create an extra save/restore. */
3866 1131261 : if (! crtl->abi->clobbers_full_reg_p (regno + j)
3867 1131261 : && ! df_regs_ever_live_p (regno + j))
3868 : {
3869 : success = false;
3870 : break;
3871 : }
3872 :
3873 1094544 : if (! targetm.hard_regno_scratch_ok (regno + j))
3874 : {
3875 : success = false;
3876 : break;
3877 : }
3878 :
3879 : /* And we don't clobber traceback for noreturn functions. */
3880 1094381 : if ((regno + j == FRAME_POINTER_REGNUM
3881 1094381 : || regno + j == HARD_FRAME_POINTER_REGNUM)
3882 49906 : && (! reload_completed || frame_pointer_needed))
3883 : {
3884 : success = false;
3885 : break;
3886 : }
3887 :
3888 1083551 : if (TEST_HARD_REG_BIT (*reg_set, regno + j)
3889 1083551 : || TEST_HARD_REG_BIT (live, regno + j))
3890 : {
3891 : success = false;
3892 : break;
3893 : }
3894 : }
3895 :
3896 4031180 : if (success)
3897 : {
3898 596564 : add_to_hard_reg_set (reg_set, mode, regno);
3899 :
3900 : /* Start the next search with the next register. */
3901 596564 : if (++raw_regno >= FIRST_PSEUDO_REGISTER)
3902 6575 : raw_regno = 0;
3903 596564 : search_ofs = raw_regno;
3904 :
3905 596564 : return gen_rtx_REG (mode, regno);
3906 : }
3907 : }
3908 :
3909 4789 : search_ofs = 0;
3910 4789 : return NULL_RTX;
3911 : }
3912 :
3913 : /* Forget all currently tracked instructions, only remember current
3914 : LIVE regset. */
3915 :
3916 : static void
3917 10961190 : peep2_reinit_state (regset live)
3918 : {
3919 10961190 : int i;
3920 :
3921 : /* Indicate that all slots except the last holds invalid data. */
3922 76728330 : for (i = 0; i < MAX_INSNS_PER_PEEP2; ++i)
3923 65767140 : peep2_insn_data[i].insn = NULL;
3924 10961190 : peep2_current_count = 0;
3925 :
3926 : /* Indicate that the last slot contains live_after data. */
3927 10961190 : peep2_insn_data[MAX_INSNS_PER_PEEP2].insn = PEEP2_EOB;
3928 10961190 : peep2_current = MAX_INSNS_PER_PEEP2;
3929 :
3930 10961190 : COPY_REG_SET (peep2_insn_data[MAX_INSNS_PER_PEEP2].live_before, live);
3931 10961190 : }
3932 :
3933 : /* Copies frame related info of an insn (OLD_INSN) to the single
3934 : insn (NEW_INSN) that was obtained by splitting OLD_INSN. */
3935 :
3936 : void
3937 133431 : copy_frame_info_to_split_insn (rtx_insn *old_insn, rtx_insn *new_insn)
3938 : {
3939 133431 : bool any_note = false;
3940 133431 : rtx note;
3941 :
3942 133431 : if (!RTX_FRAME_RELATED_P (old_insn))
3943 : return;
3944 :
3945 133431 : RTX_FRAME_RELATED_P (new_insn) = 1;
3946 :
3947 : /* Allow the backend to fill in a note during the split. */
3948 133431 : for (note = REG_NOTES (new_insn); note ; note = XEXP (note, 1))
3949 0 : switch (REG_NOTE_KIND (note))
3950 : {
3951 0 : case REG_FRAME_RELATED_EXPR:
3952 0 : case REG_CFA_DEF_CFA:
3953 0 : case REG_CFA_ADJUST_CFA:
3954 0 : case REG_CFA_OFFSET:
3955 0 : case REG_CFA_REGISTER:
3956 0 : case REG_CFA_EXPRESSION:
3957 0 : case REG_CFA_RESTORE:
3958 0 : case REG_CFA_SET_VDRAP:
3959 0 : any_note = true;
3960 0 : break;
3961 : default:
3962 : break;
3963 : }
3964 :
3965 : /* If the backend didn't supply a note, copy one over. */
3966 133431 : if (!any_note)
3967 325994 : for (note = REG_NOTES (old_insn); note ; note = XEXP (note, 1))
3968 192563 : switch (REG_NOTE_KIND (note))
3969 : {
3970 145193 : case REG_FRAME_RELATED_EXPR:
3971 145193 : case REG_CFA_DEF_CFA:
3972 145193 : case REG_CFA_ADJUST_CFA:
3973 145193 : case REG_CFA_OFFSET:
3974 145193 : case REG_CFA_REGISTER:
3975 145193 : case REG_CFA_EXPRESSION:
3976 145193 : case REG_CFA_RESTORE:
3977 145193 : case REG_CFA_SET_VDRAP:
3978 145193 : add_reg_note (new_insn, REG_NOTE_KIND (note), XEXP (note, 0));
3979 145193 : any_note = true;
3980 145193 : break;
3981 : default:
3982 : break;
3983 : }
3984 :
3985 : /* If there still isn't a note, make sure the unwind info sees the
3986 : same expression as before the split. */
3987 133431 : if (!any_note)
3988 : {
3989 2432 : rtx old_set, new_set;
3990 :
3991 : /* The old insn had better have been simple, or annotated. */
3992 2432 : old_set = single_set (old_insn);
3993 2432 : gcc_assert (old_set != NULL);
3994 :
3995 2432 : new_set = single_set (new_insn);
3996 2432 : if (!new_set || !rtx_equal_p (new_set, old_set))
3997 285 : add_reg_note (new_insn, REG_FRAME_RELATED_EXPR, old_set);
3998 : }
3999 :
4000 : /* Copy prologue/epilogue status. This is required in order to keep
4001 : proper placement of EPILOGUE_BEG and the DW_CFA_remember_state. */
4002 133431 : maybe_copy_prologue_epilogue_insn (old_insn, new_insn);
4003 : }
4004 :
4005 : /* While scanning basic block BB, we found a match of length MATCH_LEN + 1,
4006 : starting at INSN. Perform the replacement, removing the old insns and
4007 : replacing them with ATTEMPT. Returns the last insn emitted, or NULL
4008 : if the replacement is rejected. */
4009 :
4010 : static rtx_insn *
4011 2258263 : peep2_attempt (basic_block bb, rtx_insn *insn, int match_len, rtx_insn *attempt)
4012 : {
4013 2258263 : int i;
4014 2258263 : rtx_insn *last, *before_try, *x;
4015 2258263 : rtx eh_note, as_note;
4016 2258263 : rtx_insn *old_insn;
4017 2258263 : rtx_insn *new_insn;
4018 2258263 : bool was_call = false;
4019 :
4020 : /* If we are splitting an RTX_FRAME_RELATED_P insn, do not allow it to
4021 : match more than one insn, or to be split into more than one insn. */
4022 2258263 : old_insn = peep2_insn_data[peep2_current].insn;
4023 2258263 : if (RTX_FRAME_RELATED_P (old_insn))
4024 : {
4025 136190 : if (match_len != 0)
4026 : return NULL;
4027 :
4028 : /* Look for one "active" insn. I.e. ignore any "clobber" insns that
4029 : may be in the stream for the purpose of register allocation. */
4030 136190 : if (active_insn_p (attempt))
4031 : new_insn = attempt;
4032 : else
4033 34981 : new_insn = next_active_insn (attempt);
4034 136190 : if (next_active_insn (new_insn))
4035 : return NULL;
4036 :
4037 : /* We have a 1-1 replacement. Copy over any frame-related info. */
4038 133394 : copy_frame_info_to_split_insn (old_insn, new_insn);
4039 : }
4040 :
4041 : /* If we are splitting a CALL_INSN, look for the CALL_INSN
4042 : in SEQ and copy our CALL_INSN_FUNCTION_USAGE and other
4043 : cfg-related call notes. */
4044 4726975 : for (i = 0; i <= match_len; ++i)
4045 : {
4046 2473041 : int j;
4047 2473041 : rtx note;
4048 :
4049 2473041 : j = peep2_buf_position (peep2_current + i);
4050 2473041 : old_insn = peep2_insn_data[j].insn;
4051 2473041 : if (!CALL_P (old_insn))
4052 2471508 : continue;
4053 1533 : was_call = true;
4054 :
4055 : new_insn = attempt;
4056 1533 : while (new_insn != NULL_RTX)
4057 : {
4058 1533 : if (CALL_P (new_insn))
4059 : break;
4060 0 : new_insn = NEXT_INSN (new_insn);
4061 : }
4062 :
4063 1533 : gcc_assert (new_insn != NULL_RTX);
4064 :
4065 1533 : CALL_INSN_FUNCTION_USAGE (new_insn)
4066 1533 : = CALL_INSN_FUNCTION_USAGE (old_insn);
4067 1533 : CALL_INSN_ABI_ID (new_insn) = CALL_INSN_ABI_ID (old_insn);
4068 1533 : SIBLING_CALL_P (new_insn) = SIBLING_CALL_P (old_insn);
4069 :
4070 1533 : for (note = REG_NOTES (old_insn);
4071 6949 : note;
4072 5416 : note = XEXP (note, 1))
4073 5416 : switch (REG_NOTE_KIND (note))
4074 : {
4075 0 : case REG_NORETURN:
4076 0 : case REG_SETJMP:
4077 0 : case REG_TM:
4078 0 : case REG_CALL_NOCF_CHECK:
4079 0 : add_reg_note (new_insn, REG_NOTE_KIND (note),
4080 : XEXP (note, 0));
4081 0 : break;
4082 : default:
4083 : /* Discard all other reg notes. */
4084 : break;
4085 : }
4086 :
4087 : /* Croak if there is another call in the sequence. */
4088 1533 : while (++i <= match_len)
4089 : {
4090 0 : j = peep2_buf_position (peep2_current + i);
4091 0 : old_insn = peep2_insn_data[j].insn;
4092 0 : gcc_assert (!CALL_P (old_insn));
4093 : }
4094 : break;
4095 : }
4096 :
4097 : /* If we matched any instruction that had a REG_ARGS_SIZE, then
4098 : move those notes over to the new sequence. */
4099 2255467 : as_note = NULL;
4100 4610570 : for (i = match_len; i >= 0; --i)
4101 : {
4102 2473041 : int j = peep2_buf_position (peep2_current + i);
4103 2473041 : old_insn = peep2_insn_data[j].insn;
4104 :
4105 2473041 : as_note = find_reg_note (old_insn, REG_ARGS_SIZE, NULL);
4106 2473041 : if (as_note)
4107 : break;
4108 : }
4109 :
4110 2255467 : i = peep2_buf_position (peep2_current + match_len);
4111 2255467 : eh_note = find_reg_note (peep2_insn_data[i].insn, REG_EH_REGION, NULL_RTX);
4112 :
4113 : /* Replace the old sequence with the new. */
4114 2255467 : rtx_insn *peepinsn = peep2_insn_data[i].insn;
4115 4510934 : last = emit_insn_after_setloc (attempt,
4116 : peep2_insn_data[i].insn,
4117 2255467 : INSN_LOCATION (peepinsn));
4118 2255467 : if (JUMP_P (peepinsn) && JUMP_P (last))
4119 799 : CROSSING_JUMP_P (last) = CROSSING_JUMP_P (peepinsn);
4120 2255467 : before_try = PREV_INSN (insn);
4121 2255467 : delete_insn_chain (insn, peep2_insn_data[i].insn, false);
4122 :
4123 : /* Re-insert the EH_REGION notes. */
4124 2255467 : if (eh_note || (was_call && nonlocal_goto_handler_labels))
4125 : {
4126 40 : edge eh_edge;
4127 40 : edge_iterator ei;
4128 :
4129 48 : FOR_EACH_EDGE (eh_edge, ei, bb->succs)
4130 47 : if (eh_edge->flags & (EDGE_EH | EDGE_ABNORMAL_CALL))
4131 : break;
4132 :
4133 40 : if (eh_note)
4134 40 : copy_reg_eh_region_note_backward (eh_note, last, before_try);
4135 :
4136 40 : if (eh_edge)
4137 117 : for (x = last; x != before_try; x = PREV_INSN (x))
4138 78 : if (x != BB_END (bb)
4139 78 : && (can_throw_internal (x)
4140 39 : || can_nonlocal_goto (x)))
4141 : {
4142 0 : edge nfte, nehe;
4143 0 : int flags;
4144 :
4145 0 : nfte = split_block (bb, x);
4146 0 : flags = (eh_edge->flags
4147 : & (EDGE_EH | EDGE_ABNORMAL));
4148 0 : if (CALL_P (x))
4149 0 : flags |= EDGE_ABNORMAL_CALL;
4150 0 : nehe = make_edge (nfte->src, eh_edge->dest,
4151 : flags);
4152 :
4153 0 : nehe->probability = eh_edge->probability;
4154 0 : nfte->probability = nehe->probability.invert ();
4155 :
4156 0 : peep2_do_cleanup_cfg |= purge_dead_edges (nfte->dest);
4157 0 : bb = nfte->src;
4158 0 : eh_edge = nehe;
4159 : }
4160 :
4161 : /* Converting possibly trapping insn to non-trapping is
4162 : possible. Zap dummy outgoing edges. */
4163 40 : peep2_do_cleanup_cfg |= purge_dead_edges (bb);
4164 : }
4165 :
4166 : /* Re-insert the ARGS_SIZE notes. */
4167 2255467 : if (as_note)
4168 117938 : fixup_args_size_notes (before_try, last, get_args_size (as_note));
4169 :
4170 : /* Scan the new insns for embedded side effects and add appropriate
4171 : REG_INC notes. */
4172 : if (AUTO_INC_DEC)
4173 : for (x = last; x != before_try; x = PREV_INSN (x))
4174 : if (NONDEBUG_INSN_P (x))
4175 : add_auto_inc_notes (x, PATTERN (x));
4176 :
4177 : /* If we generated a jump instruction, it won't have
4178 : JUMP_LABEL set. Recompute after we're done. */
4179 5253014 : for (x = last; x != before_try; x = PREV_INSN (x))
4180 2998346 : if (JUMP_P (x))
4181 : {
4182 799 : peep2_do_rebuild_jump_labels = true;
4183 799 : break;
4184 : }
4185 :
4186 : return last;
4187 : }
4188 :
4189 : /* After performing a replacement in basic block BB, fix up the life
4190 : information in our buffer. LAST is the last of the insns that we
4191 : emitted as a replacement. PREV is the insn before the start of
4192 : the replacement. MATCH_LEN + 1 is the number of instructions that were
4193 : matched, and which now need to be replaced in the buffer. */
4194 :
4195 : static void
4196 2255467 : peep2_update_life (basic_block bb, int match_len, rtx_insn *last,
4197 : rtx_insn *prev)
4198 : {
4199 2255467 : int i = peep2_buf_position (peep2_current + match_len + 1);
4200 2255467 : rtx_insn *x;
4201 2255467 : regset_head live;
4202 :
4203 2255467 : INIT_REG_SET (&live);
4204 2255467 : COPY_REG_SET (&live, peep2_insn_data[i].live_before);
4205 :
4206 2255467 : gcc_assert (peep2_current_count >= match_len + 1);
4207 2255467 : peep2_current_count -= match_len + 1;
4208 :
4209 2255467 : x = last;
4210 2999039 : do
4211 : {
4212 2999039 : if (INSN_P (x))
4213 : {
4214 2999039 : df_insn_rescan (x);
4215 2999039 : if (peep2_current_count < MAX_INSNS_PER_PEEP2)
4216 : {
4217 2855724 : peep2_current_count++;
4218 2855724 : if (--i < 0)
4219 832005 : i = MAX_INSNS_PER_PEEP2;
4220 2855724 : peep2_insn_data[i].insn = x;
4221 2855724 : df_simulate_one_insn_backwards (bb, x, &live);
4222 2855724 : COPY_REG_SET (peep2_insn_data[i].live_before, &live);
4223 : }
4224 : }
4225 2999039 : x = PREV_INSN (x);
4226 : }
4227 2999039 : while (x != prev);
4228 2255467 : CLEAR_REG_SET (&live);
4229 :
4230 2255467 : peep2_current = i;
4231 2255467 : }
4232 :
4233 : /* Add INSN, which is in BB, at the end of the peep2 insn buffer if possible.
4234 : Return true if we added it, false otherwise. The caller will try to match
4235 : peepholes against the buffer if we return false; otherwise it will try to
4236 : add more instructions to the buffer. */
4237 :
4238 : static bool
4239 83336195 : peep2_fill_buffer (basic_block bb, rtx_insn *insn, regset live)
4240 : {
4241 83336195 : int pos;
4242 :
4243 : /* Once we have filled the maximum number of insns the buffer can hold,
4244 : allow the caller to match the insns against peepholes. We wait until
4245 : the buffer is full in case the target has similar peepholes of different
4246 : length; we always want to match the longest if possible. */
4247 83336195 : if (peep2_current_count == MAX_INSNS_PER_PEEP2)
4248 : return false;
4249 :
4250 : /* If an insn has RTX_FRAME_RELATED_P set, do not allow it to be matched with
4251 : any other pattern, lest it change the semantics of the frame info. */
4252 64282129 : if (RTX_FRAME_RELATED_P (insn))
4253 : {
4254 : /* Let the buffer drain first. */
4255 7787553 : if (peep2_current_count > 0)
4256 : return false;
4257 : /* Now the insn will be the only thing in the buffer. */
4258 : }
4259 :
4260 59939216 : pos = peep2_buf_position (peep2_current + peep2_current_count);
4261 59939216 : peep2_insn_data[pos].insn = insn;
4262 59939216 : COPY_REG_SET (peep2_insn_data[pos].live_before, live);
4263 59939216 : peep2_current_count++;
4264 :
4265 59939216 : df_simulate_one_insn_forwards (bb, insn, live);
4266 59939216 : return true;
4267 : }
4268 :
4269 : /* Perform the peephole2 optimization pass. */
4270 :
4271 : static void
4272 976479 : peephole2_optimize (void)
4273 : {
4274 976479 : rtx_insn *insn;
4275 976479 : bitmap live;
4276 976479 : int i;
4277 976479 : basic_block bb;
4278 :
4279 976479 : peep2_do_cleanup_cfg = false;
4280 976479 : peep2_do_rebuild_jump_labels = false;
4281 :
4282 976479 : df_set_flags (DF_LR_RUN_DCE);
4283 976479 : df_note_add_problem ();
4284 976479 : df_analyze ();
4285 :
4286 : /* Initialize the regsets we're going to use. */
4287 8788311 : for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4288 6835353 : peep2_insn_data[i].live_before = BITMAP_ALLOC (®_obstack);
4289 976479 : search_ofs = 0;
4290 976479 : live = BITMAP_ALLOC (®_obstack);
4291 :
4292 11937669 : FOR_EACH_BB_REVERSE_FN (bb, cfun)
4293 : {
4294 10961190 : bool past_end = false;
4295 10961190 : int pos;
4296 :
4297 10961190 : rtl_profile_for_bb (bb);
4298 :
4299 : /* Start up propagation. */
4300 21922380 : bitmap_copy (live, DF_LR_IN (bb));
4301 10961190 : df_simulate_initialize_forwards (bb, live);
4302 10961190 : peep2_reinit_state (live);
4303 :
4304 10961190 : insn = BB_HEAD (bb);
4305 208912676 : for (;;)
4306 : {
4307 208912676 : rtx_insn *attempt, *head;
4308 208912676 : int match_len;
4309 :
4310 208912676 : if (!past_end && !NONDEBUG_INSN_P (insn))
4311 : {
4312 75434904 : next_insn:
4313 135374120 : insn = NEXT_INSN (insn);
4314 135374120 : if (insn == NEXT_INSN (BB_END (bb)))
4315 10961190 : past_end = true;
4316 137629587 : continue;
4317 : }
4318 83336195 : if (!past_end && peep2_fill_buffer (bb, insn, live))
4319 59939216 : goto next_insn;
4320 :
4321 : /* If we did not fill an empty buffer, it signals the end of the
4322 : block. */
4323 73538556 : if (peep2_current_count == 0)
4324 : break;
4325 :
4326 : /* The buffer filled to the current maximum, so try to match. */
4327 :
4328 62577366 : pos = peep2_buf_position (peep2_current + peep2_current_count);
4329 62577366 : peep2_insn_data[pos].insn = PEEP2_EOB;
4330 62577366 : COPY_REG_SET (peep2_insn_data[pos].live_before, live);
4331 :
4332 : /* Match the peephole. */
4333 62577366 : head = peep2_insn_data[peep2_current].insn;
4334 62577366 : attempt = peephole2_insns (PATTERN (head), head, &match_len);
4335 62577366 : if (attempt != NULL)
4336 : {
4337 2258263 : rtx_insn *last = peep2_attempt (bb, head, match_len, attempt);
4338 2258263 : if (last)
4339 : {
4340 2255467 : peep2_update_life (bb, match_len, last, PREV_INSN (attempt));
4341 2255467 : continue;
4342 : }
4343 : }
4344 :
4345 : /* No match: advance the buffer by one insn. */
4346 60321899 : peep2_current = peep2_buf_position (peep2_current + 1);
4347 60321899 : peep2_current_count--;
4348 : }
4349 : }
4350 :
4351 976479 : default_rtl_profile ();
4352 8788311 : for (i = 0; i < MAX_INSNS_PER_PEEP2 + 1; ++i)
4353 6835353 : BITMAP_FREE (peep2_insn_data[i].live_before);
4354 976479 : BITMAP_FREE (live);
4355 976479 : if (peep2_do_rebuild_jump_labels)
4356 740 : rebuild_jump_labels (get_insns ());
4357 976479 : if (peep2_do_cleanup_cfg)
4358 0 : cleanup_cfg (CLEANUP_CFG_CHANGED);
4359 976479 : }
4360 :
4361 : /* Common predicates for use with define_bypass. */
4362 :
4363 : /* Helper function for store_data_bypass_p, handle just a single SET
4364 : IN_SET. */
4365 :
4366 : static bool
4367 0 : store_data_bypass_p_1 (rtx_insn *out_insn, rtx in_set)
4368 : {
4369 0 : if (!MEM_P (SET_DEST (in_set)))
4370 : return false;
4371 :
4372 0 : rtx out_set = single_set (out_insn);
4373 0 : if (out_set)
4374 0 : return !reg_mentioned_p (SET_DEST (out_set), SET_DEST (in_set));
4375 :
4376 0 : rtx out_pat = PATTERN (out_insn);
4377 0 : if (GET_CODE (out_pat) != PARALLEL)
4378 : return false;
4379 :
4380 0 : for (int i = 0; i < XVECLEN (out_pat, 0); i++)
4381 : {
4382 0 : rtx out_exp = XVECEXP (out_pat, 0, i);
4383 :
4384 0 : if (GET_CODE (out_exp) == CLOBBER || GET_CODE (out_exp) == USE)
4385 0 : continue;
4386 :
4387 0 : gcc_assert (GET_CODE (out_exp) == SET);
4388 :
4389 0 : if (reg_mentioned_p (SET_DEST (out_exp), SET_DEST (in_set)))
4390 : return false;
4391 : }
4392 :
4393 : return true;
4394 : }
4395 :
4396 : /* True if the dependency between OUT_INSN and IN_INSN is on the store
4397 : data not the address operand(s) of the store. IN_INSN and OUT_INSN
4398 : must be either a single_set or a PARALLEL with SETs inside. */
4399 :
4400 : bool
4401 0 : store_data_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
4402 : {
4403 0 : rtx in_set = single_set (in_insn);
4404 0 : if (in_set)
4405 0 : return store_data_bypass_p_1 (out_insn, in_set);
4406 :
4407 0 : rtx in_pat = PATTERN (in_insn);
4408 0 : if (GET_CODE (in_pat) != PARALLEL)
4409 : return false;
4410 :
4411 0 : for (int i = 0; i < XVECLEN (in_pat, 0); i++)
4412 : {
4413 0 : rtx in_exp = XVECEXP (in_pat, 0, i);
4414 :
4415 0 : if (GET_CODE (in_exp) == CLOBBER || GET_CODE (in_exp) == USE)
4416 0 : continue;
4417 :
4418 0 : gcc_assert (GET_CODE (in_exp) == SET);
4419 :
4420 0 : if (!store_data_bypass_p_1 (out_insn, in_exp))
4421 : return false;
4422 : }
4423 :
4424 : return true;
4425 : }
4426 :
4427 : /* True if the dependency between OUT_INSN and IN_INSN is in the IF_THEN_ELSE
4428 : condition, and not the THEN or ELSE branch. OUT_INSN may be either a single
4429 : or multiple set; IN_INSN should be single_set for truth, but for convenience
4430 : of insn categorization may be any JUMP or CALL insn. */
4431 :
4432 : bool
4433 0 : if_test_bypass_p (rtx_insn *out_insn, rtx_insn *in_insn)
4434 : {
4435 0 : rtx out_set, in_set;
4436 :
4437 0 : in_set = single_set (in_insn);
4438 0 : if (! in_set)
4439 : {
4440 0 : gcc_assert (JUMP_P (in_insn) || CALL_P (in_insn));
4441 : return false;
4442 : }
4443 :
4444 0 : if (GET_CODE (SET_SRC (in_set)) != IF_THEN_ELSE)
4445 : return false;
4446 0 : in_set = SET_SRC (in_set);
4447 :
4448 0 : out_set = single_set (out_insn);
4449 0 : if (out_set)
4450 : {
4451 0 : if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
4452 0 : || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
4453 0 : return false;
4454 : }
4455 : else
4456 : {
4457 0 : rtx out_pat;
4458 0 : int i;
4459 :
4460 0 : out_pat = PATTERN (out_insn);
4461 0 : gcc_assert (GET_CODE (out_pat) == PARALLEL);
4462 :
4463 0 : for (i = 0; i < XVECLEN (out_pat, 0); i++)
4464 : {
4465 0 : rtx exp = XVECEXP (out_pat, 0, i);
4466 :
4467 0 : if (GET_CODE (exp) == CLOBBER)
4468 0 : continue;
4469 :
4470 0 : gcc_assert (GET_CODE (exp) == SET);
4471 :
4472 0 : if (reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 1))
4473 0 : || reg_mentioned_p (SET_DEST (out_set), XEXP (in_set, 2)))
4474 0 : return false;
4475 : }
4476 : }
4477 :
4478 : return true;
4479 : }
4480 :
4481 : static unsigned int
4482 976479 : rest_of_handle_peephole2 (void)
4483 : {
4484 976479 : if (HAVE_peephole2)
4485 0 : peephole2_optimize ();
4486 :
4487 976479 : return 0;
4488 : }
4489 :
4490 : namespace {
4491 :
4492 : const pass_data pass_data_peephole2 =
4493 : {
4494 : RTL_PASS, /* type */
4495 : "peephole2", /* name */
4496 : OPTGROUP_NONE, /* optinfo_flags */
4497 : TV_PEEPHOLE2, /* tv_id */
4498 : 0, /* properties_required */
4499 : 0, /* properties_provided */
4500 : 0, /* properties_destroyed */
4501 : 0, /* todo_flags_start */
4502 : TODO_df_finish, /* todo_flags_finish */
4503 : };
4504 :
4505 : class pass_peephole2 : public rtl_opt_pass
4506 : {
4507 : public:
4508 292371 : pass_peephole2 (gcc::context *ctxt)
4509 584742 : : rtl_opt_pass (pass_data_peephole2, ctxt)
4510 : {}
4511 :
4512 : /* opt_pass methods: */
4513 : /* The epiphany backend creates a second instance of this pass, so we need
4514 : a clone method. */
4515 0 : opt_pass * clone () final override { return new pass_peephole2 (m_ctxt); }
4516 1504958 : bool gate (function *) final override
4517 : {
4518 1504958 : return (optimize > 0 && flag_peephole2);
4519 : }
4520 976479 : unsigned int execute (function *) final override
4521 : {
4522 976479 : return rest_of_handle_peephole2 ();
4523 : }
4524 :
4525 : }; // class pass_peephole2
4526 :
4527 : } // anon namespace
4528 :
4529 : rtl_opt_pass *
4530 292371 : make_pass_peephole2 (gcc::context *ctxt)
4531 : {
4532 292371 : return new pass_peephole2 (ctxt);
4533 : }
4534 :
4535 : namespace {
4536 :
4537 : const pass_data pass_data_split_all_insns =
4538 : {
4539 : RTL_PASS, /* type */
4540 : "split1", /* name */
4541 : OPTGROUP_NONE, /* optinfo_flags */
4542 : TV_NONE, /* tv_id */
4543 : 0, /* properties_required */
4544 : PROP_rtl_split_insns, /* properties_provided */
4545 : 0, /* properties_destroyed */
4546 : 0, /* todo_flags_start */
4547 : 0, /* todo_flags_finish */
4548 : };
4549 :
4550 : class pass_split_all_insns : public rtl_opt_pass
4551 : {
4552 : public:
4553 292371 : pass_split_all_insns (gcc::context *ctxt)
4554 584742 : : rtl_opt_pass (pass_data_split_all_insns, ctxt)
4555 : {}
4556 :
4557 : /* opt_pass methods: */
4558 : /* The epiphany backend creates a second instance of this pass, so
4559 : we need a clone method. */
4560 0 : opt_pass * clone () final override
4561 : {
4562 0 : return new pass_split_all_insns (m_ctxt);
4563 : }
4564 1504948 : unsigned int execute (function *) final override
4565 : {
4566 1504948 : split_all_insns ();
4567 1504948 : return 0;
4568 : }
4569 :
4570 : }; // class pass_split_all_insns
4571 :
4572 : } // anon namespace
4573 :
4574 : rtl_opt_pass *
4575 292371 : make_pass_split_all_insns (gcc::context *ctxt)
4576 : {
4577 292371 : return new pass_split_all_insns (ctxt);
4578 : }
4579 :
4580 : namespace {
4581 :
4582 : const pass_data pass_data_split_after_reload =
4583 : {
4584 : RTL_PASS, /* type */
4585 : "split2", /* name */
4586 : OPTGROUP_NONE, /* optinfo_flags */
4587 : TV_NONE, /* tv_id */
4588 : 0, /* properties_required */
4589 : 0, /* properties_provided */
4590 : 0, /* properties_destroyed */
4591 : 0, /* todo_flags_start */
4592 : 0, /* todo_flags_finish */
4593 : };
4594 :
4595 : class pass_split_after_reload : public rtl_opt_pass
4596 : {
4597 : public:
4598 292371 : pass_split_after_reload (gcc::context *ctxt)
4599 584742 : : rtl_opt_pass (pass_data_split_after_reload, ctxt)
4600 : {}
4601 :
4602 : /* opt_pass methods: */
4603 1504958 : bool gate (function *) final override
4604 : {
4605 : /* If optimizing, then go ahead and split insns now. */
4606 1504958 : return optimize > 0;
4607 : }
4608 :
4609 1057059 : unsigned int execute (function *) final override
4610 : {
4611 1057059 : split_all_insns ();
4612 1057059 : return 0;
4613 : }
4614 :
4615 : }; // class pass_split_after_reload
4616 :
4617 : } // anon namespace
4618 :
4619 : rtl_opt_pass *
4620 292371 : make_pass_split_after_reload (gcc::context *ctxt)
4621 : {
4622 292371 : return new pass_split_after_reload (ctxt);
4623 : }
4624 :
4625 : static bool
4626 3009916 : enable_split_before_sched2 (void)
4627 : {
4628 : #ifdef INSN_SCHEDULING
4629 2114120 : return optimize > 0 && flag_schedule_insns_after_reload;
4630 : #else
4631 : return false;
4632 : #endif
4633 : }
4634 :
4635 : namespace {
4636 :
4637 : const pass_data pass_data_split_before_sched2 =
4638 : {
4639 : RTL_PASS, /* type */
4640 : "split3", /* name */
4641 : OPTGROUP_NONE, /* optinfo_flags */
4642 : TV_NONE, /* tv_id */
4643 : 0, /* properties_required */
4644 : 0, /* properties_provided */
4645 : 0, /* properties_destroyed */
4646 : 0, /* todo_flags_start */
4647 : 0, /* todo_flags_finish */
4648 : };
4649 :
4650 : class pass_split_before_sched2 : public rtl_opt_pass
4651 : {
4652 : public:
4653 292371 : pass_split_before_sched2 (gcc::context *ctxt)
4654 584742 : : rtl_opt_pass (pass_data_split_before_sched2, ctxt)
4655 : {}
4656 :
4657 : /* opt_pass methods: */
4658 1504958 : bool gate (function *) final override
4659 : {
4660 1504958 : return enable_split_before_sched2 ();
4661 : }
4662 :
4663 976472 : unsigned int execute (function *) final override
4664 : {
4665 976472 : split_all_insns ();
4666 976472 : return 0;
4667 : }
4668 :
4669 : }; // class pass_split_before_sched2
4670 :
4671 : } // anon namespace
4672 :
4673 : rtl_opt_pass *
4674 292371 : make_pass_split_before_sched2 (gcc::context *ctxt)
4675 : {
4676 292371 : return new pass_split_before_sched2 (ctxt);
4677 : }
4678 :
4679 : namespace {
4680 :
4681 : const pass_data pass_data_split_before_regstack =
4682 : {
4683 : RTL_PASS, /* type */
4684 : "split4", /* name */
4685 : OPTGROUP_NONE, /* optinfo_flags */
4686 : TV_NONE, /* tv_id */
4687 : 0, /* properties_required */
4688 : 0, /* properties_provided */
4689 : 0, /* properties_destroyed */
4690 : 0, /* todo_flags_start */
4691 : 0, /* todo_flags_finish */
4692 : };
4693 :
4694 : class pass_split_before_regstack : public rtl_opt_pass
4695 : {
4696 : public:
4697 292371 : pass_split_before_regstack (gcc::context *ctxt)
4698 584742 : : rtl_opt_pass (pass_data_split_before_regstack, ctxt)
4699 : {}
4700 :
4701 : /* opt_pass methods: */
4702 : bool gate (function *) final override;
4703 528566 : unsigned int execute (function *) final override
4704 : {
4705 528566 : split_all_insns ();
4706 528566 : return 0;
4707 : }
4708 :
4709 : }; // class pass_split_before_regstack
4710 :
4711 : bool
4712 1504958 : pass_split_before_regstack::gate (function *)
4713 : {
4714 : #if HAVE_ATTR_length && defined (STACK_REGS)
4715 : /* If flow2 creates new instructions which need splitting
4716 : and scheduling after reload is not done, they might not be
4717 : split until final which doesn't allow splitting
4718 : if HAVE_ATTR_length. Selective scheduling can result in
4719 : further instructions that need splitting. */
4720 : #ifdef INSN_SCHEDULING
4721 2481431 : return !enable_split_before_sched2 () || flag_selective_scheduling2;
4722 : #else
4723 : return !enable_split_before_sched2 ();
4724 : #endif
4725 : #else
4726 : return false;
4727 : #endif
4728 : }
4729 :
4730 : } // anon namespace
4731 :
4732 : rtl_opt_pass *
4733 292371 : make_pass_split_before_regstack (gcc::context *ctxt)
4734 : {
4735 292371 : return new pass_split_before_regstack (ctxt);
4736 : }
4737 :
4738 : namespace {
4739 :
4740 : const pass_data pass_data_split_for_shorten_branches =
4741 : {
4742 : RTL_PASS, /* type */
4743 : "split5", /* name */
4744 : OPTGROUP_NONE, /* optinfo_flags */
4745 : TV_NONE, /* tv_id */
4746 : 0, /* properties_required */
4747 : 0, /* properties_provided */
4748 : 0, /* properties_destroyed */
4749 : 0, /* todo_flags_start */
4750 : 0, /* todo_flags_finish */
4751 : };
4752 :
4753 : class pass_split_for_shorten_branches : public rtl_opt_pass
4754 : {
4755 : public:
4756 292371 : pass_split_for_shorten_branches (gcc::context *ctxt)
4757 584742 : : rtl_opt_pass (pass_data_split_for_shorten_branches, ctxt)
4758 : {}
4759 :
4760 : /* opt_pass methods: */
4761 1504958 : bool gate (function *) final override
4762 : {
4763 : /* The placement of the splitting that we do for shorten_branches
4764 : depends on whether regstack is used by the target or not. */
4765 : #if HAVE_ATTR_length && !defined (STACK_REGS)
4766 : return true;
4767 : #else
4768 1504958 : return false;
4769 : #endif
4770 : }
4771 :
4772 0 : unsigned int execute (function *) final override
4773 : {
4774 0 : split_all_insns_noflow ();
4775 0 : return 0;
4776 : }
4777 :
4778 : }; // class pass_split_for_shorten_branches
4779 :
4780 : } // anon namespace
4781 :
4782 : rtl_opt_pass *
4783 292371 : make_pass_split_for_shorten_branches (gcc::context *ctxt)
4784 : {
4785 292371 : return new pass_split_for_shorten_branches (ctxt);
4786 : }
4787 :
4788 : /* (Re)initialize the target information after a change in target. */
4789 :
4790 : void
4791 218792 : recog_init ()
4792 : {
4793 : /* The information is zero-initialized, so we don't need to do anything
4794 : first time round. */
4795 218792 : if (!this_target_recog->x_initialized)
4796 : {
4797 217732 : this_target_recog->x_initialized = true;
4798 217732 : return;
4799 : }
4800 1060 : memset (this_target_recog->x_bool_attr_masks, 0,
4801 : sizeof (this_target_recog->x_bool_attr_masks));
4802 16140620 : for (unsigned int i = 0; i < NUM_INSN_CODES; ++i)
4803 16139560 : if (this_target_recog->x_op_alt[i])
4804 : {
4805 10172 : free (this_target_recog->x_op_alt[i]);
4806 10172 : this_target_recog->x_op_alt[i] = 0;
4807 : }
4808 : }
|