LCOV - code coverage report
Current view: top level - gcc - lra-eliminations.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 83.7 % 698 584
Test Date: 2026-08-22 16:33:35 Functions: 95.5 % 22 21
Legend: Lines:     hit not hit

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

Generated by: LCOV version 2.4-beta

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