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