LCOV - code coverage report
Current view: top level - gcc - lra-eliminations.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 510 603 84.6 %
Date: 2020-04-04 11:58:09 Functions: 17 19 89.5 %
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-2020 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                 :        225 : print_elim_table (FILE *f)
     120                 :            : {
     121                 :        225 :   class lra_elim_table *ep;
     122                 :            : 
     123                 :       1125 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     124                 :            :     {
     125                 :        900 :       fprintf (f, "%s eliminate %d to %d (offset=",
     126                 :        900 :                ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
     127                 :        900 :       print_dec (ep->offset, f);
     128                 :        900 :       fprintf (f, ", prev_offset=");
     129                 :        900 :       print_dec (ep->previous_offset, f);
     130                 :        900 :       fprintf (f, ")\n");
     131                 :            :     }
     132                 :        225 : }
     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                 :   24026800 : setup_can_eliminate (class lra_elim_table *ep, bool value)
     146                 :            : {
     147                 :   24026800 :   ep->can_eliminate = ep->prev_can_eliminate = value;
     148                 :          0 :   if (! value
     149                 :    3829770 :       && ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
     150                 :    1691740 :     frame_pointer_needed = 1;
     151                 :   24026800 :   if (!frame_pointer_needed)
     152                 :   16334900 :     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 0;
     153                 :          0 : }
     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_pod 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                 :    5996420 : setup_elimination_map (void)
     178                 :            : {
     179                 :    5996420 :   int i;
     180                 :    5996420 :   class lra_elim_table *ep;
     181                 :            : 
     182                 :  461724000 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     183                 :  455728000 :     elimination_map[i] = NULL;
     184                 :   29982100 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     185                 :   23985700 :     if (ep->can_eliminate && elimination_map[ep->from] == NULL)
     186                 :   11992800 :       elimination_map[ep->from] = ep;
     187                 :    5996420 : }
     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                 :     678027 : form_sum (rtx x, rtx y)
     199                 :            : {
     200                 :     812250 :   machine_mode mode = GET_MODE (x);
     201                 :     812250 :   poly_int64 offset;
     202                 :            : 
     203                 :     812250 :   if (mode == VOIDmode)
     204                 :      40110 :     mode = GET_MODE (y);
     205                 :            : 
     206                 :     812250 :   if (mode == VOIDmode)
     207                 :          0 :     mode = Pmode;
     208                 :            : 
     209                 :     812250 :   if (poly_int_rtx_p (x, &offset))
     210                 :      40110 :     return plus_constant (mode, y, offset);
     211                 :     772140 :   else if (poly_int_rtx_p (y, &offset))
     212                 :     399370 :     return plus_constant (mode, x, offset);
     213                 :     372770 :   else if (CONSTANT_P (x))
     214                 :          8 :     std::swap (x, y);
     215                 :            : 
     216                 :     372770 :   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
     217                 :      40118 :     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                 :     332652 :   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
     223                 :      94105 :     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                 :     238547 :   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                 :     238547 :   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                 :  249026000 : lra_get_elimination_hard_regno (int hard_regno)
     244                 :            : {
     245                 :  249026000 :   class lra_elim_table *ep;
     246                 :            : 
     247                 :  249026000 :   if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     248                 :            :     return hard_regno;
     249                 :  249026000 :   if ((ep = elimination_map[hard_regno]) == NULL)
     250                 :            :     return hard_regno;
     251                 :   17059400 :   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                 :   96138000 : get_elimination (rtx reg)
     258                 :            : {
     259                 :   96138000 :   int hard_regno;
     260                 :   96138000 :   class lra_elim_table *ep;
     261                 :            : 
     262                 :   96138000 :   lra_assert (REG_P (reg));
     263                 :   96138000 :   if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     264                 :            :     return NULL;
     265                 :   81229100 :   if ((ep = elimination_map[hard_regno]) != NULL)
     266                 :   77774700 :     return ep->from_rtx != reg ? NULL : ep;
     267                 :    3454330 :   poly_int64 offset = self_elim_offsets[hard_regno];
     268                 :    3454330 :   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                 :    1184500 : move_plus_up (rtx x)
     286                 :            : {
     287                 :    1184500 :   rtx subreg_reg;
     288                 :    1184500 :   machine_mode x_mode, subreg_reg_mode;
     289                 :            :   
     290                 :    1184500 :   if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
     291                 :    1184290 :     return x;
     292                 :        214 :   subreg_reg = SUBREG_REG (x);
     293                 :        214 :   x_mode = GET_MODE (x);
     294                 :        214 :   subreg_reg_mode = GET_MODE (subreg_reg);
     295                 :        214 :   if (!paradoxical_subreg_p (x)
     296                 :        214 :       && GET_CODE (subreg_reg) == PLUS
     297                 :          1 :       && CONSTANT_P (XEXP (subreg_reg, 1))
     298                 :          1 :       && GET_MODE_CLASS (x_mode) == MODE_INT
     299                 :        215 :       && GET_MODE_CLASS (subreg_reg_mode) == MODE_INT)
     300                 :            :     {
     301                 :          1 :       rtx cst = simplify_subreg (x_mode, XEXP (subreg_reg, 1), subreg_reg_mode,
     302                 :            :                                  subreg_lowpart_offset (x_mode,
     303                 :            :                                                         subreg_reg_mode));
     304                 :          1 :       if (cst && CONSTANT_P (cst))
     305                 :          1 :         return gen_rtx_PLUS (x_mode, lowpart_subreg (x_mode,
     306                 :            :                                                      XEXP (subreg_reg, 0),
     307                 :            :                                                      subreg_reg_mode), cst);
     308                 :            :     }
     309                 :            :   return x;
     310                 :            : }
     311                 :            : 
     312                 :            : /* Scan X and replace any eliminable registers (such as fp) with a
     313                 :            :    replacement (such as sp) if SUBST_P, plus an offset.  The offset is
     314                 :            :    a change in the offset between the eliminable register and its
     315                 :            :    substitution if UPDATE_P, or the full offset if FULL_P, or
     316                 :            :    otherwise zero.  If FULL_P, we also use the SP offsets for
     317                 :            :    elimination to SP.  If UPDATE_P, use UPDATE_SP_OFFSET for updating
     318                 :            :    offsets of register elimnable to SP.  If UPDATE_SP_OFFSET is
     319                 :            :    non-zero, don't use difference of the offset and the previous
     320                 :            :    offset.
     321                 :            : 
     322                 :            :    MEM_MODE is the mode of an enclosing MEM.  We need this to know how
     323                 :            :    much to adjust a register for, e.g., PRE_DEC.  Also, if we are
     324                 :            :    inside a MEM, we are allowed to replace a sum of a hard register
     325                 :            :    and the constant zero with the hard register, which we cannot do
     326                 :            :    outside a MEM.  In addition, we need to record the fact that a
     327                 :            :    hard register is referenced outside a MEM.
     328                 :            : 
     329                 :            :    If we make full substitution to SP for non-null INSN, add the insn
     330                 :            :    sp offset.  */
     331                 :            : rtx
     332                 :   82818700 : lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
     333                 :            :                       bool subst_p, bool update_p,
     334                 :            :                       poly_int64 update_sp_offset, bool full_p)
     335                 :            : {
     336                 :   82818700 :   enum rtx_code code = GET_CODE (x);
     337                 :   82818700 :   class lra_elim_table *ep;
     338                 :   82818700 :   rtx new_rtx;
     339                 :   82818700 :   int i, j;
     340                 :   82818700 :   const char *fmt;
     341                 :   82818700 :   int copied = 0;
     342                 :            : 
     343                 :   82818700 :   lra_assert (!update_p || !full_p);
     344                 :   82818700 :   lra_assert (known_eq (update_sp_offset, 0)
     345                 :            :               || (!subst_p && update_p && !full_p));
     346                 :   82818700 :   if (! current_function_decl)
     347                 :            :     return x;
     348                 :            : 
     349                 :   82818700 :   switch (code)
     350                 :            :     {
     351                 :            :     CASE_CONST_ANY:
     352                 :            :     case CONST:
     353                 :            :     case SYMBOL_REF:
     354                 :            :     case CODE_LABEL:
     355                 :            :     case PC:
     356                 :            :     case CC0:
     357                 :            :     case ASM_INPUT:
     358                 :            :     case ADDR_VEC:
     359                 :            :     case ADDR_DIFF_VEC:
     360                 :            :     case RETURN:
     361                 :            :       return x;
     362                 :            : 
     363                 :   21231500 :     case REG:
     364                 :            :       /* First handle the case where we encounter a bare hard register
     365                 :            :          that is eliminable.  Replace it with a PLUS.  */
     366                 :   21231500 :       if ((ep = get_elimination (x)) != NULL)
     367                 :            :         {
     368                 :    5437210 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     369                 :            : 
     370                 :    5437210 :           if (maybe_ne (update_sp_offset, 0))
     371                 :            :             {
     372                 :          0 :               if (ep->to_rtx == stack_pointer_rtx)
     373                 :          0 :                 return plus_constant (Pmode, to, update_sp_offset);
     374                 :            :               return to;
     375                 :            :             }
     376                 :    5437210 :           else if (update_p)
     377                 :     252917 :             return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
     378                 :    5228320 :           else if (full_p)
     379                 :    4645270 :             return plus_constant (Pmode, to,
     380                 :            :                                   ep->offset
     381                 :            :                                   - (insn != NULL_RTX
     382                 :     397429 :                                      && ep->to_rtx == stack_pointer_rtx
     383                 :    5042700 :                                      ? lra_get_insn_recog_data (insn)->sp_offset
     384                 :            :                                      : 0));
     385                 :            :           else
     386                 :            :             return to;
     387                 :            :         }
     388                 :   15794300 :       return x;
     389                 :            : 
     390                 :   28703000 :     case PLUS:
     391                 :            :       /* If this is the sum of an eliminable register and a constant, rework
     392                 :            :          the sum.  */
     393                 :   28703000 :       if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
     394                 :            :         {
     395                 :   28110800 :           if ((ep = get_elimination (XEXP (x, 0))) != NULL)
     396                 :            :             {
     397                 :   28013800 :               poly_int64 offset, curr_offset;
     398                 :   28013800 :               rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     399                 :            : 
     400                 :   28013800 :               if (! update_p && ! full_p)
     401                 :   14855000 :                 return gen_rtx_PLUS (Pmode, to, XEXP (x, 1));
     402                 :            :               
     403                 :   16030700 :               if (maybe_ne (update_sp_offset, 0))
     404                 :          0 :                 offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
     405                 :            :               else
     406                 :   16030700 :                 offset = (update_p
     407                 :    4638030 :                           ? ep->offset - ep->previous_offset : ep->offset);
     408                 :   16030700 :               if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     409                 :    8177560 :                 offset -= lra_get_insn_recog_data (insn)->sp_offset;
     410                 :   16030700 :               if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
     411                 :   16030700 :                   && known_eq (curr_offset, -offset))
     412                 :            :                 return to;
     413                 :            :               else
     414                 :   24287000 :                 return gen_rtx_PLUS (Pmode, to,
     415                 :            :                                      plus_constant (Pmode,
     416                 :            :                                                     XEXP (x, 1), offset));
     417                 :            :             }
     418                 :            : 
     419                 :            :           /* If the hard register is not eliminable, we are done since
     420                 :            :              the other operand is a constant.  */
     421                 :      96957 :           return x;
     422                 :            :         }
     423                 :            : 
     424                 :            :       /* If this is part of an address, we want to bring any constant
     425                 :            :          to the outermost PLUS.  We will do this by doing hard
     426                 :            :          register replacement in our operands and seeing if a constant
     427                 :            :          shows up in one of them.
     428                 :            : 
     429                 :            :          Note that there is no risk of modifying the structure of the
     430                 :            :          insn, since we only get called for its operands, thus we are
     431                 :            :          either modifying the address inside a MEM, or something like
     432                 :            :          an address operand of a load-address insn.  */
     433                 :            : 
     434                 :     592251 :       {
     435                 :     592251 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     436                 :            :                                          subst_p, update_p,
     437                 :            :                                          update_sp_offset, full_p);
     438                 :     592251 :         rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     439                 :            :                                          subst_p, update_p,
     440                 :            :                                          update_sp_offset, full_p);
     441                 :            : 
     442                 :     592251 :         new0 = move_plus_up (new0);
     443                 :     592251 :         new1 = move_plus_up (new1);
     444                 :     592251 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     445                 :     543804 :           return form_sum (new0, new1);
     446                 :            :       }
     447                 :            :       return x;
     448                 :            : 
     449                 :     118642 :     case MULT:
     450                 :            :       /* If this is the product of an eliminable hard register and a
     451                 :            :          constant, apply the distribute law and move the constant out
     452                 :            :          so that we have (plus (mult ..) ..).  This is needed in order
     453                 :            :          to keep load-address insns valid.  This case is pathological.
     454                 :            :          We ignore the possibility of overflow here.  */
     455                 :     106048 :       if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
     456                 :     223587 :           && (ep = get_elimination (XEXP (x, 0))) != NULL)
     457                 :            :         {
     458                 :          0 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     459                 :            : 
     460                 :          0 :           if (maybe_ne (update_sp_offset, 0))
     461                 :            :             {
     462                 :          0 :               if (ep->to_rtx == stack_pointer_rtx)
     463                 :          0 :                 return plus_constant (Pmode,
     464                 :          0 :                                       gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     465                 :          0 :                                       update_sp_offset * INTVAL (XEXP (x, 1)));
     466                 :          0 :               return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     467                 :            :             }
     468                 :          0 :           else if (update_p)
     469                 :          0 :             return plus_constant (Pmode,
     470                 :          0 :                                   gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     471                 :          0 :                                   (ep->offset - ep->previous_offset)
     472                 :          0 :                                   * INTVAL (XEXP (x, 1)));
     473                 :          0 :           else if (full_p)
     474                 :            :             {
     475                 :          0 :               poly_int64 offset = ep->offset;
     476                 :            : 
     477                 :          0 :               if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     478                 :          0 :                 offset -= lra_get_insn_recog_data (insn)->sp_offset;
     479                 :          0 :               return
     480                 :          0 :                 plus_constant (Pmode,
     481                 :          0 :                                gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     482                 :          0 :                                offset * INTVAL (XEXP (x, 1)));
     483                 :            :             }
     484                 :            :           else
     485                 :          0 :             return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     486                 :            :         }
     487                 :            : 
     488                 :            :       /* fall through */
     489                 :            : 
     490                 :     178136 :     case CALL:
     491                 :     178136 :     case COMPARE:
     492                 :            :     /* See comments before PLUS about handling MINUS.  */
     493                 :     178136 :     case MINUS:
     494                 :     178136 :     case DIV:      case UDIV:
     495                 :     178136 :     case MOD:      case UMOD:
     496                 :     178136 :     case AND:      case IOR:      case XOR:
     497                 :     178136 :     case ROTATERT: case ROTATE:
     498                 :     178136 :     case ASHIFTRT: case LSHIFTRT: case ASHIFT:
     499                 :     178136 :     case NE:       case EQ:
     500                 :     178136 :     case GE:       case GT:       case GEU:    case GTU:
     501                 :     178136 :     case LE:       case LT:       case LEU:    case LTU:
     502                 :     178136 :       {
     503                 :     178136 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     504                 :            :                                          subst_p, update_p, 
     505                 :            :                                          update_sp_offset, full_p);
     506                 :     178136 :         rtx new1 = XEXP (x, 1)
     507                 :     178136 :                    ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     508                 :            :                                            subst_p, update_p,
     509                 :     178136 :                                            update_sp_offset, full_p) : 0;
     510                 :            : 
     511                 :     178136 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     512                 :      58034 :           return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
     513                 :            :       }
     514                 :            :       return x;
     515                 :            : 
     516                 :        100 :     case EXPR_LIST:
     517                 :            :       /* If we have something in XEXP (x, 0), the usual case,
     518                 :            :          eliminate it.  */
     519                 :        100 :       if (XEXP (x, 0))
     520                 :            :         {
     521                 :        100 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     522                 :            :                                           subst_p, update_p,
     523                 :            :                                           update_sp_offset, full_p);
     524                 :        100 :           if (new_rtx != XEXP (x, 0))
     525                 :            :             {
     526                 :            :               /* If this is a REG_DEAD note, it is not valid anymore.
     527                 :            :                  Using the eliminated version could result in creating a
     528                 :            :                  REG_DEAD note for the stack or frame pointer.  */
     529                 :          0 :               if (REG_NOTE_KIND (x) == REG_DEAD)
     530                 :          0 :                 return (XEXP (x, 1)
     531                 :          0 :                         ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     532                 :            :                                                 subst_p, update_p,
     533                 :            :                                                 update_sp_offset, full_p)
     534                 :            :                         : NULL_RTX);
     535                 :            : 
     536                 :          0 :               x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
     537                 :            :             }
     538                 :            :         }
     539                 :            : 
     540                 :            :       /* fall through */
     541                 :            : 
     542                 :        100 :     case INSN_LIST:
     543                 :        100 :     case INT_LIST:
     544                 :            :       /* Now do eliminations in the rest of the chain.  If this was
     545                 :            :          an EXPR_LIST, this might result in allocating more memory than is
     546                 :            :          strictly needed, but it simplifies the code.  */
     547                 :        100 :       if (XEXP (x, 1))
     548                 :            :         {
     549                 :        100 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     550                 :            :                                           subst_p, update_p,
     551                 :            :                                           update_sp_offset, full_p);
     552                 :        100 :           if (new_rtx != XEXP (x, 1))
     553                 :          0 :             return
     554                 :          0 :               gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x),
     555                 :            :                               XEXP (x, 0), new_rtx);
     556                 :            :         }
     557                 :        100 :       return x;
     558                 :            : 
     559                 :            :     case PRE_INC:
     560                 :            :     case POST_INC:
     561                 :            :     case PRE_DEC:
     562                 :            :     case POST_DEC:
     563                 :            :       /* We do not support elimination of a register that is modified.
     564                 :            :          elimination_effects has already make sure that this does not
     565                 :            :          happen.  */
     566                 :            :       return x;
     567                 :            : 
     568                 :          0 :     case PRE_MODIFY:
     569                 :          0 :     case POST_MODIFY:
     570                 :            :       /* We do not support elimination of a hard register that is
     571                 :            :          modified.  LRA has already make sure that this does not
     572                 :            :          happen. The only remaining case we need to consider here is
     573                 :            :          that the increment value may be an eliminable register.  */
     574                 :          0 :       if (GET_CODE (XEXP (x, 1)) == PLUS
     575                 :          0 :           && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
     576                 :            :         {
     577                 :          0 :           rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1),
     578                 :            :                                               mem_mode, subst_p, update_p,
     579                 :            :                                               update_sp_offset, full_p);
     580                 :            : 
     581                 :          0 :           if (new_rtx != XEXP (XEXP (x, 1), 1))
     582                 :          0 :             return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
     583                 :            :                                    gen_rtx_PLUS (GET_MODE (x),
     584                 :            :                                                  XEXP (x, 0), new_rtx));
     585                 :            :         }
     586                 :          0 :       return x;
     587                 :            : 
     588                 :      11022 :     case STRICT_LOW_PART:
     589                 :      11022 :     case NEG:          case NOT:
     590                 :      11022 :     case SIGN_EXTEND:  case ZERO_EXTEND:
     591                 :      11022 :     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
     592                 :      11022 :     case FLOAT:        case FIX:
     593                 :      11022 :     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
     594                 :      11022 :     case ABS:
     595                 :      11022 :     case SQRT:
     596                 :      11022 :     case FFS:
     597                 :      11022 :     case CLZ:
     598                 :      11022 :     case CTZ:
     599                 :      11022 :     case POPCOUNT:
     600                 :      11022 :     case PARITY:
     601                 :      11022 :     case BSWAP:
     602                 :      11022 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     603                 :            :                                       subst_p, update_p,
     604                 :            :                                       update_sp_offset, full_p);
     605                 :      11022 :       if (new_rtx != XEXP (x, 0))
     606                 :       9092 :         return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
     607                 :            :       return x;
     608                 :            : 
     609                 :     233395 :     case SUBREG:
     610                 :     233395 :       new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode,
     611                 :            :                                       subst_p, update_p,
     612                 :            :                                       update_sp_offset, full_p);
     613                 :            : 
     614                 :     233395 :       if (new_rtx != SUBREG_REG (x))
     615                 :            :         {
     616                 :       1571 :           if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
     617                 :            :             {
     618                 :         29 :               SUBREG_REG (x) = new_rtx;
     619                 :         29 :               alter_subreg (&x, false);
     620                 :         29 :               return x;
     621                 :            :             }
     622                 :       1542 :           else if (! subst_p)
     623                 :            :             {
     624                 :            :               /* LRA can transform subregs itself.  So don't call
     625                 :            :                  simplify_gen_subreg until LRA transformations are
     626                 :            :                  finished.  Function simplify_gen_subreg can do
     627                 :            :                  non-trivial transformations (like truncation) which
     628                 :            :                  might make LRA work to fail.  */
     629                 :        877 :               SUBREG_REG (x) = new_rtx;
     630                 :        877 :               return x;
     631                 :            :             }
     632                 :            :           else
     633                 :        665 :             return simplify_gen_subreg (GET_MODE (x), new_rtx,
     634                 :        665 :                                         GET_MODE (new_rtx), SUBREG_BYTE (x));
     635                 :            :         }
     636                 :            : 
     637                 :            :       return x;
     638                 :            : 
     639                 :   26546000 :     case MEM:
     640                 :            :       /* Our only special processing is to pass the mode of the MEM to our
     641                 :            :          recursive call and copy the flags.  While we are here, handle this
     642                 :            :          case more efficiently.  */
     643                 :   26546000 :       return
     644                 :            :         replace_equiv_address_nv
     645                 :   26546000 :         (x,
     646                 :   26546000 :          lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
     647                 :   26546000 :                                subst_p, update_p, update_sp_offset, full_p));
     648                 :            : 
     649                 :          0 :     case USE:
     650                 :            :       /* Handle insn_list USE that a call to a pure function may generate.  */
     651                 :          0 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
     652                 :            :                                       subst_p, update_p, update_sp_offset, full_p);
     653                 :          0 :       if (new_rtx != XEXP (x, 0))
     654                 :          0 :         return gen_rtx_USE (GET_MODE (x), new_rtx);
     655                 :            :       return x;
     656                 :            : 
     657                 :          0 :     case CLOBBER:
     658                 :          0 :     case SET:
     659                 :          0 :       gcc_unreachable ();
     660                 :            : 
     661                 :      61237 :     default:
     662                 :      61237 :       break;
     663                 :            :     }
     664                 :            : 
     665                 :            :   /* Process each of our operands recursively.  If any have changed, make a
     666                 :            :      copy of the rtx.  */
     667                 :      61237 :   fmt = GET_RTX_FORMAT (code);
     668                 :     135043 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     669                 :            :     {
     670                 :      73806 :       if (*fmt == 'e')
     671                 :            :         {
     672                 :      24286 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
     673                 :            :                                           subst_p, update_p,
     674                 :            :                                           update_sp_offset, full_p);
     675                 :      24286 :           if (new_rtx != XEXP (x, i) && ! copied)
     676                 :            :             {
     677                 :      11584 :               x = shallow_copy_rtx (x);
     678                 :      11584 :               copied = 1;
     679                 :            :             }
     680                 :      24286 :           XEXP (x, i) = new_rtx;
     681                 :            :         }
     682                 :      49520 :       else if (*fmt == 'E')
     683                 :            :         {
     684                 :            :           int copied_vec = 0;
     685                 :      52385 :           for (j = 0; j < XVECLEN (x, i); j++)
     686                 :            :             {
     687                 :      34947 :               new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
     688                 :            :                                               subst_p, update_p,
     689                 :            :                                               update_sp_offset, full_p);
     690                 :      34947 :               if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
     691                 :            :                 {
     692                 :      31324 :                   rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
     693                 :      15662 :                                              XVEC (x, i)->elem);
     694                 :      15662 :                   if (! copied)
     695                 :            :                     {
     696                 :      15662 :                       x = shallow_copy_rtx (x);
     697                 :      15662 :                       copied = 1;
     698                 :            :                     }
     699                 :      15662 :                   XVEC (x, i) = new_v;
     700                 :      15662 :                   copied_vec = 1;
     701                 :            :                 }
     702                 :      34947 :               XVECEXP (x, i, j) = new_rtx;
     703                 :            :             }
     704                 :            :         }
     705                 :            :     }
     706                 :            : 
     707                 :      61237 :   return x;
     708                 :            : }
     709                 :            : 
     710                 :            : /* This function is used externally in subsequent passes of GCC.  It
     711                 :            :    always does a full elimination of X.  */
     712                 :            : rtx
     713                 :    4247840 : lra_eliminate_regs (rtx x, machine_mode mem_mode,
     714                 :            :                     rtx insn ATTRIBUTE_UNUSED)
     715                 :            : {
     716                 :    4247840 :   return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
     717                 :            : }
     718                 :            : 
     719                 :            : /* Stack pointer offset before the current insn relative to one at the
     720                 :            :    func start.  RTL insns can change SP explicitly.  We keep the
     721                 :            :    changes from one insn to another through this variable.  */
     722                 :            : static poly_int64 curr_sp_change;
     723                 :            : 
     724                 :            : /* Scan rtx X for references to elimination source or target registers
     725                 :            :    in contexts that would prevent the elimination from happening.
     726                 :            :    Update the table of eliminables to reflect the changed state.
     727                 :            :    MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not
     728                 :            :    within a MEM.  */
     729                 :            : static void
     730                 :  187117000 : mark_not_eliminable (rtx x, machine_mode mem_mode)
     731                 :            : {
     732                 :  258525000 :   enum rtx_code code = GET_CODE (x);
     733                 :  258525000 :   class lra_elim_table *ep;
     734                 :  258525000 :   int i, j;
     735                 :  258525000 :   const char *fmt;
     736                 :  258525000 :   poly_int64 offset = 0;
     737                 :            : 
     738                 :  258525000 :   switch (code)
     739                 :            :     {
     740                 :    2097180 :     case PRE_INC:
     741                 :    2097180 :     case POST_INC:
     742                 :    2097180 :     case PRE_DEC:
     743                 :    2097180 :     case POST_DEC:
     744                 :    2097180 :     case POST_MODIFY:
     745                 :    2097180 :     case PRE_MODIFY:
     746                 :    2097180 :       if (XEXP (x, 0) == stack_pointer_rtx
     747                 :    2097180 :           && ((code != PRE_MODIFY && code != POST_MODIFY)
     748                 :      73145 :               || (GET_CODE (XEXP (x, 1)) == PLUS
     749                 :      73145 :                   && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
     750                 :      73145 :                   && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
     751                 :            :         {
     752                 :    4194350 :           poly_int64 size = GET_MODE_SIZE (mem_mode);
     753                 :            :           
     754                 :            : #ifdef PUSH_ROUNDING
     755                 :            :           /* If more bytes than MEM_MODE are pushed, account for
     756                 :            :              them.  */
     757                 :    2097180 :           size = PUSH_ROUNDING (size);
     758                 :            : #endif
     759                 :    2097180 :           if (code == PRE_DEC || code == POST_DEC)
     760                 :    2024010 :             curr_sp_change -= size;
     761                 :      73166 :           else if (code == PRE_INC || code == POST_INC)
     762                 :         21 :             curr_sp_change += size;
     763                 :      73145 :           else if (code == PRE_MODIFY || code == POST_MODIFY)
     764                 :      73145 :             curr_sp_change += offset;
     765                 :            :         }
     766                 :          0 :       else if (REG_P (XEXP (x, 0))
     767                 :          0 :                && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
     768                 :            :         {
     769                 :            :           /* If we modify the source of an elimination rule, disable
     770                 :            :              it.  Do the same if it is the destination and not the
     771                 :            :              hard frame register.  */
     772                 :          0 :           for (ep = reg_eliminate;
     773                 :          0 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     774                 :            :                ep++)
     775                 :          0 :             if (ep->from_rtx == XEXP (x, 0)
     776                 :          0 :                 || (ep->to_rtx == XEXP (x, 0)
     777                 :          0 :                     && ep->to_rtx != hard_frame_pointer_rtx))
     778                 :          0 :               setup_can_eliminate (ep, false);
     779                 :            :         }
     780                 :            :       return;
     781                 :            : 
     782                 :     599897 :     case USE:
     783                 :     599897 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     784                 :            :         /* If using a hard register that is the source of an eliminate
     785                 :            :            we still think can be performed, note it cannot be
     786                 :            :            performed since we don't know how this hard register is
     787                 :            :            used.  */
     788                 :     482904 :         for (ep = reg_eliminate;
     789                 :    2414520 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     790                 :            :              ep++)
     791                 :    1931620 :           if (ep->from_rtx == XEXP (x, 0)
     792                 :          0 :               && ep->to_rtx != hard_frame_pointer_rtx)
     793                 :    1931620 :             setup_can_eliminate (ep, false);
     794                 :            :       return;
     795                 :            : 
     796                 :    6766260 :     case CLOBBER:
     797                 :    6766260 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     798                 :            :         /* If clobbering a hard register that is the replacement
     799                 :            :            register for an elimination we still think can be
     800                 :            :            performed, note that it cannot be performed.  Otherwise, we
     801                 :            :            need not be concerned about it.  */
     802                 :    6621700 :         for (ep = reg_eliminate;
     803                 :   33108500 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     804                 :            :              ep++)
     805                 :   26486800 :           if (ep->to_rtx == XEXP (x, 0)
     806                 :       4292 :               && ep->to_rtx != hard_frame_pointer_rtx)
     807                 :   26486800 :             setup_can_eliminate (ep, false);
     808                 :            :       return;
     809                 :            : 
     810                 :   50334400 :     case SET:
     811                 :   50334400 :       if (SET_DEST (x) == stack_pointer_rtx
     812                 :    1464940 :           && GET_CODE (SET_SRC (x)) == PLUS
     813                 :    1452450 :           && XEXP (SET_SRC (x), 0) == SET_DEST (x)
     814                 :   51786900 :           && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
     815                 :            :         {
     816                 :    1452450 :           curr_sp_change += offset;
     817                 :    1452450 :           return;
     818                 :            :         }
     819                 :   48882000 :       if (! REG_P (SET_DEST (x))
     820                 :   48882000 :           || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
     821                 :   36220800 :         mark_not_eliminable (SET_DEST (x), mem_mode);
     822                 :            :       else
     823                 :            :         {
     824                 :            :           /* See if this is setting the replacement hard register for
     825                 :            :              an elimination.
     826                 :            :              
     827                 :            :              If DEST is the hard frame pointer, we do nothing because
     828                 :            :              we assume that all assignments to the frame pointer are
     829                 :            :              for non-local gotos and are being done at a time when
     830                 :            :              they are valid and do not disturb anything else.  Some
     831                 :            :              machines want to eliminate a fake argument pointer (or
     832                 :            :              even a fake frame pointer) with either the real frame
     833                 :            :              pointer or the stack pointer.  Assignments to the hard
     834                 :            :              frame pointer must not prevent this elimination.  */
     835                 :   12661200 :           for (ep = reg_eliminate;
     836                 :   63305900 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     837                 :            :                ep++)
     838                 :   50644700 :             if (ep->to_rtx == SET_DEST (x)
     839                 :      26708 :                 && SET_DEST (x) != hard_frame_pointer_rtx)
     840                 :   50669700 :               setup_can_eliminate (ep, false);
     841                 :            :         }
     842                 :            :       
     843                 :   48882000 :       mark_not_eliminable (SET_SRC (x), mem_mode);
     844                 :   48882000 :       return;
     845                 :            : 
     846                 :   22526100 :     case MEM:
     847                 :            :       /* Our only special processing is to pass the mode of the MEM to
     848                 :            :          our recursive call.  */
     849                 :   22526100 :       mark_not_eliminable (XEXP (x, 0), GET_MODE (x));
     850                 :   22526100 :       return;
     851                 :            : 
     852                 :  176201000 :     default:
     853                 :  176201000 :       break;
     854                 :            :     }
     855                 :            : 
     856                 :  176201000 :   fmt = GET_RTX_FORMAT (code);
     857                 :  396938000 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     858                 :            :     {
     859                 :  220737000 :       if (*fmt == 'e')
     860                 :   80859600 :         mark_not_eliminable (XEXP (x, i), mem_mode);
     861                 :  139877000 :       else if (*fmt == 'E')
     862                 :   25249200 :         for (j = 0; j < XVECLEN (x, i); j++)
     863                 :   16729900 :           mark_not_eliminable (XVECEXP (x, i, j), mem_mode);
     864                 :            :     }
     865                 :            : }
     866                 :            : 
     867                 :            : 
     868                 :            : 
     869                 :            : /* Scan INSN and eliminate all eliminable hard registers in it.
     870                 :            : 
     871                 :            :    If REPLACE_P is true, do the replacement destructively.  Also
     872                 :            :    delete the insn as dead it if it is setting an eliminable register.
     873                 :            : 
     874                 :            :    If REPLACE_P is false, just update the offsets while keeping the
     875                 :            :    base register the same.  If FIRST_P, use the sp offset for
     876                 :            :    elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
     877                 :            :    UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
     878                 :            :    and the previous offset.  Attach the note about used elimination
     879                 :            :    for insns setting frame pointer to update elimination easy (without
     880                 :            :    parsing already generated elimination insns to find offset
     881                 :            :    previously used) in future.  */
     882                 :            : 
     883                 :            : void
     884                 :   27228900 : eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
     885                 :            :                         poly_int64 update_sp_offset)
     886                 :            : {
     887                 :   27228900 :   int icode = recog_memoized (insn);
     888                 :   27228900 :   rtx old_set = single_set (insn);
     889                 :   27228900 :   bool validate_p;
     890                 :   27228900 :   int i;
     891                 :   27228900 :   rtx substed_operand[MAX_RECOG_OPERANDS];
     892                 :   27228900 :   rtx orig_operand[MAX_RECOG_OPERANDS];
     893                 :   27228900 :   class lra_elim_table *ep;
     894                 :   27228900 :   rtx plus_src, plus_cst_src;
     895                 :   27228900 :   lra_insn_recog_data_t id;
     896                 :   27228900 :   struct lra_static_insn_data *static_id;
     897                 :            : 
     898                 :   27228900 :   if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
     899                 :            :     {
     900                 :       4384 :       lra_assert (GET_CODE (PATTERN (insn)) == USE
     901                 :            :                   || GET_CODE (PATTERN (insn)) == CLOBBER
     902                 :            :                   || GET_CODE (PATTERN (insn)) == ASM_INPUT);
     903                 :    2578280 :       return;
     904                 :            :     }
     905                 :            : 
     906                 :            :   /* We allow one special case which happens to work on all machines we
     907                 :            :      currently support: a single set with the source or a REG_EQUAL
     908                 :            :      note being a PLUS of an eliminable register and a constant.  */
     909                 :   27224500 :   plus_src = plus_cst_src = 0;
     910                 :   27224500 :   poly_int64 offset = 0;
     911                 :   27224500 :   if (old_set && REG_P (SET_DEST (old_set)))
     912                 :            :     {
     913                 :   11219100 :       if (GET_CODE (SET_SRC (old_set)) == PLUS)
     914                 :    2703120 :         plus_src = SET_SRC (old_set);
     915                 :            :       /* First see if the source is of the form (plus (...) CST).  */
     916                 :    2703120 :       if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
     917                 :    2570720 :         plus_cst_src = plus_src;
     918                 :            :       /* Check that the first operand of the PLUS is a hard reg or
     919                 :            :          the lowpart subreg of one.  */
     920                 :    2570720 :       if (plus_cst_src)
     921                 :            :         {
     922                 :    2570720 :           rtx reg = XEXP (plus_cst_src, 0);
     923                 :            : 
     924                 :    2570720 :           if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
     925                 :         21 :             reg = SUBREG_REG (reg);
     926                 :            : 
     927                 :    2570720 :           if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
     928                 :            :             plus_cst_src = 0;
     929                 :            :         }
     930                 :            :     }
     931                 :   11210500 :   if (plus_cst_src)
     932                 :            :     {
     933                 :    2562160 :       rtx reg = XEXP (plus_cst_src, 0);
     934                 :            : 
     935                 :    2562160 :       if (GET_CODE (reg) == SUBREG)
     936                 :         21 :         reg = SUBREG_REG (reg);
     937                 :            : 
     938                 :    2562160 :       if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
     939                 :            :         {
     940                 :    2562160 :           rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
     941                 :            : 
     942                 :    2562160 :           if (! replace_p)
     943                 :            :             {
     944                 :    1293740 :               if (known_eq (update_sp_offset, 0))
     945                 :    1293740 :                 offset += (ep->offset - ep->previous_offset);
     946                 :    1293740 :               if (ep->to_rtx == stack_pointer_rtx)
     947                 :            :                 {
     948                 :    1016770 :                   if (first_p)
     949                 :     637536 :                     offset -= lra_get_insn_recog_data (insn)->sp_offset;
     950                 :            :                   else
     951                 :     379230 :                     offset += update_sp_offset;
     952                 :            :                 }
     953                 :    1293740 :               offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
     954                 :            :             }
     955                 :            : 
     956                 :    2562160 :           if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
     957                 :         21 :             to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
     958                 :            :           /* If we have a nonzero offset, and the source is already a
     959                 :            :              simple REG, the following transformation would increase
     960                 :            :              the cost of the insn by replacing a simple REG with (plus
     961                 :            :              (reg sp) CST).  So try only when we already had a PLUS
     962                 :            :              before.  */
     963                 :    2562160 :           if (known_eq (offset, 0) || plus_src)
     964                 :            :             {
     965                 :    2562160 :               rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
     966                 :            : 
     967                 :    2562160 :               old_set = single_set (insn);
     968                 :            : 
     969                 :            :               /* First see if this insn remains valid when we make the
     970                 :            :                  change.  If not, try to replace the whole pattern
     971                 :            :                  with a simple set (this may help if the original insn
     972                 :            :                  was a PARALLEL that was only recognized as single_set
     973                 :            :                  due to REG_UNUSED notes).  If this isn't valid
     974                 :            :                  either, keep the INSN_CODE the same and let the
     975                 :            :                  constraint pass fix it up.  */
     976                 :    2562160 :               if (! validate_change (insn, &SET_SRC (old_set), new_src, 0))
     977                 :            :                 {
     978                 :          2 :                   rtx new_pat = gen_rtx_SET (SET_DEST (old_set), new_src);
     979                 :            : 
     980                 :          2 :                   if (! validate_change (insn, &PATTERN (insn), new_pat, 0))
     981                 :          2 :                     SET_SRC (old_set) = new_src;
     982                 :            :                 }
     983                 :    2562160 :               lra_update_insn_recog_data (insn);
     984                 :            :               /* This can't have an effect on elimination offsets, so skip
     985                 :            :                  right to the end.  */
     986                 :    2562160 :               return;
     987                 :            :             }
     988                 :            :         }
     989                 :            :     }
     990                 :            : 
     991                 :            :   /* Eliminate all eliminable registers occurring in operands that
     992                 :            :      can be handled by the constraint pass.  */
     993                 :   24662300 :   id = lra_get_insn_recog_data (insn);
     994                 :   24662300 :   static_id = id->insn_static_data;
     995                 :   24662300 :   validate_p = false;
     996                 :   70368000 :   for (i = 0; i < static_id->n_operands; i++)
     997                 :            :     {
     998                 :   45705700 :       orig_operand[i] = *id->operand_loc[i];
     999                 :   45705700 :       substed_operand[i] = *id->operand_loc[i];
    1000                 :            : 
    1001                 :            :       /* For an asm statement, every operand is eliminable.  */
    1002                 :   45705700 :       if (icode < 0 || insn_data[icode].operand[i].eliminable)
    1003                 :            :         {
    1004                 :            :           /* Check for setting a hard register that we know about.  */
    1005                 :   45625800 :           if (static_id->operand[i].type != OP_IN
    1006                 :   19702800 :               && REG_P (orig_operand[i]))
    1007                 :            :             {
    1008                 :            :               /* If we are assigning to a hard register that can be
    1009                 :            :                  eliminated, it must be as part of a PARALLEL, since
    1010                 :            :                  the code above handles single SETs.  This reg cannot
    1011                 :            :                  be longer eliminated -- it is forced by
    1012                 :            :                  mark_not_eliminable.  */
    1013                 :   40268900 :               for (ep = reg_eliminate;
    1014                 :   40268900 :                    ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
    1015                 :            :                    ep++)
    1016                 :   32215100 :                 lra_assert (ep->from_rtx != orig_operand[i]
    1017                 :            :                             || ! ep->can_eliminate);
    1018                 :            :             }
    1019                 :            : 
    1020                 :            :           /* Companion to the above plus substitution, we can allow
    1021                 :            :              invariants as the source of a plain move.  */
    1022                 :   45625800 :           substed_operand[i]
    1023                 :   91251600 :             = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
    1024                 :   45625800 :                                     replace_p, ! replace_p && ! first_p,
    1025                 :            :                                     update_sp_offset, first_p);
    1026                 :   45625800 :           if (substed_operand[i] != orig_operand[i])
    1027                 :   24911000 :             validate_p = true;
    1028                 :            :         }
    1029                 :            :     }
    1030                 :            : 
    1031                 :   24662300 :   if (! validate_p)
    1032                 :            :     return;
    1033                 :            : 
    1034                 :            :   /* Substitute the operands; the new values are in the substed_operand
    1035                 :            :      array.  */
    1036                 :   70329800 :   for (i = 0; i < static_id->n_operands; i++)
    1037                 :   45679200 :     *id->operand_loc[i] = substed_operand[i];
    1038                 :   24720600 :   for (i = 0; i < static_id->n_dups; i++)
    1039                 :      69995 :     *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]];
    1040                 :            : 
    1041                 :            :   /* If we had a move insn but now we don't, re-recognize it.
    1042                 :            :      This will cause spurious re-recognition if the old move had a
    1043                 :            :      PARALLEL since the new one still will, but we can't call
    1044                 :            :      single_set without having put new body into the insn and the
    1045                 :            :      re-recognition won't hurt in this rare case.  */
    1046                 :   24650600 :   lra_update_insn_recog_data (insn);
    1047                 :            : }
    1048                 :            : 
    1049                 :            : /* Spill pseudos which are assigned to hard registers in SET.  Add
    1050                 :            :    affected insns for processing in the subsequent constraint
    1051                 :            :    pass.  */
    1052                 :            : static void
    1053                 :    5052330 : spill_pseudos (HARD_REG_SET set)
    1054                 :            : {
    1055                 :    5052330 :   int i;
    1056                 :    5052330 :   bitmap_head to_process;
    1057                 :    5052330 :   rtx_insn *insn;
    1058                 :            : 
    1059                 :   10104700 :   if (hard_reg_set_empty_p (set))
    1060                 :          0 :     return;
    1061                 :    5052330 :   if (lra_dump_file != NULL)
    1062                 :            :     {
    1063                 :        580 :       fprintf (lra_dump_file, "       Spilling non-eliminable hard regs:");
    1064                 :      44660 :       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1065                 :      44080 :         if (TEST_HARD_REG_BIT (set, i))
    1066                 :        580 :           fprintf (lra_dump_file, " %d", i);
    1067                 :        580 :       fprintf (lra_dump_file, "\n");
    1068                 :            :     }
    1069                 :    5052330 :   bitmap_initialize (&to_process, &reg_obstack);
    1070                 :  315512000 :   for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1071                 :  149874000 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1072                 :  451292000 :         && overlaps_hard_reg_set_p (set,
    1073                 :  140858000 :                                     PSEUDO_REGNO_MODE (i), reg_renumber[i]))
    1074                 :            :       {
    1075                 :      25556 :         if (lra_dump_file != NULL)
    1076                 :          0 :           fprintf (lra_dump_file, "         Spilling r%d(%d)\n",
    1077                 :            :                    i, reg_renumber[i]);
    1078                 :      25556 :         reg_renumber[i] = -1;
    1079                 :      25556 :         bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
    1080                 :            :       }
    1081                 :   15157000 :   lra_no_alloc_regs |= set;
    1082                 : 1500060000 :   for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
    1083                 :  747503000 :     if (bitmap_bit_p (&to_process, INSN_UID (insn)))
    1084                 :            :       {
    1085                 :     150551 :         lra_push_insn (insn);
    1086                 :     150551 :         lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1087                 :            :       }
    1088                 :    5052330 :   bitmap_clear (&to_process);
    1089                 :            : }
    1090                 :            : 
    1091                 :            : /* Update all offsets and possibility for elimination on eliminable
    1092                 :            :    registers.  Spill pseudos assigned to registers which are
    1093                 :            :    uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
    1094                 :            :    insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
    1095                 :            :    registers whose offsets should be changed.  Return true if any
    1096                 :            :    elimination offset changed.  */
    1097                 :            : static bool
    1098                 :    5052330 : update_reg_eliminate (bitmap insns_with_changed_offsets)
    1099                 :            : {
    1100                 :    5052330 :   bool prev, result;
    1101                 :    5052330 :   class lra_elim_table *ep, *ep1;
    1102                 :    5052330 :   HARD_REG_SET temp_hard_reg_set;
    1103                 :            : 
    1104                 :    5052330 :   targetm.compute_frame_layout ();
    1105                 :            : 
    1106                 :            :   /* Clear self elimination offsets.  */
    1107                 :   25261600 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1108                 :   20209300 :     self_elim_offsets[ep->from] = 0;
    1109                 :   25261600 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1110                 :            :     {
    1111                 :            :       /* If it is a currently used elimination: update the previous
    1112                 :            :          offset.  */
    1113                 :   20209300 :       if (elimination_map[ep->from] == ep)
    1114                 :   10104700 :         ep->previous_offset = ep->offset;
    1115                 :            : 
    1116                 :   20209300 :       prev = ep->prev_can_eliminate;
    1117                 :   20209300 :       setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
    1118                 :   20209300 :       if (ep->can_eliminate && ! prev)
    1119                 :            :         {
    1120                 :            :           /* It is possible that not eliminable register becomes
    1121                 :            :              eliminable because we took other reasons into account to
    1122                 :            :              set up eliminable regs in the initial set up.  Just
    1123                 :            :              ignore new eliminable registers.  */
    1124                 :          0 :           setup_can_eliminate (ep, false);
    1125                 :          0 :           continue;
    1126                 :            :         }
    1127                 :   20209300 :       if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
    1128                 :            :         {
    1129                 :            :           /* We cannot use this elimination anymore -- find another
    1130                 :            :              one.  */
    1131                 :          0 :           if (lra_dump_file != NULL)
    1132                 :          0 :             fprintf (lra_dump_file,
    1133                 :            :                      "     Elimination %d to %d is not possible anymore\n",
    1134                 :            :                      ep->from, ep->to);
    1135                 :            :           /* If after processing RTL we decides that SP can be used as
    1136                 :            :              a result of elimination, it cannot be changed.  */
    1137                 :          0 :           gcc_assert ((ep->to_rtx != stack_pointer_rtx)
    1138                 :            :                       || (ep->from < FIRST_PSEUDO_REGISTER
    1139                 :            :                           && fixed_regs [ep->from]));
    1140                 :            :           /* Mark that is not eliminable anymore.  */
    1141                 :          0 :           elimination_map[ep->from] = NULL;
    1142                 :          0 :           for (ep1 = ep + 1; ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
    1143                 :          0 :             if (ep1->can_eliminate && ep1->from == ep->from)
    1144                 :            :               break;
    1145                 :          0 :           if (ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS])
    1146                 :            :             {
    1147                 :          0 :               if (lra_dump_file != NULL)
    1148                 :          0 :                 fprintf (lra_dump_file, "    Using elimination %d to %d now\n",
    1149                 :            :                          ep1->from, ep1->to);
    1150                 :          0 :               lra_assert (known_eq (ep1->previous_offset, 0));
    1151                 :          0 :               ep1->previous_offset = ep->offset;
    1152                 :            :             }
    1153                 :            :           else
    1154                 :            :             {
    1155                 :            :               /* There is no elimination anymore just use the hard
    1156                 :            :                  register `from' itself.  Setup self elimination
    1157                 :            :                  offset to restore the original offset values.  */
    1158                 :          0 :               if (lra_dump_file != NULL)
    1159                 :          0 :                 fprintf (lra_dump_file, "    %d is not eliminable at all\n",
    1160                 :            :                          ep->from);
    1161                 :          0 :               self_elim_offsets[ep->from] = -ep->offset;
    1162                 :          0 :               if (maybe_ne (ep->offset, 0))
    1163                 :          0 :                 bitmap_ior_into (insns_with_changed_offsets,
    1164                 :          0 :                                  &lra_reg_info[ep->from].insn_bitmap);
    1165                 :            :             }
    1166                 :            :         }
    1167                 :            : 
    1168                 :   20209300 :       INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset);
    1169                 :            :     }
    1170                 :    5052330 :   setup_elimination_map ();
    1171                 :    5052330 :   result = false;
    1172                 :    5052330 :   CLEAR_HARD_REG_SET (temp_hard_reg_set);
    1173                 :   25261600 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1174                 :   20209300 :     if (elimination_map[ep->from] == NULL)
    1175                 :   20209300 :       add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
    1176                 :   20209300 :     else if (elimination_map[ep->from] == ep)
    1177                 :            :       {
    1178                 :            :         /* Prevent the hard register into which we eliminate from
    1179                 :            :            the usage for pseudos.  */
    1180                 :   10104700 :         if (ep->from != ep->to)
    1181                 :   11285400 :           add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
    1182                 :   10104700 :         if (maybe_ne (ep->previous_offset, ep->offset))
    1183                 :            :           {
    1184                 :    1303240 :             bitmap_ior_into (insns_with_changed_offsets,
    1185                 :    1303240 :                              &lra_reg_info[ep->from].insn_bitmap);
    1186                 :            : 
    1187                 :            :             /* Update offset when the eliminate offset have been
    1188                 :            :                changed.  */
    1189                 :    1303240 :             lra_update_reg_val_offset (lra_reg_info[ep->from].val,
    1190                 :            :                                        ep->offset - ep->previous_offset);
    1191                 :    1303240 :             result = true;
    1192                 :            :           }
    1193                 :            :       }
    1194                 :   15157000 :   lra_no_alloc_regs |= temp_hard_reg_set;
    1195                 :   15157000 :   eliminable_regset &= ~temp_hard_reg_set;
    1196                 :    5052330 :   spill_pseudos (temp_hard_reg_set);
    1197                 :    5052330 :   return result;
    1198                 :            : }
    1199                 :            : 
    1200                 :            : /* Initialize the table of hard registers to eliminate.
    1201                 :            :    Pre-condition: global flag frame_pointer_needed has been set before
    1202                 :            :    calling this function.  */
    1203                 :            : static void
    1204                 :     944096 : init_elim_table (void)
    1205                 :            : {
    1206                 :     944096 :   class lra_elim_table *ep;
    1207                 :     944096 :   bool value_p;
    1208                 :     944096 :   const struct elim_table_1 *ep1;
    1209                 :            : 
    1210                 :     944096 :   if (!reg_eliminate)
    1211                 :     148706 :     reg_eliminate = XCNEWVEC (class lra_elim_table, NUM_ELIMINABLE_REGS);
    1212                 :            : 
    1213                 :     944096 :   memset (self_elim_offsets, 0, sizeof (self_elim_offsets));
    1214                 :            :   /* Initiate member values which will be never changed.  */
    1215                 :     944096 :   self_elim_table.can_eliminate = self_elim_table.prev_can_eliminate = true;
    1216                 :     944096 :   self_elim_table.previous_offset = 0;
    1217                 :            : 
    1218                 :     944096 :   for (ep = reg_eliminate, ep1 = reg_eliminate_1;
    1219                 :    4720480 :        ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
    1220                 :            :     {
    1221                 :    3776380 :       ep->offset = ep->previous_offset = 0;
    1222                 :    3776380 :       ep->from = ep1->from;
    1223                 :    3776380 :       ep->to = ep1->to;
    1224                 :    3776380 :       value_p = (targetm.can_eliminate (ep->from, ep->to)
    1225                 :    3776380 :                  && ! (ep->to == STACK_POINTER_REGNUM
    1226                 :    1325040 :                        && frame_pointer_needed
    1227                 :      40003 :                        && (! SUPPORTS_STACK_ALIGNMENT
    1228                 :      40003 :                            || ! stack_realign_fp)));
    1229                 :    7552770 :       setup_can_eliminate (ep, value_p);
    1230                 :            :     }
    1231                 :            : 
    1232                 :            :   /* Build the FROM and TO REG rtx's.  Note that code in gen_rtx_REG
    1233                 :            :      will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to
    1234                 :            :      equal stack_pointer_rtx.  We depend on this. Threfore we switch
    1235                 :            :      off that we are in LRA temporarily.  */
    1236                 :     944096 :   lra_in_progress = 0;
    1237                 :    4720480 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1238                 :            :     {
    1239                 :    4156940 :       ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
    1240                 :    4156940 :       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
    1241                 :    3776380 :       eliminable_reg_rtx[ep->from] = ep->from_rtx;
    1242                 :            :     }
    1243                 :     944096 :   lra_in_progress = 1;
    1244                 :     944096 : }
    1245                 :            : 
    1246                 :            : /* Function for initialization of elimination once per function.  It
    1247                 :            :    sets up sp offset for each insn.  */
    1248                 :            : static void
    1249                 :     944096 : init_elimination (void)
    1250                 :            : {
    1251                 :     944096 :   bool stop_to_sp_elimination_p;
    1252                 :     944096 :   basic_block bb;
    1253                 :     944096 :   rtx_insn *insn;
    1254                 :     944096 :   class lra_elim_table *ep;
    1255                 :            : 
    1256                 :     944096 :   init_elim_table ();
    1257                 :   10066000 :   FOR_EACH_BB_FN (bb, cfun)
    1258                 :            :     {
    1259                 :    9121910 :       curr_sp_change = 0;
    1260                 :    9121910 :       stop_to_sp_elimination_p = false;
    1261                 :  205186000 :       FOR_BB_INSNS (bb, insn)
    1262                 :   98032300 :         if (INSN_P (insn))
    1263                 :            :           {
    1264                 :   81346000 :             lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change;
    1265                 :   81346000 :             if (NONDEBUG_INSN_P (insn))
    1266                 :            :               {
    1267                 :   53306900 :                 mark_not_eliminable (PATTERN (insn), VOIDmode);
    1268                 :   53306900 :                 if (maybe_ne (curr_sp_change, 0)
    1269                 :   53306900 :                     && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
    1270                 :            :                   stop_to_sp_elimination_p = true;
    1271                 :            :               }
    1272                 :            :           }
    1273                 :    9121910 :       if (! frame_pointer_needed
    1274                 :    6229410 :           && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
    1275                 :    9170030 :           && bb->succs && bb->succs->length () != 0)
    1276                 :      40235 :         for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1277                 :      32188 :           if (ep->to == STACK_POINTER_REGNUM)
    1278                 :      48282 :             setup_can_eliminate (ep, false);
    1279                 :            :     }
    1280                 :     944096 :   setup_elimination_map ();
    1281                 :     944096 : }
    1282                 :            : 
    1283                 :            : /* Eliminate hard reg given by its location LOC.  */
    1284                 :            : void
    1285                 :   58972300 : lra_eliminate_reg_if_possible (rtx *loc)
    1286                 :            : {
    1287                 :   58972300 :   int regno;
    1288                 :   58972300 :   class lra_elim_table *ep;
    1289                 :            : 
    1290                 :   58972300 :   lra_assert (REG_P (*loc));
    1291                 :   58972300 :   if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
    1292                 :   58972300 :       || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
    1293                 :            :     return;
    1294                 :   44128600 :   if ((ep = get_elimination (*loc)) != NULL)
    1295                 :   41761500 :     *loc = ep->to_rtx;
    1296                 :            : }
    1297                 :            : 
    1298                 :            : /* Do (final if FINAL_P or first if FIRST_P) elimination in INSN.  Add
    1299                 :            :    the insn for subsequent processing in the constraint pass, update
    1300                 :            :    the insn info.  */
    1301                 :            : static void
    1302                 :   27228700 : process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
    1303                 :            : {
    1304                 :   27228700 :   eliminate_regs_in_insn (insn, final_p, first_p, 0);
    1305                 :   27228700 :   if (! final_p)
    1306                 :            :     {
    1307                 :            :       /* Check that insn changed its code.  This is a case when a move
    1308                 :            :          insn becomes an add insn and we do not want to process the
    1309                 :            :          insn as a move anymore.  */
    1310                 :   13563800 :       int icode = recog (PATTERN (insn), insn, 0);
    1311                 :            : 
    1312                 :   13563800 :       if (icode >= 0 && icode != INSN_CODE (insn))
    1313                 :            :         {
    1314                 :      34337 :           if (INSN_CODE (insn) >= 0)
    1315                 :            :             /* Insn code is changed.  It may change its operand type
    1316                 :            :                from IN to INOUT.  Inform the subsequent assignment
    1317                 :            :                subpass about this situation.  */
    1318                 :      34337 :             check_and_force_assignment_correctness_p = true;
    1319                 :      34337 :           INSN_CODE (insn) = icode;
    1320                 :      34337 :           lra_update_insn_recog_data (insn);
    1321                 :            :         }
    1322                 :   13563800 :       lra_update_insn_regno_info (insn);
    1323                 :   13563800 :       lra_push_insn (insn);
    1324                 :   13563800 :       lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1325                 :            :     }
    1326                 :   27228700 : }
    1327                 :            : 
    1328                 :            : /* Entry function to do final elimination if FINAL_P or to update
    1329                 :            :    elimination register offsets (FIRST_P if we are doing it the first
    1330                 :            :    time).  */
    1331                 :            : void
    1332                 :    5052340 : lra_eliminate (bool final_p, bool first_p)
    1333                 :            : {
    1334                 :    5052340 :   unsigned int uid;
    1335                 :    5052340 :   bitmap_head insns_with_changed_offsets;
    1336                 :    5052340 :   bitmap_iterator bi;
    1337                 :    5052340 :   class lra_elim_table *ep;
    1338                 :            : 
    1339                 :    5052340 :   gcc_assert (! final_p || ! first_p);
    1340                 :            : 
    1341                 :    5052340 :   timevar_push (TV_LRA_ELIMINATE);
    1342                 :            : 
    1343                 :    5052340 :   if (first_p)
    1344                 :     944096 :     init_elimination ();
    1345                 :            : 
    1346                 :    5052340 :   bitmap_initialize (&insns_with_changed_offsets, &reg_obstack);
    1347                 :    5052340 :   if (final_p)
    1348                 :            :     {
    1349                 :     944096 :       if (flag_checking)
    1350                 :            :         {
    1351                 :     944084 :           update_reg_eliminate (&insns_with_changed_offsets);
    1352                 :     944084 :           gcc_assert (bitmap_empty_p (&insns_with_changed_offsets));
    1353                 :            :         }
    1354                 :            :       /* We change eliminable hard registers in insns so we should do
    1355                 :            :          this for all insns containing any eliminable hard
    1356                 :            :          register.  */
    1357                 :    4720480 :       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1358                 :    3776380 :         if (elimination_map[ep->from] != NULL)
    1359                 :    3776380 :           bitmap_ior_into (&insns_with_changed_offsets,
    1360                 :    3776380 :                            &lra_reg_info[ep->from].insn_bitmap);
    1361                 :            :     }
    1362                 :    4108240 :   else if (! update_reg_eliminate (&insns_with_changed_offsets))
    1363                 :    3099780 :     goto lra_eliminate_done;
    1364                 :    1952550 :   if (lra_dump_file != NULL)
    1365                 :            :     {
    1366                 :        225 :       fprintf (lra_dump_file, "New elimination table:\n");
    1367                 :        225 :       print_elim_table (lra_dump_file);
    1368                 :            :     }
    1369                 :   29181300 :   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
    1370                 :            :     /* A dead insn can be deleted in process_insn_for_elimination.  */
    1371                 :   27228700 :     if (lra_insn_recog_data[uid] != NULL)
    1372                 :   27228700 :       process_insn_for_elimination (lra_insn_recog_data[uid]->insn,
    1373                 :            :                                     final_p, first_p);
    1374                 :    1952550 :   bitmap_clear (&insns_with_changed_offsets);
    1375                 :            : 
    1376                 :    5052340 : lra_eliminate_done:
    1377                 :    5052340 :   timevar_pop (TV_LRA_ELIMINATE);
    1378                 :    5052340 : }

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.