LCOV - code coverage report
Current view: top level - gcc - recog.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.6 % 1900 1645
Test Date: 2026-10-17 16:30:31 Functions: 86.3 % 124 107
Legend: Lines:     hit not hit

            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, &reg);
     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 (&reg_obstack);
    4291       988533 :   search_ofs = 0;
    4292       988533 :   live = BITMAP_ALLOC (&reg_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              : }
        

Generated by: LCOV version 2.5.0-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.