LCOV - code coverage report
Current view: top level - gcc - lra-eliminations.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.7 % 686 574
Test Date: 2025-08-02 13:28:05 Functions: 95.5 % 22 21
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Code for RTL register eliminations.
       2                 :             :    Copyright (C) 2010-2025 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                 :    38272212 : setup_can_eliminate (class lra_elim_table *ep, bool value)
     146                 :             : {
     147                 :    38272212 :   ep->can_eliminate = ep->prev_can_eliminate = value;
     148                 :    38272212 :   if (! value
     149                 :     6388304 :       && ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
     150                 :     2838172 :     frame_pointer_needed = 1;
     151                 :    38272212 :   if (!frame_pointer_needed)
     152                 :    25576997 :     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 0;
     153                 :    38272212 : }
     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                 :     9550333 : setup_elimination_map (void)
     178                 :             : {
     179                 :     9550333 :   int i;
     180                 :     9550333 :   class lra_elim_table *ep;
     181                 :             : 
     182                 :   888180969 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     183                 :   878630636 :     elimination_map[i] = NULL;
     184                 :    47751665 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     185                 :    38201332 :     if (ep->can_eliminate && elimination_map[ep->from] == NULL)
     186                 :    19100666 :       elimination_map[ep->from] = ep;
     187                 :     9550333 : }
     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                 :     1706521 : form_sum (rtx x, rtx y)
     199                 :             : {
     200                 :     2090086 :   machine_mode mode = GET_MODE (x);
     201                 :     2090086 :   poly_int64 offset;
     202                 :             : 
     203                 :     2090086 :   if (mode == VOIDmode)
     204                 :      126529 :     mode = GET_MODE (y);
     205                 :             : 
     206                 :     2090086 :   if (mode == VOIDmode)
     207                 :           0 :     mode = Pmode;
     208                 :             : 
     209                 :     2090086 :   if (poly_int_rtx_p (x, &offset))
     210                 :      126529 :     return plus_constant (mode, y, offset);
     211                 :     1963557 :   else if (poly_int_rtx_p (y, &offset))
     212                 :     1055223 :     return plus_constant (mode, x, offset);
     213                 :      908334 :   else if (CONSTANT_P (x))
     214                 :          14 :     std::swap (x, y);
     215                 :             : 
     216                 :      908334 :   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
     217                 :      126543 :     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                 :      781791 :   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
     223                 :      257022 :     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                 :      524769 :   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                 :      524769 :   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                 :   122360276 : lra_get_elimination_hard_regno (int hard_regno)
     244                 :             : {
     245                 :   122360276 :   class lra_elim_table *ep;
     246                 :             : 
     247                 :   122360276 :   if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     248                 :             :     return hard_regno;
     249                 :   122360276 :   if ((ep = elimination_map[hard_regno]) == NULL)
     250                 :             :     return hard_regno;
     251                 :    32639254 :   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                 :   165661528 : get_elimination (rtx reg)
     258                 :             : {
     259                 :   165661528 :   int hard_regno;
     260                 :   165661528 :   class lra_elim_table *ep;
     261                 :             : 
     262                 :   165661528 :   lra_assert (REG_P (reg));
     263                 :   165661528 :   if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     264                 :             :     return NULL;
     265                 :   137649564 :   if ((ep = elimination_map[hard_regno]) != NULL)
     266                 :   131761753 :     return ep->from_rtx != reg ? NULL : ep;
     267                 :     5887811 :   poly_int64 offset = self_elim_offsets[hard_regno];
     268                 :     5887811 :   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                 :     2831672 : move_plus_up (rtx x)
     286                 :             : {
     287                 :     2831672 :   rtx subreg_reg;
     288                 :     2831672 :   machine_mode x_mode, subreg_reg_mode;
     289                 :             : 
     290                 :     2831672 :   if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
     291                 :     2831554 :     return x;
     292                 :         118 :   subreg_reg = SUBREG_REG (x);
     293                 :         118 :   x_mode = GET_MODE (x);
     294                 :         118 :   subreg_reg_mode = GET_MODE (subreg_reg);
     295                 :         118 :   if (!paradoxical_subreg_p (x)
     296                 :         118 :       && GET_CODE (subreg_reg) == PLUS
     297                 :           4 :       && CONSTANT_P (XEXP (subreg_reg, 1))
     298                 :           4 :       && GET_MODE_CLASS (x_mode) == MODE_INT
     299                 :         122 :       && 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                 :    13307195 : note_spoff (poly_int64 offset)
     322                 :             : {
     323                 :    13307195 :   if (maybe_ne (offset, 0))
     324                 :     1398871 :     elimination_2sp_occurred_p = true;
     325                 :    12844522 :   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                 :   146768618 : 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                 :   146768618 :   enum rtx_code code = GET_CODE (x);
     353                 :   146768618 :   class lra_elim_table *ep;
     354                 :   146768618 :   rtx new_rtx;
     355                 :   146768618 :   int i, j;
     356                 :   146768618 :   const char *fmt;
     357                 :   146768618 :   int copied = 0;
     358                 :             : 
     359                 :   146768618 :   lra_assert (!update_p || !full_p);
     360                 :   146768618 :   lra_assert (known_eq (update_sp_offset, 0)
     361                 :             :               || (!subst_p && update_p && !full_p));
     362                 :   146768618 :   if (! current_function_decl)
     363                 :             :     return x;
     364                 :             : 
     365                 :   146768618 :   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                 :    41536128 :     case REG:
     379                 :             :       /* First handle the case where we encounter a bare hard register
     380                 :             :          that is eliminable.  Replace it with a PLUS.  */
     381                 :    41536128 :       if ((ep = get_elimination (x)) != NULL)
     382                 :             :         {
     383                 :    11402544 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     384                 :             : 
     385                 :    11402544 :           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                 :    11402544 :           else if (update_p)
     392                 :      651251 :             return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
     393                 :    10818473 :           else if (full_p)
     394                 :    11794177 :             return plus_constant (Pmode, to,
     395                 :     9869539 :                                   ep->offset
     396                 :             :                                   - (insn != NULL_RTX
     397                 :      677982 :                                      && ep->to_rtx == stack_pointer_rtx
     398                 :    10547521 :                                      ? note_spoff (lra_get_insn_recog_data
     399                 :      462673 :                                                    (insn)->sp_offset)
     400                 :             :                                      : 0));
     401                 :             :           else
     402                 :             :             return to;
     403                 :             :         }
     404                 :    30133584 :       return x;
     405                 :             : 
     406                 :    51375287 :     case PLUS:
     407                 :             :       /* If this is the sum of an eliminable register and a constant, rework
     408                 :             :          the sum.  */
     409                 :    51375287 :       if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
     410                 :             :         {
     411                 :    49959451 :           if ((ep = get_elimination (XEXP (x, 0))) != NULL)
     412                 :             :             {
     413                 :    49847341 :               poly_int64 offset, curr_offset;
     414                 :    49847341 :               rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     415                 :             : 
     416                 :    49847341 :               if (! update_p && ! full_p)
     417                 :    23070123 :                 return simplify_gen_binary (PLUS, Pmode, to, XEXP (x, 1));
     418                 :             : 
     419                 :    30164415 :               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                 :    30164415 :                 offset = (update_p
     425                 :    30164415 :                           ? ep->offset - ep->previous_offset : ep->offset);
     426                 :    30164415 :               if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     427                 :    25689044 :                 offset -= note_spoff (lra_get_insn_recog_data (insn)->sp_offset);
     428                 :    30164415 :               if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
     429                 :    30164415 :                   && known_eq (curr_offset, -offset))
     430                 :             :                 return to;
     431                 :             :               else
     432                 :    39845501 :                 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                 :      112110 :           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                 :     1415836 :       {
     453                 :     1415836 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     454                 :             :                                          subst_p, update_p,
     455                 :             :                                          update_sp_offset, full_p);
     456                 :     1415836 :         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                 :     1415836 :         new0 = move_plus_up (new0);
     461                 :     1415836 :         new1 = move_plus_up (new1);
     462                 :     1415836 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     463                 :     1322956 :           return form_sum (new0, new1);
     464                 :             :       }
     465                 :             :       return x;
     466                 :             : 
     467                 :      260822 :     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                 :      243576 :       if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
     474                 :      502576 :           && (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                 :      399044 :     case CALL:
     510                 :      399044 :     case COMPARE:
     511                 :             :     /* See comments before PLUS about handling MINUS.  */
     512                 :      399044 :     case MINUS:
     513                 :      399044 :     case DIV:      case UDIV:
     514                 :      399044 :     case MOD:      case UMOD:
     515                 :      399044 :     case AND:      case IOR:      case XOR:
     516                 :      399044 :     case ROTATERT: case ROTATE:
     517                 :      399044 :     case ASHIFTRT: case LSHIFTRT: case ASHIFT:
     518                 :      399044 :     case NE:       case EQ:
     519                 :      399044 :     case GE:       case GT:       case GEU:    case GTU:
     520                 :      399044 :     case LE:       case LT:       case LEU:    case LTU:
     521                 :      399044 :       {
     522                 :      399044 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     523                 :             :                                          subst_p, update_p,
     524                 :             :                                          update_sp_offset, full_p);
     525                 :      399044 :         rtx new1 = XEXP (x, 1)
     526                 :      399044 :                    ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     527                 :             :                                            subst_p, update_p,
     528                 :             :                                            update_sp_offset, full_p) : 0;
     529                 :             : 
     530                 :      399044 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     531                 :      113622 :           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                 :      540181 :     case PRE_INC:
     579                 :      540181 :     case POST_INC:
     580                 :      540181 :     case PRE_DEC:
     581                 :      540181 :     case POST_DEC:
     582                 :             :       /* Recurse to adjust elimination offsets in a spilled pseudo.  */
     583                 :      540181 :       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                 :         302 :     case PRE_MODIFY:
     591                 :         302 :     case POST_MODIFY:
     592                 :             :       /* Recurse to adjust elimination offsets in a spilled pseudo.  */
     593                 :         302 :       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                 :         302 :       if (GET_CODE (XEXP (x, 1)) == PLUS
     600                 :         302 :           && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
     601                 :             :         {
     602                 :         302 :           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                 :         302 :           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                 :         302 :       return x;
     612                 :             : 
     613                 :       38670 :     case STRICT_LOW_PART:
     614                 :       38670 :     case NEG:          case NOT:
     615                 :       38670 :     case SIGN_EXTEND:  case ZERO_EXTEND:
     616                 :       38670 :     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
     617                 :       38670 :     case FLOAT:        case FIX:
     618                 :       38670 :     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
     619                 :       38670 :     case ABS:
     620                 :       38670 :     case SQRT:
     621                 :       38670 :     case FFS:
     622                 :       38670 :     case CLZ:
     623                 :       38670 :     case CTZ:
     624                 :       38670 :     case POPCOUNT:
     625                 :       38670 :     case PARITY:
     626                 :       38670 :     case BSWAP:
     627                 :       38670 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     628                 :             :                                       subst_p, update_p,
     629                 :             :                                       update_sp_offset, full_p);
     630                 :       38670 :       if (new_rtx != XEXP (x, 0))
     631                 :       29406 :         return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
     632                 :             :       return x;
     633                 :             : 
     634                 :      618954 :     case SUBREG:
     635                 :      618954 :       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                 :      618954 :       if (new_rtx != SUBREG_REG (x))
     640                 :             :         {
     641                 :        8104 :           if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
     642                 :             :             {
     643                 :          12 :               SUBREG_REG (x) = new_rtx;
     644                 :          12 :               alter_subreg (&x, false);
     645                 :          12 :               return x;
     646                 :             :             }
     647                 :        8092 :           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                 :        5144 :               SUBREG_REG (x) = new_rtx;
     655                 :        5144 :               return x;
     656                 :             :             }
     657                 :             :           else
     658                 :        2948 :             return simplify_gen_subreg (GET_MODE (x), new_rtx,
     659                 :        2948 :                                         GET_MODE (new_rtx), SUBREG_BYTE (x));
     660                 :             :         }
     661                 :             : 
     662                 :             :       return x;
     663                 :             : 
     664                 :    44489448 :     case MEM:
     665                 :             :       /* Our only special processing is to pass the mode of the MEM to our
     666                 :             :          recursive call and copy the flags.  While we are here, handle this
     667                 :             :          case more efficiently.  */
     668                 :    44489448 :       return
     669                 :             :         replace_equiv_address_nv
     670                 :    44489448 :         (x,
     671                 :    44489448 :          lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
     672                 :    44489448 :                                subst_p, update_p, update_sp_offset, full_p));
     673                 :             : 
     674                 :           0 :     case USE:
     675                 :             :       /* Handle insn_list USE that a call to a pure function may generate.  */
     676                 :           0 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
     677                 :             :                                       subst_p, update_p, update_sp_offset, full_p);
     678                 :           0 :       if (new_rtx != XEXP (x, 0))
     679                 :           0 :         return gen_rtx_USE (GET_MODE (x), new_rtx);
     680                 :             :       return x;
     681                 :             : 
     682                 :           0 :     case CLOBBER:
     683                 :           0 :     case ASM_OPERANDS:
     684                 :           0 :       gcc_assert (insn && DEBUG_INSN_P (insn));
     685                 :             :       break;
     686                 :             : 
     687                 :           0 :     case SET:
     688                 :           0 :       gcc_unreachable ();
     689                 :             : 
     690                 :             :     default:
     691                 :             :       break;
     692                 :             :     }
     693                 :             : 
     694                 :             :   /* Process each of our operands recursively.  If any have changed, make a
     695                 :             :      copy of the rtx.  */
     696                 :       77893 :   fmt = GET_RTX_FORMAT (code);
     697                 :      168271 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     698                 :             :     {
     699                 :       90378 :       if (*fmt == 'e')
     700                 :             :         {
     701                 :       23596 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
     702                 :             :                                           subst_p, update_p,
     703                 :             :                                           update_sp_offset, full_p);
     704                 :       23596 :           if (new_rtx != XEXP (x, i) && ! copied)
     705                 :             :             {
     706                 :       10945 :               x = shallow_copy_rtx (x);
     707                 :       10945 :               copied = 1;
     708                 :             :             }
     709                 :       23596 :           XEXP (x, i) = new_rtx;
     710                 :             :         }
     711                 :       66782 :       else if (*fmt == 'E')
     712                 :             :         {
     713                 :             :           int copied_vec = 0;
     714                 :       38725 :           for (j = 0; j < XVECLEN (x, i); j++)
     715                 :             :             {
     716                 :       26007 :               new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
     717                 :             :                                               subst_p, update_p,
     718                 :             :                                               update_sp_offset, full_p);
     719                 :       26007 :               if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
     720                 :             :                 {
     721                 :       24192 :                   rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
     722                 :       12096 :                                              XVEC (x, i)->elem);
     723                 :       12096 :                   if (! copied)
     724                 :             :                     {
     725                 :       12096 :                       x = shallow_copy_rtx (x);
     726                 :       12096 :                       copied = 1;
     727                 :             :                     }
     728                 :       12096 :                   XVEC (x, i) = new_v;
     729                 :       12096 :                   copied_vec = 1;
     730                 :             :                 }
     731                 :       26007 :               XVECEXP (x, i, j) = new_rtx;
     732                 :             :             }
     733                 :             :         }
     734                 :             :     }
     735                 :             : 
     736                 :       77893 :   return x;
     737                 :             : }
     738                 :             : 
     739                 :             : /* This function is used externally in subsequent passes of GCC.  It
     740                 :             :    always does a full elimination of X.  */
     741                 :             : rtx
     742                 :     9191557 : lra_eliminate_regs (rtx x, machine_mode mem_mode,
     743                 :             :                     rtx insn ATTRIBUTE_UNUSED)
     744                 :             : {
     745                 :     9191557 :   return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
     746                 :             : }
     747                 :             : 
     748                 :             : /* Stack pointer offset before the current insn relative to one at the
     749                 :             :    func start.  RTL insns can change SP explicitly.  We keep the
     750                 :             :    changes from one insn to another through this variable.  */
     751                 :             : static poly_int64 curr_sp_change;
     752                 :             : 
     753                 :             : /* Scan rtx X for references to elimination source or target registers
     754                 :             :    in contexts that would prevent the elimination from happening.
     755                 :             :    Update the table of eliminables to reflect the changed state.
     756                 :             :    MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not
     757                 :             :    within a MEM.  */
     758                 :             : static void
     759                 :   355817759 : mark_not_eliminable (rtx x, machine_mode mem_mode)
     760                 :             : {
     761                 :   489563109 :   enum rtx_code code = GET_CODE (x);
     762                 :   489563109 :   class lra_elim_table *ep;
     763                 :   489563109 :   int i, j;
     764                 :   489563109 :   const char *fmt;
     765                 :   489563109 :   poly_int64 offset = 0;
     766                 :             : 
     767                 :   489563109 :   switch (code)
     768                 :             :     {
     769                 :     1964315 :     case PRE_INC:
     770                 :     1964315 :     case POST_INC:
     771                 :     1964315 :     case PRE_DEC:
     772                 :     1964315 :     case POST_DEC:
     773                 :     1964315 :     case POST_MODIFY:
     774                 :     1964315 :     case PRE_MODIFY:
     775                 :     1964315 :       if (XEXP (x, 0) == stack_pointer_rtx
     776                 :     1964315 :           && ((code != PRE_MODIFY && code != POST_MODIFY)
     777                 :      105801 :               || (GET_CODE (XEXP (x, 1)) == PLUS
     778                 :      105801 :                   && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
     779                 :      105801 :                   && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
     780                 :             :         {
     781                 :     3928630 :           poly_int64 size = GET_MODE_SIZE (mem_mode);
     782                 :             : 
     783                 :             : #ifdef PUSH_ROUNDING
     784                 :             :           /* If more bytes than MEM_MODE are pushed, account for
     785                 :             :              them.  */
     786                 :     1964315 :           size = PUSH_ROUNDING (size);
     787                 :             : #endif
     788                 :     1964315 :           if (code == PRE_DEC || code == POST_DEC)
     789                 :   355817759 :             curr_sp_change -= size;
     790                 :      105845 :           else if (code == PRE_INC || code == POST_INC)
     791                 :   355817759 :             curr_sp_change += size;
     792                 :      105801 :           else if (code == PRE_MODIFY || code == POST_MODIFY)
     793                 :   355817759 :             curr_sp_change += offset;
     794                 :             :         }
     795                 :           0 :       else if (REG_P (XEXP (x, 0))
     796                 :           0 :                && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
     797                 :             :         {
     798                 :             :           /* If we modify the source of an elimination rule, disable
     799                 :             :              it.  Do the same if it is the destination and not the
     800                 :             :              hard frame register.  */
     801                 :           0 :           for (ep = reg_eliminate;
     802                 :           0 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     803                 :             :                ep++)
     804                 :           0 :             if (ep->from_rtx == XEXP (x, 0)
     805                 :           0 :                 || (ep->to_rtx == XEXP (x, 0)
     806                 :           0 :                     && ep->to_rtx != hard_frame_pointer_rtx))
     807                 :           0 :               setup_can_eliminate (ep, false);
     808                 :             :         }
     809                 :             :       return;
     810                 :             : 
     811                 :      856257 :     case USE:
     812                 :      856257 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     813                 :             :         /* If using a hard register that is the source of an eliminate
     814                 :             :            we still think can be performed, note it cannot be
     815                 :             :            performed since we don't know how this hard register is
     816                 :             :            used.  */
     817                 :     3763115 :         for (ep = reg_eliminate;
     818                 :     3763115 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     819                 :             :              ep++)
     820                 :     3010492 :           if (ep->from_rtx == XEXP (x, 0)
     821                 :           0 :               && ep->to_rtx != hard_frame_pointer_rtx)
     822                 :           0 :             setup_can_eliminate (ep, false);
     823                 :             :       return;
     824                 :             : 
     825                 :    12881570 :     case CLOBBER:
     826                 :    12881570 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     827                 :             :         /* If clobbering a hard register that is the replacement
     828                 :             :            register for an elimination we still think can be
     829                 :             :            performed, note that it cannot be performed.  Otherwise, we
     830                 :             :            need not be concerned about it.  */
     831                 :    62701660 :         for (ep = reg_eliminate;
     832                 :    62701660 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     833                 :             :              ep++)
     834                 :    50161328 :           if (ep->to_rtx == XEXP (x, 0)
     835                 :        4386 :               && ep->to_rtx != hard_frame_pointer_rtx)
     836                 :           2 :             setup_can_eliminate (ep, false);
     837                 :             :       return;
     838                 :             : 
     839                 :    98704457 :     case SET:
     840                 :    98704457 :       if (SET_DEST (x) == stack_pointer_rtx
     841                 :     2171778 :           && GET_CODE (SET_SRC (x)) == PLUS
     842                 :     2145993 :           && XEXP (SET_SRC (x), 0) == SET_DEST (x)
     843                 :   100850382 :           && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
     844                 :             :         {
     845                 :     2145925 :           curr_sp_change += offset;
     846                 :     2145925 :           return;
     847                 :             :         }
     848                 :    96558532 :       if (! REG_P (SET_DEST (x))
     849                 :    96558532 :           || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
     850                 :    74680423 :         mark_not_eliminable (SET_DEST (x), mem_mode);
     851                 :             :       else
     852                 :             :         {
     853                 :             :           /* See if this is setting the replacement hard register for
     854                 :             :              an elimination.
     855                 :             : 
     856                 :             :              If DEST is the hard frame pointer, we do nothing because
     857                 :             :              we assume that all assignments to the frame pointer are
     858                 :             :              for non-local gotos and are being done at a time when
     859                 :             :              they are valid and do not disturb anything else.  Some
     860                 :             :              machines want to eliminate a fake argument pointer (or
     861                 :             :              even a fake frame pointer) with either the real frame
     862                 :             :              pointer or the stack pointer.  Assignments to the hard
     863                 :             :              frame pointer must not prevent this elimination.  */
     864                 :   109390545 :           for (ep = reg_eliminate;
     865                 :   109390545 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     866                 :             :                ep++)
     867                 :    87512436 :             if (ep->to_rtx == SET_DEST (x)
     868                 :       53508 :                 && SET_DEST (x) != hard_frame_pointer_rtx)
     869                 :       51706 :               setup_can_eliminate (ep, false);
     870                 :             :         }
     871                 :             : 
     872                 :    96558532 :       mark_not_eliminable (SET_SRC (x), mem_mode);
     873                 :    96558532 :       return;
     874                 :             : 
     875                 :    37186818 :     case MEM:
     876                 :             :       /* Our only special processing is to pass the mode of the MEM to
     877                 :             :          our recursive call.  */
     878                 :    37186818 :       mark_not_eliminable (XEXP (x, 0), GET_MODE (x));
     879                 :    37186818 :       return;
     880                 :             : 
     881                 :   337969692 :     default:
     882                 :   337969692 :       break;
     883                 :             :     }
     884                 :             : 
     885                 :   337969692 :   fmt = GET_RTX_FORMAT (code);
     886                 :   755944586 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     887                 :             :     {
     888                 :   417974894 :       if (*fmt == 'e')
     889                 :   146197272 :         mark_not_eliminable (XEXP (x, i), mem_mode);
     890                 :   271777622 :       else if (*fmt == 'E')
     891                 :    47156968 :         for (j = 0; j < XVECLEN (x, i); j++)
     892                 :    31620844 :           mark_not_eliminable (XVECEXP (x, i, j), mem_mode);
     893                 :             :     }
     894                 :             : }
     895                 :             : 
     896                 :             : 
     897                 :             : 
     898                 :             : /* Scan INSN and eliminate all eliminable hard registers in it.
     899                 :             : 
     900                 :             :    If REPLACE_P is true, do the replacement destructively.  Also
     901                 :             :    delete the insn as dead it if it is setting an eliminable register.
     902                 :             : 
     903                 :             :    If REPLACE_P is false, just update the offsets while keeping the
     904                 :             :    base register the same.  If FIRST_P, use the sp offset for
     905                 :             :    elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
     906                 :             :    UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
     907                 :             :    and the previous offset.  Attach the note about used elimination
     908                 :             :    for insns setting frame pointer to update elimination easy (without
     909                 :             :    parsing already generated elimination insns to find offset
     910                 :             :    previously used) in future.  */
     911                 :             : 
     912                 :             : void
     913                 :    49666330 : eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
     914                 :             :                         poly_int64 update_sp_offset)
     915                 :             : {
     916                 :    49666330 :   int icode = recog_memoized (insn);
     917                 :    49666330 :   rtx set, old_set = single_set (insn);
     918                 :    49666330 :   bool validate_p;
     919                 :    49666330 :   int i;
     920                 :    49666330 :   rtx substed_operand[MAX_RECOG_OPERANDS];
     921                 :    49666330 :   rtx orig_operand[MAX_RECOG_OPERANDS];
     922                 :    49666330 :   class lra_elim_table *ep;
     923                 :    49666330 :   rtx plus_src, plus_cst_src;
     924                 :    49666330 :   lra_insn_recog_data_t id;
     925                 :    49666330 :   struct lra_static_insn_data *static_id;
     926                 :             : 
     927                 :    49666330 :   if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
     928                 :             :     {
     929                 :       13921 :       lra_assert (GET_CODE (PATTERN (insn)) == USE
     930                 :             :                   || GET_CODE (PATTERN (insn)) == CLOBBER
     931                 :             :                   || GET_CODE (PATTERN (insn)) == ASM_INPUT);
     932                 :     7276967 :       return;
     933                 :             :     }
     934                 :             : 
     935                 :             :   /* We allow one special case which happens to work on all machines we
     936                 :             :      currently support: a single set with the source or a REG_EQUAL
     937                 :             :      note being a PLUS of an eliminable register and a constant.  */
     938                 :    49652409 :   plus_src = plus_cst_src = 0;
     939                 :    49652409 :   poly_int64 offset = 0;
     940                 :    49652409 :   if (old_set && REG_P (SET_DEST (old_set)))
     941                 :             :     {
     942                 :    20703489 :       if (GET_CODE (SET_SRC (old_set)) == PLUS)
     943                 :     4504281 :         plus_src = SET_SRC (old_set);
     944                 :             :       /* First see if the source is of the form (plus (...) CST).  */
     945                 :     4504281 :       if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
     946                 :             :         plus_cst_src = plus_src;
     947                 :             :       /* If we are doing initial offset computation, then utilize
     948                 :             :          eqivalences to discover a constant for the second term
     949                 :             :          of PLUS_SRC.  */
     950                 :    16520605 :       else if (plus_src && REG_P (XEXP (plus_src, 1)))
     951                 :             :         {
     952                 :       29114 :           int regno = REGNO (XEXP (plus_src, 1));
     953                 :       29114 :           if (regno < ira_reg_equiv_len
     954                 :       29114 :               && ira_reg_equiv[regno].constant != NULL_RTX
     955                 :        1240 :               && !replace_p
     956                 :       30318 :               && poly_int_rtx_p (ira_reg_equiv[regno].constant, &offset))
     957                 :         101 :             plus_cst_src = plus_src;
     958                 :             :         }
     959                 :             :       /* Check that the first operand of the PLUS is a hard reg or
     960                 :             :          the lowpart subreg of one.  */
     961                 :     4182985 :       if (plus_cst_src)
     962                 :             :         {
     963                 :     4182985 :           rtx reg = XEXP (plus_cst_src, 0);
     964                 :             : 
     965                 :     4182985 :           if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
     966                 :          89 :             reg = SUBREG_REG (reg);
     967                 :             : 
     968                 :     4182985 :           if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
     969                 :             :             plus_cst_src = 0;
     970                 :             :         }
     971                 :             :     }
     972                 :     4155129 :   if (plus_cst_src)
     973                 :             :     {
     974                 :     4155129 :       rtx reg = XEXP (plus_cst_src, 0);
     975                 :             : 
     976                 :     4155129 :       if (GET_CODE (reg) == SUBREG)
     977                 :          89 :         reg = SUBREG_REG (reg);
     978                 :             : 
     979                 :     4155129 :       if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
     980                 :             :         {
     981                 :     4155129 :           rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
     982                 :             : 
     983                 :     1879355 :           if (! replace_p)
     984                 :             :             {
     985                 :     2275774 :               if (known_eq (update_sp_offset, 0))
     986                 :     2275774 :                 offset += (!first_p
     987                 :     2275774 :                            ? ep->offset - ep->previous_offset : ep->offset);
     988                 :     2275774 :               if (ep->to_rtx == stack_pointer_rtx)
     989                 :             :                 {
     990                 :     1751051 :                   if (first_p)
     991                 :      929573 :                     offset -= lra_get_insn_recog_data (insn)->sp_offset;
     992                 :             :                   else
     993                 :     2275774 :                     offset += update_sp_offset;
     994                 :             :                 }
     995                 :     2275774 :               offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
     996                 :             :             }
     997                 :             : 
     998                 :     4155129 :           if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
     999                 :          89 :             to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
    1000                 :             :           /* If we have a nonzero offset, and the source is already a
    1001                 :             :              simple REG, the following transformation would increase
    1002                 :             :              the cost of the insn by replacing a simple REG with (plus
    1003                 :             :              (reg sp) CST).  So try only when we already had a PLUS
    1004                 :             :              before.  */
    1005                 :     4155129 :           if (known_eq (offset, 0) || plus_src)
    1006                 :             :             {
    1007                 :     4155129 :               rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
    1008                 :             : 
    1009                 :     4155129 :               old_set = single_set (insn);
    1010                 :             : 
    1011                 :             :               /* First see if this insn remains valid when we make the
    1012                 :             :                  change.  If not, try to replace the whole pattern
    1013                 :             :                  with a simple set (this may help if the original insn
    1014                 :             :                  was a PARALLEL that was only recognized as single_set
    1015                 :             :                  due to REG_UNUSED notes).  If this isn't valid
    1016                 :             :                  either, keep the INSN_CODE the same and let the
    1017                 :             :                  constraint pass fix it up.  */
    1018                 :     4155129 :               if (! validate_change (insn, &SET_SRC (old_set), new_src, 0))
    1019                 :             :                 {
    1020                 :          11 :                   rtx new_pat = gen_rtx_SET (SET_DEST (old_set), new_src);
    1021                 :             : 
    1022                 :          11 :                   if (! validate_change (insn, &PATTERN (insn), new_pat, 0))
    1023                 :          11 :                     SET_SRC (old_set) = new_src;
    1024                 :             :                 }
    1025                 :     4155129 :               lra_update_insn_recog_data (insn);
    1026                 :             :               /* This can't have an effect on elimination offsets, so skip
    1027                 :             :                  right to the end.  */
    1028                 :     4155129 :               return;
    1029                 :             :             }
    1030                 :             :         }
    1031                 :             :     }
    1032                 :             : 
    1033                 :             :   /* Eliminate all eliminable registers occurring in operands that
    1034                 :             :      can be handled by the constraint pass.  */
    1035                 :    45497280 :   id = lra_get_insn_recog_data (insn);
    1036                 :    45497280 :   static_id = id->insn_static_data;
    1037                 :    45497280 :   validate_p = false;
    1038                 :   128133412 :   for (i = 0; i < static_id->n_operands; i++)
    1039                 :             :     {
    1040                 :    82636132 :       orig_operand[i] = *id->operand_loc[i];
    1041                 :    82636132 :       substed_operand[i] = *id->operand_loc[i];
    1042                 :             : 
    1043                 :             :       /* For an asm statement, every operand is eliminable.  */
    1044                 :    82636132 :       if (icode < 0 || insn_data[icode].operand[i].eliminable)
    1045                 :             :         {
    1046                 :             :           /* Check for setting a hard register that we know about.  */
    1047                 :    82340373 :           if (static_id->operand[i].type != OP_IN
    1048                 :    34287216 :               && REG_P (orig_operand[i]))
    1049                 :             :             {
    1050                 :             :               /* If we are assigning to a hard register that can be
    1051                 :             :                  eliminated, it must be as part of a PARALLEL, since
    1052                 :             :                  the code above handles single SETs.  This reg cannot
    1053                 :             :                  be longer eliminated -- it is forced by
    1054                 :             :                  mark_not_eliminable.  */
    1055                 :    77853660 :               for (ep = reg_eliminate;
    1056                 :    77853660 :                    ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
    1057                 :             :                    ep++)
    1058                 :    62282928 :                 lra_assert (ep->from_rtx != orig_operand[i]
    1059                 :             :                             || ! ep->can_eliminate);
    1060                 :             :             }
    1061                 :             : 
    1062                 :             :           /* Companion to the above plus substitution, we can allow
    1063                 :             :              invariants as the source of a plain move.  */
    1064                 :    82340373 :           substed_operand[i]
    1065                 :   164680746 :             = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
    1066                 :    82340373 :                                     replace_p, ! replace_p && ! first_p,
    1067                 :             :                                     update_sp_offset, first_p);
    1068                 :    82340373 :           if (substed_operand[i] != orig_operand[i])
    1069                 :    82636132 :             validate_p = true;
    1070                 :             :         }
    1071                 :             :     }
    1072                 :             : 
    1073                 :    45497280 :   if (! validate_p)
    1074                 :             :     return;
    1075                 :             : 
    1076                 :             :   /* Substitute the operands; the new values are in the substed_operand
    1077                 :             :      array.  */
    1078                 :   118600175 :   for (i = 0; i < static_id->n_operands; i++)
    1079                 :    76210812 :     *id->operand_loc[i] = substed_operand[i];
    1080                 :    42488274 :   for (i = 0; i < static_id->n_dups; i++)
    1081                 :       98911 :     *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]];
    1082                 :             : 
    1083                 :             :   /* Transform plus (plus (hard reg, const), pseudo) to plus (plus (pseudo,
    1084                 :             :      const), hard reg) in order to keep insn containing eliminated register
    1085                 :             :      after all reloads calculating its offset.  This permits to keep register
    1086                 :             :      pressure under control and helps to avoid LRA cycling in patalogical
    1087                 :             :      cases.  */
    1088                 :    21999795 :   if (! replace_p && (set = single_set (insn)) != NULL
    1089                 :    15753306 :       && GET_CODE (SET_SRC (set)) == PLUS
    1090                 :    42748566 :       && GET_CODE (XEXP (SET_SRC (set), 0)) == PLUS)
    1091                 :             :     {
    1092                 :       24925 :       rtx reg1, reg2, op1, op2;
    1093                 :             : 
    1094                 :       24925 :       reg1 = op1 = XEXP (XEXP (SET_SRC (set), 0), 0);
    1095                 :       24925 :       reg2 = op2 = XEXP (SET_SRC (set), 1);
    1096                 :       24925 :       if (GET_CODE (reg1) == SUBREG)
    1097                 :           0 :         reg1 = SUBREG_REG (reg1);
    1098                 :       24925 :       if (GET_CODE (reg2) == SUBREG)
    1099                 :           0 :         reg2 = SUBREG_REG (reg2);
    1100                 :       21588 :       if (REG_P (reg1) && REG_P (reg2)
    1101                 :        7876 :           && REGNO (reg1) < FIRST_PSEUDO_REGISTER
    1102                 :        7876 :           && REGNO (reg2) >= FIRST_PSEUDO_REGISTER
    1103                 :        7898 :           && GET_MODE (reg1) == Pmode
    1104                 :       32801 :           && !have_addptr3_insn (lra_pmode_pseudo, reg1,
    1105                 :             :                                  XEXP (XEXP (SET_SRC (set), 0), 1)))
    1106                 :             :         {
    1107                 :        7876 :           XEXP (XEXP (SET_SRC (set), 0), 0) = op2;
    1108                 :        7876 :           XEXP (SET_SRC (set), 1) = op1;
    1109                 :             :         }
    1110                 :             :     }
    1111                 :             : 
    1112                 :             :   /* If we had a move insn but now we don't, re-recognize it.
    1113                 :             :      This will cause spurious re-recognition if the old move had a
    1114                 :             :      PARALLEL since the new one still will, but we can't call
    1115                 :             :      single_set without having put new body into the insn and the
    1116                 :             :      re-recognition won't hurt in this rare case.  */
    1117                 :    42389363 :   lra_update_insn_recog_data (insn);
    1118                 :             : }
    1119                 :             : 
    1120                 :             : /* Spill pseudos which are assigned to hard registers in SET, record them in
    1121                 :             :    SPILLED_PSEUDOS unless it is null, and return the recorded pseudos number.
    1122                 :             :    Add affected insns for processing in the subsequent constraint pass.  */
    1123                 :             : static int
    1124                 :     8080736 : spill_pseudos (HARD_REG_SET set, int *spilled_pseudos)
    1125                 :             : {
    1126                 :     8080736 :   int i, n;
    1127                 :     8080736 :   bitmap_head to_process;
    1128                 :     8080736 :   rtx_insn *insn;
    1129                 :             : 
    1130                 :    16161472 :   if (hard_reg_set_empty_p (set))
    1131                 :             :     return 0;
    1132                 :     8080736 :   if (lra_dump_file != NULL)
    1133                 :             :     {
    1134                 :         485 :       fprintf (lra_dump_file, "       Spilling non-eliminable hard regs:");
    1135                 :       45590 :       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1136                 :       44620 :         if (TEST_HARD_REG_BIT (set, i))
    1137                 :         485 :           fprintf (lra_dump_file, " %d", i);
    1138                 :         485 :       fprintf (lra_dump_file, "\n");
    1139                 :             :     }
    1140                 :     8080736 :   bitmap_initialize (&to_process, &reg_obstack);
    1141                 :     8080736 :   n = 0;
    1142                 :   529936810 :   for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1143                 :   249893081 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1144                 :   521856074 :         && overlaps_hard_reg_set_p (set,
    1145                 :   237310776 :                                     PSEUDO_REGNO_MODE (i), reg_renumber[i]))
    1146                 :             :       {
    1147                 :       27082 :         if (lra_dump_file != NULL)
    1148                 :           0 :           fprintf (lra_dump_file, "         Spilling r%d(%d)\n",
    1149                 :             :                    i, reg_renumber[i]);
    1150                 :       27082 :         reg_renumber[i] = -1;
    1151                 :       27082 :         if (spilled_pseudos != NULL)
    1152                 :           0 :           spilled_pseudos[n++] = i;
    1153                 :       27082 :         bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
    1154                 :             :       }
    1155                 :     8080736 :   lra_no_alloc_regs |= set;
    1156                 :  1304545276 :   for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
    1157                 :  1296464540 :     if (bitmap_bit_p (&to_process, INSN_UID (insn)))
    1158                 :             :       {
    1159                 :      175263 :         lra_push_insn (insn);
    1160                 :      175263 :         lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1161                 :             :       }
    1162                 :     8080736 :   bitmap_clear (&to_process);
    1163                 :     8080736 :   return n;
    1164                 :             : }
    1165                 :             : 
    1166                 :             : /* Update all offsets and possibility for elimination on eliminable
    1167                 :             :    registers.  Spill pseudos assigned to registers which are
    1168                 :             :    uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
    1169                 :             :    insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
    1170                 :             :    registers whose offsets should be changed.  Return true if any
    1171                 :             :    elimination offset changed.  */
    1172                 :             : static bool
    1173                 :     8080736 : update_reg_eliminate (bitmap insns_with_changed_offsets)
    1174                 :             : {
    1175                 :     8080736 :   bool prev, result;
    1176                 :     8080736 :   class lra_elim_table *ep, *ep1;
    1177                 :     8080736 :   HARD_REG_SET temp_hard_reg_set;
    1178                 :             : 
    1179                 :     8080736 :   targetm.compute_frame_layout ();
    1180                 :             : 
    1181                 :             :   /* Clear self elimination offsets.  */
    1182                 :    40403680 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1183                 :    32322944 :     self_elim_offsets[ep->from] = 0;
    1184                 :    40403680 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1185                 :             :     {
    1186                 :             :       /* If it is a currently used elimination: update the previous
    1187                 :             :          offset.  */
    1188                 :    32322944 :       if (elimination_map[ep->from] == ep)
    1189                 :             :         {
    1190                 :    16161472 :           ep->previous_offset = ep->offset;
    1191                 :             :           /* Restore the stack_pointer_rtx into to_rtx, that
    1192                 :             :              lra_update_fp2sp_elimination set to from_rtx, so that the assert
    1193                 :             :              below still checks what it was supposed to check.  */
    1194                 :    16161472 :           if (ep->from_rtx == ep->to_rtx
    1195                 :           0 :               && ep->from != ep->to
    1196                 :           0 :               && ep->from == FRAME_POINTER_REGNUM)
    1197                 :           0 :             ep->to_rtx = stack_pointer_rtx;
    1198                 :             :         }
    1199                 :             : 
    1200                 :    32322944 :       prev = ep->prev_can_eliminate;
    1201                 :    32322944 :       setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
    1202                 :    32322944 :       if (ep->can_eliminate && ! prev)
    1203                 :             :         {
    1204                 :             :           /* It is possible that not eliminable register becomes
    1205                 :             :              eliminable because we took other reasons into account to
    1206                 :             :              set up eliminable regs in the initial set up.  Just
    1207                 :             :              ignore new eliminable registers.  */
    1208                 :           0 :           setup_can_eliminate (ep, false);
    1209                 :           0 :           continue;
    1210                 :             :         }
    1211                 :    32322944 :       if (!ep->can_eliminate && elimination_map[ep->from] == ep)
    1212                 :             :         {
    1213                 :             :           /* We cannot use this elimination anymore -- find another
    1214                 :             :              one.  */
    1215                 :           0 :           if (lra_dump_file != NULL)
    1216                 :           0 :             fprintf (lra_dump_file,
    1217                 :             :                      "     Elimination %d to %d is not possible anymore\n",
    1218                 :             :                      ep->from, ep->to);
    1219                 :             :           /* If after processing RTL we decides that SP can be used as a result
    1220                 :             :              of elimination, it cannot be changed.  For frame pointer to stack
    1221                 :             :              pointer elimination the condition is a bit relaxed and we just require
    1222                 :             :              that actual elimination has not been done yet.   */
    1223                 :           0 :           gcc_assert (ep->to_rtx != stack_pointer_rtx
    1224                 :             :                       || !elimination_2sp_occurred_p
    1225                 :             :                       || (ep->from < FIRST_PSEUDO_REGISTER
    1226                 :             :                           && fixed_regs [ep->from]));
    1227                 :             : 
    1228                 :             :           /* Mark that is not eliminable anymore.  */
    1229                 :           0 :           elimination_map[ep->from] = NULL;
    1230                 :           0 :           for (ep1 = ep + 1; ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
    1231                 :           0 :             if (ep1->can_eliminate && ep1->from == ep->from)
    1232                 :             :               break;
    1233                 :           0 :           if (ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS])
    1234                 :             :             {
    1235                 :           0 :               if (lra_dump_file != NULL)
    1236                 :           0 :                 fprintf (lra_dump_file, "    Using elimination %d to %d now\n",
    1237                 :             :                          ep1->from, ep1->to);
    1238                 :           0 :               lra_assert (known_eq (ep1->previous_offset, -1));
    1239                 :           0 :               ep1->previous_offset = ep->offset;
    1240                 :             :             }
    1241                 :             :           else
    1242                 :             :             {
    1243                 :             :               /* There is no elimination anymore just use the hard
    1244                 :             :                  register `from' itself.  Setup self elimination
    1245                 :             :                  offset to restore the original offset values.  */
    1246                 :           0 :               if (lra_dump_file != NULL)
    1247                 :           0 :                 fprintf (lra_dump_file, "    %d is not eliminable at all\n",
    1248                 :             :                          ep->from);
    1249                 :           0 :               self_elim_offsets[ep->from] = -ep->offset;
    1250                 :           0 :               if (maybe_ne (ep->offset, 0))
    1251                 :           0 :                 bitmap_ior_into (insns_with_changed_offsets,
    1252                 :           0 :                                  &lra_reg_info[ep->from].insn_bitmap);
    1253                 :             :             }
    1254                 :             :         }
    1255                 :             : 
    1256                 :    32322944 :       INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset);
    1257                 :             :     }
    1258                 :     8080736 :   setup_elimination_map ();
    1259                 :     8080736 :   result = false;
    1260                 :     8080736 :   CLEAR_HARD_REG_SET (temp_hard_reg_set);
    1261                 :    40403680 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1262                 :    32322944 :     if (elimination_map[ep->from] == NULL)
    1263                 :           0 :       add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
    1264                 :    32322944 :     else if (elimination_map[ep->from] == ep)
    1265                 :             :       {
    1266                 :             :         /* Prevent the hard register into which we eliminate from
    1267                 :             :            the usage for pseudos.  */
    1268                 :    16161472 :         if (ep->from != ep->to)
    1269                 :    17758272 :           add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
    1270                 :    16161472 :         if (maybe_ne (ep->previous_offset, ep->offset))
    1271                 :             :           {
    1272                 :     3304102 :             bitmap_ior_into (insns_with_changed_offsets,
    1273                 :     3304102 :                              &lra_reg_info[ep->from].insn_bitmap);
    1274                 :             : 
    1275                 :             :             /* Update offset when the eliminate offset have been
    1276                 :             :                changed.  */
    1277                 :     3304102 :             lra_update_reg_val_offset (lra_reg_info[ep->from].val,
    1278                 :     3304102 :                                        ep->offset - ep->previous_offset);
    1279                 :     3304102 :             result = true;
    1280                 :             :           }
    1281                 :             :       }
    1282                 :     8080736 :   lra_no_alloc_regs |= temp_hard_reg_set;
    1283                 :     8080736 :   eliminable_regset &= ~temp_hard_reg_set;
    1284                 :     8080736 :   spill_pseudos (temp_hard_reg_set, NULL);
    1285                 :     8080736 :   return result;
    1286                 :             : }
    1287                 :             : 
    1288                 :             : /* Initialize the table of hard registers to eliminate.
    1289                 :             :    Pre-condition: global flag frame_pointer_needed has been set before
    1290                 :             :    calling this function.  */
    1291                 :             : static void
    1292                 :     1469597 : init_elim_table (void)
    1293                 :             : {
    1294                 :     1469597 :   class lra_elim_table *ep;
    1295                 :     1469597 :   bool value_p;
    1296                 :     1469597 :   const struct elim_table_1 *ep1;
    1297                 :             : 
    1298                 :     1469597 :   if (!reg_eliminate)
    1299                 :      207464 :     reg_eliminate = XCNEWVEC (class lra_elim_table, NUM_ELIMINABLE_REGS);
    1300                 :             : 
    1301                 :     1469597 :   memset (self_elim_offsets, 0, sizeof (self_elim_offsets));
    1302                 :             :   /* Initiate member values which will be never changed.  */
    1303                 :     1469597 :   self_elim_table.can_eliminate = self_elim_table.prev_can_eliminate = true;
    1304                 :     1469597 :   self_elim_table.previous_offset = 0;
    1305                 :             : 
    1306                 :     1469597 :   for (ep = reg_eliminate, ep1 = reg_eliminate_1;
    1307                 :     7347985 :        ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
    1308                 :             :     {
    1309                 :     5878388 :       ep->offset = ep->previous_offset = -1;
    1310                 :     5878388 :       ep->from = ep1->from;
    1311                 :     5878388 :       ep->to = ep1->to;
    1312                 :     5878388 :       value_p = (targetm.can_eliminate (ep->from, ep->to)
    1313                 :     5878388 :                  && ! (ep->to == STACK_POINTER_REGNUM
    1314                 :     1995531 :                        && frame_pointer_needed
    1315                 :       57969 :                        && (! SUPPORTS_STACK_ALIGNMENT
    1316                 :       57969 :                            || ! stack_realign_fp)));
    1317                 :     5878388 :       setup_can_eliminate (ep, value_p);
    1318                 :             :     }
    1319                 :             : 
    1320                 :             :   /* Build the FROM and TO REG rtx's.  Note that code in gen_rtx_REG
    1321                 :             :      will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to
    1322                 :             :      equal stack_pointer_rtx.  We depend on this. Threfore we switch
    1323                 :             :      off that we are in LRA temporarily.  */
    1324                 :     1469597 :   lra_in_progress = false;
    1325                 :     7347985 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1326                 :             :     {
    1327                 :     6381044 :       ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
    1328                 :     6381044 :       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
    1329                 :     5878388 :       eliminable_reg_rtx[ep->from] = ep->from_rtx;
    1330                 :             :     }
    1331                 :     1469597 :   lra_in_progress = true;
    1332                 :     1469597 : }
    1333                 :             : 
    1334                 :             : /* Function for initialization of elimination once per function.  It
    1335                 :             :    sets up sp offset for each insn.  */
    1336                 :             : static void
    1337                 :     1469597 : init_elimination (void)
    1338                 :             : {
    1339                 :     1469597 :   bool stop_to_sp_elimination_p;
    1340                 :     1469597 :   basic_block bb;
    1341                 :     1469597 :   rtx_insn *insn;
    1342                 :     1469597 :   class lra_elim_table *ep;
    1343                 :             : 
    1344                 :     1469597 :   init_elim_table ();
    1345                 :    16034053 :   FOR_EACH_BB_FN (bb, cfun)
    1346                 :             :     {
    1347                 :    14564456 :       curr_sp_change = 0;
    1348                 :    14564456 :       stop_to_sp_elimination_p = false;
    1349                 :   175667470 :       FOR_BB_INSNS (bb, insn)
    1350                 :   161103014 :         if (INSN_P (insn))
    1351                 :             :           {
    1352                 :   134397808 :             lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change;
    1353                 :   134397808 :             if (NONDEBUG_INSN_P (insn))
    1354                 :             :               {
    1355                 :    85755815 :                 mark_not_eliminable (PATTERN (insn), VOIDmode);
    1356                 :    85755815 :                 if (maybe_ne (curr_sp_change, 0)
    1357                 :    85755815 :                     && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
    1358                 :             :                   stop_to_sp_elimination_p = true;
    1359                 :             :               }
    1360                 :             :           }
    1361                 :    14564456 :       if (! frame_pointer_needed
    1362                 :     9926922 :           && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
    1363                 :    14617948 :           && bb->succs && bb->succs->length () != 0)
    1364                 :       47930 :         for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1365                 :       38344 :           if (ep->to == STACK_POINTER_REGNUM)
    1366                 :       19172 :             setup_can_eliminate (ep, false);
    1367                 :             :     }
    1368                 :     1469597 :   setup_elimination_map ();
    1369                 :     1469597 : }
    1370                 :             : 
    1371                 :             : /* Update and return stack pointer OFFSET after processing X.  */
    1372                 :             : poly_int64
    1373                 :    17563405 : lra_update_sp_offset (rtx x, poly_int64 offset)
    1374                 :             : {
    1375                 :    17563405 :   curr_sp_change = offset;
    1376                 :    17563405 :   mark_not_eliminable (x, VOIDmode);
    1377                 :    17563405 :   return curr_sp_change;
    1378                 :             : }
    1379                 :             : 
    1380                 :             : 
    1381                 :             : /* Eliminate hard reg given by its location LOC.  */
    1382                 :             : void
    1383                 :    93752899 : lra_eliminate_reg_if_possible (rtx *loc)
    1384                 :             : {
    1385                 :    93752899 :   int regno;
    1386                 :    93752899 :   class lra_elim_table *ep;
    1387                 :             : 
    1388                 :    93752899 :   lra_assert (REG_P (*loc));
    1389                 :    93752899 :   if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
    1390                 :    93752899 :       || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
    1391                 :             :     return;
    1392                 :    69769066 :   if ((ep = get_elimination (*loc)) != NULL)
    1393                 :    66356739 :     *loc = ep->to_rtx;
    1394                 :             : }
    1395                 :             : 
    1396                 :             : /* Do (final if FINAL_P or first if FIRST_P) elimination in INSN.  Add
    1397                 :             :    the insn for subsequent processing in the constraint pass, update
    1398                 :             :    the insn info.  */
    1399                 :             : static void
    1400                 :    49666207 : process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
    1401                 :             : {
    1402                 :    49666207 :   eliminate_regs_in_insn (insn, final_p, first_p, 0);
    1403                 :    49666207 :   if (! final_p)
    1404                 :             :     {
    1405                 :             :       /* Check that insn changed its code.  This is a case when a move
    1406                 :             :          insn becomes an add insn and we do not want to process the
    1407                 :             :          insn as a move anymore.  */
    1408                 :    27381940 :       int icode = recog (PATTERN (insn), insn, 0);
    1409                 :             : 
    1410                 :    27381940 :       if (icode >= 0 && icode != INSN_CODE (insn))
    1411                 :             :         {
    1412                 :       90699 :           if (INSN_CODE (insn) >= 0)
    1413                 :             :             /* Insn code is changed.  It may change its operand type
    1414                 :             :                from IN to INOUT.  Inform the subsequent assignment
    1415                 :             :                subpass about this situation.  */
    1416                 :       90699 :             check_and_force_assignment_correctness_p = true;
    1417                 :       90699 :           INSN_CODE (insn) = icode;
    1418                 :       90699 :           lra_update_insn_recog_data (insn);
    1419                 :             :         }
    1420                 :    27381940 :       lra_update_insn_regno_info (insn);
    1421                 :    27381940 :       lra_push_insn (insn);
    1422                 :    27381940 :       lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1423                 :             :     }
    1424                 :    49666207 : }
    1425                 :             : 
    1426                 :             : /* Update frame pointer to stack pointer elimination if we started with
    1427                 :             :    permitted frame pointer elimination and now target reports that we can not
    1428                 :             :    do this elimination anymore.  Record spilled pseudos in SPILLED_PSEUDOS
    1429                 :             :    unless it is null, and return the recorded pseudos number.  */
    1430                 :             : int
    1431                 :      199293 : lra_update_fp2sp_elimination (int *spilled_pseudos)
    1432                 :             : {
    1433                 :      199293 :   int n;
    1434                 :      199293 :   HARD_REG_SET set;
    1435                 :      199293 :   class lra_elim_table *ep;
    1436                 :             : 
    1437                 :      199293 :   if (frame_pointer_needed || !targetm.frame_pointer_required ())
    1438                 :      199293 :     return 0;
    1439                 :           0 :   gcc_assert (!elimination_2sp_occurred_p);
    1440                 :           0 :   ep = elimination_map[FRAME_POINTER_REGNUM];
    1441                 :           0 :   if (ep->to == STACK_POINTER_REGNUM)
    1442                 :             :     {
    1443                 :             :       /* Prevent any further uses of fp, say in spill addresses, from being
    1444                 :             :          eliminated to sp and affected by sp offsets.  Alas, deactivating the
    1445                 :             :          elimination altogether causes the next chosen fp elimination to miss
    1446                 :             :          the offset propagation, so it may keep -1 as its prev_offset, and that
    1447                 :             :          will make subsequent offsets incorrect.  */
    1448                 :           0 :       ep->to_rtx = ep->from_rtx;
    1449                 :           0 :       setup_can_eliminate (ep, false);
    1450                 :             :     }
    1451                 :             :   else
    1452                 :           0 :     for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1453                 :           0 :       if (ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
    1454                 :           0 :         setup_can_eliminate (ep, false);
    1455                 :           0 :   if (lra_dump_file != NULL)
    1456                 :           0 :     fprintf (lra_dump_file,
    1457                 :             :              "        Frame pointer can not be eliminated anymore\n");
    1458                 :           0 :   frame_pointer_needed = true;
    1459                 :             :   /* If !lra_reg_spill_p, we likely have incomplete range information
    1460                 :             :      for pseudos assigned to the frame pointer that will have to be
    1461                 :             :      spilled, and so we may end up incorrectly sharing them unless we
    1462                 :             :      get live range information for them.  */
    1463                 :           0 :   if (lra_complete_live_ranges ())
    1464                 :             :     /* If lives ranges changed, update the aggregate live ranges in
    1465                 :             :        slots as well before spilling any further pseudos.  */
    1466                 :           0 :     lra_recompute_slots_live_ranges ();
    1467                 :           0 :   CLEAR_HARD_REG_SET (set);
    1468                 :           0 :   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
    1469                 :           0 :   n = spill_pseudos (set, spilled_pseudos);
    1470                 :           0 :   return n;
    1471                 :             : }
    1472                 :             : 
    1473                 :             : /* Return true if we have a pseudo assigned to hard frame pointer.  */
    1474                 :             : bool
    1475                 :        1874 : lra_fp_pseudo_p (void)
    1476                 :             : {
    1477                 :        1874 :   HARD_REG_SET set;
    1478                 :             : 
    1479                 :        1874 :   if (frame_pointer_needed)
    1480                 :             :     /* At this stage it means we have no pseudos assigned to FP:  */
    1481                 :             :     return false;
    1482                 :        1614 :   CLEAR_HARD_REG_SET (set);
    1483                 :        1614 :   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
    1484                 :      133040 :   for (int i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1485                 :       40954 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1486                 :      166269 :         && overlaps_hard_reg_set_p (set, PSEUDO_REGNO_MODE (i),
    1487                 :             :                                     reg_renumber[i]))
    1488                 :             :       return true;
    1489                 :             :   return false;
    1490                 :             : }
    1491                 :             : 
    1492                 :             : /* Entry function to do final elimination if FINAL_P or to update
    1493                 :             :    elimination register offsets (FIRST_P if we are doing it the first
    1494                 :             :    time).  */
    1495                 :             : void
    1496                 :     8080756 : lra_eliminate (bool final_p, bool first_p)
    1497                 :             : {
    1498                 :     8080756 :   unsigned int uid;
    1499                 :     8080756 :   bitmap_head insns_with_changed_offsets;
    1500                 :     8080756 :   bitmap_iterator bi;
    1501                 :     8080756 :   class lra_elim_table *ep;
    1502                 :             : 
    1503                 :     8080756 :   gcc_assert (! final_p || ! first_p);
    1504                 :             : 
    1505                 :     8080756 :   timevar_push (TV_LRA_ELIMINATE);
    1506                 :             : 
    1507                 :     8080756 :   if (first_p)
    1508                 :             :     {
    1509                 :     1469597 :       elimination_2sp_occurred_p = false;
    1510                 :     1469597 :       init_elimination ();
    1511                 :             :     }
    1512                 :             : 
    1513                 :     8080756 :   bitmap_initialize (&insns_with_changed_offsets, &reg_obstack);
    1514                 :     8080756 :   if (final_p)
    1515                 :             :     {
    1516                 :     1469597 :       if (flag_checking)
    1517                 :             :         {
    1518                 :     1469577 :           update_reg_eliminate (&insns_with_changed_offsets);
    1519                 :     1469577 :           gcc_assert (bitmap_empty_p (&insns_with_changed_offsets));
    1520                 :             :         }
    1521                 :             :       /* We change eliminable hard registers in insns so we should do
    1522                 :             :          this for all insns containing any eliminable hard
    1523                 :             :          register.  */
    1524                 :     7347985 :       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1525                 :     5878388 :         if (elimination_map[ep->from] != NULL)
    1526                 :     5878388 :           bitmap_ior_into (&insns_with_changed_offsets,
    1527                 :     5878388 :                            &lra_reg_info[ep->from].insn_bitmap);
    1528                 :             :     }
    1529                 :     6611159 :   else if (! update_reg_eliminate (&insns_with_changed_offsets))
    1530                 :     4943336 :     goto lra_eliminate_done;
    1531                 :     3137420 :   if (lra_dump_file != NULL)
    1532                 :             :     {
    1533                 :         194 :       fprintf (lra_dump_file, "New elimination table:\n");
    1534                 :         194 :       print_elim_table (lra_dump_file);
    1535                 :             :     }
    1536                 :    52803627 :   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
    1537                 :             :     /* A dead insn can be deleted in process_insn_for_elimination.  */
    1538                 :    49666207 :     if (lra_insn_recog_data[uid] != NULL)
    1539                 :    49666207 :       process_insn_for_elimination (lra_insn_recog_data[uid]->insn,
    1540                 :             :                                     final_p, first_p);
    1541                 :     3137420 :   bitmap_clear (&insns_with_changed_offsets);
    1542                 :             : 
    1543                 :     8080756 : lra_eliminate_done:
    1544                 :     8080756 :   timevar_pop (TV_LRA_ELIMINATE);
    1545                 :     8080756 : }
        

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