LCOV - code coverage report
Current view: top level - gcc - lra-eliminations.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.8 % 690 578
Test Date: 2026-02-28 14:20:25 Functions: 95.5 % 22 21
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Code for RTL register eliminations.
       2              :    Copyright (C) 2010-2026 Free Software Foundation, Inc.
       3              :    Contributed by Vladimir Makarov <vmakarov@redhat.com>.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.    */
      20              : 
      21              : /* Eliminable registers (like a soft argument or frame pointer) are
      22              :    widely used in RTL.  These eliminable registers should be replaced
      23              :    by real hard registers (like the stack pointer or hard frame
      24              :    pointer) plus some offset.  The offsets usually change whenever the
      25              :    stack is expanded.  We know the final offsets only at the very end
      26              :    of LRA.
      27              : 
      28              :    Within LRA, we usually keep the RTL in such a state that the
      29              :    eliminable registers can be replaced by just the corresponding hard
      30              :    register (without any offset).  To achieve this we should add the
      31              :    initial elimination offset at the beginning of LRA and update the
      32              :    offsets whenever the stack is expanded.  We need to do this before
      33              :    every constraint pass because the choice of offset often affects
      34              :    whether a particular address or memory constraint is satisfied.
      35              : 
      36              :    We keep RTL code at most time in such state that the virtual
      37              :    registers can be changed by just the corresponding hard registers
      38              :    (with zero offsets) and we have the right RTL code.  To achieve this
      39              :    we should add initial offset at the beginning of LRA work and update
      40              :    offsets after each stack expanding.  But actually we update virtual
      41              :    registers to the same virtual registers + corresponding offsets
      42              :    before every constraint pass because it affects constraint
      43              :    satisfaction (e.g. an address displacement became too big for some
      44              :    target).
      45              : 
      46              :    The final change of eliminable registers to the corresponding hard
      47              :    registers are done at the very end of LRA when there were no change
      48              :    in offsets anymore:
      49              : 
      50              :                      fp + 42     =>  sp + 42
      51              : 
      52              : */
      53              : 
      54              : #include "config.h"
      55              : #include "system.h"
      56              : #include "coretypes.h"
      57              : #include "backend.h"
      58              : #include "target.h"
      59              : #include "rtl.h"
      60              : #include "tree.h"
      61              : #include "df.h"
      62              : #include "memmodel.h"
      63              : #include "tm_p.h"
      64              : #include "optabs.h"
      65              : #include "regs.h"
      66              : #include "ira.h"
      67              : #include "recog.h"
      68              : #include "output.h"
      69              : #include "rtl-error.h"
      70              : #include "lra-int.h"
      71              : 
      72              : /* This structure is used to record information about hard register
      73              :    eliminations.  */
      74              : class lra_elim_table
      75              : {
      76              : public:
      77              :   /* Hard register number to be eliminated.  */
      78              :   int from;
      79              :   /* Hard register number used as replacement.  */
      80              :   int to;
      81              :   /* Difference between values of the two hard registers above on
      82              :      previous iteration.  */
      83              :   poly_int64 previous_offset;
      84              :   /* Difference between the values on the current iteration.  */
      85              :   poly_int64 offset;
      86              :   /* Nonzero if this elimination can be done.  */
      87              :   bool can_eliminate;
      88              :   /* CAN_ELIMINATE since the last check.  */
      89              :   bool prev_can_eliminate;
      90              :   /* REG rtx for the register to be eliminated.  We cannot simply
      91              :      compare the number since we might then spuriously replace a hard
      92              :      register corresponding to a pseudo assigned to the reg to be
      93              :      eliminated.  */
      94              :   rtx from_rtx;
      95              :   /* REG rtx for the replacement.  */
      96              :   rtx to_rtx;
      97              : };
      98              : 
      99              : /* The elimination table.  Each array entry describes one possible way
     100              :    of eliminating a register in favor of another.  If there is more
     101              :    than one way of eliminating a particular register, the most
     102              :    preferred should be specified first.  */
     103              : static class lra_elim_table *reg_eliminate = 0;
     104              : 
     105              : /* This is an intermediate structure to initialize the table.  It has
     106              :    exactly the members provided by ELIMINABLE_REGS.  */
     107              : static const struct elim_table_1
     108              : {
     109              :   const int from;
     110              :   const int to;
     111              : } reg_eliminate_1[] =
     112              : 
     113              :   ELIMINABLE_REGS;
     114              : 
     115              : #define NUM_ELIMINABLE_REGS ARRAY_SIZE (reg_eliminate_1)
     116              : 
     117              : /* Print info about elimination table to file F.  */
     118              : static void
     119          194 : print_elim_table (FILE *f)
     120              : {
     121          194 :   class lra_elim_table *ep;
     122              : 
     123          970 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     124              :     {
     125          776 :       fprintf (f, "%s eliminate %d to %d (offset=",
     126          776 :                ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
     127          776 :       print_dec (ep->offset, f);
     128          776 :       fprintf (f, ", prev_offset=");
     129          776 :       print_dec (ep->previous_offset, f);
     130          776 :       fprintf (f, ")\n");
     131              :     }
     132          194 : }
     133              : 
     134              : /* Print info about elimination table to stderr.  */
     135              : void
     136            0 : lra_debug_elim_table (void)
     137              : {
     138            0 :   print_elim_table (stderr);
     139            0 : }
     140              : 
     141              : /* Setup possibility of elimination in elimination table element EP to
     142              :    VALUE.  Setup FRAME_POINTER_NEEDED if elimination from frame
     143              :    pointer to stack pointer is not possible anymore.  */
     144              : static void
     145     38292098 : setup_can_eliminate (class lra_elim_table *ep, bool value)
     146              : {
     147     38292098 :   ep->can_eliminate = ep->prev_can_eliminate = value;
     148     38292098 :   if (! value
     149      6326064 :       && ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
     150      2796919 :     frame_pointer_needed = 1;
     151     38292098 :   if (!frame_pointer_needed)
     152     25724885 :     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 0;
     153     38292098 : }
     154              : 
     155              : /* Map: eliminable "from" register -> its current elimination,
     156              :    or NULL if none.  The elimination table may contain more than
     157              :    one elimination for the same hard register, but this map specifies
     158              :    the one that we are currently using.  */
     159              : static class lra_elim_table *elimination_map[FIRST_PSEUDO_REGISTER];
     160              : 
     161              : /* When an eliminable hard register becomes not eliminable, we use the
     162              :    following special structure to restore original offsets for the
     163              :    register.  */
     164              : static class lra_elim_table self_elim_table;
     165              : 
     166              : /* Offsets should be used to restore original offsets for eliminable
     167              :    hard register which just became not eliminable.  Zero,
     168              :    otherwise.  */
     169              : static poly_int64 self_elim_offsets[FIRST_PSEUDO_REGISTER];
     170              : 
     171              : /* Map: hard regno -> RTL presentation.       RTL presentations of all
     172              :    potentially eliminable hard registers are stored in the map.  */
     173              : static rtx eliminable_reg_rtx[FIRST_PSEUDO_REGISTER];
     174              : 
     175              : /* Set up ELIMINATION_MAP of the currently used eliminations.  */
     176              : static void
     177      9554359 : setup_elimination_map (void)
     178              : {
     179      9554359 :   int i;
     180      9554359 :   class lra_elim_table *ep;
     181              : 
     182    888555387 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     183    879001028 :     elimination_map[i] = NULL;
     184     47771795 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     185     38217436 :     if (ep->can_eliminate && elimination_map[ep->from] == NULL)
     186     19108718 :       elimination_map[ep->from] = ep;
     187      9554359 : }
     188              : 
     189              : 
     190              : 
     191              : /* Compute the sum of X and Y, making canonicalizations assumed in an
     192              :    address, namely: sum constant integers, surround the sum of two
     193              :    constants with a CONST, put the constant as the second operand, and
     194              :    group the constant on the outermost sum.
     195              : 
     196              :    This routine assumes both inputs are already in canonical form.  */
     197              : static rtx
     198      1718462 : form_sum (rtx x, rtx y)
     199              : {
     200      2085642 :   machine_mode mode = GET_MODE (x);
     201      2085642 :   poly_int64 offset;
     202              : 
     203      2085642 :   if (mode == VOIDmode)
     204       119404 :     mode = GET_MODE (y);
     205              : 
     206      2085642 :   if (mode == VOIDmode)
     207            0 :     mode = Pmode;
     208              : 
     209      2085642 :   if (poly_int_rtx_p (x, &offset))
     210       119404 :     return plus_constant (mode, y, offset);
     211      1966238 :   else if (poly_int_rtx_p (y, &offset))
     212      1079666 :     return plus_constant (mode, x, offset);
     213       886572 :   else if (CONSTANT_P (x))
     214           14 :     std::swap (x, y);
     215              : 
     216       886572 :   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
     217       119418 :     return form_sum (XEXP (x, 0), form_sum (XEXP (x, 1), y));
     218              : 
     219              :   /* Note that if the operands of Y are specified in the opposite
     220              :      order in the recursive calls below, infinite recursion will
     221              :      occur.  */
     222       767154 :   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
     223       247762 :     return form_sum (form_sum (x, XEXP (y, 0)), XEXP (y, 1));
     224              : 
     225              :   /* If both constant, encapsulate sum.  Otherwise, just form sum.  A
     226              :      constant will have been placed second.  */
     227       519392 :   if (CONSTANT_P (x) && CONSTANT_P (y))
     228              :     {
     229            0 :       if (GET_CODE (x) == CONST)
     230            0 :         x = XEXP (x, 0);
     231            0 :       if (GET_CODE (y) == CONST)
     232            0 :         y = XEXP (y, 0);
     233              : 
     234            0 :       return gen_rtx_CONST (VOIDmode, gen_rtx_PLUS (mode, x, y));
     235              :     }
     236              : 
     237       519392 :   return gen_rtx_PLUS (mode, x, y);
     238              : }
     239              : 
     240              : /* Return the current substitution hard register of the elimination of
     241              :    HARD_REGNO.  If HARD_REGNO is not eliminable, return itself.  */
     242              : int
     243    120539787 : lra_get_elimination_hard_regno (int hard_regno)
     244              : {
     245    120539787 :   class lra_elim_table *ep;
     246              : 
     247    120539787 :   if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     248              :     return hard_regno;
     249    120539787 :   if ((ep = elimination_map[hard_regno]) == NULL)
     250              :     return hard_regno;
     251     32041562 :   return ep->to;
     252              : }
     253              : 
     254              : /* Return elimination which will be used for hard reg REG, NULL
     255              :    otherwise.  */
     256              : static class lra_elim_table *
     257    163536975 : get_elimination (rtx reg)
     258              : {
     259    163536975 :   int hard_regno;
     260    163536975 :   class lra_elim_table *ep;
     261              : 
     262    163536975 :   lra_assert (REG_P (reg));
     263    163536975 :   if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     264              :     return NULL;
     265    135746144 :   if ((ep = elimination_map[hard_regno]) != NULL)
     266    129926843 :     return ep->from_rtx != reg ? NULL : ep;
     267      5819301 :   poly_int64 offset = self_elim_offsets[hard_regno];
     268      5819301 :   if (known_eq (offset, 0))
     269              :     return NULL;
     270              :   /* This is an iteration to restore offsets just after HARD_REGNO
     271              :      stopped to be eliminable.  */
     272            0 :   self_elim_table.from = self_elim_table.to = hard_regno;
     273            0 :   self_elim_table.from_rtx
     274            0 :     = self_elim_table.to_rtx
     275            0 :     = eliminable_reg_rtx[hard_regno];
     276            0 :   lra_assert (self_elim_table.from_rtx != NULL);
     277            0 :   self_elim_table.offset = offset;
     278            0 :   return &self_elim_table;
     279              : }
     280              : 
     281              : /* Transform (subreg (plus reg const)) to (plus (subreg reg) const)
     282              :    when it is possible.  Return X or the transformation result if the
     283              :    transformation is done.  */
     284              : static rtx
     285      2884476 : move_plus_up (rtx x)
     286              : {
     287      2884476 :   rtx subreg_reg;
     288      2884476 :   machine_mode x_mode, subreg_reg_mode;
     289              : 
     290      2884476 :   if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
     291      2884378 :     return x;
     292           98 :   subreg_reg = SUBREG_REG (x);
     293           98 :   x_mode = GET_MODE (x);
     294           98 :   subreg_reg_mode = GET_MODE (subreg_reg);
     295           98 :   if (!paradoxical_subreg_p (x)
     296           98 :       && GET_CODE (subreg_reg) == PLUS
     297            4 :       && CONSTANT_P (XEXP (subreg_reg, 1))
     298            4 :       && GET_MODE_CLASS (x_mode) == MODE_INT
     299          102 :       && GET_MODE_CLASS (subreg_reg_mode) == MODE_INT)
     300              :     {
     301            2 :       rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
     302              :                                  subreg_lowpart_offset (x_mode,
     303              :                                                         subreg_reg_mode));
     304            2 :       if (cst && CONSTANT_P (cst))
     305              :         {
     306            2 :           rtx lowpart = lowpart_subreg (x_mode, XEXP (subreg_reg, 0),
     307              :                                         subreg_reg_mode);
     308            2 :           if (lowpart)
     309            2 :             return gen_rtx_PLUS (x_mode, lowpart, cst);
     310              :         }
     311              :     }
     312              :   return x;
     313              : }
     314              : 
     315              : /* Flag that we already applied nonzero stack pointer elimination
     316              :    offset; such sp updates cannot currently be undone.  */
     317              : static bool elimination_2sp_occurred_p = false;
     318              : 
     319              : /* Take note of any nonzero sp-OFFSET used in eliminations to sp.  */
     320              : static inline poly_int64
     321     13011129 : note_spoff (poly_int64 offset)
     322              : {
     323     13011129 :   if (maybe_ne (offset, 0))
     324      1417636 :     elimination_2sp_occurred_p = true;
     325     12561469 :   return offset;
     326              : }
     327              : 
     328              : /* Scan X and replace any eliminable registers (such as fp) with a
     329              :    replacement (such as sp) if SUBST_P, plus an offset.  The offset is
     330              :    a change in the offset between the eliminable register and its
     331              :    substitution if UPDATE_P, or the full offset if FULL_P, or
     332              :    otherwise zero.  If FULL_P, we also use the SP offsets for
     333              :    elimination to SP.  If UPDATE_P, use UPDATE_SP_OFFSET for updating
     334              :    offsets of register elimnable to SP.  If UPDATE_SP_OFFSET is
     335              :    non-zero, don't use difference of the offset and the previous
     336              :    offset.
     337              : 
     338              :    MEM_MODE is the mode of an enclosing MEM.  We need this to know how
     339              :    much to adjust a register for, e.g., PRE_DEC.  Also, if we are
     340              :    inside a MEM, we are allowed to replace a sum of a hard register
     341              :    and the constant zero with the hard register, which we cannot do
     342              :    outside a MEM.  In addition, we need to record the fact that a
     343              :    hard register is referenced outside a MEM.
     344              : 
     345              :    If we make full substitution to SP for non-null INSN, add the insn
     346              :    sp offset.  */
     347              : rtx
     348    145280949 : lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
     349              :                       bool subst_p, bool update_p,
     350              :                       poly_int64 update_sp_offset, bool full_p)
     351              : {
     352    145280949 :   enum rtx_code code = GET_CODE (x);
     353    145280949 :   class lra_elim_table *ep;
     354    145280949 :   rtx new_rtx;
     355    145280949 :   int i, j;
     356    145280949 :   const char *fmt;
     357    145280949 :   int copied = 0;
     358              : 
     359    145280949 :   lra_assert (!update_p || !full_p);
     360    145280949 :   lra_assert (known_eq (update_sp_offset, 0)
     361              :               || (!subst_p && update_p && !full_p));
     362    145280949 :   if (! current_function_decl)
     363              :     return x;
     364              : 
     365    145280949 :   switch (code)
     366              :     {
     367              :     CASE_CONST_ANY:
     368              :     case CONST:
     369              :     case SYMBOL_REF:
     370              :     case CODE_LABEL:
     371              :     case PC:
     372              :     case ASM_INPUT:
     373              :     case ADDR_VEC:
     374              :     case ADDR_DIFF_VEC:
     375              :     case RETURN:
     376              :       return x;
     377              : 
     378     41189871 :     case REG:
     379              :       /* First handle the case where we encounter a bare hard register
     380              :          that is eliminable.  Replace it with a PLUS.  */
     381     41189871 :       if ((ep = get_elimination (x)) != NULL)
     382              :         {
     383     11333110 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     384              : 
     385     11333110 :           if (maybe_ne (update_sp_offset, 0))
     386              :             {
     387            0 :               if (ep->to_rtx == stack_pointer_rtx)
     388            0 :                 return plus_constant (Pmode, to, note_spoff (update_sp_offset));
     389              :               return to;
     390              :             }
     391     11333110 :           else if (update_p)
     392       800202 :             return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
     393     10603972 :           else if (full_p)
     394     11567906 :             return plus_constant (Pmode, to,
     395      9619774 :                                   ep->offset
     396              :                                   - (insn != NULL_RTX
     397       663227 :                                      && ep->to_rtx == stack_pointer_rtx
     398     10283001 :                                      ? note_spoff (lra_get_insn_recog_data
     399       449660 :                                                    (insn)->sp_offset)
     400              :                                      : 0));
     401              :           else
     402              :             return to;
     403              :         }
     404     29856761 :       return x;
     405              : 
     406     50509143 :     case PLUS:
     407              :       /* If this is the sum of an eliminable register and a constant, rework
     408              :          the sum.  */
     409     50509143 :       if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
     410              :         {
     411     49066905 :           if ((ep = get_elimination (XEXP (x, 0))) != NULL)
     412              :             {
     413     48961896 :               poly_int64 offset, curr_offset;
     414     48961896 :               rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     415              : 
     416     48961896 :               if (! update_p && ! full_p)
     417     22668919 :                 return simplify_gen_binary (PLUS, Pmode, to, XEXP (x, 1));
     418              : 
     419     29647516 :               if (maybe_ne (update_sp_offset, 0))
     420            0 :                 offset = (ep->to_rtx == stack_pointer_rtx
     421            0 :                           ? note_spoff (update_sp_offset)
     422              :                           : 0);
     423              :               else
     424     29647516 :                 offset = (update_p
     425     29647516 :                           ? ep->offset - ep->previous_offset : ep->offset);
     426     29647516 :               if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     427     25122938 :                 offset -= note_spoff (lra_get_insn_recog_data (insn)->sp_offset);
     428     29647516 :               if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
     429     29647516 :                   && known_eq (curr_offset, -offset))
     430              :                 return to;
     431              :               else
     432     39097155 :                 return gen_rtx_PLUS (Pmode, to,
     433              :                                      plus_constant (Pmode,
     434              :                                                     XEXP (x, 1), offset));
     435              :             }
     436              : 
     437              :           /* If the hard register is not eliminable, we are done since
     438              :              the other operand is a constant.  */
     439       105009 :           return x;
     440              :         }
     441              : 
     442              :       /* If this is part of an address, we want to bring any constant
     443              :          to the outermost PLUS.  We will do this by doing hard
     444              :          register replacement in our operands and seeing if a constant
     445              :          shows up in one of them.
     446              : 
     447              :          Note that there is no risk of modifying the structure of the
     448              :          insn, since we only get called for its operands, thus we are
     449              :          either modifying the address inside a MEM, or something like
     450              :          an address operand of a load-address insn.  */
     451              : 
     452      1442238 :       {
     453      1442238 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     454              :                                          subst_p, update_p,
     455              :                                          update_sp_offset, full_p);
     456      1442238 :         rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     457              :                                          subst_p, update_p,
     458              :                                          update_sp_offset, full_p);
     459              : 
     460      1442238 :         new0 = move_plus_up (new0);
     461      1442238 :         new1 = move_plus_up (new1);
     462      1442238 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     463      1351282 :           return form_sum (new0, new1);
     464              :       }
     465              :       return x;
     466              : 
     467       259501 :     case MULT:
     468              :       /* If this is the product of an eliminable hard register and a
     469              :          constant, apply the distribute law and move the constant out
     470              :          so that we have (plus (mult ..) ..).  This is needed in order
     471              :          to keep load-address insns valid.  This case is pathological.
     472              :          We ignore the possibility of overflow here.  */
     473       242373 :       if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
     474       499714 :           && (ep = get_elimination (XEXP (x, 0))) != NULL)
     475              :         {
     476            0 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     477              : 
     478            0 :           if (maybe_ne (update_sp_offset, 0))
     479              :             {
     480            0 :               if (ep->to_rtx == stack_pointer_rtx)
     481            0 :                 return plus_constant (Pmode,
     482            0 :                                       gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     483            0 :                                       note_spoff (update_sp_offset)
     484            0 :                                       * INTVAL (XEXP (x, 1)));
     485            0 :               return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     486              :             }
     487            0 :           else if (update_p)
     488            0 :             return plus_constant (Pmode,
     489            0 :                                   gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     490            0 :                                   (ep->offset - ep->previous_offset)
     491            0 :                                   * INTVAL (XEXP (x, 1)));
     492            0 :           else if (full_p)
     493              :             {
     494            0 :               poly_int64 offset = ep->offset;
     495              : 
     496            0 :               if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     497            0 :                 offset -= note_spoff (lra_get_insn_recog_data (insn)->sp_offset);
     498            0 :               return
     499            0 :                 plus_constant (Pmode,
     500            0 :                                gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     501            0 :                                offset * INTVAL (XEXP (x, 1)));
     502              :             }
     503              :           else
     504            0 :             return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     505              :         }
     506              : 
     507              :       /* fall through */
     508              : 
     509       394899 :     case CALL:
     510       394899 :     case COMPARE:
     511              :     /* See comments before PLUS about handling MINUS.  */
     512       394899 :     case MINUS:
     513       394899 :     case DIV:      case UDIV:
     514       394899 :     case MOD:      case UMOD:
     515       394899 :     case AND:      case IOR:      case XOR:
     516       394899 :     case ROTATERT: case ROTATE:
     517       394899 :     case ASHIFTRT: case LSHIFTRT: case ASHIFT:
     518       394899 :     case NE:       case EQ:
     519       394899 :     case GE:       case GT:       case GEU:    case GTU:
     520       394899 :     case LE:       case LT:       case LEU:    case LTU:
     521       394899 :       {
     522       394899 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     523              :                                          subst_p, update_p,
     524              :                                          update_sp_offset, full_p);
     525       394899 :         rtx new1 = XEXP (x, 1)
     526       394899 :                    ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     527              :                                            subst_p, update_p,
     528              :                                            update_sp_offset, full_p) : 0;
     529              : 
     530       394899 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     531       113441 :           return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
     532              :       }
     533              :       return x;
     534              : 
     535           55 :     case EXPR_LIST:
     536              :       /* If we have something in XEXP (x, 0), the usual case,
     537              :          eliminate it.  */
     538           55 :       if (XEXP (x, 0))
     539              :         {
     540           55 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     541              :                                           subst_p, update_p,
     542              :                                           update_sp_offset, full_p);
     543           55 :           if (new_rtx != XEXP (x, 0))
     544              :             {
     545              :               /* If this is a REG_DEAD note, it is not valid anymore.
     546              :                  Using the eliminated version could result in creating a
     547              :                  REG_DEAD note for the stack or frame pointer.  */
     548            0 :               if (REG_NOTE_KIND (x) == REG_DEAD)
     549            0 :                 return (XEXP (x, 1)
     550            0 :                         ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     551              :                                                 subst_p, update_p,
     552              :                                                 update_sp_offset, full_p)
     553              :                         : NULL_RTX);
     554              : 
     555            0 :               x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
     556              :             }
     557              :         }
     558              : 
     559              :       /* fall through */
     560              : 
     561           55 :     case INSN_LIST:
     562           55 :     case INT_LIST:
     563              :       /* Now do eliminations in the rest of the chain.  If this was
     564              :          an EXPR_LIST, this might result in allocating more memory than is
     565              :          strictly needed, but it simplifies the code.  */
     566           55 :       if (XEXP (x, 1))
     567              :         {
     568           55 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     569              :                                           subst_p, update_p,
     570              :                                           update_sp_offset, full_p);
     571           55 :           if (new_rtx != XEXP (x, 1))
     572            0 :             return
     573            0 :               gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x),
     574              :                               XEXP (x, 0), new_rtx);
     575              :         }
     576           55 :       return x;
     577              : 
     578       534627 :     case PRE_INC:
     579       534627 :     case POST_INC:
     580       534627 :     case PRE_DEC:
     581       534627 :     case POST_DEC:
     582              :       /* Recurse to adjust elimination offsets in a spilled pseudo.  */
     583       534627 :       if (GET_CODE (XEXP (x, 0)) == MEM)
     584              :         break;
     585              :       /* We do not support elimination of a register that is modified.
     586              :          elimination_effects has already make sure that this does not
     587              :          happen.  */
     588              :       return x;
     589              : 
     590          198 :     case PRE_MODIFY:
     591          198 :     case POST_MODIFY:
     592              :       /* Recurse to adjust elimination offsets in a spilled pseudo.  */
     593          198 :       if (GET_CODE (XEXP (x, 0)) == MEM)
     594              :         break;
     595              :       /* We do not support elimination of a hard register that is
     596              :          modified.  LRA has already make sure that this does not
     597              :          happen. The only remaining case we need to consider here is
     598              :          that the increment value may be an eliminable register.  */
     599          198 :       if (GET_CODE (XEXP (x, 1)) == PLUS
     600          198 :           && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
     601              :         {
     602          198 :           rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1),
     603              :                                               mem_mode, subst_p, update_p,
     604              :                                               update_sp_offset, full_p);
     605              : 
     606          198 :           if (new_rtx != XEXP (XEXP (x, 1), 1))
     607            0 :             return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
     608              :                                    gen_rtx_PLUS (GET_MODE (x),
     609              :                                                  XEXP (x, 0), new_rtx));
     610              :         }
     611          198 :       return x;
     612              : 
     613        33835 :     case STRICT_LOW_PART:
     614        33835 :     case NEG:          case NOT:
     615        33835 :     case SIGN_EXTEND:  case ZERO_EXTEND:
     616        33835 :     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
     617        33835 :     case FLOAT:        case FIX:
     618        33835 :     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
     619        33835 :     case ABS:
     620        33835 :     case SQRT:
     621        33835 :     case FFS:
     622        33835 :     case CLZ:
     623        33835 :     case CTZ:
     624        33835 :     case POPCOUNT:
     625        33835 :     case PARITY:
     626        33835 :     case BSWAP:
     627        33835 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     628              :                                       subst_p, update_p,
     629              :                                       update_sp_offset, full_p);
     630        33835 :       if (new_rtx != XEXP (x, 0))
     631        24812 :         return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
     632              :       return x;
     633              : 
     634       609005 :     case SUBREG:
     635       609005 :       new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode,
     636              :                                       subst_p, update_p,
     637              :                                       update_sp_offset, full_p);
     638              : 
     639       609005 :       if (new_rtx != SUBREG_REG (x))
     640              :         {
     641         6430 :           if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
     642              :             {
     643           11 :               SUBREG_REG (x) = new_rtx;
     644           11 :               alter_subreg (&x, false);
     645           11 :               return x;
     646              :             }
     647         6419 :           else if (! subst_p)
     648              :             {
     649              :               /* LRA can transform subregs itself.  So don't call
     650              :                  simplify_gen_subreg until LRA transformations are
     651              :                  finished.  Function simplify_gen_subreg can do
     652              :                  non-trivial transformations (like truncation) which
     653              :                  might make LRA work to fail.  */
     654         4026 :               SUBREG_REG (x) = new_rtx;
     655         4026 :               return x;
     656              :             }
     657              :           else
     658              :             {
     659         4786 :               rtx nx = simplify_gen_subreg (GET_MODE (x), new_rtx,
     660         2393 :                                             GET_MODE (new_rtx), SUBREG_BYTE (x));
     661              :               /* If inside a debug insn, then generate the subreg manually as it might
     662              :                  be an invalid one for outside of a debug insn.  */
     663         2393 :               if (DEBUG_INSN_P (insn) && !nx)
     664            1 :                 nx = gen_rtx_raw_SUBREG (GET_MODE (x), new_rtx, SUBREG_BYTE (x));
     665            7 :               gcc_assert (nx);
     666         2393 :               return nx;
     667              :             }
     668              :         }
     669              : 
     670              :       return x;
     671              : 
     672     44213793 :     case MEM:
     673              :       /* Our only special processing is to pass the mode of the MEM to our
     674              :          recursive call and copy the flags.  While we are here, handle this
     675              :          case more efficiently.  */
     676     44213793 :       return
     677              :         replace_equiv_address_nv
     678     44213793 :         (x,
     679     44213793 :          lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
     680     44213793 :                                subst_p, update_p, update_sp_offset, full_p));
     681              : 
     682            0 :     case USE:
     683              :       /* Handle insn_list USE that a call to a pure function may generate.  */
     684            0 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
     685              :                                       subst_p, update_p, update_sp_offset, full_p);
     686            0 :       if (new_rtx != XEXP (x, 0))
     687            0 :         return gen_rtx_USE (GET_MODE (x), new_rtx);
     688              :       return x;
     689              : 
     690            0 :     case CLOBBER:
     691            0 :     case ASM_OPERANDS:
     692            0 :       gcc_assert (insn && DEBUG_INSN_P (insn));
     693              :       break;
     694              : 
     695            0 :     case SET:
     696            0 :       gcc_unreachable ();
     697              : 
     698              :     default:
     699              :       break;
     700              :     }
     701              : 
     702              :   /* Process each of our operands recursively.  If any have changed, make a
     703              :      copy of the rtx.  */
     704        71708 :   fmt = GET_RTX_FORMAT (code);
     705       156052 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     706              :     {
     707        84344 :       if (*fmt == 'e')
     708              :         {
     709        24104 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
     710              :                                           subst_p, update_p,
     711              :                                           update_sp_offset, full_p);
     712        24104 :           if (new_rtx != XEXP (x, i) && ! copied)
     713              :             {
     714        11335 :               x = shallow_copy_rtx (x);
     715        11335 :               copied = 1;
     716              :             }
     717        24104 :           XEXP (x, i) = new_rtx;
     718              :         }
     719        60240 :       else if (*fmt == 'E')
     720              :         {
     721              :           int copied_vec = 0;
     722        37040 :           for (j = 0; j < XVECLEN (x, i); j++)
     723              :             {
     724        24756 :               new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
     725              :                                               subst_p, update_p,
     726              :                                               update_sp_offset, full_p);
     727        24756 :               if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
     728              :                 {
     729        23280 :                   rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
     730        11640 :                                              XVEC (x, i)->elem);
     731        11640 :                   if (! copied)
     732              :                     {
     733        11640 :                       x = shallow_copy_rtx (x);
     734        11640 :                       copied = 1;
     735              :                     }
     736        11640 :                   XVEC (x, i) = new_v;
     737        11640 :                   copied_vec = 1;
     738              :                 }
     739        24756 :               XVECEXP (x, i, j) = new_rtx;
     740              :             }
     741              :         }
     742              :     }
     743              : 
     744        71708 :   return x;
     745              : }
     746              : 
     747              : /* This function is used externally in subsequent passes of GCC.  It
     748              :    always does a full elimination of X.  */
     749              : rtx
     750      8956547 : lra_eliminate_regs (rtx x, machine_mode mem_mode,
     751              :                     rtx insn ATTRIBUTE_UNUSED)
     752              : {
     753      8956547 :   return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
     754              : }
     755              : 
     756              : /* Stack pointer offset before the current insn relative to one at the
     757              :    func start.  RTL insns can change SP explicitly.  We keep the
     758              :    changes from one insn to another through this variable.  */
     759              : static poly_int64 curr_sp_change;
     760              : 
     761              : /* Scan rtx X for references to elimination source or target registers
     762              :    in contexts that would prevent the elimination from happening.
     763              :    Update the table of eliminables to reflect the changed state.
     764              :    MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not
     765              :    within a MEM.  */
     766              : static void
     767    356389193 : mark_not_eliminable (rtx x, machine_mode mem_mode)
     768              : {
     769    489987644 :   enum rtx_code code = GET_CODE (x);
     770    489987644 :   class lra_elim_table *ep;
     771    489987644 :   int i, j;
     772    489987644 :   const char *fmt;
     773    489987644 :   poly_int64 offset = 0;
     774              : 
     775    489987644 :   switch (code)
     776              :     {
     777      1981224 :     case PRE_INC:
     778      1981224 :     case POST_INC:
     779      1981224 :     case PRE_DEC:
     780      1981224 :     case POST_DEC:
     781      1981224 :     case POST_MODIFY:
     782      1981224 :     case PRE_MODIFY:
     783      1981224 :       if (XEXP (x, 0) == stack_pointer_rtx
     784      1981224 :           && ((code != PRE_MODIFY && code != POST_MODIFY)
     785       107321 :               || (GET_CODE (XEXP (x, 1)) == PLUS
     786       107321 :                   && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
     787       107321 :                   && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
     788              :         {
     789      3962448 :           poly_int64 size = GET_MODE_SIZE (mem_mode);
     790              : 
     791              : #ifdef PUSH_ROUNDING
     792              :           /* If more bytes than MEM_MODE are pushed, account for
     793              :              them.  */
     794      1981224 :           size = PUSH_ROUNDING (size);
     795              : #endif
     796      1981224 :           if (code == PRE_DEC || code == POST_DEC)
     797    356389193 :             curr_sp_change -= size;
     798       107365 :           else if (code == PRE_INC || code == POST_INC)
     799    356389193 :             curr_sp_change += size;
     800       107321 :           else if (code == PRE_MODIFY || code == POST_MODIFY)
     801    356389193 :             curr_sp_change += offset;
     802              :         }
     803            0 :       else if (REG_P (XEXP (x, 0))
     804            0 :                && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
     805              :         {
     806              :           /* If we modify the source of an elimination rule, disable
     807              :              it.  Do the same if it is the destination and not the
     808              :              hard frame register.  */
     809            0 :           for (ep = reg_eliminate;
     810            0 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     811              :                ep++)
     812            0 :             if (ep->from_rtx == XEXP (x, 0)
     813            0 :                 || (ep->to_rtx == XEXP (x, 0)
     814            0 :                     && ep->to_rtx != hard_frame_pointer_rtx))
     815            0 :               setup_can_eliminate (ep, false);
     816              :         }
     817              :       return;
     818              : 
     819       864198 :     case USE:
     820       864198 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     821              :         /* If using a hard register that is the source of an eliminate
     822              :            we still think can be performed, note it cannot be
     823              :            performed since we don't know how this hard register is
     824              :            used.  */
     825      3799265 :         for (ep = reg_eliminate;
     826      3799265 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     827              :              ep++)
     828      3039412 :           if (ep->from_rtx == XEXP (x, 0)
     829            0 :               && ep->to_rtx != hard_frame_pointer_rtx)
     830            0 :             setup_can_eliminate (ep, false);
     831              :       return;
     832              : 
     833     12870041 :     case CLOBBER:
     834     12870041 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     835              :         /* If clobbering a hard register that is the replacement
     836              :            register for an elimination we still think can be
     837              :            performed, note that it cannot be performed.  Otherwise, we
     838              :            need not be concerned about it.  */
     839     62668525 :         for (ep = reg_eliminate;
     840     62668525 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     841              :              ep++)
     842     50134820 :           if (ep->to_rtx == XEXP (x, 0)
     843         4390 :               && ep->to_rtx != hard_frame_pointer_rtx)
     844            2 :             setup_can_eliminate (ep, false);
     845              :       return;
     846              : 
     847     98488806 :     case SET:
     848     98488806 :       if (SET_DEST (x) == stack_pointer_rtx
     849      2187952 :           && GET_CODE (SET_SRC (x)) == PLUS
     850      2160016 :           && XEXP (SET_SRC (x), 0) == SET_DEST (x)
     851    100648754 :           && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
     852              :         {
     853      2159948 :           curr_sp_change += offset;
     854      2159948 :           return;
     855              :         }
     856     96328858 :       if (! REG_P (SET_DEST (x))
     857     96328858 :           || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
     858     74706633 :         mark_not_eliminable (SET_DEST (x), mem_mode);
     859              :       else
     860              :         {
     861              :           /* See if this is setting the replacement hard register for
     862              :              an elimination.
     863              : 
     864              :              If DEST is the hard frame pointer, we do nothing because
     865              :              we assume that all assignments to the frame pointer are
     866              :              for non-local gotos and are being done at a time when
     867              :              they are valid and do not disturb anything else.  Some
     868              :              machines want to eliminate a fake argument pointer (or
     869              :              even a fake frame pointer) with either the real frame
     870              :              pointer or the stack pointer.  Assignments to the hard
     871              :              frame pointer must not prevent this elimination.  */
     872    108111125 :           for (ep = reg_eliminate;
     873    108111125 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     874              :                ep++)
     875     86488900 :             if (ep->to_rtx == SET_DEST (x)
     876        57814 :                 && SET_DEST (x) != hard_frame_pointer_rtx)
     877        56008 :               setup_can_eliminate (ep, false);
     878              :         }
     879              : 
     880     96328858 :       mark_not_eliminable (SET_SRC (x), mem_mode);
     881     96328858 :       return;
     882              : 
     883     37269593 :     case MEM:
     884              :       /* Our only special processing is to pass the mode of the MEM to
     885              :          our recursive call.  */
     886     37269593 :       mark_not_eliminable (XEXP (x, 0), GET_MODE (x));
     887     37269593 :       return;
     888              : 
     889    338513782 :     default:
     890    338513782 :       break;
     891              :     }
     892              : 
     893    338513782 :   fmt = GET_RTX_FORMAT (code);
     894    757455024 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     895              :     {
     896    418941242 :       if (*fmt == 'e')
     897    146776329 :         mark_not_eliminable (XEXP (x, i), mem_mode);
     898    272164913 :       else if (*fmt == 'E')
     899     47507553 :         for (j = 0; j < XVECLEN (x, i); j++)
     900     31868179 :           mark_not_eliminable (XVECEXP (x, i, j), mem_mode);
     901              :     }
     902              : }
     903              : 
     904              : 
     905              : 
     906              : /* Scan INSN and eliminate all eliminable hard registers in it.
     907              : 
     908              :    If REPLACE_P is true, do the replacement destructively.  Also
     909              :    delete the insn as dead it if it is setting an eliminable register.
     910              : 
     911              :    If REPLACE_P is false, just update the offsets while keeping the
     912              :    base register the same.  If FIRST_P, use the sp offset for
     913              :    elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
     914              :    UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
     915              :    and the previous offset.  Attach the note about used elimination
     916              :    for insns setting frame pointer to update elimination easy (without
     917              :    parsing already generated elimination insns to find offset
     918              :    previously used) in future.  */
     919              : 
     920              : void
     921     48749045 : eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
     922              :                         poly_int64 update_sp_offset)
     923              : {
     924     48749045 :   int icode = recog_memoized (insn);
     925     48749045 :   rtx set, old_set = single_set (insn);
     926     48749045 :   bool validate_p;
     927     48749045 :   int i;
     928     48749045 :   rtx substed_operand[MAX_RECOG_OPERANDS];
     929     48749045 :   rtx orig_operand[MAX_RECOG_OPERANDS];
     930     48749045 :   class lra_elim_table *ep;
     931     48749045 :   rtx plus_src, plus_cst_src;
     932     48749045 :   lra_insn_recog_data_t id;
     933     48749045 :   struct lra_static_insn_data *static_id;
     934              : 
     935     48749045 :   if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
     936              :     {
     937         9857 :       lra_assert (GET_CODE (PATTERN (insn)) == USE
     938              :                   || GET_CODE (PATTERN (insn)) == CLOBBER
     939              :                   || GET_CODE (PATTERN (insn)) == ASM_INPUT);
     940      7113959 :       return;
     941              :     }
     942              : 
     943              :   /* We allow one special case which happens to work on all machines we
     944              :      currently support: a single set with the source or a REG_EQUAL
     945              :      note being a PLUS of an eliminable register and a constant.  */
     946     48739188 :   plus_src = plus_cst_src = 0;
     947     48739188 :   poly_int64 offset = 0;
     948     48739188 :   if (old_set && REG_P (SET_DEST (old_set)))
     949              :     {
     950     20423957 :       if (GET_CODE (SET_SRC (old_set)) == PLUS)
     951      4359047 :         plus_src = SET_SRC (old_set);
     952              :       /* First see if the source is of the form (plus (...) CST).  */
     953      4359047 :       if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
     954              :         plus_cst_src = plus_src;
     955              :       /* If we are doing initial offset computation, then utilize
     956              :          eqivalences to discover a constant for the second term
     957              :          of PLUS_SRC.  */
     958     16384415 :       else if (plus_src && REG_P (XEXP (plus_src, 1)))
     959              :         {
     960        31143 :           int regno = REGNO (XEXP (plus_src, 1));
     961        31143 :           if (regno < ira_reg_equiv_len
     962        31143 :               && ira_reg_equiv[regno].constant != NULL_RTX
     963         2813 :               && !replace_p
     964        33920 :               && poly_int_rtx_p (ira_reg_equiv[regno].constant, &offset))
     965          100 :             plus_cst_src = plus_src;
     966              :         }
     967              :       /* Check that the first operand of the PLUS is a hard reg or
     968              :          the lowpart subreg of one.  */
     969      4039642 :       if (plus_cst_src)
     970              :         {
     971      4039642 :           rtx reg = XEXP (plus_cst_src, 0);
     972              : 
     973      4039642 :           if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
     974           83 :             reg = SUBREG_REG (reg);
     975              : 
     976      4039642 :           if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
     977              :             plus_cst_src = 0;
     978              :         }
     979              :     }
     980      4013653 :   if (plus_cst_src)
     981              :     {
     982      4013653 :       rtx reg = XEXP (plus_cst_src, 0);
     983              : 
     984      4013653 :       if (GET_CODE (reg) == SUBREG)
     985           83 :         reg = SUBREG_REG (reg);
     986              : 
     987      4013653 :       if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
     988              :         {
     989      4013653 :           rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
     990              : 
     991      1828396 :           if (! replace_p)
     992              :             {
     993      2185257 :               if (known_eq (update_sp_offset, 0))
     994      2185257 :                 offset += (!first_p
     995      2185257 :                            ? ep->offset - ep->previous_offset : ep->offset);
     996      2185257 :               if (ep->to_rtx == stack_pointer_rtx)
     997              :                 {
     998      1660293 :                   if (first_p)
     999       880456 :                     offset -= lra_get_insn_recog_data (insn)->sp_offset;
    1000              :                   else
    1001      2185257 :                     offset += update_sp_offset;
    1002              :                 }
    1003      2185257 :               offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
    1004              :             }
    1005              : 
    1006      4013653 :           if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
    1007           83 :             to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
    1008              :           /* If we have a nonzero offset, and the source is already a
    1009              :              simple REG, the following transformation would increase
    1010              :              the cost of the insn by replacing a simple REG with (plus
    1011              :              (reg sp) CST).  So try only when we already had a PLUS
    1012              :              before.  */
    1013      4013653 :           if (known_eq (offset, 0) || plus_src)
    1014              :             {
    1015      4013653 :               rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
    1016              : 
    1017      4013653 :               old_set = single_set (insn);
    1018              : 
    1019              :               /* First see if this insn remains valid when we make the
    1020              :                  change.  If not, try to replace the whole pattern
    1021              :                  with a simple set (this may help if the original insn
    1022              :                  was a PARALLEL that was only recognized as single_set
    1023              :                  due to REG_UNUSED notes).  If this isn't valid
    1024              :                  either, keep the INSN_CODE the same and let the
    1025              :                  constraint pass fix it up.  */
    1026      4013653 :               if (! validate_change (insn, &SET_SRC (old_set), new_src, 0))
    1027              :                 {
    1028           11 :                   rtx new_pat = gen_rtx_SET (SET_DEST (old_set), new_src);
    1029              : 
    1030           11 :                   if (! validate_change (insn, &PATTERN (insn), new_pat, 0))
    1031           11 :                     SET_SRC (old_set) = new_src;
    1032              :                 }
    1033      4013653 :               lra_update_insn_recog_data (insn);
    1034              :               /* This can't have an effect on elimination offsets, so skip
    1035              :                  right to the end.  */
    1036      4013653 :               return;
    1037              :             }
    1038              :         }
    1039              :     }
    1040              : 
    1041              :   /* Eliminate all eliminable registers occurring in operands that
    1042              :      can be handled by the constraint pass.  */
    1043     44725535 :   id = lra_get_insn_recog_data (insn);
    1044     44725535 :   static_id = id->insn_static_data;
    1045     44725535 :   validate_p = false;
    1046    126307534 :   for (i = 0; i < static_id->n_operands; i++)
    1047              :     {
    1048     81581999 :       orig_operand[i] = *id->operand_loc[i];
    1049     81581999 :       substed_operand[i] = *id->operand_loc[i];
    1050              : 
    1051              :       /* For an asm statement, every operand is eliminable.  */
    1052     81581999 :       if (icode < 0 || insn_data[icode].operand[i].eliminable)
    1053              :         {
    1054              :           /* Check for setting a hard register that we know about.  */
    1055     81282454 :           if (static_id->operand[i].type != OP_IN
    1056     34017758 :               && REG_P (orig_operand[i]))
    1057              :             {
    1058              :               /* If we are assigning to a hard register that can be
    1059              :                  eliminated, it must be as part of a PARALLEL, since
    1060              :                  the code above handles single SETs.  This reg cannot
    1061              :                  be longer eliminated -- it is forced by
    1062              :                  mark_not_eliminable.  */
    1063     77172330 :               for (ep = reg_eliminate;
    1064     77172330 :                    ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
    1065              :                    ep++)
    1066     61737864 :                 lra_assert (ep->from_rtx != orig_operand[i]
    1067              :                             || ! ep->can_eliminate);
    1068              :             }
    1069              : 
    1070              :           /* Companion to the above plus substitution, we can allow
    1071              :              invariants as the source of a plain move.  */
    1072     81282454 :           substed_operand[i]
    1073    162564908 :             = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
    1074     81282454 :                                     replace_p, ! replace_p && ! first_p,
    1075              :                                     update_sp_offset, first_p);
    1076     81282454 :           if (substed_operand[i] != orig_operand[i])
    1077     81581999 :             validate_p = true;
    1078              :         }
    1079              :     }
    1080              : 
    1081     44725535 :   if (! validate_p)
    1082              :     return;
    1083              : 
    1084              :   /* Substitute the operands; the new values are in the substed_operand
    1085              :      array.  */
    1086    116822822 :   for (i = 0; i < static_id->n_operands; i++)
    1087     75187736 :     *id->operand_loc[i] = substed_operand[i];
    1088     41734792 :   for (i = 0; i < static_id->n_dups; i++)
    1089        99706 :     *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]];
    1090              : 
    1091              :   /* Transform plus (plus (hard reg, const), pseudo) to plus (plus (pseudo,
    1092              :      const), hard reg) in order to keep insn containing eliminated register
    1093              :      after all reloads calculating its offset.  This permits to keep register
    1094              :      pressure under control and helps to avoid LRA cycling in patalogical
    1095              :      cases.  */
    1096     21577263 :   if (! replace_p && (set = single_set (insn)) != NULL
    1097     15623987 :       && GET_CODE (SET_SRC (set)) == PLUS
    1098     42007153 :       && GET_CODE (XEXP (SET_SRC (set), 0)) == PLUS)
    1099              :     {
    1100        23850 :       rtx reg1, reg2, op1, op2;
    1101              : 
    1102        23850 :       reg1 = op1 = XEXP (XEXP (SET_SRC (set), 0), 0);
    1103        23850 :       reg2 = op2 = XEXP (SET_SRC (set), 1);
    1104        23850 :       if (GET_CODE (reg1) == SUBREG)
    1105            0 :         reg1 = SUBREG_REG (reg1);
    1106        23850 :       if (GET_CODE (reg2) == SUBREG)
    1107            0 :         reg2 = SUBREG_REG (reg2);
    1108        20384 :       if (REG_P (reg1) && REG_P (reg2)
    1109         7973 :           && REGNO (reg1) < FIRST_PSEUDO_REGISTER
    1110         7973 :           && REGNO (reg2) >= FIRST_PSEUDO_REGISTER
    1111         8010 :           && GET_MODE (reg1) == Pmode
    1112        31823 :           && !have_addptr3_insn (lra_pmode_pseudo, reg1,
    1113              :                                  XEXP (XEXP (SET_SRC (set), 0), 1)))
    1114              :         {
    1115         7973 :           XEXP (XEXP (SET_SRC (set), 0), 0) = op2;
    1116         7973 :           XEXP (SET_SRC (set), 1) = op1;
    1117              :         }
    1118              :     }
    1119              : 
    1120              :   /* If we had a move insn but now we don't, re-recognize it.
    1121              :      This will cause spurious re-recognition if the old move had a
    1122              :      PARALLEL since the new one still will, but we can't call
    1123              :      single_set without having put new body into the insn and the
    1124              :      re-recognition won't hurt in this rare case.  */
    1125     41635086 :   lra_update_insn_recog_data (insn);
    1126              : }
    1127              : 
    1128              : /* Spill pseudos which are assigned to hard registers in SET, record them in
    1129              :    SPILLED_PSEUDOS unless it is null, and return the recorded pseudos number.
    1130              :    Add affected insns for processing in the subsequent constraint pass.  */
    1131              : static int
    1132      8082997 : spill_pseudos (HARD_REG_SET set, int *spilled_pseudos)
    1133              : {
    1134      8082997 :   int i, n;
    1135      8082997 :   bitmap_head to_process;
    1136      8082997 :   rtx_insn *insn;
    1137              : 
    1138     16165994 :   if (hard_reg_set_empty_p (set))
    1139              :     return 0;
    1140      8082997 :   if (lra_dump_file != NULL)
    1141              :     {
    1142          485 :       fprintf (lra_dump_file, "       Spilling non-eliminable hard regs:");
    1143        45590 :       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1144        44620 :         if (TEST_HARD_REG_BIT (set, i))
    1145          485 :           fprintf (lra_dump_file, " %d", i);
    1146          485 :       fprintf (lra_dump_file, "\n");
    1147              :     }
    1148      8082997 :   bitmap_initialize (&to_process, &reg_obstack);
    1149      8082997 :   n = 0;
    1150    529341847 :   for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1151    249489397 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1152    521258850 :         && overlaps_hard_reg_set_p (set,
    1153    236816307 :                                     PSEUDO_REGNO_MODE (i), reg_renumber[i]))
    1154              :       {
    1155        26243 :         if (lra_dump_file != NULL)
    1156            0 :           fprintf (lra_dump_file, "         Spilling r%d(%d)\n",
    1157              :                    i, reg_renumber[i]);
    1158        26243 :         reg_renumber[i] = -1;
    1159        26243 :         if (spilled_pseudos != NULL)
    1160            0 :           spilled_pseudos[n++] = i;
    1161        26243 :         bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
    1162              :       }
    1163      8082997 :   lra_no_alloc_regs |= set;
    1164   1306705713 :   for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
    1165   1298622716 :     if (bitmap_bit_p (&to_process, INSN_UID (insn)))
    1166              :       {
    1167       169484 :         lra_push_insn (insn);
    1168       169484 :         lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1169              :       }
    1170      8082997 :   bitmap_clear (&to_process);
    1171      8082997 :   return n;
    1172              : }
    1173              : 
    1174              : /* Update all offsets and possibility for elimination on eliminable
    1175              :    registers.  Spill pseudos assigned to registers which are
    1176              :    uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
    1177              :    insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
    1178              :    registers whose offsets should be changed.  Return true if any
    1179              :    elimination offset changed.  */
    1180              : static bool
    1181      8082997 : update_reg_eliminate (bitmap insns_with_changed_offsets)
    1182              : {
    1183      8082997 :   bool prev, result;
    1184      8082997 :   class lra_elim_table *ep, *ep1;
    1185      8082997 :   HARD_REG_SET temp_hard_reg_set;
    1186              : 
    1187      8082997 :   targetm.compute_frame_layout ();
    1188              : 
    1189              :   /* Clear self elimination offsets.  */
    1190     40414985 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1191     32331988 :     self_elim_offsets[ep->from] = 0;
    1192     40414985 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1193              :     {
    1194              :       /* If it is a currently used elimination: update the previous
    1195              :          offset.  */
    1196     32331988 :       if (elimination_map[ep->from] == ep)
    1197              :         {
    1198     16165994 :           ep->previous_offset = ep->offset;
    1199              :           /* Restore the stack_pointer_rtx into to_rtx, that
    1200              :              lra_update_fp2sp_elimination set to from_rtx, so that the assert
    1201              :              below still checks what it was supposed to check.  */
    1202     16165994 :           if (ep->from_rtx == ep->to_rtx
    1203            0 :               && ep->from != ep->to
    1204            0 :               && ep->from == FRAME_POINTER_REGNUM)
    1205            0 :             ep->to_rtx = stack_pointer_rtx;
    1206              :         }
    1207              : 
    1208     32331988 :       prev = ep->prev_can_eliminate;
    1209     32331988 :       setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
    1210     32331988 :       if (ep->can_eliminate && ! prev)
    1211              :         {
    1212              :           /* It is possible that not eliminable register becomes
    1213              :              eliminable because we took other reasons into account to
    1214              :              set up eliminable regs in the initial set up.  Just
    1215              :              ignore new eliminable registers.  */
    1216            0 :           setup_can_eliminate (ep, false);
    1217            0 :           continue;
    1218              :         }
    1219     32331988 :       if (!ep->can_eliminate && elimination_map[ep->from] == ep)
    1220              :         {
    1221              :           /* We cannot use this elimination anymore -- find another
    1222              :              one.  */
    1223            0 :           if (lra_dump_file != NULL)
    1224            0 :             fprintf (lra_dump_file,
    1225              :                      "     Elimination %d to %d is not possible anymore\n",
    1226              :                      ep->from, ep->to);
    1227              :           /* If after processing RTL we decides that SP can be used as a result
    1228              :              of elimination, it cannot be changed.  For frame pointer to stack
    1229              :              pointer elimination the condition is a bit relaxed and we just require
    1230              :              that actual elimination has not been done yet.   */
    1231            0 :           gcc_assert (ep->to_rtx != stack_pointer_rtx
    1232              :                       || !elimination_2sp_occurred_p
    1233              :                       || (ep->from < FIRST_PSEUDO_REGISTER
    1234              :                           && fixed_regs [ep->from]));
    1235              : 
    1236              :           /* Mark that is not eliminable anymore.  */
    1237            0 :           elimination_map[ep->from] = NULL;
    1238            0 :           for (ep1 = ep + 1; ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
    1239            0 :             if (ep1->can_eliminate && ep1->from == ep->from)
    1240              :               break;
    1241            0 :           if (ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS])
    1242              :             {
    1243            0 :               if (lra_dump_file != NULL)
    1244            0 :                 fprintf (lra_dump_file, "    Using elimination %d to %d now\n",
    1245              :                          ep1->from, ep1->to);
    1246            0 :               lra_assert (known_eq (ep1->previous_offset, -1));
    1247            0 :               ep1->previous_offset = ep->offset;
    1248              :             }
    1249              :           else
    1250              :             {
    1251              :               /* There is no elimination anymore just use the hard
    1252              :                  register `from' itself.  Setup self elimination
    1253              :                  offset to restore the original offset values.  */
    1254            0 :               if (lra_dump_file != NULL)
    1255            0 :                 fprintf (lra_dump_file, "    %d is not eliminable at all\n",
    1256              :                          ep->from);
    1257            0 :               self_elim_offsets[ep->from] = -ep->offset;
    1258            0 :               if (maybe_ne (ep->offset, 0))
    1259            0 :                 bitmap_ior_into (insns_with_changed_offsets,
    1260            0 :                                  &lra_reg_info[ep->from].insn_bitmap);
    1261              :             }
    1262              :         }
    1263              : 
    1264     32331988 :       INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset);
    1265              :     }
    1266      8082997 :   setup_elimination_map ();
    1267      8082997 :   result = false;
    1268      8082997 :   CLEAR_HARD_REG_SET (temp_hard_reg_set);
    1269     40414985 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1270     32331988 :     if (elimination_map[ep->from] == NULL)
    1271            0 :       add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
    1272     32331988 :     else if (elimination_map[ep->from] == ep)
    1273              :       {
    1274              :         /* Prevent the hard register into which we eliminate from
    1275              :            the usage for pseudos.  */
    1276     16165994 :         if (ep->from != ep->to)
    1277     17767290 :           add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
    1278     16165994 :         if (maybe_ne (ep->previous_offset, ep->offset))
    1279              :           {
    1280      3304603 :             bitmap_ior_into (insns_with_changed_offsets,
    1281      3304603 :                              &lra_reg_info[ep->from].insn_bitmap);
    1282              : 
    1283              :             /* Update offset when the eliminate offset have been
    1284              :                changed.  */
    1285      3304603 :             lra_update_reg_val_offset (lra_reg_info[ep->from].val,
    1286      3304603 :                                        ep->offset - ep->previous_offset);
    1287      3304603 :             result = true;
    1288              :           }
    1289              :       }
    1290      8082997 :   lra_no_alloc_regs |= temp_hard_reg_set;
    1291      8082997 :   eliminable_regset &= ~temp_hard_reg_set;
    1292      8082997 :   spill_pseudos (temp_hard_reg_set, NULL);
    1293      8082997 :   return result;
    1294              : }
    1295              : 
    1296              : /* Initialize the table of hard registers to eliminate.
    1297              :    Pre-condition: global flag frame_pointer_needed has been set before
    1298              :    calling this function.  */
    1299              : static void
    1300      1471362 : init_elim_table (void)
    1301              : {
    1302      1471362 :   class lra_elim_table *ep;
    1303      1471362 :   bool value_p;
    1304      1471362 :   const struct elim_table_1 *ep1;
    1305              : 
    1306      1471362 :   if (!reg_eliminate)
    1307       207982 :     reg_eliminate = XCNEWVEC (class lra_elim_table, NUM_ELIMINABLE_REGS);
    1308              : 
    1309      1471362 :   memset (self_elim_offsets, 0, sizeof (self_elim_offsets));
    1310              :   /* Initiate member values which will be never changed.  */
    1311      1471362 :   self_elim_table.can_eliminate = self_elim_table.prev_can_eliminate = true;
    1312      1471362 :   self_elim_table.previous_offset = 0;
    1313              : 
    1314      1471362 :   for (ep = reg_eliminate, ep1 = reg_eliminate_1;
    1315      7356810 :        ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
    1316              :     {
    1317      5885448 :       ep->offset = ep->previous_offset = -1;
    1318      5885448 :       ep->from = ep1->from;
    1319      5885448 :       ep->to = ep1->to;
    1320      5885448 :       value_p = (targetm.can_eliminate (ep->from, ep->to)
    1321      5885448 :                  && ! (ep->to == STACK_POINTER_REGNUM
    1322      2011611 :                        && frame_pointer_needed
    1323        59577 :                        && (! SUPPORTS_STACK_ALIGNMENT
    1324        59577 :                            || ! stack_realign_fp)));
    1325      5885448 :       setup_can_eliminate (ep, value_p);
    1326              :     }
    1327              : 
    1328              :   /* Build the FROM and TO REG rtx's.  Note that code in gen_rtx_REG
    1329              :      will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to
    1330              :      equal stack_pointer_rtx.  We depend on this. Threfore we switch
    1331              :      off that we are in LRA temporarily.  */
    1332      1471362 :   lra_in_progress = false;
    1333      7356810 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1334              :     {
    1335      6391000 :       ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
    1336      6391000 :       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
    1337      5885448 :       eliminable_reg_rtx[ep->from] = ep->from_rtx;
    1338              :     }
    1339      1471362 :   lra_in_progress = true;
    1340      1471362 : }
    1341              : 
    1342              : /* Function for initialization of elimination once per function.  It
    1343              :    sets up sp offset for each insn.  */
    1344              : static void
    1345      1471362 : init_elimination (void)
    1346              : {
    1347      1471362 :   bool stop_to_sp_elimination_p;
    1348      1471362 :   basic_block bb;
    1349      1471362 :   rtx_insn *insn;
    1350      1471362 :   class lra_elim_table *ep;
    1351              : 
    1352      1471362 :   init_elim_table ();
    1353     15984076 :   FOR_EACH_BB_FN (bb, cfun)
    1354              :     {
    1355     14512714 :       curr_sp_change = 0;
    1356     14512714 :       stop_to_sp_elimination_p = false;
    1357    175572362 :       FOR_BB_INSNS (bb, insn)
    1358    161059648 :         if (INSN_P (insn))
    1359              :           {
    1360    134292054 :             lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change;
    1361    134292054 :             if (NONDEBUG_INSN_P (insn))
    1362              :               {
    1363     85409049 :                 mark_not_eliminable (PATTERN (insn), VOIDmode);
    1364     85409049 :                 if (maybe_ne (curr_sp_change, 0)
    1365     85409049 :                     && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
    1366              :                   stop_to_sp_elimination_p = true;
    1367              :               }
    1368              :           }
    1369     14512714 :       if (! frame_pointer_needed
    1370      9916507 :           && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
    1371     14566236 :           && bb->succs && bb->succs->length () != 0)
    1372        46630 :         for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1373        37304 :           if (ep->to == STACK_POINTER_REGNUM)
    1374        18652 :             setup_can_eliminate (ep, false);
    1375              :     }
    1376      1471362 :   setup_elimination_map ();
    1377      1471362 : }
    1378              : 
    1379              : /* Update and return stack pointer OFFSET after processing X.  */
    1380              : poly_int64
    1381     17629003 : lra_update_sp_offset (rtx x, poly_int64 offset)
    1382              : {
    1383     17629003 :   curr_sp_change = offset;
    1384     17629003 :   mark_not_eliminable (x, VOIDmode);
    1385     17629003 :   return curr_sp_change;
    1386              : }
    1387              : 
    1388              : 
    1389              : /* Eliminate hard reg given by its location LOC.  */
    1390              : void
    1391     93527443 : lra_eliminate_reg_if_possible (rtx *loc)
    1392              : {
    1393     93527443 :   int regno;
    1394     93527443 :   class lra_elim_table *ep;
    1395              : 
    1396     93527443 :   lra_assert (REG_P (*loc));
    1397     93527443 :   if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
    1398     93527443 :       || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
    1399              :     return;
    1400     69026333 :   if ((ep = get_elimination (*loc)) != NULL)
    1401     65618184 :     *loc = ep->to_rtx;
    1402              : }
    1403              : 
    1404              : /* Do (final if FINAL_P or first if FIRST_P) elimination in INSN.  Add
    1405              :    the insn for subsequent processing in the constraint pass, update
    1406              :    the insn info.  */
    1407              : static void
    1408     48748971 : process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
    1409              : {
    1410     48748971 :   eliminate_regs_in_insn (insn, final_p, first_p, 0);
    1411     48748971 :   if (! final_p)
    1412              :     {
    1413              :       /* Check that insn changed its code.  This is a case when a move
    1414              :          insn becomes an add insn and we do not want to process the
    1415              :          insn as a move anymore.  */
    1416     26849927 :       int icode = recog (PATTERN (insn), insn, 0);
    1417              : 
    1418     26849927 :       if (icode >= 0 && icode != INSN_CODE (insn))
    1419              :         {
    1420       105728 :           if (INSN_CODE (insn) >= 0)
    1421              :             /* Insn code is changed.  It may change its operand type
    1422              :                from IN to INOUT.  Inform the subsequent assignment
    1423              :                subpass about this situation.  */
    1424       105728 :             check_and_force_assignment_correctness_p = true;
    1425       105728 :           INSN_CODE (insn) = icode;
    1426       105728 :           lra_update_insn_recog_data (insn);
    1427              :         }
    1428     26849927 :       lra_update_insn_regno_info (insn);
    1429     26849927 :       lra_push_insn (insn);
    1430     26849927 :       lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1431              :     }
    1432     48748971 : }
    1433              : 
    1434              : /* Update frame pointer to stack pointer elimination if we started with
    1435              :    permitted frame pointer elimination and now target reports that we can not
    1436              :    do this elimination anymore.  Record spilled pseudos in SPILLED_PSEUDOS
    1437              :    unless it is null, and return the recorded pseudos number.  */
    1438              : int
    1439       197959 : lra_update_fp2sp_elimination (int *spilled_pseudos)
    1440              : {
    1441       197959 :   int n;
    1442       197959 :   HARD_REG_SET set;
    1443       197959 :   class lra_elim_table *ep;
    1444              : 
    1445       197959 :   if (frame_pointer_needed || !targetm.frame_pointer_required ())
    1446       197959 :     return 0;
    1447            0 :   gcc_assert (!elimination_2sp_occurred_p);
    1448            0 :   ep = elimination_map[FRAME_POINTER_REGNUM];
    1449            0 :   if (ep->to == STACK_POINTER_REGNUM)
    1450              :     {
    1451              :       /* Prevent any further uses of fp, say in spill addresses, from being
    1452              :          eliminated to sp and affected by sp offsets.  Alas, deactivating the
    1453              :          elimination altogether causes the next chosen fp elimination to miss
    1454              :          the offset propagation, so it may keep -1 as its prev_offset, and that
    1455              :          will make subsequent offsets incorrect.  */
    1456            0 :       ep->to_rtx = ep->from_rtx;
    1457            0 :       setup_can_eliminate (ep, false);
    1458              :     }
    1459              :   else
    1460            0 :     for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1461            0 :       if (ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
    1462            0 :         setup_can_eliminate (ep, false);
    1463            0 :   if (lra_dump_file != NULL)
    1464            0 :     fprintf (lra_dump_file,
    1465              :              "        Frame pointer can not be eliminated anymore\n");
    1466            0 :   frame_pointer_needed = true;
    1467              :   /* If !lra_reg_spill_p, we likely have incomplete range information
    1468              :      for pseudos assigned to the frame pointer that will have to be
    1469              :      spilled, and so we may end up incorrectly sharing them unless we
    1470              :      get live range information for them.  */
    1471            0 :   if (lra_complete_live_ranges ())
    1472              :     /* If lives ranges changed, update the aggregate live ranges in
    1473              :        slots as well before spilling any further pseudos.  */
    1474            0 :     lra_recompute_slots_live_ranges ();
    1475            0 :   CLEAR_HARD_REG_SET (set);
    1476            0 :   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
    1477            0 :   n = spill_pseudos (set, spilled_pseudos);
    1478            0 :   return n;
    1479              : }
    1480              : 
    1481              : /* Return true if we have a pseudo assigned to hard frame pointer.  */
    1482              : bool
    1483         1839 : lra_fp_pseudo_p (void)
    1484              : {
    1485         1839 :   HARD_REG_SET set;
    1486              : 
    1487         1839 :   if (frame_pointer_needed)
    1488              :     /* At this stage it means we have no pseudos assigned to FP:  */
    1489              :     return false;
    1490         1597 :   CLEAR_HARD_REG_SET (set);
    1491         1597 :   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
    1492       150863 :   for (int i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1493        46596 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1494       187650 :         && overlaps_hard_reg_set_p (set, PSEUDO_REGNO_MODE (i),
    1495              :                                     reg_renumber[i]))
    1496              :       return true;
    1497              :   return false;
    1498              : }
    1499              : 
    1500              : /* Entry function to do final elimination if FINAL_P or to update
    1501              :    elimination register offsets (FIRST_P if we are doing it the first
    1502              :    time).  */
    1503              : void
    1504      8083017 : lra_eliminate (bool final_p, bool first_p)
    1505              : {
    1506      8083017 :   unsigned int uid;
    1507      8083017 :   bitmap_head insns_with_changed_offsets;
    1508      8083017 :   bitmap_iterator bi;
    1509      8083017 :   class lra_elim_table *ep;
    1510              : 
    1511      8083017 :   gcc_assert (! final_p || ! first_p);
    1512              : 
    1513      8083017 :   timevar_push (TV_LRA_ELIMINATE);
    1514              : 
    1515      8083017 :   if (first_p)
    1516              :     {
    1517      1471362 :       elimination_2sp_occurred_p = false;
    1518      1471362 :       init_elimination ();
    1519              :     }
    1520              : 
    1521      8083017 :   bitmap_initialize (&insns_with_changed_offsets, &reg_obstack);
    1522      8083017 :   if (final_p)
    1523              :     {
    1524      1471362 :       if (flag_checking)
    1525              :         {
    1526      1471342 :           update_reg_eliminate (&insns_with_changed_offsets);
    1527      1471342 :           gcc_assert (bitmap_empty_p (&insns_with_changed_offsets));
    1528              :         }
    1529              :       /* We change eliminable hard registers in insns so we should do
    1530              :          this for all insns containing any eliminable hard
    1531              :          register.  */
    1532      7356810 :       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1533      5885448 :         if (elimination_map[ep->from] != NULL)
    1534      5885448 :           bitmap_ior_into (&insns_with_changed_offsets,
    1535      5885448 :                            &lra_reg_info[ep->from].insn_bitmap);
    1536              :     }
    1537      6611655 :   else if (! update_reg_eliminate (&insns_with_changed_offsets))
    1538      4943743 :     goto lra_eliminate_done;
    1539      3139274 :   if (lra_dump_file != NULL)
    1540              :     {
    1541          194 :       fprintf (lra_dump_file, "New elimination table:\n");
    1542          194 :       print_elim_table (lra_dump_file);
    1543              :     }
    1544     51888245 :   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
    1545              :     /* A dead insn can be deleted in process_insn_for_elimination.  */
    1546     48748971 :     if (lra_insn_recog_data[uid] != NULL)
    1547     48748971 :       process_insn_for_elimination (lra_insn_recog_data[uid]->insn,
    1548              :                                     final_p, first_p);
    1549      3139274 :   bitmap_clear (&insns_with_changed_offsets);
    1550              : 
    1551      8083017 : lra_eliminate_done:
    1552      8083017 :   timevar_pop (TV_LRA_ELIMINATE);
    1553      8083017 : }
        

Generated by: LCOV version 2.4-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.