LCOV - code coverage report
Current view: top level - gcc - lra-eliminations.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 85.0 % 658 559
Test Date: 2024-04-20 14:03:02 Functions: 95.2 % 21 20
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-2024 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                 :         209 : print_elim_table (FILE *f)
     120                 :             : {
     121                 :         209 :   class lra_elim_table *ep;
     122                 :             : 
     123                 :        1045 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     124                 :             :     {
     125                 :         836 :       fprintf (f, "%s eliminate %d to %d (offset=",
     126                 :         836 :                ep->can_eliminate ? "Can" : "Can't", ep->from, ep->to);
     127                 :         836 :       print_dec (ep->offset, f);
     128                 :         836 :       fprintf (f, ", prev_offset=");
     129                 :         836 :       print_dec (ep->previous_offset, f);
     130                 :         836 :       fprintf (f, ")\n");
     131                 :             :     }
     132                 :         209 : }
     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                 :    36494978 : setup_can_eliminate (class lra_elim_table *ep, bool value)
     146                 :             : {
     147                 :    36494978 :   ep->can_eliminate = ep->prev_can_eliminate = value;
     148                 :    36494978 :   if (! value
     149                 :     6356040 :       && ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
     150                 :     2859737 :     frame_pointer_needed = 1;
     151                 :    36494978 :   if (!frame_pointer_needed)
     152                 :    23862592 :     REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 0;
     153                 :    36494978 : }
     154                 :             : 
     155                 :             : /* Map: eliminable "from" register -> its current elimination,
     156                 :             :    or NULL if none.  The elimination table may contain more than
     157                 :             :    one elimination for the same hard register, but this map specifies
     158                 :             :    the one that we are currently using.  */
     159                 :             : static class lra_elim_table *elimination_map[FIRST_PSEUDO_REGISTER];
     160                 :             : 
     161                 :             : /* When an eliminable hard register becomes not eliminable, we use the
     162                 :             :    following special structure to restore original offsets for the
     163                 :             :    register.  */
     164                 :             : static class lra_elim_table self_elim_table;
     165                 :             : 
     166                 :             : /* Offsets should be used to restore original offsets for eliminable
     167                 :             :    hard register which just became not eliminable.  Zero,
     168                 :             :    otherwise.  */
     169                 :             : static poly_int64 self_elim_offsets[FIRST_PSEUDO_REGISTER];
     170                 :             : 
     171                 :             : /* Map: hard regno -> RTL presentation.       RTL presentations of all
     172                 :             :    potentially eliminable hard registers are stored in the map.  */
     173                 :             : static rtx eliminable_reg_rtx[FIRST_PSEUDO_REGISTER];
     174                 :             : 
     175                 :             : /* Set up ELIMINATION_MAP of the currently used eliminations.  */
     176                 :             : static void
     177                 :     9106297 : setup_elimination_map (void)
     178                 :             : {
     179                 :     9106297 :   int i;
     180                 :     9106297 :   class lra_elim_table *ep;
     181                 :             : 
     182                 :   846885621 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
     183                 :   837779324 :     elimination_map[i] = NULL;
     184                 :    45531485 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
     185                 :    36425188 :     if (ep->can_eliminate && elimination_map[ep->from] == NULL)
     186                 :    18212594 :       elimination_map[ep->from] = ep;
     187                 :     9106297 : }
     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                 :     1102791 : form_sum (rtx x, rtx y)
     199                 :             : {
     200                 :     1313290 :   machine_mode mode = GET_MODE (x);
     201                 :     1313290 :   poly_int64 offset;
     202                 :             : 
     203                 :     1313290 :   if (mode == VOIDmode)
     204                 :       61636 :     mode = GET_MODE (y);
     205                 :             : 
     206                 :     1313290 :   if (mode == VOIDmode)
     207                 :           0 :     mode = Pmode;
     208                 :             : 
     209                 :     1313290 :   if (poly_int_rtx_p (x, &offset))
     210                 :       61636 :     return plus_constant (mode, y, offset);
     211                 :     1251654 :   else if (poly_int_rtx_p (y, &offset))
     212                 :      702742 :     return plus_constant (mode, x, offset);
     213                 :      548912 :   else if (CONSTANT_P (x))
     214                 :          14 :     std::swap (x, y);
     215                 :             : 
     216                 :      548912 :   if (GET_CODE (x) == PLUS && CONSTANT_P (XEXP (x, 1)))
     217                 :       61650 :     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                 :      487262 :   if (GET_CODE (y) == PLUS && CONSTANT_P (XEXP (y, 1)))
     223                 :      148849 :     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                 :      338413 :   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                 :      338413 :   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                 :   329263522 : lra_get_elimination_hard_regno (int hard_regno)
     244                 :             : {
     245                 :   329263522 :   class lra_elim_table *ep;
     246                 :             : 
     247                 :   329263522 :   if (hard_regno < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     248                 :             :     return hard_regno;
     249                 :   329263522 :   if ((ep = elimination_map[hard_regno]) == NULL)
     250                 :             :     return hard_regno;
     251                 :    27709550 :   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                 :   137333268 : get_elimination (rtx reg)
     258                 :             : {
     259                 :   137333268 :   int hard_regno;
     260                 :   137333268 :   class lra_elim_table *ep;
     261                 :             : 
     262                 :   137333268 :   lra_assert (REG_P (reg));
     263                 :   137333268 :   if ((hard_regno = REGNO (reg)) < 0 || hard_regno >= FIRST_PSEUDO_REGISTER)
     264                 :             :     return NULL;
     265                 :   114483705 :   if ((ep = elimination_map[hard_regno]) != NULL)
     266                 :   109380738 :     return ep->from_rtx != reg ? NULL : ep;
     267                 :     5102967 :   poly_int64 offset = self_elim_offsets[hard_regno];
     268                 :     5102967 :   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                 :     1862394 : move_plus_up (rtx x)
     286                 :             : {
     287                 :     1862394 :   rtx subreg_reg;
     288                 :     1862394 :   machine_mode x_mode, subreg_reg_mode;
     289                 :             : 
     290                 :     1862394 :   if (GET_CODE (x) != SUBREG || !subreg_lowpart_p (x))
     291                 :     1862265 :     return x;
     292                 :         129 :   subreg_reg = SUBREG_REG (x);
     293                 :         129 :   x_mode = GET_MODE (x);
     294                 :         129 :   subreg_reg_mode = GET_MODE (subreg_reg);
     295                 :         129 :   if (!paradoxical_subreg_p (x)
     296                 :         129 :       && GET_CODE (subreg_reg) == PLUS
     297                 :           1 :       && CONSTANT_P (XEXP (subreg_reg, 1))
     298                 :           1 :       && GET_MODE_CLASS (x_mode) == MODE_INT
     299                 :         130 :       && 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                 :             : /* Flag that we already did frame pointer to stack pointer elimination.  */
     313                 :             : static bool elimination_fp2sp_occured_p = false;
     314                 :             : 
     315                 :             : /* Scan X and replace any eliminable registers (such as fp) with a
     316                 :             :    replacement (such as sp) if SUBST_P, plus an offset.  The offset is
     317                 :             :    a change in the offset between the eliminable register and its
     318                 :             :    substitution if UPDATE_P, or the full offset if FULL_P, or
     319                 :             :    otherwise zero.  If FULL_P, we also use the SP offsets for
     320                 :             :    elimination to SP.  If UPDATE_P, use UPDATE_SP_OFFSET for updating
     321                 :             :    offsets of register elimnable to SP.  If UPDATE_SP_OFFSET is
     322                 :             :    non-zero, don't use difference of the offset and the previous
     323                 :             :    offset.
     324                 :             : 
     325                 :             :    MEM_MODE is the mode of an enclosing MEM.  We need this to know how
     326                 :             :    much to adjust a register for, e.g., PRE_DEC.  Also, if we are
     327                 :             :    inside a MEM, we are allowed to replace a sum of a hard register
     328                 :             :    and the constant zero with the hard register, which we cannot do
     329                 :             :    outside a MEM.  In addition, we need to record the fact that a
     330                 :             :    hard register is referenced outside a MEM.
     331                 :             : 
     332                 :             :    If we make full substitution to SP for non-null INSN, add the insn
     333                 :             :    sp offset.  */
     334                 :             : rtx
     335                 :   118326619 : lra_eliminate_regs_1 (rtx_insn *insn, rtx x, machine_mode mem_mode,
     336                 :             :                       bool subst_p, bool update_p,
     337                 :             :                       poly_int64 update_sp_offset, bool full_p)
     338                 :             : {
     339                 :   118326619 :   enum rtx_code code = GET_CODE (x);
     340                 :   118326619 :   class lra_elim_table *ep;
     341                 :   118326619 :   rtx new_rtx;
     342                 :   118326619 :   int i, j;
     343                 :   118326619 :   const char *fmt;
     344                 :   118326619 :   int copied = 0;
     345                 :             : 
     346                 :   118326619 :   lra_assert (!update_p || !full_p);
     347                 :   118326619 :   lra_assert (known_eq (update_sp_offset, 0)
     348                 :             :               || (!subst_p && update_p && !full_p));
     349                 :   118326619 :   if (! current_function_decl)
     350                 :             :     return x;
     351                 :             : 
     352                 :   118326619 :   switch (code)
     353                 :             :     {
     354                 :             :     CASE_CONST_ANY:
     355                 :             :     case CONST:
     356                 :             :     case SYMBOL_REF:
     357                 :             :     case CODE_LABEL:
     358                 :             :     case PC:
     359                 :             :     case ASM_INPUT:
     360                 :             :     case ADDR_VEC:
     361                 :             :     case ADDR_DIFF_VEC:
     362                 :             :     case RETURN:
     363                 :             :       return x;
     364                 :             : 
     365                 :    32720773 :     case REG:
     366                 :             :       /* First handle the case where we encounter a bare hard register
     367                 :             :          that is eliminable.  Replace it with a PLUS.  */
     368                 :    32720773 :       if ((ep = get_elimination (x)) != NULL)
     369                 :             :         {
     370                 :     8372463 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     371                 :             : 
     372                 :     8372463 :           if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM)
     373                 :     1272121 :             elimination_fp2sp_occured_p = true;
     374                 :             : 
     375                 :     8372463 :           if (maybe_ne (update_sp_offset, 0))
     376                 :             :             {
     377                 :           0 :               if (ep->to_rtx == stack_pointer_rtx)
     378                 :           0 :                 return plus_constant (Pmode, to, update_sp_offset);
     379                 :             :               return to;
     380                 :             :             }
     381                 :     8372463 :           else if (update_p)
     382                 :      350100 :             return plus_constant (Pmode, to, ep->offset - ep->previous_offset);
     383                 :     8022363 :           else if (full_p)
     384                 :     7286445 :             return plus_constant (Pmode, to,
     385                 :     7286445 :                                   ep->offset
     386                 :             :                                   - (insn != NULL_RTX
     387                 :      529397 :                                      && ep->to_rtx == stack_pointer_rtx
     388                 :     7644571 :                                      ? lra_get_insn_recog_data (insn)->sp_offset
     389                 :             :                                      : 0));
     390                 :             :           else
     391                 :             :             return to;
     392                 :             :         }
     393                 :    24348310 :       return x;
     394                 :             : 
     395                 :    41192315 :     case PLUS:
     396                 :             :       /* If this is the sum of an eliminable register and a constant, rework
     397                 :             :          the sum.  */
     398                 :    41192315 :       if (REG_P (XEXP (x, 0)) && CONSTANT_P (XEXP (x, 1)))
     399                 :             :         {
     400                 :    40261118 :           if ((ep = get_elimination (XEXP (x, 0))) != NULL)
     401                 :             :             {
     402                 :    40172130 :               poly_int64 offset, curr_offset;
     403                 :    40172130 :               rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     404                 :             : 
     405                 :    40172130 :               if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM)
     406                 :    26560689 :                 elimination_fp2sp_occured_p = true;
     407                 :             : 
     408                 :    40172130 :               if (! update_p && ! full_p)
     409                 :    17605175 :                 return simplify_gen_binary (PLUS, Pmode, to, XEXP (x, 1));
     410                 :             : 
     411                 :    22566955 :               if (maybe_ne (update_sp_offset, 0))
     412                 :           0 :                 offset = ep->to_rtx == stack_pointer_rtx ? update_sp_offset : 0;
     413                 :             :               else
     414                 :    22566955 :                 offset = (update_p
     415                 :    22566955 :                           ? ep->offset - ep->previous_offset : ep->offset);
     416                 :    22566955 :               if (full_p && insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     417                 :    10406744 :                 offset -= lra_get_insn_recog_data (insn)->sp_offset;
     418                 :    22566955 :               if (poly_int_rtx_p (XEXP (x, 1), &curr_offset)
     419                 :    22566955 :                   && known_eq (curr_offset, -offset))
     420                 :             :                 return to;
     421                 :             :               else
     422                 :    21763302 :                 return gen_rtx_PLUS (Pmode, to,
     423                 :             :                                      plus_constant (Pmode,
     424                 :             :                                                     XEXP (x, 1), offset));
     425                 :             :             }
     426                 :             : 
     427                 :             :           /* If the hard register is not eliminable, we are done since
     428                 :             :              the other operand is a constant.  */
     429                 :       88988 :           return x;
     430                 :             :         }
     431                 :             : 
     432                 :             :       /* If this is part of an address, we want to bring any constant
     433                 :             :          to the outermost PLUS.  We will do this by doing hard
     434                 :             :          register replacement in our operands and seeing if a constant
     435                 :             :          shows up in one of them.
     436                 :             : 
     437                 :             :          Note that there is no risk of modifying the structure of the
     438                 :             :          insn, since we only get called for its operands, thus we are
     439                 :             :          either modifying the address inside a MEM, or something like
     440                 :             :          an address operand of a load-address insn.  */
     441                 :             : 
     442                 :      931197 :       {
     443                 :      931197 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     444                 :             :                                          subst_p, update_p,
     445                 :             :                                          update_sp_offset, full_p);
     446                 :      931197 :         rtx new1 = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     447                 :             :                                          subst_p, update_p,
     448                 :             :                                          update_sp_offset, full_p);
     449                 :             : 
     450                 :      931197 :         new0 = move_plus_up (new0);
     451                 :      931197 :         new1 = move_plus_up (new1);
     452                 :      931197 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     453                 :      892292 :           return form_sum (new0, new1);
     454                 :             :       }
     455                 :             :       return x;
     456                 :             : 
     457                 :      185116 :     case MULT:
     458                 :             :       /* If this is the product of an eliminable hard register and a
     459                 :             :          constant, apply the distribute law and move the constant out
     460                 :             :          so that we have (plus (mult ..) ..).  This is needed in order
     461                 :             :          to keep load-address insns valid.  This case is pathological.
     462                 :             :          We ignore the possibility of overflow here.  */
     463                 :      170433 :       if (REG_P (XEXP (x, 0)) && CONST_INT_P (XEXP (x, 1))
     464                 :      353687 :           && (ep = get_elimination (XEXP (x, 0))) != NULL)
     465                 :             :         {
     466                 :           0 :           rtx to = subst_p ? ep->to_rtx : ep->from_rtx;
     467                 :             : 
     468                 :           0 :           if (ep->to_rtx == stack_pointer_rtx && ep->from == FRAME_POINTER_REGNUM)
     469                 :           0 :             elimination_fp2sp_occured_p = true;
     470                 :             : 
     471                 :           0 :           if (maybe_ne (update_sp_offset, 0))
     472                 :             :             {
     473                 :           0 :               if (ep->to_rtx == stack_pointer_rtx)
     474                 :           0 :                 return plus_constant (Pmode,
     475                 :           0 :                                       gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     476                 :           0 :                                       update_sp_offset * INTVAL (XEXP (x, 1)));
     477                 :           0 :               return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     478                 :             :             }
     479                 :           0 :           else if (update_p)
     480                 :           0 :             return plus_constant (Pmode,
     481                 :           0 :                                   gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     482                 :           0 :                                   (ep->offset - ep->previous_offset)
     483                 :           0 :                                   * INTVAL (XEXP (x, 1)));
     484                 :           0 :           else if (full_p)
     485                 :             :             {
     486                 :           0 :               poly_int64 offset = ep->offset;
     487                 :             : 
     488                 :           0 :               if (insn != NULL_RTX && ep->to_rtx == stack_pointer_rtx)
     489                 :           0 :                 offset -= lra_get_insn_recog_data (insn)->sp_offset;
     490                 :           0 :               return
     491                 :           0 :                 plus_constant (Pmode,
     492                 :           0 :                                gen_rtx_MULT (Pmode, to, XEXP (x, 1)),
     493                 :           0 :                                offset * INTVAL (XEXP (x, 1)));
     494                 :             :             }
     495                 :             :           else
     496                 :           0 :             return gen_rtx_MULT (Pmode, to, XEXP (x, 1));
     497                 :             :         }
     498                 :             : 
     499                 :             :       /* fall through */
     500                 :             : 
     501                 :      288662 :     case CALL:
     502                 :      288662 :     case COMPARE:
     503                 :             :     /* See comments before PLUS about handling MINUS.  */
     504                 :      288662 :     case MINUS:
     505                 :      288662 :     case DIV:      case UDIV:
     506                 :      288662 :     case MOD:      case UMOD:
     507                 :      288662 :     case AND:      case IOR:      case XOR:
     508                 :      288662 :     case ROTATERT: case ROTATE:
     509                 :      288662 :     case ASHIFTRT: case LSHIFTRT: case ASHIFT:
     510                 :      288662 :     case NE:       case EQ:
     511                 :      288662 :     case GE:       case GT:       case GEU:    case GTU:
     512                 :      288662 :     case LE:       case LT:       case LEU:    case LTU:
     513                 :      288662 :       {
     514                 :      288662 :         rtx new0 = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     515                 :             :                                          subst_p, update_p,
     516                 :             :                                          update_sp_offset, full_p);
     517                 :      288662 :         rtx new1 = XEXP (x, 1)
     518                 :      288662 :                    ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     519                 :             :                                            subst_p, update_p,
     520                 :      288662 :                                            update_sp_offset, full_p) : 0;
     521                 :             : 
     522                 :      288662 :         if (new0 != XEXP (x, 0) || new1 != XEXP (x, 1))
     523                 :       96746 :           return gen_rtx_fmt_ee (code, GET_MODE (x), new0, new1);
     524                 :             :       }
     525                 :             :       return x;
     526                 :             : 
     527                 :          55 :     case EXPR_LIST:
     528                 :             :       /* If we have something in XEXP (x, 0), the usual case,
     529                 :             :          eliminate it.  */
     530                 :          55 :       if (XEXP (x, 0))
     531                 :             :         {
     532                 :          55 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     533                 :             :                                           subst_p, update_p,
     534                 :             :                                           update_sp_offset, full_p);
     535                 :          55 :           if (new_rtx != XEXP (x, 0))
     536                 :             :             {
     537                 :             :               /* If this is a REG_DEAD note, it is not valid anymore.
     538                 :             :                  Using the eliminated version could result in creating a
     539                 :             :                  REG_DEAD note for the stack or frame pointer.  */
     540                 :           0 :               if (REG_NOTE_KIND (x) == REG_DEAD)
     541                 :           0 :                 return (XEXP (x, 1)
     542                 :           0 :                         ? lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     543                 :             :                                                 subst_p, update_p,
     544                 :             :                                                 update_sp_offset, full_p)
     545                 :             :                         : NULL_RTX);
     546                 :             : 
     547                 :           0 :               x = alloc_reg_note (REG_NOTE_KIND (x), new_rtx, XEXP (x, 1));
     548                 :             :             }
     549                 :             :         }
     550                 :             : 
     551                 :             :       /* fall through */
     552                 :             : 
     553                 :          55 :     case INSN_LIST:
     554                 :          55 :     case INT_LIST:
     555                 :             :       /* Now do eliminations in the rest of the chain.  If this was
     556                 :             :          an EXPR_LIST, this might result in allocating more memory than is
     557                 :             :          strictly needed, but it simplifies the code.  */
     558                 :          55 :       if (XEXP (x, 1))
     559                 :             :         {
     560                 :          55 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 1), mem_mode,
     561                 :             :                                           subst_p, update_p,
     562                 :             :                                           update_sp_offset, full_p);
     563                 :          55 :           if (new_rtx != XEXP (x, 1))
     564                 :           0 :             return
     565                 :           0 :               gen_rtx_fmt_ee (GET_CODE (x), GET_MODE (x),
     566                 :             :                               XEXP (x, 0), new_rtx);
     567                 :             :         }
     568                 :          55 :       return x;
     569                 :             : 
     570                 :             :     case PRE_INC:
     571                 :             :     case POST_INC:
     572                 :             :     case PRE_DEC:
     573                 :             :     case POST_DEC:
     574                 :             :       /* We do not support elimination of a register that is modified.
     575                 :             :          elimination_effects has already make sure that this does not
     576                 :             :          happen.  */
     577                 :             :       return x;
     578                 :             : 
     579                 :         258 :     case PRE_MODIFY:
     580                 :         258 :     case POST_MODIFY:
     581                 :             :       /* We do not support elimination of a hard register that is
     582                 :             :          modified.  LRA has already make sure that this does not
     583                 :             :          happen. The only remaining case we need to consider here is
     584                 :             :          that the increment value may be an eliminable register.  */
     585                 :         258 :       if (GET_CODE (XEXP (x, 1)) == PLUS
     586                 :         258 :           && XEXP (XEXP (x, 1), 0) == XEXP (x, 0))
     587                 :             :         {
     588                 :         258 :           rtx new_rtx = lra_eliminate_regs_1 (insn, XEXP (XEXP (x, 1), 1),
     589                 :             :                                               mem_mode, subst_p, update_p,
     590                 :             :                                               update_sp_offset, full_p);
     591                 :             : 
     592                 :         258 :           if (new_rtx != XEXP (XEXP (x, 1), 1))
     593                 :           0 :             return gen_rtx_fmt_ee (code, GET_MODE (x), XEXP (x, 0),
     594                 :             :                                    gen_rtx_PLUS (GET_MODE (x),
     595                 :             :                                                  XEXP (x, 0), new_rtx));
     596                 :             :         }
     597                 :         258 :       return x;
     598                 :             : 
     599                 :       30063 :     case STRICT_LOW_PART:
     600                 :       30063 :     case NEG:          case NOT:
     601                 :       30063 :     case SIGN_EXTEND:  case ZERO_EXTEND:
     602                 :       30063 :     case TRUNCATE:     case FLOAT_EXTEND: case FLOAT_TRUNCATE:
     603                 :       30063 :     case FLOAT:        case FIX:
     604                 :       30063 :     case UNSIGNED_FIX: case UNSIGNED_FLOAT:
     605                 :       30063 :     case ABS:
     606                 :       30063 :     case SQRT:
     607                 :       30063 :     case FFS:
     608                 :       30063 :     case CLZ:
     609                 :       30063 :     case CTZ:
     610                 :       30063 :     case POPCOUNT:
     611                 :       30063 :     case PARITY:
     612                 :       30063 :     case BSWAP:
     613                 :       30063 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), mem_mode,
     614                 :             :                                       subst_p, update_p,
     615                 :             :                                       update_sp_offset, full_p);
     616                 :       30063 :       if (new_rtx != XEXP (x, 0))
     617                 :       20142 :         return gen_rtx_fmt_e (code, GET_MODE (x), new_rtx);
     618                 :             :       return x;
     619                 :             : 
     620                 :      614056 :     case SUBREG:
     621                 :      614056 :       new_rtx = lra_eliminate_regs_1 (insn, SUBREG_REG (x), mem_mode,
     622                 :             :                                       subst_p, update_p,
     623                 :             :                                       update_sp_offset, full_p);
     624                 :             : 
     625                 :      614056 :       if (new_rtx != SUBREG_REG (x))
     626                 :             :         {
     627                 :        5079 :           if (MEM_P (new_rtx) && !paradoxical_subreg_p (x))
     628                 :             :             {
     629                 :          17 :               SUBREG_REG (x) = new_rtx;
     630                 :          17 :               alter_subreg (&x, false);
     631                 :          17 :               return x;
     632                 :             :             }
     633                 :        5062 :           else if (! subst_p)
     634                 :             :             {
     635                 :             :               /* LRA can transform subregs itself.  So don't call
     636                 :             :                  simplify_gen_subreg until LRA transformations are
     637                 :             :                  finished.  Function simplify_gen_subreg can do
     638                 :             :                  non-trivial transformations (like truncation) which
     639                 :             :                  might make LRA work to fail.  */
     640                 :        2978 :               SUBREG_REG (x) = new_rtx;
     641                 :        2978 :               return x;
     642                 :             :             }
     643                 :             :           else
     644                 :        2084 :             return simplify_gen_subreg (GET_MODE (x), new_rtx,
     645                 :        2084 :                                         GET_MODE (new_rtx), SUBREG_BYTE (x));
     646                 :             :         }
     647                 :             : 
     648                 :             :       return x;
     649                 :             : 
     650                 :    36663570 :     case MEM:
     651                 :             :       /* Our only special processing is to pass the mode of the MEM to our
     652                 :             :          recursive call and copy the flags.  While we are here, handle this
     653                 :             :          case more efficiently.  */
     654                 :    36663570 :       return
     655                 :             :         replace_equiv_address_nv
     656                 :    36663570 :         (x,
     657                 :    36663570 :          lra_eliminate_regs_1 (insn, XEXP (x, 0), GET_MODE (x),
     658                 :    36663570 :                                subst_p, update_p, update_sp_offset, full_p));
     659                 :             : 
     660                 :           0 :     case USE:
     661                 :             :       /* Handle insn_list USE that a call to a pure function may generate.  */
     662                 :           0 :       new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, 0), VOIDmode,
     663                 :             :                                       subst_p, update_p, update_sp_offset, full_p);
     664                 :           0 :       if (new_rtx != XEXP (x, 0))
     665                 :           0 :         return gen_rtx_USE (GET_MODE (x), new_rtx);
     666                 :             :       return x;
     667                 :             : 
     668                 :           2 :     case CLOBBER:
     669                 :           2 :     case ASM_OPERANDS:
     670                 :           2 :       gcc_assert (insn && DEBUG_INSN_P (insn));
     671                 :             :       break;
     672                 :             : 
     673                 :           0 :     case SET:
     674                 :           0 :       gcc_unreachable ();
     675                 :             : 
     676                 :             :     default:
     677                 :             :       break;
     678                 :             :     }
     679                 :             : 
     680                 :             :   /* Process each of our operands recursively.  If any have changed, make a
     681                 :             :      copy of the rtx.  */
     682                 :       78265 :   fmt = GET_RTX_FORMAT (code);
     683                 :      170280 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     684                 :             :     {
     685                 :       92015 :       if (*fmt == 'e')
     686                 :             :         {
     687                 :       25678 :           new_rtx = lra_eliminate_regs_1 (insn, XEXP (x, i), mem_mode,
     688                 :             :                                           subst_p, update_p,
     689                 :             :                                           update_sp_offset, full_p);
     690                 :       25678 :           if (new_rtx != XEXP (x, i) && ! copied)
     691                 :             :             {
     692                 :       11803 :               x = shallow_copy_rtx (x);
     693                 :       11803 :               copied = 1;
     694                 :             :             }
     695                 :       25678 :           XEXP (x, i) = new_rtx;
     696                 :             :         }
     697                 :       66337 :       else if (*fmt == 'E')
     698                 :             :         {
     699                 :             :           int copied_vec = 0;
     700                 :       49795 :           for (j = 0; j < XVECLEN (x, i); j++)
     701                 :             :             {
     702                 :       33362 :               new_rtx = lra_eliminate_regs_1 (insn, XVECEXP (x, i, j), mem_mode,
     703                 :             :                                               subst_p, update_p,
     704                 :             :                                               update_sp_offset, full_p);
     705                 :       33362 :               if (new_rtx != XVECEXP (x, i, j) && ! copied_vec)
     706                 :             :                 {
     707                 :       31760 :                   rtvec new_v = gen_rtvec_v (XVECLEN (x, i),
     708                 :       15880 :                                              XVEC (x, i)->elem);
     709                 :       15880 :                   if (! copied)
     710                 :             :                     {
     711                 :       15880 :                       x = shallow_copy_rtx (x);
     712                 :       15880 :                       copied = 1;
     713                 :             :                     }
     714                 :       15880 :                   XVEC (x, i) = new_v;
     715                 :       15880 :                   copied_vec = 1;
     716                 :             :                 }
     717                 :       33362 :               XVECEXP (x, i, j) = new_rtx;
     718                 :             :             }
     719                 :             :         }
     720                 :             :     }
     721                 :             : 
     722                 :       78265 :   return x;
     723                 :             : }
     724                 :             : 
     725                 :             : /* This function is used externally in subsequent passes of GCC.  It
     726                 :             :    always does a full elimination of X.  */
     727                 :             : rtx
     728                 :     6757048 : lra_eliminate_regs (rtx x, machine_mode mem_mode,
     729                 :             :                     rtx insn ATTRIBUTE_UNUSED)
     730                 :             : {
     731                 :     6757048 :   return lra_eliminate_regs_1 (NULL, x, mem_mode, true, false, 0, true);
     732                 :             : }
     733                 :             : 
     734                 :             : /* Stack pointer offset before the current insn relative to one at the
     735                 :             :    func start.  RTL insns can change SP explicitly.  We keep the
     736                 :             :    changes from one insn to another through this variable.  */
     737                 :             : static poly_int64 curr_sp_change;
     738                 :             : 
     739                 :             : /* Scan rtx X for references to elimination source or target registers
     740                 :             :    in contexts that would prevent the elimination from happening.
     741                 :             :    Update the table of eliminables to reflect the changed state.
     742                 :             :    MEM_MODE is the mode of an enclosing MEM rtx, or VOIDmode if not
     743                 :             :    within a MEM.  */
     744                 :             : static void
     745                 :   301574292 : mark_not_eliminable (rtx x, machine_mode mem_mode)
     746                 :             : {
     747                 :   417345258 :   enum rtx_code code = GET_CODE (x);
     748                 :   417345258 :   class lra_elim_table *ep;
     749                 :   417345258 :   int i, j;
     750                 :   417345258 :   const char *fmt;
     751                 :   417345258 :   poly_int64 offset = 0;
     752                 :             : 
     753                 :   417345258 :   switch (code)
     754                 :             :     {
     755                 :     1804825 :     case PRE_INC:
     756                 :     1804825 :     case POST_INC:
     757                 :     1804825 :     case PRE_DEC:
     758                 :     1804825 :     case POST_DEC:
     759                 :     1804825 :     case POST_MODIFY:
     760                 :     1804825 :     case PRE_MODIFY:
     761                 :     1804825 :       if (XEXP (x, 0) == stack_pointer_rtx
     762                 :     1804825 :           && ((code != PRE_MODIFY && code != POST_MODIFY)
     763                 :      110412 :               || (GET_CODE (XEXP (x, 1)) == PLUS
     764                 :      110412 :                   && XEXP (x, 0) == XEXP (XEXP (x, 1), 0)
     765                 :      110412 :                   && poly_int_rtx_p (XEXP (XEXP (x, 1), 1), &offset))))
     766                 :             :         {
     767                 :     3609650 :           poly_int64 size = GET_MODE_SIZE (mem_mode);
     768                 :             : 
     769                 :             : #ifdef PUSH_ROUNDING
     770                 :             :           /* If more bytes than MEM_MODE are pushed, account for
     771                 :             :              them.  */
     772                 :     1804825 :           size = PUSH_ROUNDING (size);
     773                 :             : #endif
     774                 :     1804825 :           if (code == PRE_DEC || code == POST_DEC)
     775                 :   301574292 :             curr_sp_change -= size;
     776                 :      110456 :           else if (code == PRE_INC || code == POST_INC)
     777                 :   301574292 :             curr_sp_change += size;
     778                 :      110412 :           else if (code == PRE_MODIFY || code == POST_MODIFY)
     779                 :   301574292 :             curr_sp_change += offset;
     780                 :             :         }
     781                 :           0 :       else if (REG_P (XEXP (x, 0))
     782                 :           0 :                && REGNO (XEXP (x, 0)) >= FIRST_PSEUDO_REGISTER)
     783                 :             :         {
     784                 :             :           /* If we modify the source of an elimination rule, disable
     785                 :             :              it.  Do the same if it is the destination and not the
     786                 :             :              hard frame register.  */
     787                 :           0 :           for (ep = reg_eliminate;
     788                 :           0 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     789                 :             :                ep++)
     790                 :           0 :             if (ep->from_rtx == XEXP (x, 0)
     791                 :           0 :                 || (ep->to_rtx == XEXP (x, 0)
     792                 :           0 :                     && ep->to_rtx != hard_frame_pointer_rtx))
     793                 :           0 :               setup_can_eliminate (ep, false);
     794                 :             :         }
     795                 :             :       return;
     796                 :             : 
     797                 :      860340 :     case USE:
     798                 :      860340 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     799                 :             :         /* If using a hard register that is the source of an eliminate
     800                 :             :            we still think can be performed, note it cannot be
     801                 :             :            performed since we don't know how this hard register is
     802                 :             :            used.  */
     803                 :     3649090 :         for (ep = reg_eliminate;
     804                 :     3649090 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     805                 :             :              ep++)
     806                 :     2919272 :           if (ep->from_rtx == XEXP (x, 0)
     807                 :           0 :               && ep->to_rtx != hard_frame_pointer_rtx)
     808                 :           0 :             setup_can_eliminate (ep, false);
     809                 :             :       return;
     810                 :             : 
     811                 :    10374741 :     case CLOBBER:
     812                 :    10374741 :       if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER)
     813                 :             :         /* If clobbering a hard register that is the replacement
     814                 :             :            register for an elimination we still think can be
     815                 :             :            performed, note that it cannot be performed.  Otherwise, we
     816                 :             :            need not be concerned about it.  */
     817                 :    50249770 :         for (ep = reg_eliminate;
     818                 :    50249770 :              ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     819                 :             :              ep++)
     820                 :    40199816 :           if (ep->to_rtx == XEXP (x, 0)
     821                 :        4370 :               && ep->to_rtx != hard_frame_pointer_rtx)
     822                 :           2 :             setup_can_eliminate (ep, false);
     823                 :             :       return;
     824                 :             : 
     825                 :    84963251 :     case SET:
     826                 :    84963251 :       if (SET_DEST (x) == stack_pointer_rtx
     827                 :     2036219 :           && GET_CODE (SET_SRC (x)) == PLUS
     828                 :     2010321 :           && XEXP (SET_SRC (x), 0) == SET_DEST (x)
     829                 :    86973568 :           && poly_int_rtx_p (XEXP (SET_SRC (x), 1), &offset))
     830                 :             :         {
     831                 :     2010317 :           curr_sp_change += offset;
     832                 :     2010317 :           return;
     833                 :             :         }
     834                 :    82952934 :       if (! REG_P (SET_DEST (x))
     835                 :    82952934 :           || REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER)
     836                 :    63425790 :         mark_not_eliminable (SET_DEST (x), mem_mode);
     837                 :             :       else
     838                 :             :         {
     839                 :             :           /* See if this is setting the replacement hard register for
     840                 :             :              an elimination.
     841                 :             : 
     842                 :             :              If DEST is the hard frame pointer, we do nothing because
     843                 :             :              we assume that all assignments to the frame pointer are
     844                 :             :              for non-local gotos and are being done at a time when
     845                 :             :              they are valid and do not disturb anything else.  Some
     846                 :             :              machines want to eliminate a fake argument pointer (or
     847                 :             :              even a fake frame pointer) with either the real frame
     848                 :             :              pointer or the stack pointer.  Assignments to the hard
     849                 :             :              frame pointer must not prevent this elimination.  */
     850                 :    97635720 :           for (ep = reg_eliminate;
     851                 :    97635720 :                ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
     852                 :             :                ep++)
     853                 :    78108576 :             if (ep->to_rtx == SET_DEST (x)
     854                 :       53608 :                 && SET_DEST (x) != hard_frame_pointer_rtx)
     855                 :       51804 :               setup_can_eliminate (ep, false);
     856                 :             :         }
     857                 :             : 
     858                 :    82952934 :       mark_not_eliminable (SET_SRC (x), mem_mode);
     859                 :    82952934 :       return;
     860                 :             : 
     861                 :    32818032 :     case MEM:
     862                 :             :       /* Our only special processing is to pass the mode of the MEM to
     863                 :             :          our recursive call.  */
     864                 :    32818032 :       mark_not_eliminable (XEXP (x, 0), GET_MODE (x));
     865                 :    32818032 :       return;
     866                 :             : 
     867                 :   286524069 :     default:
     868                 :   286524069 :       break;
     869                 :             :     }
     870                 :             : 
     871                 :   286524069 :   fmt = GET_RTX_FORMAT (code);
     872                 :   641482499 :   for (i = 0; i < GET_RTX_LENGTH (code); i++, fmt++)
     873                 :             :     {
     874                 :   354958430 :       if (*fmt == 'e')
     875                 :   123280406 :         mark_not_eliminable (XEXP (x, i), mem_mode);
     876                 :   231678024 :       else if (*fmt == 'E')
     877                 :    38294529 :         for (j = 0; j < XVECLEN (x, i); j++)
     878                 :    25550610 :           mark_not_eliminable (XVECEXP (x, i, j), mem_mode);
     879                 :             :     }
     880                 :             : }
     881                 :             : 
     882                 :             : 
     883                 :             : 
     884                 :             : /* Scan INSN and eliminate all eliminable hard registers in it.
     885                 :             : 
     886                 :             :    If REPLACE_P is true, do the replacement destructively.  Also
     887                 :             :    delete the insn as dead it if it is setting an eliminable register.
     888                 :             : 
     889                 :             :    If REPLACE_P is false, just update the offsets while keeping the
     890                 :             :    base register the same.  If FIRST_P, use the sp offset for
     891                 :             :    elimination to sp.  Otherwise, use UPDATE_SP_OFFSET for this.  If
     892                 :             :    UPDATE_SP_OFFSET is non-zero, don't use difference of the offset
     893                 :             :    and the previous offset.  Attach the note about used elimination
     894                 :             :    for insns setting frame pointer to update elimination easy (without
     895                 :             :    parsing already generated elimination insns to find offset
     896                 :             :    previously used) in future.  */
     897                 :             : 
     898                 :             : void
     899                 :    39824329 : eliminate_regs_in_insn (rtx_insn *insn, bool replace_p, bool first_p,
     900                 :             :                         poly_int64 update_sp_offset)
     901                 :             : {
     902                 :    39824329 :   int icode = recog_memoized (insn);
     903                 :    39824329 :   rtx set, old_set = single_set (insn);
     904                 :    39824329 :   bool validate_p;
     905                 :    39824329 :   int i;
     906                 :    39824329 :   rtx substed_operand[MAX_RECOG_OPERANDS];
     907                 :    39824329 :   rtx orig_operand[MAX_RECOG_OPERANDS];
     908                 :    39824329 :   class lra_elim_table *ep;
     909                 :    39824329 :   rtx plus_src, plus_cst_src;
     910                 :    39824329 :   lra_insn_recog_data_t id;
     911                 :    39824329 :   struct lra_static_insn_data *static_id;
     912                 :             : 
     913                 :    39824329 :   if (icode < 0 && asm_noperands (PATTERN (insn)) < 0 && ! DEBUG_INSN_P (insn))
     914                 :             :     {
     915                 :       12942 :       lra_assert (GET_CODE (PATTERN (insn)) == USE
     916                 :             :                   || GET_CODE (PATTERN (insn)) == CLOBBER
     917                 :             :                   || GET_CODE (PATTERN (insn)) == ASM_INPUT);
     918                 :     3189535 :       return;
     919                 :             :     }
     920                 :             : 
     921                 :             :   /* We allow one special case which happens to work on all machines we
     922                 :             :      currently support: a single set with the source or a REG_EQUAL
     923                 :             :      note being a PLUS of an eliminable register and a constant.  */
     924                 :    39811387 :   plus_src = plus_cst_src = 0;
     925                 :    39811387 :   poly_int64 offset = 0;
     926                 :    39811387 :   if (old_set && REG_P (SET_DEST (old_set)))
     927                 :             :     {
     928                 :    16582074 :       if (GET_CODE (SET_SRC (old_set)) == PLUS)
     929                 :     3433736 :         plus_src = SET_SRC (old_set);
     930                 :             :       /* First see if the source is of the form (plus (...) CST).  */
     931                 :     3433736 :       if (plus_src && poly_int_rtx_p (XEXP (plus_src, 1), &offset))
     932                 :             :         plus_cst_src = plus_src;
     933                 :             :       /* If we are doing initial offset computation, then utilize
     934                 :             :          eqivalences to discover a constant for the second term
     935                 :             :          of PLUS_SRC.  */
     936                 :    13408901 :       else if (plus_src && REG_P (XEXP (plus_src, 1)))
     937                 :             :         {
     938                 :       20961 :           int regno = REGNO (XEXP (plus_src, 1));
     939                 :       20961 :           if (regno < ira_reg_equiv_len
     940                 :       20961 :               && ira_reg_equiv[regno].constant != NULL_RTX
     941                 :        1175 :               && !replace_p
     942                 :       22103 :               && poly_int_rtx_p (ira_reg_equiv[regno].constant, &offset))
     943                 :          98 :             plus_cst_src = plus_src;
     944                 :             :         }
     945                 :             :       /* Check that the first operand of the PLUS is a hard reg or
     946                 :             :          the lowpart subreg of one.  */
     947                 :     3173271 :       if (plus_cst_src)
     948                 :             :         {
     949                 :     3173271 :           rtx reg = XEXP (plus_cst_src, 0);
     950                 :             : 
     951                 :     3173271 :           if (GET_CODE (reg) == SUBREG && subreg_lowpart_p (reg))
     952                 :          71 :             reg = SUBREG_REG (reg);
     953                 :             : 
     954                 :     3173271 :           if (!REG_P (reg) || REGNO (reg) >= FIRST_PSEUDO_REGISTER)
     955                 :             :             plus_cst_src = 0;
     956                 :             :         }
     957                 :             :     }
     958                 :     3163805 :   if (plus_cst_src)
     959                 :             :     {
     960                 :     3163805 :       rtx reg = XEXP (plus_cst_src, 0);
     961                 :             : 
     962                 :     3163805 :       if (GET_CODE (reg) == SUBREG)
     963                 :          71 :         reg = SUBREG_REG (reg);
     964                 :             : 
     965                 :     3163805 :       if (REG_P (reg) && (ep = get_elimination (reg)) != NULL)
     966                 :             :         {
     967                 :     3163805 :           rtx to_rtx = replace_p ? ep->to_rtx : ep->from_rtx;
     968                 :             : 
     969                 :     3163805 :           if (! replace_p)
     970                 :             :             {
     971                 :     1731108 :               if (known_eq (update_sp_offset, 0))
     972                 :     1731108 :                 offset += (ep->offset - ep->previous_offset);
     973                 :     1731108 :               if (ep->to_rtx == stack_pointer_rtx)
     974                 :             :                 {
     975                 :     1384859 :                   if (first_p)
     976                 :      847902 :                     offset -= lra_get_insn_recog_data (insn)->sp_offset;
     977                 :             :                   else
     978                 :     1731108 :                     offset += update_sp_offset;
     979                 :             :                 }
     980                 :     1731108 :               offset = trunc_int_for_mode (offset, GET_MODE (plus_cst_src));
     981                 :             :             }
     982                 :             : 
     983                 :     3163805 :           if (GET_CODE (XEXP (plus_cst_src, 0)) == SUBREG)
     984                 :          71 :             to_rtx = gen_lowpart (GET_MODE (XEXP (plus_cst_src, 0)), to_rtx);
     985                 :             :           /* If we have a nonzero offset, and the source is already a
     986                 :             :              simple REG, the following transformation would increase
     987                 :             :              the cost of the insn by replacing a simple REG with (plus
     988                 :             :              (reg sp) CST).  So try only when we already had a PLUS
     989                 :             :              before.  */
     990                 :     3163805 :           if (known_eq (offset, 0) || plus_src)
     991                 :             :             {
     992                 :     3163805 :               rtx new_src = plus_constant (GET_MODE (to_rtx), to_rtx, offset);
     993                 :             : 
     994                 :     3163805 :               old_set = single_set (insn);
     995                 :             : 
     996                 :             :               /* First see if this insn remains valid when we make the
     997                 :             :                  change.  If not, try to replace the whole pattern
     998                 :             :                  with a simple set (this may help if the original insn
     999                 :             :                  was a PARALLEL that was only recognized as single_set
    1000                 :             :                  due to REG_UNUSED notes).  If this isn't valid
    1001                 :             :                  either, keep the INSN_CODE the same and let the
    1002                 :             :                  constraint pass fix it up.  */
    1003                 :     3163805 :               if (! validate_change (insn, &SET_SRC (old_set), new_src, 0))
    1004                 :             :                 {
    1005                 :          11 :                   rtx new_pat = gen_rtx_SET (SET_DEST (old_set), new_src);
    1006                 :             : 
    1007                 :          11 :                   if (! validate_change (insn, &PATTERN (insn), new_pat, 0))
    1008                 :          11 :                     SET_SRC (old_set) = new_src;
    1009                 :             :                 }
    1010                 :     3163805 :               lra_update_insn_recog_data (insn);
    1011                 :             :               /* This can't have an effect on elimination offsets, so skip
    1012                 :             :                  right to the end.  */
    1013                 :     3163805 :               return;
    1014                 :             :             }
    1015                 :             :         }
    1016                 :             :     }
    1017                 :             : 
    1018                 :             :   /* Eliminate all eliminable registers occurring in operands that
    1019                 :             :      can be handled by the constraint pass.  */
    1020                 :    36647582 :   id = lra_get_insn_recog_data (insn);
    1021                 :    36647582 :   static_id = id->insn_static_data;
    1022                 :    36647582 :   validate_p = false;
    1023                 :   103611240 :   for (i = 0; i < static_id->n_operands; i++)
    1024                 :             :     {
    1025                 :    66963658 :       orig_operand[i] = *id->operand_loc[i];
    1026                 :    66963658 :       substed_operand[i] = *id->operand_loc[i];
    1027                 :             : 
    1028                 :             :       /* For an asm statement, every operand is eliminable.  */
    1029                 :    66963658 :       if (icode < 0 || insn_data[icode].operand[i].eliminable)
    1030                 :             :         {
    1031                 :             :           /* Check for setting a hard register that we know about.  */
    1032                 :    66721831 :           if (static_id->operand[i].type != OP_IN
    1033                 :    28000489 :               && REG_P (orig_operand[i]))
    1034                 :             :             {
    1035                 :             :               /* If we are assigning to a hard register that can be
    1036                 :             :                  eliminated, it must be as part of a PARALLEL, since
    1037                 :             :                  the code above handles single SETs.  This reg cannot
    1038                 :             :                  be longer eliminated -- it is forced by
    1039                 :             :                  mark_not_eliminable.  */
    1040                 :    63130300 :               for (ep = reg_eliminate;
    1041                 :    63130300 :                    ep < &reg_eliminate[NUM_ELIMINABLE_REGS];
    1042                 :             :                    ep++)
    1043                 :    50504240 :                 lra_assert (ep->from_rtx != orig_operand[i]
    1044                 :             :                             || ! ep->can_eliminate);
    1045                 :             :             }
    1046                 :             : 
    1047                 :             :           /* Companion to the above plus substitution, we can allow
    1048                 :             :              invariants as the source of a plain move.  */
    1049                 :    66721831 :           substed_operand[i]
    1050                 :   133443662 :             = lra_eliminate_regs_1 (insn, *id->operand_loc[i], VOIDmode,
    1051                 :    66721831 :                                     replace_p, ! replace_p && ! first_p,
    1052                 :             :                                     update_sp_offset, first_p);
    1053                 :    66721831 :           if (substed_operand[i] != orig_operand[i])
    1054                 :    66963658 :             validate_p = true;
    1055                 :             :         }
    1056                 :             :     }
    1057                 :             : 
    1058                 :    36647582 :   if (! validate_p)
    1059                 :             :     return;
    1060                 :             : 
    1061                 :             :   /* Substitute the operands; the new values are in the substed_operand
    1062                 :             :      array.  */
    1063                 :   103570080 :   for (i = 0; i < static_id->n_operands; i++)
    1064                 :    66935286 :     *id->operand_loc[i] = substed_operand[i];
    1065                 :    36727730 :   for (i = 0; i < static_id->n_dups; i++)
    1066                 :       92936 :     *id->dup_loc[i] = substed_operand[(int) static_id->dup_num[i]];
    1067                 :             : 
    1068                 :             :   /* Transform plus (plus (hard reg, const), pseudo) to plus (plus (pseudo,
    1069                 :             :      const), hard reg) in order to keep insn containing eliminated register
    1070                 :             :      after all reloads calculating its offset.  This permits to keep register
    1071                 :             :      pressure under control and helps to avoid LRA cycling in patalogical
    1072                 :             :      cases.  */
    1073                 :    18531165 :   if (! replace_p && (set = single_set (insn)) != NULL
    1074                 :    13834588 :       && GET_CODE (SET_SRC (set)) == PLUS
    1075                 :    36933689 :       && GET_CODE (XEXP (SET_SRC (set), 0)) == PLUS)
    1076                 :             :     {
    1077                 :       11686 :       rtx reg1, reg2, op1, op2;
    1078                 :             : 
    1079                 :       11686 :       reg1 = op1 = XEXP (XEXP (SET_SRC (set), 0), 0);
    1080                 :       11686 :       reg2 = op2 = XEXP (SET_SRC (set), 1);
    1081                 :       11686 :       if (GET_CODE (reg1) == SUBREG)
    1082                 :           0 :         reg1 = SUBREG_REG (reg1);
    1083                 :       11686 :       if (GET_CODE (reg2) == SUBREG)
    1084                 :           0 :         reg2 = SUBREG_REG (reg2);
    1085                 :       10526 :       if (REG_P (reg1) && REG_P (reg2)
    1086                 :        6454 :           && REGNO (reg1) < FIRST_PSEUDO_REGISTER
    1087                 :        6454 :           && REGNO (reg2) >= FIRST_PSEUDO_REGISTER
    1088                 :        6454 :           && GET_MODE (reg1) == Pmode
    1089                 :       18140 :           && !have_addptr3_insn (lra_pmode_pseudo, reg1,
    1090                 :             :                                  XEXP (XEXP (SET_SRC (set), 0), 1)))
    1091                 :             :         {
    1092                 :        6454 :           XEXP (XEXP (SET_SRC (set), 0), 0) = op2;
    1093                 :        6454 :           XEXP (SET_SRC (set), 1) = op1;
    1094                 :             :         }
    1095                 :             :     }
    1096                 :             : 
    1097                 :             :   /* If we had a move insn but now we don't, re-recognize it.
    1098                 :             :      This will cause spurious re-recognition if the old move had a
    1099                 :             :      PARALLEL since the new one still will, but we can't call
    1100                 :             :      single_set without having put new body into the insn and the
    1101                 :             :      re-recognition won't hurt in this rare case.  */
    1102                 :    36634794 :   lra_update_insn_recog_data (insn);
    1103                 :             : }
    1104                 :             : 
    1105                 :             : /* Spill pseudos which are assigned to hard registers in SET, record them in
    1106                 :             :    SPILLED_PSEUDOS unless it is null, and return the recorded pseudos number.
    1107                 :             :    Add affected insns for processing in the subsequent constraint pass.  */
    1108                 :             : static int
    1109                 :     7679533 : spill_pseudos (HARD_REG_SET set, int *spilled_pseudos)
    1110                 :             : {
    1111                 :     7679533 :   int i, n;
    1112                 :     7679533 :   bitmap_head to_process;
    1113                 :     7679533 :   rtx_insn *insn;
    1114                 :             : 
    1115                 :    15359066 :   if (hard_reg_set_empty_p (set))
    1116                 :             :     return 0;
    1117                 :     7679533 :   if (lra_dump_file != NULL)
    1118                 :             :     {
    1119                 :         525 :       fprintf (lra_dump_file, "       Spilling non-eliminable hard regs:");
    1120                 :       49350 :       for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1121                 :       48300 :         if (TEST_HARD_REG_BIT (set, i))
    1122                 :         525 :           fprintf (lra_dump_file, " %d", i);
    1123                 :         525 :       fprintf (lra_dump_file, "\n");
    1124                 :             :     }
    1125                 :     7679533 :   bitmap_initialize (&to_process, &reg_obstack);
    1126                 :     7679533 :   n = 0;
    1127                 :   480395817 :   for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
    1128                 :   237344680 :     if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
    1129                 :   472716284 :         && overlaps_hard_reg_set_p (set,
    1130                 :   226916134 :                                     PSEUDO_REGNO_MODE (i), reg_renumber[i]))
    1131                 :             :       {
    1132                 :       26240 :         if (lra_dump_file != NULL)
    1133                 :           0 :           fprintf (lra_dump_file, "         Spilling r%d(%d)\n",
    1134                 :             :                    i, reg_renumber[i]);
    1135                 :       26240 :         reg_renumber[i] = -1;
    1136                 :       26240 :         if (spilled_pseudos != NULL)
    1137                 :           0 :           spilled_pseudos[n++] = i;
    1138                 :       26240 :         bitmap_ior_into (&to_process, &lra_reg_info[i].insn_bitmap);
    1139                 :             :       }
    1140                 :     7679533 :   lra_no_alloc_regs |= set;
    1141                 :  1125706225 :   for (insn = get_insns (); insn != NULL_RTX; insn = NEXT_INSN (insn))
    1142                 :  1118026692 :     if (bitmap_bit_p (&to_process, INSN_UID (insn)))
    1143                 :             :       {
    1144                 :      169525 :         lra_push_insn (insn);
    1145                 :      169525 :         lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1146                 :             :       }
    1147                 :     7679533 :   bitmap_clear (&to_process);
    1148                 :     7679533 :   return n;
    1149                 :             : }
    1150                 :             : 
    1151                 :             : /* Update all offsets and possibility for elimination on eliminable
    1152                 :             :    registers.  Spill pseudos assigned to registers which are
    1153                 :             :    uneliminable, update LRA_NO_ALLOC_REGS and ELIMINABLE_REG_SET.  Add
    1154                 :             :    insns to INSNS_WITH_CHANGED_OFFSETS containing eliminable hard
    1155                 :             :    registers whose offsets should be changed.  Return true if any
    1156                 :             :    elimination offset changed.  */
    1157                 :             : static bool
    1158                 :     7679533 : update_reg_eliminate (bitmap insns_with_changed_offsets)
    1159                 :             : {
    1160                 :     7679533 :   bool prev, result;
    1161                 :     7679533 :   class lra_elim_table *ep, *ep1;
    1162                 :     7679533 :   HARD_REG_SET temp_hard_reg_set;
    1163                 :             : 
    1164                 :     7679533 :   targetm.compute_frame_layout ();
    1165                 :             : 
    1166                 :             :   /* Clear self elimination offsets.  */
    1167                 :    38397665 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1168                 :    30718132 :     self_elim_offsets[ep->from] = 0;
    1169                 :    38397665 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1170                 :             :     {
    1171                 :             :       /* If it is a currently used elimination: update the previous
    1172                 :             :          offset.  */
    1173                 :    30718132 :       if (elimination_map[ep->from] == ep)
    1174                 :    15359066 :         ep->previous_offset = ep->offset;
    1175                 :             : 
    1176                 :    30718132 :       prev = ep->prev_can_eliminate;
    1177                 :    30718132 :       setup_can_eliminate (ep, targetm.can_eliminate (ep->from, ep->to));
    1178                 :    30718132 :       if (ep->can_eliminate && ! prev)
    1179                 :             :         {
    1180                 :             :           /* It is possible that not eliminable register becomes
    1181                 :             :              eliminable because we took other reasons into account to
    1182                 :             :              set up eliminable regs in the initial set up.  Just
    1183                 :             :              ignore new eliminable registers.  */
    1184                 :           0 :           setup_can_eliminate (ep, false);
    1185                 :           0 :           continue;
    1186                 :             :         }
    1187                 :    30718132 :       if (ep->can_eliminate != prev && elimination_map[ep->from] == ep)
    1188                 :             :         {
    1189                 :             :           /* We cannot use this elimination anymore -- find another
    1190                 :             :              one.  */
    1191                 :           0 :           if (lra_dump_file != NULL)
    1192                 :           0 :             fprintf (lra_dump_file,
    1193                 :             :                      "     Elimination %d to %d is not possible anymore\n",
    1194                 :             :                      ep->from, ep->to);
    1195                 :             :           /* If after processing RTL we decides that SP can be used as a result
    1196                 :             :              of elimination, it cannot be changed.  For frame pointer to stack
    1197                 :             :              pointer elimination the condition is a bit relaxed and we just require
    1198                 :             :              that actual elimination has not been done yet.   */
    1199                 :           0 :           gcc_assert (ep->to_rtx != stack_pointer_rtx
    1200                 :             :                       || (ep->from == FRAME_POINTER_REGNUM
    1201                 :             :                           && !elimination_fp2sp_occured_p)
    1202                 :             :                       || (ep->from < FIRST_PSEUDO_REGISTER
    1203                 :             :                           && fixed_regs [ep->from]));
    1204                 :             : 
    1205                 :             :           /* Mark that is not eliminable anymore.  */
    1206                 :           0 :           elimination_map[ep->from] = NULL;
    1207                 :           0 :           for (ep1 = ep + 1; ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep1++)
    1208                 :           0 :             if (ep1->can_eliminate && ep1->from == ep->from)
    1209                 :             :               break;
    1210                 :           0 :           if (ep1 < &reg_eliminate[NUM_ELIMINABLE_REGS])
    1211                 :             :             {
    1212                 :           0 :               if (lra_dump_file != NULL)
    1213                 :           0 :                 fprintf (lra_dump_file, "    Using elimination %d to %d now\n",
    1214                 :             :                          ep1->from, ep1->to);
    1215                 :           0 :               lra_assert (known_eq (ep1->previous_offset, 0));
    1216                 :           0 :               ep1->previous_offset = ep->offset;
    1217                 :             :             }
    1218                 :             :           else
    1219                 :             :             {
    1220                 :             :               /* There is no elimination anymore just use the hard
    1221                 :             :                  register `from' itself.  Setup self elimination
    1222                 :             :                  offset to restore the original offset values.  */
    1223                 :           0 :               if (lra_dump_file != NULL)
    1224                 :           0 :                 fprintf (lra_dump_file, "    %d is not eliminable at all\n",
    1225                 :             :                          ep->from);
    1226                 :           0 :               self_elim_offsets[ep->from] = -ep->offset;
    1227                 :           0 :               if (maybe_ne (ep->offset, 0))
    1228                 :           0 :                 bitmap_ior_into (insns_with_changed_offsets,
    1229                 :           0 :                                  &lra_reg_info[ep->from].insn_bitmap);
    1230                 :             :             }
    1231                 :             :         }
    1232                 :             : 
    1233                 :    30718132 :       INITIAL_ELIMINATION_OFFSET (ep->from, ep->to, ep->offset);
    1234                 :             :     }
    1235                 :     7679533 :   setup_elimination_map ();
    1236                 :     7679533 :   result = false;
    1237                 :     7679533 :   CLEAR_HARD_REG_SET (temp_hard_reg_set);
    1238                 :    38397665 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1239                 :    30718132 :     if (elimination_map[ep->from] == NULL)
    1240                 :           0 :       add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->from);
    1241                 :    30718132 :     else if (elimination_map[ep->from] == ep)
    1242                 :             :       {
    1243                 :             :         /* Prevent the hard register into which we eliminate from
    1244                 :             :            the usage for pseudos.  */
    1245                 :    15359066 :         if (ep->from != ep->to)
    1246                 :    15359066 :           add_to_hard_reg_set (&temp_hard_reg_set, Pmode, ep->to);
    1247                 :    15359066 :         if (maybe_ne (ep->previous_offset, ep->offset))
    1248                 :             :           {
    1249                 :     1998211 :             bitmap_ior_into (insns_with_changed_offsets,
    1250                 :     1998211 :                              &lra_reg_info[ep->from].insn_bitmap);
    1251                 :             : 
    1252                 :             :             /* Update offset when the eliminate offset have been
    1253                 :             :                changed.  */
    1254                 :     1998211 :             lra_update_reg_val_offset (lra_reg_info[ep->from].val,
    1255                 :     1998211 :                                        ep->offset - ep->previous_offset);
    1256                 :     1998211 :             result = true;
    1257                 :             :           }
    1258                 :             :       }
    1259                 :     7679533 :   lra_no_alloc_regs |= temp_hard_reg_set;
    1260                 :     7679533 :   eliminable_regset &= ~temp_hard_reg_set;
    1261                 :     7679533 :   spill_pseudos (temp_hard_reg_set, NULL);
    1262                 :     7679533 :   return result;
    1263                 :             : }
    1264                 :             : 
    1265                 :             : /* Initialize the table of hard registers to eliminate.
    1266                 :             :    Pre-condition: global flag frame_pointer_needed has been set before
    1267                 :             :    calling this function.  */
    1268                 :             : static void
    1269                 :     1426764 : init_elim_table (void)
    1270                 :             : {
    1271                 :     1426764 :   class lra_elim_table *ep;
    1272                 :     1426764 :   bool value_p;
    1273                 :     1426764 :   const struct elim_table_1 *ep1;
    1274                 :             : 
    1275                 :     1426764 :   if (!reg_eliminate)
    1276                 :      205688 :     reg_eliminate = XCNEWVEC (class lra_elim_table, NUM_ELIMINABLE_REGS);
    1277                 :             : 
    1278                 :     1426764 :   memset (self_elim_offsets, 0, sizeof (self_elim_offsets));
    1279                 :             :   /* Initiate member values which will be never changed.  */
    1280                 :     1426764 :   self_elim_table.can_eliminate = self_elim_table.prev_can_eliminate = true;
    1281                 :     1426764 :   self_elim_table.previous_offset = 0;
    1282                 :             : 
    1283                 :     1426764 :   for (ep = reg_eliminate, ep1 = reg_eliminate_1;
    1284                 :     7133820 :        ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++, ep1++)
    1285                 :             :     {
    1286                 :     5707056 :       ep->offset = ep->previous_offset = 0;
    1287                 :     5707056 :       ep->from = ep1->from;
    1288                 :     5707056 :       ep->to = ep1->to;
    1289                 :     5707056 :       value_p = (targetm.can_eliminate (ep->from, ep->to)
    1290                 :     5707056 :                  && ! (ep->to == STACK_POINTER_REGNUM
    1291                 :     1906342 :                        && frame_pointer_needed
    1292                 :       51652 :                        && (! SUPPORTS_STACK_ALIGNMENT
    1293                 :       51652 :                            || ! stack_realign_fp)));
    1294                 :     5707056 :       setup_can_eliminate (ep, value_p);
    1295                 :             :     }
    1296                 :             : 
    1297                 :             :   /* Build the FROM and TO REG rtx's.  Note that code in gen_rtx_REG
    1298                 :             :      will cause, e.g., gen_rtx_REG (Pmode, STACK_POINTER_REGNUM) to
    1299                 :             :      equal stack_pointer_rtx.  We depend on this. Threfore we switch
    1300                 :             :      off that we are in LRA temporarily.  */
    1301                 :     1426764 :   lra_in_progress = false;
    1302                 :     7133820 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1303                 :             :     {
    1304                 :     5707056 :       ep->from_rtx = gen_rtx_REG (Pmode, ep->from);
    1305                 :     5707056 :       ep->to_rtx = gen_rtx_REG (Pmode, ep->to);
    1306                 :     5707056 :       eliminable_reg_rtx[ep->from] = ep->from_rtx;
    1307                 :             :     }
    1308                 :     1426764 :   lra_in_progress = true;
    1309                 :     1426764 : }
    1310                 :             : 
    1311                 :             : /* Function for initialization of elimination once per function.  It
    1312                 :             :    sets up sp offset for each insn.  */
    1313                 :             : static void
    1314                 :     1426764 : init_elimination (void)
    1315                 :             : {
    1316                 :     1426764 :   bool stop_to_sp_elimination_p;
    1317                 :     1426764 :   basic_block bb;
    1318                 :     1426764 :   rtx_insn *insn;
    1319                 :     1426764 :   class lra_elim_table *ep;
    1320                 :             : 
    1321                 :     1426764 :   init_elim_table ();
    1322                 :    14721932 :   FOR_EACH_BB_FN (bb, cfun)
    1323                 :             :     {
    1324                 :    13295168 :       curr_sp_change = 0;
    1325                 :    13295168 :       stop_to_sp_elimination_p = false;
    1326                 :   157586794 :       FOR_BB_INSNS (bb, insn)
    1327                 :   144291626 :         if (INSN_P (insn))
    1328                 :             :           {
    1329                 :   119817887 :             lra_get_insn_recog_data (insn)->sp_offset = curr_sp_change;
    1330                 :   119817887 :             if (NONDEBUG_INSN_P (insn))
    1331                 :             :               {
    1332                 :    81393820 :                 mark_not_eliminable (PATTERN (insn), VOIDmode);
    1333                 :    81393820 :                 if (maybe_ne (curr_sp_change, 0)
    1334                 :    81393820 :                     && find_reg_note (insn, REG_LABEL_OPERAND, NULL_RTX))
    1335                 :             :                   stop_to_sp_elimination_p = true;
    1336                 :             :               }
    1337                 :             :           }
    1338                 :    13295168 :       if (! frame_pointer_needed
    1339                 :     8885566 :           && (maybe_ne (curr_sp_change, 0) || stop_to_sp_elimination_p)
    1340                 :    13348405 :           && bb->succs && bb->succs->length () != 0)
    1341                 :       44960 :         for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1342                 :       35968 :           if (ep->to == STACK_POINTER_REGNUM)
    1343                 :       17984 :             setup_can_eliminate (ep, false);
    1344                 :             :     }
    1345                 :     1426764 :   setup_elimination_map ();
    1346                 :     1426764 : }
    1347                 :             : 
    1348                 :             : /* Update and return stack pointer OFFSET after processing X.  */
    1349                 :             : poly_int64
    1350                 :     7923666 : lra_update_sp_offset (rtx x, poly_int64 offset)
    1351                 :             : {
    1352                 :     7923666 :   curr_sp_change = offset;
    1353                 :     7923666 :   mark_not_eliminable (x, VOIDmode);
    1354                 :     7923666 :   return curr_sp_change;
    1355                 :             : }
    1356                 :             : 
    1357                 :             : 
    1358                 :             : /* Eliminate hard reg given by its location LOC.  */
    1359                 :             : void
    1360                 :    82256120 : lra_eliminate_reg_if_possible (rtx *loc)
    1361                 :             : {
    1362                 :    82256120 :   int regno;
    1363                 :    82256120 :   class lra_elim_table *ep;
    1364                 :             : 
    1365                 :    82256120 :   lra_assert (REG_P (*loc));
    1366                 :    82256120 :   if ((regno = REGNO (*loc)) >= FIRST_PSEUDO_REGISTER
    1367                 :    82256120 :       || ! TEST_HARD_REG_BIT (lra_no_alloc_regs, regno))
    1368                 :             :     return;
    1369                 :    61019001 :   if ((ep = get_elimination (*loc)) != NULL)
    1370                 :    57672340 :     *loc = ep->to_rtx;
    1371                 :             : }
    1372                 :             : 
    1373                 :             : /* Do (final if FINAL_P or first if FIRST_P) elimination in INSN.  Add
    1374                 :             :    the insn for subsequent processing in the constraint pass, update
    1375                 :             :    the insn info.  */
    1376                 :             : static void
    1377                 :    39824266 : process_insn_for_elimination (rtx_insn *insn, bool final_p, bool first_p)
    1378                 :             : {
    1379                 :    39824266 :   eliminate_regs_in_insn (insn, final_p, first_p, 0);
    1380                 :    39824266 :   if (! final_p)
    1381                 :             :     {
    1382                 :             :       /* Check that insn changed its code.  This is a case when a move
    1383                 :             :          insn becomes an add insn and we do not want to process the
    1384                 :             :          insn as a move anymore.  */
    1385                 :    20272294 :       int icode = recog (PATTERN (insn), insn, 0);
    1386                 :             : 
    1387                 :    20272294 :       if (icode >= 0 && icode != INSN_CODE (insn))
    1388                 :             :         {
    1389                 :       43718 :           if (INSN_CODE (insn) >= 0)
    1390                 :             :             /* Insn code is changed.  It may change its operand type
    1391                 :             :                from IN to INOUT.  Inform the subsequent assignment
    1392                 :             :                subpass about this situation.  */
    1393                 :       43718 :             check_and_force_assignment_correctness_p = true;
    1394                 :       43718 :           INSN_CODE (insn) = icode;
    1395                 :       43718 :           lra_update_insn_recog_data (insn);
    1396                 :             :         }
    1397                 :    20272294 :       lra_update_insn_regno_info (insn);
    1398                 :    20272294 :       lra_push_insn (insn);
    1399                 :    20272294 :       lra_set_used_insn_alternative (insn, LRA_UNKNOWN_ALT);
    1400                 :             :     }
    1401                 :    39824266 : }
    1402                 :             : 
    1403                 :             : /* Update frame pointer to stack pointer elimination if we started with
    1404                 :             :    permitted frame pointer elimination and now target reports that we can not
    1405                 :             :    do this elimination anymore.  Record spilled pseudos in SPILLED_PSEUDOS
    1406                 :             :    unless it is null, and return the recorded pseudos number.  */
    1407                 :             : int
    1408                 :      142897 : lra_update_fp2sp_elimination (int *spilled_pseudos)
    1409                 :             : {
    1410                 :      142897 :   int n;
    1411                 :      142897 :   HARD_REG_SET set;
    1412                 :      142897 :   class lra_elim_table *ep;
    1413                 :             : 
    1414                 :      142897 :   if (frame_pointer_needed || !targetm.frame_pointer_required ())
    1415                 :      142897 :     return 0;
    1416                 :           0 :   gcc_assert (!elimination_fp2sp_occured_p);
    1417                 :           0 :   if (lra_dump_file != NULL)
    1418                 :           0 :     fprintf (lra_dump_file,
    1419                 :             :              "        Frame pointer can not be eliminated anymore\n");
    1420                 :           0 :   frame_pointer_needed = true;
    1421                 :           0 :   CLEAR_HARD_REG_SET (set);
    1422                 :           0 :   add_to_hard_reg_set (&set, Pmode, HARD_FRAME_POINTER_REGNUM);
    1423                 :           0 :   n = spill_pseudos (set, spilled_pseudos);
    1424                 :           0 :   for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1425                 :           0 :     if (ep->from == FRAME_POINTER_REGNUM && ep->to == STACK_POINTER_REGNUM)
    1426                 :           0 :       setup_can_eliminate (ep, false);
    1427                 :             :   return n;
    1428                 :             : }
    1429                 :             : 
    1430                 :             : /* Entry function to do final elimination if FINAL_P or to update
    1431                 :             :    elimination register offsets (FIRST_P if we are doing it the first
    1432                 :             :    time).  */
    1433                 :             : void
    1434                 :     7679557 : lra_eliminate (bool final_p, bool first_p)
    1435                 :             : {
    1436                 :     7679557 :   unsigned int uid;
    1437                 :     7679557 :   bitmap_head insns_with_changed_offsets;
    1438                 :     7679557 :   bitmap_iterator bi;
    1439                 :     7679557 :   class lra_elim_table *ep;
    1440                 :             : 
    1441                 :     7679557 :   gcc_assert (! final_p || ! first_p);
    1442                 :             : 
    1443                 :     7679557 :   timevar_push (TV_LRA_ELIMINATE);
    1444                 :             : 
    1445                 :     7679557 :   if (first_p)
    1446                 :             :     {
    1447                 :     1426764 :       elimination_fp2sp_occured_p = false;
    1448                 :     1426764 :       init_elimination ();
    1449                 :             :     }
    1450                 :             : 
    1451                 :     7679557 :   bitmap_initialize (&insns_with_changed_offsets, &reg_obstack);
    1452                 :     7679557 :   if (final_p)
    1453                 :             :     {
    1454                 :     1426764 :       if (flag_checking)
    1455                 :             :         {
    1456                 :     1426740 :           update_reg_eliminate (&insns_with_changed_offsets);
    1457                 :     1426740 :           gcc_assert (bitmap_empty_p (&insns_with_changed_offsets));
    1458                 :             :         }
    1459                 :             :       /* We change eliminable hard registers in insns so we should do
    1460                 :             :          this for all insns containing any eliminable hard
    1461                 :             :          register.  */
    1462                 :     7133820 :       for (ep = reg_eliminate; ep < &reg_eliminate[NUM_ELIMINABLE_REGS]; ep++)
    1463                 :     5707056 :         if (elimination_map[ep->from] != NULL)
    1464                 :     5707056 :           bitmap_ior_into (&insns_with_changed_offsets,
    1465                 :     5707056 :                            &lra_reg_info[ep->from].insn_bitmap);
    1466                 :             :     }
    1467                 :     6252793 :   else if (! update_reg_eliminate (&insns_with_changed_offsets))
    1468                 :     4706625 :     goto lra_eliminate_done;
    1469                 :     2972932 :   if (lra_dump_file != NULL)
    1470                 :             :     {
    1471                 :         209 :       fprintf (lra_dump_file, "New elimination table:\n");
    1472                 :         209 :       print_elim_table (lra_dump_file);
    1473                 :             :     }
    1474                 :    42797198 :   EXECUTE_IF_SET_IN_BITMAP (&insns_with_changed_offsets, 0, uid, bi)
    1475                 :             :     /* A dead insn can be deleted in process_insn_for_elimination.  */
    1476                 :    39824266 :     if (lra_insn_recog_data[uid] != NULL)
    1477                 :    39824266 :       process_insn_for_elimination (lra_insn_recog_data[uid]->insn,
    1478                 :             :                                     final_p, first_p);
    1479                 :     2972932 :   bitmap_clear (&insns_with_changed_offsets);
    1480                 :             : 
    1481                 :     7679557 : lra_eliminate_done:
    1482                 :     7679557 :   timevar_pop (TV_LRA_ELIMINATE);
    1483                 :     7679557 : }
        

Generated by: LCOV version 2.1-beta

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