LCOV - code coverage report
Current view: top level - gcc - regcprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.9 % 675 620
Test Date: 2026-03-28 14:25:54 Functions: 96.6 % 29 28
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Copy propagation on hard registers for the GNU compiler.
       2              :    Copyright (C) 2000-2026 Free Software Foundation, Inc.
       3              : 
       4              :    This file is part of GCC.
       5              : 
       6              :    GCC is free software; you can redistribute it and/or modify it
       7              :    under the terms of the GNU General Public License as published by
       8              :    the Free Software Foundation; either version 3, or (at your option)
       9              :    any later version.
      10              : 
      11              :    GCC is distributed in the hope that it will be useful, but WITHOUT
      12              :    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
      13              :    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
      14              :    License for more details.
      15              : 
      16              :    You should have received a copy of the GNU General Public License
      17              :    along with GCC; see the file COPYING3.  If not see
      18              :    <http://www.gnu.org/licenses/>.  */
      19              : 
      20              : #include "config.h"
      21              : #include "system.h"
      22              : #include "coretypes.h"
      23              : #include "backend.h"
      24              : #include "rtl.h"
      25              : #include "df.h"
      26              : #include "memmodel.h"
      27              : #include "tm_p.h"
      28              : #include "insn-config.h"
      29              : #include "regs.h"
      30              : #include "emit-rtl.h"
      31              : #include "recog.h"
      32              : #include "diagnostic-core.h"
      33              : #include "addresses.h"
      34              : #include "tree-pass.h"
      35              : #include "rtl-iter.h"
      36              : #include "cfgrtl.h"
      37              : #include "target.h"
      38              : #include "function-abi.h"
      39              : #include "cfgcleanup.h"
      40              : 
      41              : /* The following code does forward propagation of hard register copies.
      42              :    The object is to eliminate as many dependencies as possible, so that
      43              :    we have the most scheduling freedom.  As a side effect, we also clean
      44              :    up some silly register allocation decisions made by reload.  This
      45              :    code may be obsoleted by a new register allocator.  */
      46              : 
      47              : /* DEBUG_INSNs aren't changed right away, as doing so might extend the
      48              :    lifetime of a register and get the DEBUG_INSN subsequently reset.
      49              :    So they are queued instead, and updated only when the register is
      50              :    used in some subsequent real insn before it is set.  */
      51              : struct queued_debug_insn_change
      52              : {
      53              :   struct queued_debug_insn_change *next;
      54              :   rtx_insn *insn;
      55              :   rtx *loc;
      56              :   rtx new_rtx;
      57              : };
      58              : 
      59              : /* For each register, we have a list of registers that contain the same
      60              :    value.  The OLDEST_REGNO field points to the head of the list, and
      61              :    the NEXT_REGNO field runs through the list.  The MODE field indicates
      62              :    what mode the data is known to be in; this field is VOIDmode when the
      63              :    register is not known to contain valid data.  The FRAME_RELATED field
      64              :    indicates if the instruction that updated this register is frame
      65              :    related or not.  */
      66              : 
      67              : struct value_data_entry
      68              : {
      69              :   machine_mode mode;
      70              :   unsigned int oldest_regno;
      71              :   unsigned int next_regno;
      72              :   bool frame_related;
      73              :   struct queued_debug_insn_change *debug_insn_changes;
      74              : };
      75              : 
      76              : struct value_data
      77              : {
      78              :   struct value_data_entry e[FIRST_PSEUDO_REGISTER];
      79              :   unsigned int max_value_regs;
      80              :   unsigned int n_debug_insn_changes;
      81              : };
      82              : 
      83              : static object_allocator<queued_debug_insn_change> queued_debug_insn_change_pool
      84              :   ("debug insn changes pool");
      85              : 
      86              : static bool skip_debug_insn_p;
      87              : 
      88              : static void kill_value_one_regno (unsigned, struct value_data *);
      89              : static void kill_value_regno (unsigned, unsigned, struct value_data *);
      90              : static void kill_value (const_rtx, struct value_data *);
      91              : static void set_value_regno (unsigned, machine_mode, struct value_data *);
      92              : static void init_value_data (struct value_data *);
      93              : static void kill_clobbered_value (rtx, const_rtx, void *);
      94              : static void kill_set_value (rtx, const_rtx, void *);
      95              : static void copy_value (rtx, rtx, struct value_data *, bool frame_related);
      96              : static bool mode_change_ok (machine_mode, machine_mode,
      97              :                             unsigned int);
      98              : static rtx maybe_mode_change (machine_mode, machine_mode,
      99              :                               machine_mode, unsigned int, unsigned int);
     100              : static bool incompatible_frame_status (bool, bool);
     101              : static rtx find_oldest_value_reg (enum reg_class, rtx, struct value_data *, bool frame_related);
     102              : static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx_insn *,
     103              :                                       struct value_data *);
     104              : static bool replace_oldest_value_addr (rtx *, enum reg_class,
     105              :                                        machine_mode, addr_space_t,
     106              :                                        rtx_insn *, struct value_data *);
     107              : static bool replace_oldest_value_mem (rtx, rtx_insn *, struct value_data *);
     108              : static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
     109              : extern void debug_value_data (struct value_data *);
     110              : static void validate_value_data (struct value_data *);
     111              : 
     112              : /* Free all queued updates for DEBUG_INSNs that change some reg to
     113              :    register REGNO.  */
     114              : 
     115              : static void
     116       259020 : free_debug_insn_changes (struct value_data *vd, unsigned int regno)
     117              : {
     118       259020 :   struct queued_debug_insn_change *cur, *next;
     119       700615 :   for (cur = vd->e[regno].debug_insn_changes; cur; cur = next)
     120              :     {
     121       441595 :       next = cur->next;
     122       441595 :       --vd->n_debug_insn_changes;
     123       441595 :       queued_debug_insn_change_pool.remove (cur);
     124              :     }
     125       259020 :   vd->e[regno].debug_insn_changes = NULL;
     126       259020 : }
     127              : 
     128              : /* Kill register REGNO.  This involves removing it from any value
     129              :    lists, and resetting the value mode to VOIDmode.  This is only a
     130              :    helper function; it does not handle any hard registers overlapping
     131              :    with REGNO.  */
     132              : 
     133              : static void
     134     84085349 : kill_value_one_regno (unsigned int regno, struct value_data *vd)
     135              : {
     136     84085349 :   unsigned int i, next;
     137              : 
     138     84085349 :   if (vd->e[regno].oldest_regno != regno)
     139              :     {
     140       107130 :       for (i = vd->e[regno].oldest_regno;
     141      3051109 :            vd->e[i].next_regno != regno;
     142       107130 :            i = vd->e[i].next_regno)
     143       107130 :         continue;
     144      2943979 :       vd->e[i].next_regno = vd->e[regno].next_regno;
     145              :     }
     146     81141370 :   else if ((next = vd->e[regno].next_regno) != INVALID_REGNUM)
     147              :     {
     148      4591937 :       for (i = next; i != INVALID_REGNUM; i = vd->e[i].next_regno)
     149      2358580 :         vd->e[i].oldest_regno = next;
     150              :     }
     151              : 
     152     84085349 :   vd->e[regno].mode = VOIDmode;
     153     84085349 :   vd->e[regno].oldest_regno = regno;
     154     84085349 :   vd->e[regno].next_regno = INVALID_REGNUM;
     155     84085349 :   vd->e[regno].frame_related = false;
     156     84085349 :   if (vd->e[regno].debug_insn_changes)
     157       105273 :     free_debug_insn_changes (vd, regno);
     158              : 
     159     84085349 :   if (flag_checking)
     160     84085092 :     validate_value_data (vd);
     161     84085349 : }
     162              : 
     163              : /* Kill the value in register REGNO for NREGS, and any other registers
     164              :    whose values overlap.  */
     165              : 
     166              : static void
     167     83804268 : kill_value_regno (unsigned int regno, unsigned int nregs,
     168              :                   struct value_data *vd)
     169              : {
     170     83804268 :   unsigned int j;
     171              : 
     172              :   /* Kill the value we're told to kill.  */
     173    167810633 :   for (j = 0; j < nregs; ++j)
     174     84006365 :     kill_value_one_regno (regno + j, vd);
     175              : 
     176              :   /* Kill everything that overlapped what we're told to kill.  */
     177     83804268 :   if (regno < vd->max_value_regs)
     178              :     j = 0;
     179              :   else
     180     72060694 :     j = regno - vd->max_value_regs;
     181    151770484 :   for (; j < regno; ++j)
     182              :     {
     183     67966216 :       unsigned int i, n;
     184     67966216 :       if (vd->e[j].mode == VOIDmode)
     185     53038798 :         continue;
     186     14927418 :       n = hard_regno_nregs (j, vd->e[j].mode);
     187     14927418 :       if (j + n > regno)
     188       118476 :         for (i = 0; i < n; ++i)
     189        78984 :           kill_value_one_regno (j + i, vd);
     190              :     }
     191     83804268 : }
     192              : 
     193              : /* Kill X.  This is a convenience function wrapping kill_value_regno
     194              :    so that we mind the mode the register is in.  */
     195              : 
     196              : static void
     197     92618131 : kill_value (const_rtx x, struct value_data *vd)
     198              : {
     199     92618131 :   if (GET_CODE (x) == SUBREG)
     200              :     {
     201            6 :       rtx tmp = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
     202            3 :                                  GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
     203            3 :       x = tmp ? tmp : SUBREG_REG (x);
     204              :     }
     205     92618131 :   if (REG_P (x))
     206     69126979 :     kill_value_regno (REGNO (x), REG_NREGS (x), vd);
     207     92618131 : }
     208              : 
     209              : /* Remember that REGNO is valid in MODE.  */
     210              : 
     211              : static void
     212     53362904 : set_value_regno (unsigned int regno, machine_mode mode,
     213              :                  struct value_data *vd)
     214              : {
     215     53362904 :   unsigned int nregs;
     216              : 
     217     53362904 :   vd->e[regno].mode = mode;
     218              : 
     219     50830051 :   nregs = hard_regno_nregs (regno, mode);
     220     53362904 :   if (nregs > vd->max_value_regs)
     221      4875412 :     vd->max_value_regs = nregs;
     222            0 : }
     223              : 
     224              : /* Initialize VD such that there are no known relationships between regs.  */
     225              : 
     226              : static void
     227      5070748 : init_value_data (struct value_data *vd)
     228              : {
     229      5070748 :   int i;
     230    471579564 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
     231              :     {
     232    466508816 :       vd->e[i].mode = VOIDmode;
     233    466508816 :       vd->e[i].oldest_regno = i;
     234    466508816 :       vd->e[i].next_regno = INVALID_REGNUM;
     235    466508816 :       vd->e[i].debug_insn_changes = NULL;
     236    466508816 :       vd->e[i].frame_related = false;
     237              :     }
     238      5070748 :   vd->max_value_regs = 0;
     239      5070748 :   vd->n_debug_insn_changes = 0;
     240      5070748 : }
     241              : 
     242              : /* Called through note_stores.  If X is clobbered, kill its value.  */
     243              : 
     244              : static void
     245     79144631 : kill_clobbered_value (rtx x, const_rtx set, void *data)
     246              : {
     247     79144631 :   struct value_data *const vd = (struct value_data *) data;
     248              : 
     249     79144631 :   if (GET_CODE (set) == CLOBBER)
     250     10354156 :     kill_value (x, vd);
     251     79144631 : }
     252              : 
     253              : /* A structure passed as data to kill_set_value through note_stores.  */
     254              : struct kill_set_value_data
     255              : {
     256              :   struct value_data *vd;
     257              :   rtx ignore_set_reg;
     258              :   bool insn_is_frame_related;
     259              : };
     260              : 
     261              : /* Called through note_stores.  If X is set, not clobbered, kill its
     262              :    current value and install it as the root of its own value list.  */
     263              : 
     264              : static void
     265     79022399 : kill_set_value (rtx x, const_rtx set, void *data)
     266              : {
     267     79022399 :   struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data;
     268     79022399 :   if (rtx_equal_p (x, ksvd->ignore_set_reg))
     269              :     return;
     270              : 
     271     78932285 :   if (GET_CODE (set) != CLOBBER)
     272              :     {
     273     68578141 :       kill_value (x, ksvd->vd);
     274     68578141 :       if (REG_P (x))
     275              :         {
     276     46350253 :           set_value_regno (REGNO (x), GET_MODE (x), ksvd->vd);
     277     46350253 :           ksvd->vd->e[REGNO(x)].frame_related = ksvd->insn_is_frame_related;
     278              :         }
     279              :     }
     280              : }
     281              : 
     282              : /* Kill any register used in X as the base of an auto-increment expression,
     283              :    and install that register as the root of its own value list.  */
     284              : 
     285              : static void
     286     73271024 : kill_autoinc_value (rtx_insn *insn, struct value_data *vd)
     287              : {
     288     73271024 :   subrtx_iterator::array_type array;
     289    474211411 :   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
     290              :     {
     291    400940387 :       const_rtx x = *iter;
     292    400940387 :       if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
     293              :         {
     294      4389684 :           x = XEXP (x, 0);
     295      4389684 :           kill_value (x, vd);
     296      4389684 :           set_value_regno (REGNO (x), GET_MODE (x), vd);
     297      4389684 :           vd->e[REGNO(x)].frame_related = RTX_FRAME_RELATED_P (insn);
     298      4389684 :           iter.skip_subrtxes ();
     299              :         }
     300              :     }
     301     73271024 : }
     302              : 
     303              : /* Assert that SRC has been copied to DEST.  Adjust the data structures
     304              :    to reflect that SRC contains an older copy of the shared value.  */
     305              : 
     306              : static void
     307      6195627 : copy_value (rtx dest, rtx src, struct value_data *vd, bool frame_related)
     308              : {
     309      6195627 :   unsigned int dr = REGNO (dest);
     310      6195627 :   unsigned int sr = REGNO (src);
     311      6195627 :   unsigned int dn, sn;
     312      6195627 :   unsigned int i;
     313              : 
     314              :   /* ??? At present, it's possible to see noop sets.  It'd be nice if
     315              :      this were cleaned up beforehand...  */
     316      6195627 :   if (sr == dr)
     317              :     return;
     318              : 
     319              :   /* Do not propagate copies to the stack pointer, as that can leave
     320              :      memory accesses with no scheduling dependency on the stack update.  */
     321      6195627 :   if (dr == STACK_POINTER_REGNUM)
     322              :     return;
     323              : 
     324              :   /* Likewise with the frame pointer, if we're using one.  */
     325      6192057 :   if (frame_pointer_needed && dr == HARD_FRAME_POINTER_REGNUM)
     326              :     return;
     327              : 
     328              :   /* Do not propagate copies to fixed or global registers, patterns
     329              :      can be relying to see particular fixed register or users can
     330              :      expect the chosen global register in asm.  */
     331      6143180 :   if (fixed_regs[dr] || global_regs[dr])
     332              :     return;
     333              : 
     334              :   /* If SRC and DEST overlap, don't record anything.  */
     335      6143163 :   dn = REG_NREGS (dest);
     336      6143163 :   sn = REG_NREGS (src);
     337      6143163 :   if ((dr > sr && dr < sr + sn)
     338      6143163 :       || (sr > dr && sr < dr + dn))
     339              :     return;
     340              : 
     341              :   /* If SRC had no assigned mode (i.e. we didn't know it was live)
     342              :      assign it now and assume the value came from an input argument
     343              :      or somesuch.  */
     344      6143163 :   if (vd->e[sr].mode == VOIDmode)
     345      2512839 :     set_value_regno (sr, vd->e[dr].mode, vd);
     346              : 
     347      3630324 :   else if (!ordered_p (GET_MODE_PRECISION (vd->e[sr].mode),
     348      3630324 :                        GET_MODE_PRECISION (GET_MODE (src))))
     349              :     return;
     350              : 
     351              :   /* If we are narrowing the input to a smaller number of hard regs,
     352              :      and it is in big endian, we are really extracting a high part.
     353              :      Since we generally associate a low part of a value with the value itself,
     354              :      we must not do the same for the high part.
     355              :      Note we can still get low parts for the same mode combination through
     356              :      a two-step copy involving differently sized hard regs.
     357              :      Assume hard regs fr* are 32 bits each, while r* are 64 bits each:
     358              :      (set (reg:DI r0) (reg:DI fr0))
     359              :      (set (reg:SI fr2) (reg:SI r0))
     360              :      loads the low part of (reg:DI fr0) - i.e. fr1 - into fr2, while:
     361              :      (set (reg:SI fr2) (reg:SI fr0))
     362              :      loads the high part of (reg:DI fr0) into fr2.
     363              : 
     364              :      We can't properly represent the latter case in our tables, so don't
     365              :      record anything then.  */
     366      3630324 :   else if (sn < hard_regno_nregs (sr, vd->e[sr].mode)
     367      3630324 :            && maybe_ne (subreg_lowpart_offset (GET_MODE (dest),
     368              :                                                vd->e[sr].mode), 0U))
     369            0 :     return;
     370              : 
     371              :   /* If SRC had been assigned a mode narrower than the copy, we can't
     372              :      link DEST into the chain, because not all of the pieces of the
     373              :      copy came from oldest_regno.  */
     374      3630324 :   else if (sn > hard_regno_nregs (sr, vd->e[sr].mode))
     375              :     return;
     376              : 
     377              :   /* If a narrower value is copied using wider mode, the upper bits
     378              :      are undefined (could be e.g. a former paradoxical subreg).  Signal
     379              :      in that case we've only copied value using the narrower mode.
     380              :      Consider:
     381              :      (set (reg:DI r14) (mem:DI ...))
     382              :      (set (reg:QI si) (reg:QI r14))
     383              :      (set (reg:DI bp) (reg:DI r14))
     384              :      (set (reg:DI r14) (const_int ...))
     385              :      (set (reg:DI dx) (reg:DI si))
     386              :      (set (reg:DI si) (const_int ...))
     387              :      (set (reg:DI dx) (reg:DI bp))
     388              :      The last set is not redundant, while the low 8 bits of dx are already
     389              :      equal to low 8 bits of bp, the other bits are undefined.  */
     390      3630324 :   else if (partial_subreg_p (vd->e[sr].mode, GET_MODE (src)))
     391              :     {
     392        20032 :       if (!REG_CAN_CHANGE_MODE_P (sr, GET_MODE (src), vd->e[sr].mode)
     393        20032 :           || !REG_CAN_CHANGE_MODE_P (dr, vd->e[sr].mode, GET_MODE (dest)))
     394           18 :         return;
     395        20014 :       set_value_regno (dr, vd->e[sr].mode, vd);
     396              :     }
     397              : 
     398              :   /* Link DR at the end of the value chain used by SR.  */
     399              : 
     400      6143145 :   vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
     401              : 
     402      6465269 :   for (i = sr; vd->e[i].next_regno != INVALID_REGNUM; i = vd->e[i].next_regno)
     403       322124 :     continue;
     404      6143145 :   vd->e[i].next_regno = dr;
     405              : 
     406      6143145 :   vd->e[dr].frame_related = frame_related;
     407              : 
     408      6143145 :   if (flag_checking)
     409      6143116 :     validate_value_data (vd);
     410       322124 : }
     411              : 
     412              : /* Return true if a mode change from ORIG to NEW is allowed for REGNO.  */
     413              : 
     414              : static bool
     415       271010 : mode_change_ok (machine_mode orig_mode, machine_mode new_mode,
     416              :                 unsigned int regno ATTRIBUTE_UNUSED)
     417              : {
     418       271010 :   if (partial_subreg_p (orig_mode, new_mode))
     419              :     return false;
     420              : 
     421       264337 :   return REG_CAN_CHANGE_MODE_P (regno, orig_mode, new_mode);
     422              : }
     423              : 
     424              : /* Register REGNO was originally set in ORIG_MODE.  It - or a copy of it -
     425              :    was copied in COPY_MODE to COPY_REGNO, and then COPY_REGNO was accessed
     426              :    in NEW_MODE.
     427              :    Return a NEW_MODE rtx for REGNO if that's OK, otherwise return NULL_RTX.  */
     428              : 
     429              : static rtx
     430      1712491 : maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
     431              :                    machine_mode new_mode, unsigned int regno,
     432              :                    unsigned int copy_regno ATTRIBUTE_UNUSED)
     433              : {
     434              :   /* All three modes precision have to be ordered to each other,
     435              :      otherwise partial_subreg_p won't work.  */
     436      1712491 :   if (!ordered_p (GET_MODE_PRECISION (orig_mode),
     437      1712491 :                   GET_MODE_PRECISION (copy_mode))
     438      1712491 :       || !ordered_p (GET_MODE_PRECISION (copy_mode),
     439      1712491 :                      GET_MODE_PRECISION (new_mode)))
     440              :     return NULL_RTX;
     441              : 
     442      1712491 :   if (partial_subreg_p (copy_mode, orig_mode)
     443      1712491 :       && partial_subreg_p (copy_mode, new_mode))
     444              :     return NULL_RTX;
     445              : 
     446              :   /* Avoid creating multiple copies of the stack pointer.  Some ports
     447              :      assume there is one and only one stack pointer.
     448              : 
     449              :      It's unclear if we need to do the same for other special registers.  */
     450      1711464 :   if (regno == STACK_POINTER_REGNUM)
     451              :     {
     452        24821 :       if (orig_mode == new_mode && new_mode == GET_MODE (stack_pointer_rtx))
     453              :         return stack_pointer_rtx;
     454              :       else
     455              :         return NULL_RTX;
     456              :     }
     457              : 
     458      1686643 :   if (orig_mode == new_mode)
     459      1546628 :     return gen_raw_REG (new_mode, regno);
     460       140015 :   else if (mode_change_ok (orig_mode, new_mode, regno)
     461       140015 :            && mode_change_ok (copy_mode, new_mode, copy_regno))
     462              :     {
     463       130995 :       int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
     464       130995 :       int use_nregs = hard_regno_nregs (copy_regno, new_mode);
     465       130995 :       poly_uint64 bytes_per_reg;
     466       261990 :       if (!can_div_trunc_p (GET_MODE_SIZE (copy_mode),
     467              :                             copy_nregs, &bytes_per_reg))
     468       130865 :         return NULL_RTX;
     469       130995 :       poly_uint64 copy_offset = bytes_per_reg * (copy_nregs - use_nregs);
     470       130995 :       poly_uint64 offset
     471       130995 :         = subreg_size_lowpart_offset (GET_MODE_SIZE (new_mode) + copy_offset,
     472       130995 :                                       GET_MODE_SIZE (orig_mode));
     473       130995 :       regno += subreg_regno_offset (regno, orig_mode, offset, new_mode);
     474       130995 :       if (targetm.hard_regno_mode_ok (regno, new_mode))
     475       130865 :         return gen_raw_REG (new_mode, regno);
     476              :     }
     477              :   return NULL_RTX;
     478              : }
     479              : 
     480              : /* Copy propagation must not replace a value in a frame-related
     481              :    instruction with one produced by a non–frame-related instruction.
     482              :    Doing so may cause the DCE pass to delete the original frame-related
     483              :    instruction, which would in turn produce incorrect DWARF information
     484              :    (see PR122274).  TO_FRAME_RELATED indicates whether the destination
     485              :    instruction receiving the propagated value is frame-related.
     486              :    FROM_FRAME_RELATED indicates whether the instruction providing that
     487              :    value is frame-related.
     488              :    Return true if copy propagation is not permitted.  */
     489              : 
     490              : static bool
     491      1712491 : incompatible_frame_status (bool to_frame_related, bool from_frame_related)
     492              : {
     493      1712491 :   return to_frame_related && !from_frame_related;
     494              : }
     495              : 
     496              : /* Find the oldest copy of the value contained in REGNO that is in
     497              :    register class CL and has mode MODE.  If found, return an rtx
     498              :    of that oldest register, otherwise return NULL.  */
     499              : 
     500              : static rtx
     501     80828835 : find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd, bool frame_related)
     502              : {
     503     80828835 :   unsigned int regno = REGNO (reg);
     504     80828835 :   machine_mode mode = GET_MODE (reg);
     505     80828835 :   unsigned int i;
     506              : 
     507     80828835 :   gcc_assert (regno < FIRST_PSEUDO_REGISTER);
     508              : 
     509              :   /* If we are accessing REG in some mode other that what we set it in,
     510              :      make sure that the replacement is valid.  In particular, consider
     511              :         (set (reg:DI r11) (...))
     512              :         (set (reg:SI r9) (reg:SI r11))
     513              :         (set (reg:SI r10) (...))
     514              :         (set (...) (reg:DI r9))
     515              :      Replacing r9 with r11 is invalid.  */
     516     80828835 :   if (mode != vd->e[regno].mode
     517     80828835 :       && (REG_NREGS (reg) > hard_regno_nregs (regno, vd->e[regno].mode)
     518      4269181 :           || !REG_CAN_CHANGE_MODE_P (regno, mode, vd->e[regno].mode)))
     519     35781688 :     return NULL_RTX;
     520              : 
     521     45621898 :   for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
     522              :     {
     523      1988956 :       machine_mode oldmode = vd->e[i].mode;
     524      1988956 :       rtx new_rtx;
     525              : 
     526      1988956 :       if (!in_hard_reg_set_p (reg_class_contents[cl], mode, i))
     527       566281 :         continue;
     528              : 
     529      1422675 :       if (incompatible_frame_status (frame_related, vd->e[i].frame_related))
     530            0 :         continue;
     531              : 
     532      1422675 :       new_rtx = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
     533      1422675 :       if (new_rtx)
     534              :         {
     535              :           /* NEW_RTX may be the global stack pointer rtx, in which case we
     536              :              must not modify it's attributes.  */
     537      1414205 :           if (new_rtx != stack_pointer_rtx)
     538              :             {
     539      1405940 :               ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (reg);
     540      1405940 :               REG_ATTRS (new_rtx) = REG_ATTRS (reg);
     541      1405940 :               REG_POINTER (new_rtx) = REG_POINTER (reg);
     542              :             }
     543      1414205 :           return new_rtx;
     544              :         }
     545              :     }
     546              : 
     547              :   return NULL_RTX;
     548              : }
     549              : 
     550              : /* If possible, replace the register at *LOC with the oldest register
     551              :    in register class CL.  Return true if successfully replaced.  */
     552              : 
     553              : static bool
     554     64451070 : replace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx_insn *insn,
     555              :                           struct value_data *vd)
     556              : {
     557     64461832 :   rtx new_rtx = find_oldest_value_reg (cl, *loc, vd, RTX_FRAME_RELATED_P (insn));
     558     64451070 :   if (new_rtx && (!DEBUG_INSN_P (insn) || !skip_debug_insn_p))
     559              :     {
     560      1107597 :       if (DEBUG_INSN_P (insn))
     561              :         {
     562       575594 :           struct queued_debug_insn_change *change;
     563              : 
     564       575594 :           if (dump_file)
     565            2 :             fprintf (dump_file, "debug_insn %u: queued replacing reg %u with %u\n",
     566            2 :                      INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
     567              : 
     568       575594 :           change = queued_debug_insn_change_pool.allocate ();
     569       575594 :           change->next = vd->e[REGNO (new_rtx)].debug_insn_changes;
     570       575594 :           change->insn = insn;
     571       575594 :           change->loc = loc;
     572       575594 :           change->new_rtx = new_rtx;
     573       575594 :           vd->e[REGNO (new_rtx)].debug_insn_changes = change;
     574       575594 :           ++vd->n_debug_insn_changes;
     575       575594 :           return true;
     576              :         }
     577       532003 :       if (dump_file)
     578           25 :         fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
     579           25 :                  INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
     580              : 
     581       532003 :       validate_change (insn, loc, new_rtx, 1);
     582       532003 :       return true;
     583              :     }
     584              :   return false;
     585              : }
     586              : 
     587              : /* Similar to replace_oldest_value_reg, but *LOC contains an address.
     588              :    Adapted from find_reloads_address_1.  CL is INDEX_REG_CLASS or
     589              :    BASE_REG_CLASS depending on how the register is being considered.  */
     590              : 
     591              : static bool
     592     97472520 : replace_oldest_value_addr (rtx *loc, enum reg_class cl,
     593              :                            machine_mode mode, addr_space_t as,
     594              :                            rtx_insn *insn, struct value_data *vd)
     595              : {
     596     97472520 :   rtx x = *loc;
     597     97472520 :   RTX_CODE code = GET_CODE (x);
     598     97472520 :   const char *fmt;
     599     97472520 :   int i, j;
     600     97472520 :   bool changed = false;
     601              : 
     602     97472520 :   switch (code)
     603              :     {
     604     28000126 :     case PLUS:
     605     28000126 :       if (DEBUG_INSN_P (insn))
     606              :         break;
     607              : 
     608     22126555 :       {
     609     22126555 :         rtx orig_op0 = XEXP (x, 0);
     610     22126555 :         rtx orig_op1 = XEXP (x, 1);
     611     22126555 :         RTX_CODE code0 = GET_CODE (orig_op0);
     612     22126555 :         RTX_CODE code1 = GET_CODE (orig_op1);
     613     22126555 :         rtx op0 = orig_op0;
     614     22126555 :         rtx op1 = orig_op1;
     615     22126555 :         rtx *locI = NULL;
     616     22126555 :         rtx *locB = NULL;
     617     22126555 :         enum rtx_code index_code = SCRATCH;
     618              : 
     619     22126555 :         if (GET_CODE (op0) == SUBREG)
     620              :           {
     621            0 :             op0 = SUBREG_REG (op0);
     622            0 :             code0 = GET_CODE (op0);
     623              :           }
     624              : 
     625     22126555 :         if (GET_CODE (op1) == SUBREG)
     626              :           {
     627            0 :             op1 = SUBREG_REG (op1);
     628            0 :             code1 = GET_CODE (op1);
     629              :           }
     630              : 
     631     22126555 :         if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
     632     21606111 :             || code0 == ZERO_EXTEND || code1 == MEM)
     633              :           {
     634       520444 :             locI = &XEXP (x, 0);
     635       520444 :             locB = &XEXP (x, 1);
     636       520444 :             index_code = GET_CODE (*locI);
     637              :           }
     638     21606111 :         else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
     639     21604701 :                  || code1 == ZERO_EXTEND || code0 == MEM)
     640              :           {
     641         1410 :             locI = &XEXP (x, 1);
     642         1410 :             locB = &XEXP (x, 0);
     643         1410 :             index_code = GET_CODE (*locI);
     644              :           }
     645     21604701 :         else if (code0 == CONST_INT || code0 == CONST
     646     21604701 :                  || code0 == SYMBOL_REF || code0 == LABEL_REF)
     647              :           {
     648       748276 :             locB = &XEXP (x, 1);
     649       748276 :             index_code = GET_CODE (XEXP (x, 0));
     650              :           }
     651     20856425 :         else if (code1 == CONST_INT || code1 == CONST
     652              :                  || code1 == SYMBOL_REF || code1 == LABEL_REF)
     653              :           {
     654     19740165 :             locB = &XEXP (x, 0);
     655     19740165 :             index_code = GET_CODE (XEXP (x, 1));
     656              :           }
     657      1116260 :         else if (code0 == REG && code1 == REG)
     658              :           {
     659       921320 :             int index_op;
     660       921320 :             unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
     661              : 
     662          401 :             if (REGNO_OK_FOR_INDEX_P (regno1)
     663       921320 :                 && regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
     664              :               index_op = 1;
     665            0 :             else if (REGNO_OK_FOR_INDEX_P (regno0)
     666          401 :                      && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
     667              :               index_op = 0;
     668            0 :             else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
     669            0 :                      || REGNO_OK_FOR_INDEX_P (regno1))
     670              :               index_op = 1;
     671            0 :             else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
     672              :               index_op = 0;
     673              :             else
     674       920919 :               index_op = 1;
     675              : 
     676       921320 :             locI = &XEXP (x, index_op);
     677       921320 :             locB = &XEXP (x, !index_op);
     678       921320 :             index_code = GET_CODE (*locI);
     679              :           }
     680       194940 :         else if (code0 == REG)
     681              :           {
     682            0 :             locI = &XEXP (x, 0);
     683            0 :             locB = &XEXP (x, 1);
     684            0 :             index_code = GET_CODE (*locI);
     685              :           }
     686       194940 :         else if (code1 == REG)
     687              :           {
     688       194940 :             locI = &XEXP (x, 1);
     689       194940 :             locB = &XEXP (x, 0);
     690       194940 :             index_code = GET_CODE (*locI);
     691              :           }
     692              : 
     693     22126555 :         if (locI)
     694      1638114 :           changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS,
     695              :                                                 mode, as, insn, vd);
     696     22126555 :         if (locB)
     697     22126555 :           changed |= replace_oldest_value_addr (locB,
     698              :                                                 base_reg_class (mode, as, PLUS,
     699              :                                                                 index_code),
     700              :                                                 mode, as, insn, vd);
     701              :         return changed;
     702              :       }
     703              : 
     704              :     case POST_INC:
     705              :     case POST_DEC:
     706              :     case POST_MODIFY:
     707              :     case PRE_INC:
     708              :     case PRE_DEC:
     709              :     case PRE_MODIFY:
     710              :       return false;
     711              : 
     712      1878605 :     case MEM:
     713      1878605 :       return replace_oldest_value_mem (x, insn, vd);
     714              : 
     715     37302497 :     case REG:
     716     37302497 :       return replace_oldest_value_reg (loc, cl, insn, vd);
     717              : 
     718              :     default:
     719              :       break;
     720              :     }
     721              : 
     722     31806760 :   fmt = GET_RTX_FORMAT (code);
     723     74534877 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     724              :     {
     725     42728117 :       if (fmt[i] == 'e')
     726     16475033 :         changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode, as,
     727              :                                               insn, vd);
     728     26253084 :       else if (fmt[i] == 'E')
     729       352121 :         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
     730       206328 :           changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
     731              :                                                 mode, as, insn, vd);
     732              :     }
     733              : 
     734              :   return changed;
     735              : }
     736              : 
     737              : /* Similar to replace_oldest_value_reg, but X contains a memory.  */
     738              : 
     739              : static bool
     740     30314018 : replace_oldest_value_mem (rtx x, rtx_insn *insn, struct value_data *vd)
     741              : {
     742     30314018 :   enum reg_class cl;
     743              : 
     744     30314018 :   if (DEBUG_INSN_P (insn))
     745              :     cl = ALL_REGS;
     746              :   else
     747     28435413 :     cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH);
     748              : 
     749     30314018 :   return replace_oldest_value_addr (&XEXP (x, 0), cl,
     750     30314018 :                                     GET_MODE (x), MEM_ADDR_SPACE (x),
     751     30314018 :                                     insn, vd);
     752              : }
     753              : 
     754              : /* Apply all queued updates for DEBUG_INSNs that change some reg to
     755              :    register REGNO.  */
     756              : 
     757              : static void
     758       177287 : apply_debug_insn_changes (struct value_data *vd, unsigned int regno)
     759              : {
     760       177287 :   struct queued_debug_insn_change *change;
     761       177287 :   rtx_insn *last_insn = vd->e[regno].debug_insn_changes->insn;
     762              : 
     763       177287 :   for (change = vd->e[regno].debug_insn_changes;
     764       510702 :        change;
     765       333415 :        change = change->next)
     766              :     {
     767       333415 :       if (last_insn != change->insn)
     768              :         {
     769       152815 :           apply_change_group ();
     770       152815 :           last_insn = change->insn;
     771              :         }
     772       333415 :       validate_change (change->insn, change->loc, change->new_rtx, 1);
     773              :     }
     774       177287 :   apply_change_group ();
     775       177287 : }
     776              : 
     777              : /* Called via note_uses, for all used registers in a real insn
     778              :    apply DEBUG_INSN changes that change registers to the used
     779              :    registers.  */
     780              : 
     781              : static void
     782       945827 : cprop_find_used_regs (rtx *loc, void *data)
     783              : {
     784       945827 :   struct value_data *const vd = (struct value_data *) data;
     785       945827 :   subrtx_iterator::array_type array;
     786      3497762 :   FOR_EACH_SUBRTX (iter, array, *loc, NONCONST)
     787              :     {
     788      2551935 :       const_rtx x = *iter;
     789      2551935 :       if (REG_P (x))
     790              :         {
     791       871824 :           unsigned int regno = REGNO (x);
     792       871824 :           if (vd->e[regno].debug_insn_changes)
     793              :             {
     794       153747 :               apply_debug_insn_changes (vd, regno);
     795       153747 :               free_debug_insn_changes (vd, regno);
     796              :             }
     797              :         }
     798              :     }
     799       945827 : }
     800              : 
     801              : /* Apply clobbers of INSN in PATTERN and C_I_F_U to value_data VD.  */
     802              : 
     803              : static void
     804     73361138 : kill_clobbered_values (rtx_insn *insn, struct value_data *vd)
     805              : {
     806            0 :   note_stores (insn, kill_clobbered_value, vd);
     807        90114 : }
     808              : 
     809              : /* Perform the forward copy propagation on basic block BB.  */
     810              : 
     811              : static bool
     812     12231346 : copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
     813              : {
     814     12231346 :   bool anything_changed = false;
     815     12231346 :   rtx_insn *insn, *next;
     816              : 
     817     12231346 :   for (insn = BB_HEAD (bb); ; insn = next)
     818              :     {
     819    156067282 :       int n_ops, i, predicated;
     820    156067282 :       bool is_asm, any_replacements;
     821    156067282 :       rtx set;
     822    156067282 :       rtx link;
     823    156067282 :       bool changed = false;
     824    156067282 :       struct kill_set_value_data ksvd;
     825              : 
     826    156067282 :       next = NEXT_INSN (insn);
     827    156067282 :       if (!NONDEBUG_INSN_P (insn))
     828              :         {
     829     82608323 :           if (DEBUG_BIND_INSN_P (insn))
     830              :             {
     831     42033777 :               rtx loc = INSN_VAR_LOCATION_LOC (insn);
     832     42033777 :               if (!VAR_LOC_UNKNOWN_P (loc))
     833     23490129 :                 replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
     834     23490129 :                                            ALL_REGS, GET_MODE (loc),
     835              :                                            ADDR_SPACE_GENERIC, insn, vd);
     836              :             }
     837              : 
     838     82608323 :           if (insn == BB_END (bb))
     839              :             break;
     840              :           else
     841     82370122 :             continue;
     842              :         }
     843              : 
     844     73458959 :       set = single_set (insn);
     845              : 
     846              :       /* Detect noop sets and remove them before processing side effects.  */
     847     73458959 :       if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
     848              :         {
     849      6325490 :           unsigned int regno = REGNO (SET_SRC (set));
     850      6325490 :           rtx r1 = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     851              :                                           SET_DEST (set), vd, false);
     852      6325490 :           rtx r2 = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     853              :                                           SET_SRC (set), vd, false);
     854      6325490 :           if (rtx_equal_p (r1 ? r1 : SET_DEST (set), r2 ? r2 : SET_SRC (set)))
     855              :             {
     856        63838 :               bool last = insn == BB_END (bb);
     857        63838 :               delete_insn (insn);
     858        63838 :               if (last)
     859              :                 break;
     860        61689 :               continue;
     861        61689 :             }
     862              :         }
     863              : 
     864              :       /* Detect obviously dead sets (via REG_UNUSED notes) and remove them.  */
     865              :       if (set
     866     67455233 :           && !RTX_FRAME_RELATED_P (insn)
     867     63539270 :           && NONJUMP_INSN_P (insn)
     868     53398883 :           && !may_trap_p (set)
     869     46443865 :           && find_reg_note (insn, REG_UNUSED, SET_DEST (set))
     870       249660 :           && !side_effects_p (SET_SRC (set))
     871       124097 :           && !side_effects_p (SET_DEST (set)))
     872              :         {
     873       124097 :           bool last = insn == BB_END (bb);
     874       124097 :           delete_insn_and_edges (insn);
     875       124097 :           if (last)
     876              :             break;
     877       124094 :           continue;
     878       124094 :         }
     879              : 
     880              : 
     881     73271024 :       extract_constrain_insn (insn);
     882     73271024 :       preprocess_constraints (insn);
     883     73271024 :       const operand_alternative *op_alt = which_op_alt ();
     884     73271024 :       n_ops = recog_data.n_operands;
     885     73271024 :       is_asm = asm_noperands (PATTERN (insn)) >= 0;
     886              : 
     887              :       /* Simplify the code below by promoting OP_OUT to OP_INOUT
     888              :          in predicated instructions.  */
     889              : 
     890     73271024 :       predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
     891    226516061 :       for (i = 0; i < n_ops; ++i)
     892              :         {
     893    153245037 :           int matches = op_alt[i].matches;
     894    153245037 :           if (matches >= 0 || op_alt[i].matched >= 0
     895    135879020 :               || (predicated && recog_data.operand_type[i] == OP_OUT))
     896     17366017 :             recog_data.operand_type[i] = OP_INOUT;
     897              :         }
     898              : 
     899              :       /* Apply changes to earlier DEBUG_INSNs if possible.  */
     900     73271024 :       if (vd->n_debug_insn_changes)
     901       701021 :         note_uses (&PATTERN (insn), cprop_find_used_regs, vd);
     902              : 
     903              :       /* For each earlyclobber operand, zap the value data.  */
     904    226516061 :       for (i = 0; i < n_ops; i++)
     905    153245037 :         if (op_alt[i].earlyclobber)
     906        12544 :           kill_value (recog_data.operand[i], vd);
     907              : 
     908              :       /* Within asms, a clobber cannot overlap inputs or outputs.
     909              :          I wouldn't think this were true for regular insns, but
     910              :          scan_rtx treats them like that...  */
     911     73271024 :       kill_clobbered_values (insn, vd);
     912              : 
     913              :       /* Kill all auto-incremented values.  */
     914              :       /* ??? REG_INC is useless, since stack pushes aren't done that way.  */
     915     73271024 :       kill_autoinc_value (insn, vd);
     916              : 
     917              :       /* Kill all early-clobbered operands.  */
     918    299787085 :       for (i = 0; i < n_ops; i++)
     919    153245037 :         if (op_alt[i].earlyclobber)
     920        12544 :           kill_value (recog_data.operand[i], vd);
     921              : 
     922              :       /* If we have dead sets in the insn, then we need to note these as we
     923              :          would clobbers.  */
     924    141618124 :       for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     925              :         {
     926     68347123 :           if (REG_NOTE_KIND (link) == REG_UNUSED)
     927              :             {
     928      9180948 :               kill_value (XEXP (link, 0), vd);
     929              :               /* Furthermore, if the insn looked like a single-set,
     930              :                  but the dead store kills the source value of that
     931              :                  set, then we can no-longer use the plain move
     932              :                  special case below.  */
     933      9180948 :               if (set
     934      9180948 :                   && reg_overlap_mentioned_p (XEXP (link, 0), SET_SRC (set)))
     935              :                 set = NULL;
     936              :             }
     937              : 
     938              :           /* We need to keep CFI info correct, and the same on all paths,
     939              :              so we cannot normally replace the registers REG_CFA_REGISTER
     940              :              refers to.  Bail.  */
     941     68347123 :           if (REG_NOTE_KIND (link) == REG_CFA_REGISTER)
     942           23 :             goto did_replacement;
     943              :         }
     944              : 
     945              :       /* Special-case plain move instructions, since we may well
     946              :          be able to do the move from a different register class.  */
     947     73271001 :       if (set && REG_P (SET_SRC (set)))
     948              :         {
     949     16431623 :           rtx src = SET_SRC (set);
     950     16431623 :           rtx dest = SET_DEST (set);
     951     16431623 :           unsigned int regno = REGNO (src);
     952     16431623 :           machine_mode mode = GET_MODE (src);
     953     16431623 :           unsigned int i;
     954     16431623 :           rtx new_rtx;
     955              : 
     956              :           /* If we are accessing SRC in some mode other that what we
     957              :              set it in, make sure that the replacement is valid.  */
     958     16431623 :           if (mode != vd->e[regno].mode)
     959              :             {
     960      6547403 :               if (REG_NREGS (src)
     961      6547403 :                   > hard_regno_nregs (regno, vd->e[regno].mode))
     962      5216755 :                 goto no_move_special_case;
     963              : 
     964              :               /* And likewise, if we are narrowing on big endian the transformation
     965              :                  is also invalid.  */
     966      1330648 :               if (REG_NREGS (src) < hard_regno_nregs (regno, vd->e[regno].mode)
     967      1330648 :                   && maybe_ne (subreg_lowpart_offset (mode,
     968              :                                                       vd->e[regno].mode), 0U))
     969            0 :                 goto no_move_special_case;
     970              :             }
     971              : 
     972              :           /* If the destination is also a register, try to find a source
     973              :              register in the same class.  */
     974     11214868 :           if (REG_P (dest))
     975              :             {
     976     11180355 :               new_rtx = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     977      3726785 :                                                src, vd, RTX_FRAME_RELATED_P (insn));
     978              : 
     979      3726785 :               if (new_rtx && validate_change (insn, &SET_SRC (set), new_rtx, 0))
     980              :                 {
     981        70548 :                   if (dump_file)
     982            2 :                     fprintf (dump_file,
     983              :                              "insn %u: replaced reg %u with %u\n",
     984            2 :                              INSN_UID (insn), regno, REGNO (new_rtx));
     985        70548 :                   changed = true;
     986        70548 :                   goto did_replacement;
     987              :                 }
     988              :               /* We need to re-extract as validate_change clobbers
     989              :                  recog_data.  */
     990      3656237 :               extract_constrain_insn (insn);
     991      3656237 :               preprocess_constraints (insn);
     992              :             }
     993              : 
     994              :           /* Otherwise, try all valid registers and see if its valid.  */
     995     11160390 :           for (i = vd->e[regno].oldest_regno; i != regno;
     996        16070 :                i = vd->e[i].next_regno)
     997              :             {
     998       289816 :               if (incompatible_frame_status (RTX_FRAME_RELATED_P (insn), vd->e[i].frame_related))
     999            0 :                 continue;
    1000       289816 :               new_rtx = maybe_mode_change (vd->e[i].mode, vd->e[regno].mode,
    1001              :                                        mode, i, regno);
    1002       289816 :               if (new_rtx != NULL_RTX)
    1003              :                 {
    1004              :                   /* Don't propagate for a more expensive reg-reg move.  */
    1005       287909 :                   if (REG_P (dest))
    1006              :                     {
    1007       134435 :                       enum reg_class from = REGNO_REG_CLASS (regno);
    1008       134435 :                       enum reg_class to = REGNO_REG_CLASS (REGNO (dest));
    1009       134435 :                       enum reg_class new_from = REGNO_REG_CLASS (i);
    1010       134435 :                       unsigned int original_cost
    1011       134435 :                         = targetm.register_move_cost (mode, from, to);
    1012       134435 :                       unsigned int after_cost
    1013       134435 :                         = targetm.register_move_cost (mode, new_from, to);
    1014       134435 :                       if (after_cost > original_cost)
    1015         8246 :                         continue;
    1016              :                     }
    1017              : 
    1018       279663 :                   if (validate_change (insn, &SET_SRC (set), new_rtx, 0))
    1019              :                     {
    1020              :                       /* NEW_RTX may be the global stack pointer rtx, in which
    1021              :                          case we must not modify it's attributes.  */
    1022       273746 :                       if (new_rtx != stack_pointer_rtx)
    1023              :                         {
    1024       257394 :                           ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (src);
    1025       257394 :                           REG_ATTRS (new_rtx) = REG_ATTRS (src);
    1026       257394 :                           REG_POINTER (new_rtx) = REG_POINTER (src);
    1027              :                         }
    1028       273746 :                       if (dump_file)
    1029            1 :                         fprintf (dump_file,
    1030              :                                  "insn %u: replaced reg %u with %u\n",
    1031            1 :                                  INSN_UID (insn), regno, REGNO (new_rtx));
    1032       273746 :                       changed = true;
    1033       273746 :                       goto did_replacement;
    1034              :                     }
    1035              :                   /* We need to re-extract as validate_change clobbers
    1036              :                      recog_data.  */
    1037         5917 :                   extract_constrain_insn (insn);
    1038         5917 :                   preprocess_constraints (insn);
    1039              :                 }
    1040              :             }
    1041              :         }
    1042     56839378 :       no_move_special_case:
    1043              : 
    1044              :       any_replacements = false;
    1045              : 
    1046              :       /* For each input operand, replace a hard register with the
    1047              :          eldest live copy that's in an appropriate register class.  */
    1048    225483121 :       for (i = 0; i < n_ops; i++)
    1049              :         {
    1050    152556414 :           bool replaced = false;
    1051              : 
    1052              :           /* Don't scan match_operand here, since we've no reg class
    1053              :              information to pass down.  Any operands that we could
    1054              :              substitute in will be represented elsewhere.  */
    1055    152556414 :           if (recog_data.constraints[i][0] == '\0')
    1056     27472209 :             continue;
    1057              : 
    1058              :           /* Don't replace in asms intentionally referencing hard regs.  */
    1059       150787 :           if (is_asm && REG_P (recog_data.operand[i])
    1060    125215856 :               && (REGNO (recog_data.operand[i])
    1061       131651 :                   == ORIGINAL_REGNO (recog_data.operand[i])))
    1062         2018 :             continue;
    1063              : 
    1064    125082187 :           if (recog_data.operand_type[i] == OP_IN)
    1065              :             {
    1066     64696525 :               if (op_alt[i].is_address)
    1067      3222343 :                 replaced
    1068      3222343 :                   = replace_oldest_value_addr (recog_data.operand_loc[i],
    1069              :                                                alternative_class (op_alt, i),
    1070              :                                                VOIDmode, ADDR_SPACE_GENERIC,
    1071              :                                                insn, vd);
    1072     61474182 :               else if (REG_P (recog_data.operand[i]))
    1073     27148573 :                 replaced
    1074     27148573 :                   = replace_oldest_value_reg (recog_data.operand_loc[i],
    1075              :                                               alternative_class (op_alt, i),
    1076              :                                               insn, vd);
    1077     34325609 :               else if (MEM_P (recog_data.operand[i]))
    1078     14265627 :                 replaced = replace_oldest_value_mem (recog_data.operand[i],
    1079              :                                                      insn, vd);
    1080              :             }
    1081     60385662 :           else if (MEM_P (recog_data.operand[i]))
    1082     14169786 :             replaced = replace_oldest_value_mem (recog_data.operand[i],
    1083              :                                                  insn, vd);
    1084              : 
    1085              :           /* If we performed any replacement, update match_dups.  */
    1086     58806329 :           if (replaced)
    1087              :             {
    1088       530692 :               int j;
    1089       530692 :               rtx new_rtx;
    1090              : 
    1091       530692 :               new_rtx = *recog_data.operand_loc[i];
    1092       530692 :               recog_data.operand[i] = new_rtx;
    1093       558147 :               for (j = 0; j < recog_data.n_dups; j++)
    1094        27455 :                 if (recog_data.dup_num[j] == i)
    1095         9326 :                   validate_unshare_change (insn, recog_data.dup_loc[j], new_rtx, 1);
    1096              : 
    1097              :               any_replacements = true;
    1098              :             }
    1099              :         }
    1100              : 
    1101     72926707 :       if (any_replacements)
    1102              :         {
    1103       527781 :           if (! apply_change_group ())
    1104              :             {
    1105          350 :               if (dump_file)
    1106            0 :                 fprintf (dump_file,
    1107              :                          "insn %u: reg replacements not verified\n",
    1108            0 :                          INSN_UID (insn));
    1109              :             }
    1110              :           else
    1111              :             changed = true;
    1112              :         }
    1113              : 
    1114       344317 :     did_replacement:
    1115       344317 :       if (changed)
    1116              :         {
    1117       871725 :           anything_changed = true;
    1118              : 
    1119              :           /* If something changed, perhaps further changes to earlier
    1120              :              DEBUG_INSNs can be applied.  */
    1121       871725 :           if (vd->n_debug_insn_changes)
    1122       116024 :             note_uses (&PATTERN (insn), cprop_find_used_regs, vd);
    1123       871725 :           df_insn_rescan (insn);
    1124              :         }
    1125              : 
    1126     73271024 :       ksvd.vd = vd;
    1127     73271024 :       ksvd.ignore_set_reg = NULL_RTX;
    1128     73271024 :       ksvd.insn_is_frame_related = false;
    1129              : 
    1130              :       /* Clobber call-clobbered registers.  */
    1131     73271024 :       if (CALL_P (insn))
    1132              :         {
    1133      5459799 :           unsigned int set_regno = INVALID_REGNUM;
    1134      5459799 :           unsigned int set_nregs = 0;
    1135      5459799 :           unsigned int regno;
    1136      5459799 :           rtx exp;
    1137              : 
    1138     16087661 :           for (exp = CALL_INSN_FUNCTION_USAGE (insn); exp; exp = XEXP (exp, 1))
    1139              :             {
    1140     10717976 :               rtx x = XEXP (exp, 0);
    1141     10717976 :               if (GET_CODE (x) == SET)
    1142              :                 {
    1143        90114 :                   rtx dest = SET_DEST (x);
    1144        90114 :                   kill_value (dest, vd);
    1145        90114 :                   set_value_regno (REGNO (dest), GET_MODE (dest), vd);
    1146        90114 :                   copy_value (dest, SET_SRC (x), vd, false);
    1147        90114 :                   ksvd.ignore_set_reg = dest;
    1148        90114 :                   set_regno = REGNO (dest);
    1149        90114 :                   set_nregs = REG_NREGS (dest);
    1150        90114 :                   break;
    1151              :                 }
    1152              :             }
    1153              : 
    1154      5459799 :           function_abi callee_abi = insn_callee_abi (insn);
    1155    513221106 :           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1156    502301508 :             if (vd->e[regno].mode != VOIDmode
    1157     24432129 :                 && callee_abi.clobbers_reg_p (vd->e[regno].mode, regno)
    1158    517068911 :                 && (regno < set_regno || regno >= set_regno + set_nregs))
    1159     14677289 :               kill_value_regno (regno, 1, vd);
    1160              : 
    1161              :           /* If SET was seen in CALL_INSN_FUNCTION_USAGE, and SET_SRC
    1162              :              of the SET isn't clobbered by CALLEE_ABI, but instead among
    1163              :              CLOBBERs on the CALL_INSN, we could wrongly assume the
    1164              :              value in it is still live.  */
    1165      5459799 :           if (ksvd.ignore_set_reg)
    1166        90114 :             kill_clobbered_values (insn, vd);
    1167              :         }
    1168              : 
    1169    152679646 :       bool copy_p = (set
    1170     67011878 :                      && REG_P (SET_DEST (set))
    1171    118134406 :                      && REG_P (SET_SRC (set)));
    1172      6137619 :       bool noop_p = (copy_p
    1173      6137619 :                      && rtx_equal_p (SET_DEST (set), SET_SRC (set)));
    1174              : 
    1175              :       /* If a noop move is using narrower mode than we have recorded,
    1176              :          we need to either remove the noop move, or kill_set_value.  */
    1177        32106 :       if (noop_p
    1178        32106 :           && partial_subreg_p (GET_MODE (SET_DEST (set)),
    1179        32106 :                                vd->e[REGNO (SET_DEST (set))].mode))
    1180              :         {
    1181         1985 :           if (noop_move_p (insn))
    1182              :             {
    1183         1985 :               bool last = insn == BB_END (bb);
    1184         1985 :               delete_insn (insn);
    1185         1985 :               if (last)
    1186              :                 break;
    1187              :             }
    1188              :           else
    1189              :             noop_p = false;
    1190              :         }
    1191              : 
    1192     73271003 :       if (!noop_p)
    1193              :         {
    1194     73238918 :           ksvd.insn_is_frame_related = RTX_FRAME_RELATED_P (insn);
    1195              : 
    1196              :           /* Notice stores.  */
    1197     73238918 :           note_stores (insn, kill_set_value, &ksvd);
    1198              : 
    1199              :           /* Notice copies.  */
    1200     73238918 :           if (copy_p)
    1201              :             {
    1202      6105513 :               df_insn_rescan (insn);
    1203      6105513 :               copy_value (SET_DEST (set), SET_SRC (set), vd, RTX_FRAME_RELATED_P (insn));
    1204              :             }
    1205              :         }
    1206              : 
    1207     73271003 :       if (insn == BB_END (bb))
    1208              :         break;
    1209              :     }
    1210              : 
    1211     12231346 :   return anything_changed;
    1212              : }
    1213              : 
    1214              : /* Dump the value chain data to stderr.  */
    1215              : 
    1216              : DEBUG_FUNCTION void
    1217            0 : debug_value_data (struct value_data *vd)
    1218              : {
    1219            0 :   HARD_REG_SET set;
    1220            0 :   unsigned int i, j;
    1221              : 
    1222            0 :   CLEAR_HARD_REG_SET (set);
    1223              : 
    1224            0 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1225            0 :     if (vd->e[i].oldest_regno == i)
    1226              :       {
    1227            0 :         if (vd->e[i].mode == VOIDmode)
    1228              :           {
    1229            0 :             if (vd->e[i].next_regno != INVALID_REGNUM)
    1230            0 :               fprintf (stderr, "[%u] Bad next_regno for empty chain (%u)\n",
    1231              :                        i, vd->e[i].next_regno);
    1232            0 :             continue;
    1233              :           }
    1234              : 
    1235            0 :         SET_HARD_REG_BIT (set, i);
    1236            0 :         fprintf (stderr, "[%u %s] ", i, GET_MODE_NAME (vd->e[i].mode));
    1237              : 
    1238            0 :         for (j = vd->e[i].next_regno;
    1239            0 :              j != INVALID_REGNUM;
    1240            0 :              j = vd->e[j].next_regno)
    1241              :           {
    1242            0 :             if (TEST_HARD_REG_BIT (set, j))
    1243              :               {
    1244            0 :                 fprintf (stderr, "[%u] Loop in regno chain\n", j);
    1245            0 :                 return;
    1246              :               }
    1247              : 
    1248            0 :             if (vd->e[j].oldest_regno != i)
    1249              :               {
    1250            0 :                 fprintf (stderr, "[%u] Bad oldest_regno (%u)\n",
    1251              :                          j, vd->e[j].oldest_regno);
    1252            0 :                 return;
    1253              :               }
    1254            0 :             SET_HARD_REG_BIT (set, j);
    1255            0 :             fprintf (stderr, "[%u %s] ", j, GET_MODE_NAME (vd->e[j].mode));
    1256              :           }
    1257            0 :         fputc ('\n', stderr);
    1258              :       }
    1259              : 
    1260            0 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1261            0 :     if (! TEST_HARD_REG_BIT (set, i)
    1262            0 :         && (vd->e[i].mode != VOIDmode
    1263            0 :             || vd->e[i].oldest_regno != i
    1264            0 :             || vd->e[i].next_regno != INVALID_REGNUM))
    1265            0 :       fprintf (stderr, "[%u] Non-empty reg in chain (%s %u %i)\n",
    1266            0 :                i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
    1267              :                vd->e[i].next_regno);
    1268              : }
    1269              : 
    1270              : /* Do copyprop_hardreg_forward_1 for a single basic block BB.
    1271              :    DEBUG_INSN is skipped since we do not want to involve DF related
    1272              :    staff as how it is handled in function pass_cprop_hardreg::execute.
    1273              : 
    1274              :    NOTE: Currently it is only used for shrink-wrap.  Maybe extend it
    1275              :    to handle DEBUG_INSN for other uses.  */
    1276              : 
    1277              : void
    1278       356447 : copyprop_hardreg_forward_bb_without_debug_insn (basic_block bb)
    1279              : {
    1280       356447 :   struct value_data *vd;
    1281       356447 :   vd = XNEWVEC (struct value_data, 1);
    1282       356447 :   init_value_data (vd);
    1283              : 
    1284       356447 :   skip_debug_insn_p = true;
    1285       356447 :   copyprop_hardreg_forward_1 (bb, vd);
    1286       356447 :   free (vd);
    1287       356447 :   skip_debug_insn_p = false;
    1288       356447 : }
    1289              : 
    1290              : static void
    1291     90228208 : validate_value_data (struct value_data *vd)
    1292              : {
    1293     90228208 :   HARD_REG_SET set;
    1294     90228208 :   unsigned int i, j;
    1295              : 
    1296     90228208 :   CLEAR_HARD_REG_SET (set);
    1297              : 
    1298   8391223344 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1299   8300995136 :     if (vd->e[i].oldest_regno == i)
    1300              :       {
    1301   8273077718 :         if (vd->e[i].mode == VOIDmode)
    1302              :           {
    1303   7949702911 :             if (vd->e[i].next_regno != INVALID_REGNUM)
    1304            0 :               internal_error ("%qs: [%u] bad %<next_regno%> for empty chain (%u)",
    1305              :                               __func__, i, vd->e[i].next_regno);
    1306   7949702911 :             continue;
    1307              :           }
    1308              : 
    1309    323374807 :         SET_HARD_REG_BIT (set, i);
    1310              : 
    1311    323374807 :         for (j = vd->e[i].next_regno;
    1312    351292225 :              j != INVALID_REGNUM;
    1313     27917418 :              j = vd->e[j].next_regno)
    1314              :           {
    1315     27917418 :             if (TEST_HARD_REG_BIT (set, j))
    1316            0 :               internal_error ("%qs: loop in %<next_regno%> chain (%u)",
    1317              :                               __func__, j);
    1318     27917418 :             if (vd->e[j].oldest_regno != i)
    1319            0 :               internal_error ("%qs: [%u] bad %<oldest_regno%> (%u)",
    1320              :                               __func__, j, vd->e[j].oldest_regno);
    1321              : 
    1322     27917418 :             SET_HARD_REG_BIT (set, j);
    1323              :           }
    1324              :       }
    1325              : 
    1326   8391223344 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1327   8300995136 :     if (! TEST_HARD_REG_BIT (set, i)
    1328   8300995136 :         && (vd->e[i].mode != VOIDmode
    1329   7949702911 :             || vd->e[i].oldest_regno != i
    1330   7949702911 :             || vd->e[i].next_regno != INVALID_REGNUM))
    1331            0 :       internal_error ("%qs: [%u] non-empty register in chain (%s %u %i)",
    1332              :                       __func__, i,
    1333            0 :                       GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
    1334              :                       vd->e[i].next_regno);
    1335     90228208 : }
    1336              : 
    1337              : 
    1338              : namespace {
    1339              : 
    1340              : const pass_data pass_data_cprop_hardreg =
    1341              : {
    1342              :   RTL_PASS, /* type */
    1343              :   "cprop_hardreg", /* name */
    1344              :   OPTGROUP_NONE, /* optinfo_flags */
    1345              :   TV_CPROP_REGISTERS, /* tv_id */
    1346              :   0, /* properties_required */
    1347              :   0, /* properties_provided */
    1348              :   0, /* properties_destroyed */
    1349              :   0, /* todo_flags_start */
    1350              :   TODO_df_finish, /* todo_flags_finish */
    1351              : };
    1352              : 
    1353              : class pass_cprop_hardreg : public rtl_opt_pass
    1354              : {
    1355              : public:
    1356       287872 :   pass_cprop_hardreg (gcc::context *ctxt)
    1357       575744 :     : rtl_opt_pass (pass_data_cprop_hardreg, ctxt)
    1358              :   {}
    1359              : 
    1360              :   /* opt_pass methods: */
    1361      1480955 :   bool gate (function *) final override
    1362              :     {
    1363      1480955 :       return (optimize > 0 && (flag_cprop_registers));
    1364              :     }
    1365              : 
    1366              :   unsigned int execute (function *) final override;
    1367              : 
    1368              : }; // class pass_cprop_hardreg
    1369              : 
    1370              : static bool
    1371     11874899 : cprop_hardreg_bb (basic_block bb, struct value_data *all_vd, sbitmap visited)
    1372              : {
    1373     11874899 :   bitmap_set_bit (visited, bb->index);
    1374              : 
    1375              :   /* If a block has a single predecessor, that we've already
    1376              :      processed, begin with the value data that was live at
    1377              :      the end of the predecessor block.  */
    1378              :   /* ??? Ought to use more intelligent queuing of blocks.  */
    1379     11874899 :   if (single_pred_p (bb)
    1380      8792933 :       && bitmap_bit_p (visited, single_pred (bb)->index)
    1381     19153971 :       && ! (single_pred_edge (bb)->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
    1382              :     {
    1383      7160598 :       all_vd[bb->index] = all_vd[single_pred (bb)->index];
    1384      7160598 :       if (all_vd[bb->index].n_debug_insn_changes)
    1385              :         {
    1386              :           unsigned int regno;
    1387              : 
    1388       498076 :           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1389              :             {
    1390       498076 :               if (all_vd[bb->index].e[regno].debug_insn_changes)
    1391              :                 {
    1392              :                   struct queued_debug_insn_change *cur;
    1393       108435 :                   for (cur = all_vd[bb->index].e[regno].debug_insn_changes;
    1394       179732 :                        cur; cur = cur->next)
    1395       108435 :                     --all_vd[bb->index].n_debug_insn_changes;
    1396        71297 :                   all_vd[bb->index].e[regno].debug_insn_changes = NULL;
    1397        71297 :                   if (all_vd[bb->index].n_debug_insn_changes == 0)
    1398              :                     break;
    1399              :                 }
    1400              :             }
    1401              :         }
    1402              :     }
    1403              :   else
    1404      4714301 :     init_value_data (all_vd + bb->index);
    1405              : 
    1406     11874899 :   return copyprop_hardreg_forward_1 (bb, all_vd + bb->index);
    1407              : }
    1408              : 
    1409              : static void
    1410        49036 : cprop_hardreg_debug (function *fun, struct value_data *all_vd)
    1411              : {
    1412        49036 :   basic_block bb;
    1413              : 
    1414      3237408 :   FOR_EACH_BB_FN (bb, fun)
    1415      3188372 :     if (all_vd[bb->index].n_debug_insn_changes)
    1416              :       {
    1417        81775 :         unsigned int regno;
    1418        81775 :         bitmap live;
    1419              : 
    1420        81775 :         live = df_get_live_out (bb);
    1421       591363 :         for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1422       591363 :           if (all_vd[bb->index].e[regno].debug_insn_changes)
    1423              :             {
    1424        84416 :               if (REGNO_REG_SET_P (live, regno))
    1425        23540 :                 apply_debug_insn_changes (all_vd + bb->index, regno);
    1426              : 
    1427        84416 :               struct queued_debug_insn_change *cur;
    1428        84416 :               for (cur = all_vd[bb->index].e[regno].debug_insn_changes;
    1429       218415 :                    cur; cur = cur->next)
    1430       133999 :                 --all_vd[bb->index].n_debug_insn_changes;
    1431        84416 :               all_vd[bb->index].e[regno].debug_insn_changes = NULL;
    1432        84416 :               if (all_vd[bb->index].n_debug_insn_changes == 0)
    1433              :                 break;
    1434              :             }
    1435              :       }
    1436              : 
    1437        49036 :   queued_debug_insn_change_pool.release ();
    1438        49036 : }
    1439              : 
    1440              : unsigned int
    1441      1040225 : pass_cprop_hardreg::execute (function *fun)
    1442              : {
    1443      1040225 :   struct value_data *all_vd;
    1444      1040225 :   basic_block bb;
    1445              : 
    1446      1040225 :   all_vd = XNEWVEC (struct value_data, last_basic_block_for_fn (fun));
    1447              : 
    1448      1040225 :   auto_sbitmap visited (last_basic_block_for_fn (fun));
    1449      1040225 :   bitmap_clear (visited);
    1450              : 
    1451      1040225 :   auto_vec<int> worklist1, worklist2;
    1452      1040225 :   auto_vec<int> *curr = &worklist1;
    1453      1040225 :   auto_vec<int> *next = &worklist2;
    1454      1040225 :   bool any_debug_changes = false;
    1455      1040225 :   bool any_changes = false;
    1456              : 
    1457              :   /* We need accurate notes.  Earlier passes such as if-conversion may
    1458              :      leave notes in an inconsistent state.  */
    1459      1040225 :   df_note_add_problem ();
    1460      1040225 :   df_analyze ();
    1461              : 
    1462              :   /* It is tempting to set DF_LR_RUN_DCE, but DCE may choose to delete
    1463              :      an insn and this pass would not have visibility into the removal.
    1464              :      This pass would then potentially use the source of that
    1465              :      INSN for propagation purposes, generating invalid code.
    1466              : 
    1467              :      So we just ask for updated notes and handle trivial deletions
    1468              :      within this pass where we can update this passes internal
    1469              :      data structures appropriately.  */
    1470      1040225 :   df_set_flags (DF_DEFER_INSN_RESCAN);
    1471              : 
    1472     12442374 :   FOR_EACH_BB_FN (bb, fun)
    1473              :     {
    1474     11402149 :       if (cprop_hardreg_bb (bb, all_vd, visited))
    1475              :         {
    1476       469085 :           curr->safe_push (bb->index);
    1477       469085 :           any_changes = true;
    1478              :         }
    1479     11402149 :       if (all_vd[bb->index].n_debug_insn_changes)
    1480        69935 :         any_debug_changes = true;
    1481              :     }
    1482              : 
    1483              :   /* We must call df_analyze here unconditionally to ensure that the
    1484              :      REG_UNUSED and REG_DEAD notes are consistent with and without -g.  */
    1485      1040225 :   df_analyze ();
    1486              : 
    1487      1040225 :   if (MAY_HAVE_DEBUG_BIND_INSNS && any_debug_changes)
    1488        40306 :     cprop_hardreg_debug (fun, all_vd);
    1489              : 
    1490              :   /* Repeat pass up to PASSES times, but only processing basic blocks
    1491              :      that have changed on the previous iteration.  CURR points to the
    1492              :      current worklist, and each iteration populates the NEXT worklist,
    1493              :      swapping pointers after each cycle.  */
    1494              : 
    1495      1040225 :   unsigned int passes = optimize > 1 ? 3 : 2;
    1496      1220992 :   for (unsigned int pass = 2; pass <= passes && !curr->is_empty (); pass++)
    1497              :     {
    1498       180767 :       any_debug_changes = false;
    1499       180767 :       bitmap_clear (visited);
    1500       180767 :       next->truncate (0);
    1501       653517 :       for (int index : *curr)
    1502              :         {
    1503       472750 :           bb = BASIC_BLOCK_FOR_FN (fun, index);
    1504       472750 :           if (cprop_hardreg_bb (bb, all_vd, visited))
    1505              :             {
    1506         4372 :               next->safe_push (bb->index);
    1507         4372 :               any_changes = true;
    1508              :             }
    1509       472750 :           if (all_vd[bb->index].n_debug_insn_changes)
    1510        11840 :             any_debug_changes = true;
    1511              :         }
    1512              : 
    1513       180767 :       df_analyze ();
    1514       180767 :       if (MAY_HAVE_DEBUG_BIND_INSNS && any_debug_changes)
    1515         8730 :         cprop_hardreg_debug (fun, all_vd);
    1516       180767 :       std::swap (curr, next);
    1517              :     }
    1518              : 
    1519      1040225 :   free (all_vd);
    1520              : 
    1521              :   /* Copy propagation of the sp register into an mem's address
    1522              :      can cause what was a trapping instruction into
    1523              :      a non-trapping one so cleanup after that in the case of non-call
    1524              :      exceptions.  */
    1525      1040225 :   if (any_changes
    1526       177905 :       && cfun->can_throw_non_call_exceptions
    1527      1091646 :       && purge_all_dead_edges ())
    1528            4 :     cleanup_cfg (0);
    1529      1040225 :   return 0;
    1530      1040225 : }
    1531              : 
    1532              : } // anon namespace
    1533              : 
    1534              : rtl_opt_pass *
    1535       287872 : make_pass_cprop_hardreg (gcc::context *ctxt)
    1536              : {
    1537       287872 :   return new pass_cprop_hardreg (ctxt);
    1538              : }
        

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.