LCOV - code coverage report
Current view: top level - gcc - regcprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 91.7 % 664 609
Test Date: 2026-02-28 14:20:25 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              : 
      40              : /* The following code does forward propagation of hard register copies.
      41              :    The object is to eliminate as many dependencies as possible, so that
      42              :    we have the most scheduling freedom.  As a side effect, we also clean
      43              :    up some silly register allocation decisions made by reload.  This
      44              :    code may be obsoleted by a new register allocator.  */
      45              : 
      46              : /* DEBUG_INSNs aren't changed right away, as doing so might extend the
      47              :    lifetime of a register and get the DEBUG_INSN subsequently reset.
      48              :    So they are queued instead, and updated only when the register is
      49              :    used in some subsequent real insn before it is set.  */
      50              : struct queued_debug_insn_change
      51              : {
      52              :   struct queued_debug_insn_change *next;
      53              :   rtx_insn *insn;
      54              :   rtx *loc;
      55              :   rtx new_rtx;
      56              : };
      57              : 
      58              : /* For each register, we have a list of registers that contain the same
      59              :    value.  The OLDEST_REGNO field points to the head of the list, and
      60              :    the NEXT_REGNO field runs through the list.  The MODE field indicates
      61              :    what mode the data is known to be in; this field is VOIDmode when the
      62              :    register is not known to contain valid data.  The FRAME_RELATED field
      63              :    indicates if the instruction that updated this register is frame
      64              :    related or not.  */
      65              : 
      66              : struct value_data_entry
      67              : {
      68              :   machine_mode mode;
      69              :   unsigned int oldest_regno;
      70              :   unsigned int next_regno;
      71              :   bool frame_related;
      72              :   struct queued_debug_insn_change *debug_insn_changes;
      73              : };
      74              : 
      75              : struct value_data
      76              : {
      77              :   struct value_data_entry e[FIRST_PSEUDO_REGISTER];
      78              :   unsigned int max_value_regs;
      79              :   unsigned int n_debug_insn_changes;
      80              : };
      81              : 
      82              : static object_allocator<queued_debug_insn_change> queued_debug_insn_change_pool
      83              :   ("debug insn changes pool");
      84              : 
      85              : static bool skip_debug_insn_p;
      86              : 
      87              : static void kill_value_one_regno (unsigned, struct value_data *);
      88              : static void kill_value_regno (unsigned, unsigned, struct value_data *);
      89              : static void kill_value (const_rtx, struct value_data *);
      90              : static void set_value_regno (unsigned, machine_mode, struct value_data *);
      91              : static void init_value_data (struct value_data *);
      92              : static void kill_clobbered_value (rtx, const_rtx, void *);
      93              : static void kill_set_value (rtx, const_rtx, void *);
      94              : static void copy_value (rtx, rtx, struct value_data *, bool frame_related);
      95              : static bool mode_change_ok (machine_mode, machine_mode,
      96              :                             unsigned int);
      97              : static rtx maybe_mode_change (machine_mode, machine_mode,
      98              :                               machine_mode, unsigned int, unsigned int);
      99              : static bool incompatible_frame_status (bool, bool);
     100              : static rtx find_oldest_value_reg (enum reg_class, rtx, struct value_data *, bool frame_related);
     101              : static bool replace_oldest_value_reg (rtx *, enum reg_class, rtx_insn *,
     102              :                                       struct value_data *);
     103              : static bool replace_oldest_value_addr (rtx *, enum reg_class,
     104              :                                        machine_mode, addr_space_t,
     105              :                                        rtx_insn *, struct value_data *);
     106              : static bool replace_oldest_value_mem (rtx, rtx_insn *, struct value_data *);
     107              : static bool copyprop_hardreg_forward_1 (basic_block, struct value_data *);
     108              : extern void debug_value_data (struct value_data *);
     109              : static void validate_value_data (struct value_data *);
     110              : 
     111              : /* Free all queued updates for DEBUG_INSNs that change some reg to
     112              :    register REGNO.  */
     113              : 
     114              : static void
     115       262474 : free_debug_insn_changes (struct value_data *vd, unsigned int regno)
     116              : {
     117       262474 :   struct queued_debug_insn_change *cur, *next;
     118       714037 :   for (cur = vd->e[regno].debug_insn_changes; cur; cur = next)
     119              :     {
     120       451563 :       next = cur->next;
     121       451563 :       --vd->n_debug_insn_changes;
     122       451563 :       queued_debug_insn_change_pool.remove (cur);
     123              :     }
     124       262474 :   vd->e[regno].debug_insn_changes = NULL;
     125       262474 : }
     126              : 
     127              : /* Kill register REGNO.  This involves removing it from any value
     128              :    lists, and resetting the value mode to VOIDmode.  This is only a
     129              :    helper function; it does not handle any hard registers overlapping
     130              :    with REGNO.  */
     131              : 
     132              : static void
     133     84042250 : kill_value_one_regno (unsigned int regno, struct value_data *vd)
     134              : {
     135     84042250 :   unsigned int i, next;
     136              : 
     137     84042250 :   if (vd->e[regno].oldest_regno != regno)
     138              :     {
     139       106794 :       for (i = vd->e[regno].oldest_regno;
     140      3045448 :            vd->e[i].next_regno != regno;
     141       106794 :            i = vd->e[i].next_regno)
     142       106794 :         continue;
     143      2938654 :       vd->e[i].next_regno = vd->e[regno].next_regno;
     144              :     }
     145     81103596 :   else if ((next = vd->e[regno].next_regno) != INVALID_REGNUM)
     146              :     {
     147      4600055 :       for (i = next; i != INVALID_REGNUM; i = vd->e[i].next_regno)
     148      2362291 :         vd->e[i].oldest_regno = next;
     149              :     }
     150              : 
     151     84042250 :   vd->e[regno].mode = VOIDmode;
     152     84042250 :   vd->e[regno].oldest_regno = regno;
     153     84042250 :   vd->e[regno].next_regno = INVALID_REGNUM;
     154     84042250 :   vd->e[regno].frame_related = false;
     155     84042250 :   if (vd->e[regno].debug_insn_changes)
     156       106089 :     free_debug_insn_changes (vd, regno);
     157              : 
     158     84042250 :   if (flag_checking)
     159     84041993 :     validate_value_data (vd);
     160     84042250 : }
     161              : 
     162              : /* Kill the value in register REGNO for NREGS, and any other registers
     163              :    whose values overlap.  */
     164              : 
     165              : static void
     166     83760343 : kill_value_regno (unsigned int regno, unsigned int nregs,
     167              :                   struct value_data *vd)
     168              : {
     169     83760343 :   unsigned int j;
     170              : 
     171              :   /* Kill the value we're told to kill.  */
     172    167722721 :   for (j = 0; j < nregs; ++j)
     173     83962378 :     kill_value_one_regno (regno + j, vd);
     174              : 
     175              :   /* Kill everything that overlapped what we're told to kill.  */
     176     83760343 :   if (regno < vd->max_value_regs)
     177              :     j = 0;
     178              :   else
     179     72003554 :     j = regno - vd->max_value_regs;
     180    151649884 :   for (; j < regno; ++j)
     181              :     {
     182     67889541 :       unsigned int i, n;
     183     67889541 :       if (vd->e[j].mode == VOIDmode)
     184     53009379 :         continue;
     185     14880162 :       n = hard_regno_nregs (j, vd->e[j].mode);
     186     14880162 :       if (j + n > regno)
     187       119808 :         for (i = 0; i < n; ++i)
     188        79872 :           kill_value_one_regno (j + i, vd);
     189              :     }
     190     83760343 : }
     191              : 
     192              : /* Kill X.  This is a convenience function wrapping kill_value_regno
     193              :    so that we mind the mode the register is in.  */
     194              : 
     195              : static void
     196     92580549 : kill_value (const_rtx x, struct value_data *vd)
     197              : {
     198     92580549 :   if (GET_CODE (x) == SUBREG)
     199              :     {
     200            6 :       rtx tmp = simplify_subreg (GET_MODE (x), SUBREG_REG (x),
     201            3 :                                  GET_MODE (SUBREG_REG (x)), SUBREG_BYTE (x));
     202            3 :       x = tmp ? tmp : SUBREG_REG (x);
     203              :     }
     204     92580549 :   if (REG_P (x))
     205     69085333 :     kill_value_regno (REGNO (x), REG_NREGS (x), vd);
     206     92580549 : }
     207              : 
     208              : /* Remember that REGNO is valid in MODE.  */
     209              : 
     210              : static void
     211     53353577 : set_value_regno (unsigned int regno, machine_mode mode,
     212              :                  struct value_data *vd)
     213              : {
     214     53353577 :   unsigned int nregs;
     215              : 
     216     53353577 :   vd->e[regno].mode = mode;
     217              : 
     218     50806751 :   nregs = hard_regno_nregs (regno, mode);
     219     53353577 :   if (nregs > vd->max_value_regs)
     220      4890849 :     vd->max_value_regs = nregs;
     221            0 : }
     222              : 
     223              : /* Initialize VD such that there are no known relationships between regs.  */
     224              : 
     225              : static void
     226      5087947 : init_value_data (struct value_data *vd)
     227              : {
     228      5087947 :   int i;
     229    473179071 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
     230              :     {
     231    468091124 :       vd->e[i].mode = VOIDmode;
     232    468091124 :       vd->e[i].oldest_regno = i;
     233    468091124 :       vd->e[i].next_regno = INVALID_REGNUM;
     234    468091124 :       vd->e[i].debug_insn_changes = NULL;
     235    468091124 :       vd->e[i].frame_related = false;
     236              :     }
     237      5087947 :   vd->max_value_regs = 0;
     238      5087947 :   vd->n_debug_insn_changes = 0;
     239      5087947 : }
     240              : 
     241              : /* Called through note_stores.  If X is clobbered, kill its value.  */
     242              : 
     243              : static void
     244     79119290 : kill_clobbered_value (rtx x, const_rtx set, void *data)
     245              : {
     246     79119290 :   struct value_data *const vd = (struct value_data *) data;
     247              : 
     248     79119290 :   if (GET_CODE (set) == CLOBBER)
     249     10348359 :     kill_value (x, vd);
     250     79119290 : }
     251              : 
     252              : /* A structure passed as data to kill_set_value through note_stores.  */
     253              : struct kill_set_value_data
     254              : {
     255              :   struct value_data *vd;
     256              :   rtx ignore_set_reg;
     257              :   bool insn_is_frame_related;
     258              : };
     259              : 
     260              : /* Called through note_stores.  If X is set, not clobbered, kill its
     261              :    current value and install it as the root of its own value list.  */
     262              : 
     263              : static void
     264     78995640 : kill_set_value (rtx x, const_rtx set, void *data)
     265              : {
     266     78995640 :   struct kill_set_value_data *ksvd = (struct kill_set_value_data *) data;
     267     78995640 :   if (rtx_equal_p (x, ksvd->ignore_set_reg))
     268              :     return;
     269              : 
     270     78903795 :   if (GET_CODE (set) != CLOBBER)
     271              :     {
     272     68555448 :       kill_value (x, ksvd->vd);
     273     68555448 :       if (REG_P (x))
     274              :         {
     275     46324752 :           set_value_regno (REGNO (x), GET_MODE (x), ksvd->vd);
     276     46324752 :           ksvd->vd->e[REGNO(x)].frame_related = ksvd->insn_is_frame_related;
     277              :         }
     278              :     }
     279              : }
     280              : 
     281              : /* Kill any register used in X as the base of an auto-increment expression,
     282              :    and install that register as the root of its own value list.  */
     283              : 
     284              : static void
     285     73270507 : kill_autoinc_value (rtx_insn *insn, struct value_data *vd)
     286              : {
     287     73270507 :   subrtx_iterator::array_type array;
     288    474194446 :   FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
     289              :     {
     290    400923939 :       const_rtx x = *iter;
     291    400923939 :       if (GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
     292              :         {
     293      4390154 :           x = XEXP (x, 0);
     294      4390154 :           kill_value (x, vd);
     295      4390154 :           set_value_regno (REGNO (x), GET_MODE (x), vd);
     296      4390154 :           vd->e[REGNO(x)].frame_related = RTX_FRAME_RELATED_P (insn);
     297      4390154 :           iter.skip_subrtxes ();
     298              :         }
     299              :     }
     300     73270507 : }
     301              : 
     302              : /* Assert that SRC has been copied to DEST.  Adjust the data structures
     303              :    to reflect that SRC contains an older copy of the shared value.  */
     304              : 
     305              : static void
     306      6201967 : copy_value (rtx dest, rtx src, struct value_data *vd, bool frame_related)
     307              : {
     308      6201967 :   unsigned int dr = REGNO (dest);
     309      6201967 :   unsigned int sr = REGNO (src);
     310      6201967 :   unsigned int dn, sn;
     311      6201967 :   unsigned int i;
     312              : 
     313              :   /* ??? At present, it's possible to see noop sets.  It'd be nice if
     314              :      this were cleaned up beforehand...  */
     315      6201967 :   if (sr == dr)
     316              :     return;
     317              : 
     318              :   /* Do not propagate copies to the stack pointer, as that can leave
     319              :      memory accesses with no scheduling dependency on the stack update.  */
     320      6201967 :   if (dr == STACK_POINTER_REGNUM)
     321              :     return;
     322              : 
     323              :   /* Likewise with the frame pointer, if we're using one.  */
     324      6198397 :   if (frame_pointer_needed && dr == HARD_FRAME_POINTER_REGNUM)
     325              :     return;
     326              : 
     327              :   /* Do not propagate copies to fixed or global registers, patterns
     328              :      can be relying to see particular fixed register or users can
     329              :      expect the chosen global register in asm.  */
     330      6149519 :   if (fixed_regs[dr] || global_regs[dr])
     331              :     return;
     332              : 
     333              :   /* If SRC and DEST overlap, don't record anything.  */
     334      6149502 :   dn = REG_NREGS (dest);
     335      6149502 :   sn = REG_NREGS (src);
     336      6149502 :   if ((dr > sr && dr < sr + sn)
     337      6149502 :       || (sr > dr && sr < dr + dn))
     338              :     return;
     339              : 
     340              :   /* If SRC had no assigned mode (i.e. we didn't know it was live)
     341              :      assign it now and assume the value came from an input argument
     342              :      or somesuch.  */
     343      6149502 :   if (vd->e[sr].mode == VOIDmode)
     344      2527039 :     set_value_regno (sr, vd->e[dr].mode, vd);
     345              : 
     346      3622463 :   else if (!ordered_p (GET_MODE_PRECISION (vd->e[sr].mode),
     347      3622463 :                        GET_MODE_PRECISION (GET_MODE (src))))
     348              :     return;
     349              : 
     350              :   /* If we are narrowing the input to a smaller number of hard regs,
     351              :      and it is in big endian, we are really extracting a high part.
     352              :      Since we generally associate a low part of a value with the value itself,
     353              :      we must not do the same for the high part.
     354              :      Note we can still get low parts for the same mode combination through
     355              :      a two-step copy involving differently sized hard regs.
     356              :      Assume hard regs fr* are 32 bits each, while r* are 64 bits each:
     357              :      (set (reg:DI r0) (reg:DI fr0))
     358              :      (set (reg:SI fr2) (reg:SI r0))
     359              :      loads the low part of (reg:DI fr0) - i.e. fr1 - into fr2, while:
     360              :      (set (reg:SI fr2) (reg:SI fr0))
     361              :      loads the high part of (reg:DI fr0) into fr2.
     362              : 
     363              :      We can't properly represent the latter case in our tables, so don't
     364              :      record anything then.  */
     365      3622463 :   else if (sn < hard_regno_nregs (sr, vd->e[sr].mode)
     366      3622463 :            && maybe_ne (subreg_lowpart_offset (GET_MODE (dest),
     367              :                                                vd->e[sr].mode), 0U))
     368            0 :     return;
     369              : 
     370              :   /* If SRC had been assigned a mode narrower than the copy, we can't
     371              :      link DEST into the chain, because not all of the pieces of the
     372              :      copy came from oldest_regno.  */
     373      3622463 :   else if (sn > hard_regno_nregs (sr, vd->e[sr].mode))
     374              :     return;
     375              : 
     376              :   /* If a narrower value is copied using wider mode, the upper bits
     377              :      are undefined (could be e.g. a former paradoxical subreg).  Signal
     378              :      in that case we've only copied value using the narrower mode.
     379              :      Consider:
     380              :      (set (reg:DI r14) (mem:DI ...))
     381              :      (set (reg:QI si) (reg:QI r14))
     382              :      (set (reg:DI bp) (reg:DI r14))
     383              :      (set (reg:DI r14) (const_int ...))
     384              :      (set (reg:DI dx) (reg:DI si))
     385              :      (set (reg:DI si) (const_int ...))
     386              :      (set (reg:DI dx) (reg:DI bp))
     387              :      The last set is not redundant, while the low 8 bits of dx are already
     388              :      equal to low 8 bits of bp, the other bits are undefined.  */
     389      3622463 :   else if (partial_subreg_p (vd->e[sr].mode, GET_MODE (src)))
     390              :     {
     391        19802 :       if (!REG_CAN_CHANGE_MODE_P (sr, GET_MODE (src), vd->e[sr].mode)
     392        19802 :           || !REG_CAN_CHANGE_MODE_P (dr, vd->e[sr].mode, GET_MODE (dest)))
     393           15 :         return;
     394        19787 :       set_value_regno (dr, vd->e[sr].mode, vd);
     395              :     }
     396              : 
     397              :   /* Link DR at the end of the value chain used by SR.  */
     398              : 
     399      6149487 :   vd->e[dr].oldest_regno = vd->e[sr].oldest_regno;
     400              : 
     401      6471619 :   for (i = sr; vd->e[i].next_regno != INVALID_REGNUM; i = vd->e[i].next_regno)
     402       322132 :     continue;
     403      6149487 :   vd->e[i].next_regno = dr;
     404              : 
     405      6149487 :   vd->e[dr].frame_related = frame_related;
     406              : 
     407      6149487 :   if (flag_checking)
     408      6149458 :     validate_value_data (vd);
     409       322132 : }
     410              : 
     411              : /* Return true if a mode change from ORIG to NEW is allowed for REGNO.  */
     412              : 
     413              : static bool
     414       267796 : mode_change_ok (machine_mode orig_mode, machine_mode new_mode,
     415              :                 unsigned int regno ATTRIBUTE_UNUSED)
     416              : {
     417       267796 :   if (partial_subreg_p (orig_mode, new_mode))
     418              :     return false;
     419              : 
     420       261250 :   return REG_CAN_CHANGE_MODE_P (regno, orig_mode, new_mode);
     421              : }
     422              : 
     423              : /* Register REGNO was originally set in ORIG_MODE.  It - or a copy of it -
     424              :    was copied in COPY_MODE to COPY_REGNO, and then COPY_REGNO was accessed
     425              :    in NEW_MODE.
     426              :    Return a NEW_MODE rtx for REGNO if that's OK, otherwise return NULL_RTX.  */
     427              : 
     428              : static rtx
     429      1730736 : maybe_mode_change (machine_mode orig_mode, machine_mode copy_mode,
     430              :                    machine_mode new_mode, unsigned int regno,
     431              :                    unsigned int copy_regno ATTRIBUTE_UNUSED)
     432              : {
     433      1730736 :   if (partial_subreg_p (copy_mode, orig_mode)
     434      1730736 :       && partial_subreg_p (copy_mode, new_mode))
     435              :     return NULL_RTX;
     436              : 
     437              :   /* Avoid creating multiple copies of the stack pointer.  Some ports
     438              :      assume there is one and only one stack pointer.
     439              : 
     440              :      It's unclear if we need to do the same for other special registers.  */
     441      1729724 :   if (regno == STACK_POINTER_REGNUM)
     442              :     {
     443        24815 :       if (orig_mode == new_mode && new_mode == GET_MODE (stack_pointer_rtx))
     444              :         return stack_pointer_rtx;
     445              :       else
     446              :         return NULL_RTX;
     447              :     }
     448              : 
     449      1704909 :   if (orig_mode == new_mode)
     450      1566644 :     return gen_raw_REG (new_mode, regno);
     451       138265 :   else if (mode_change_ok (orig_mode, new_mode, regno)
     452       138265 :            && mode_change_ok (copy_mode, new_mode, copy_regno))
     453              :     {
     454       129531 :       int copy_nregs = hard_regno_nregs (copy_regno, copy_mode);
     455       129531 :       int use_nregs = hard_regno_nregs (copy_regno, new_mode);
     456       129531 :       poly_uint64 bytes_per_reg;
     457       259062 :       if (!can_div_trunc_p (GET_MODE_SIZE (copy_mode),
     458              :                             copy_nregs, &bytes_per_reg))
     459       129401 :         return NULL_RTX;
     460       129531 :       poly_uint64 copy_offset = bytes_per_reg * (copy_nregs - use_nregs);
     461       129531 :       poly_uint64 offset
     462       129531 :         = subreg_size_lowpart_offset (GET_MODE_SIZE (new_mode) + copy_offset,
     463       129531 :                                       GET_MODE_SIZE (orig_mode));
     464       129531 :       regno += subreg_regno_offset (regno, orig_mode, offset, new_mode);
     465       129531 :       if (targetm.hard_regno_mode_ok (regno, new_mode))
     466       129401 :         return gen_raw_REG (new_mode, regno);
     467              :     }
     468              :   return NULL_RTX;
     469              : }
     470              : 
     471              : /* Copy propagation must not replace a value in a frame-related
     472              :    instruction with one produced by a non–frame-related instruction.
     473              :    Doing so may cause the DCE pass to delete the original frame-related
     474              :    instruction, which would in turn produce incorrect DWARF information
     475              :    (see PR122274).  TO_FRAME_RELATED indicates whether the destination
     476              :    instruction receiving the propagated value is frame-related.
     477              :    FROM_FRAME_RELATED indicates whether the instruction providing that
     478              :    value is frame-related.
     479              :    Return true if copy propagation is not permitted.  */
     480              : 
     481              : static bool
     482      1730736 : incompatible_frame_status (bool to_frame_related, bool from_frame_related)
     483              : {
     484      1730736 :   return to_frame_related && !from_frame_related;
     485              : }
     486              : 
     487              : /* Find the oldest copy of the value contained in REGNO that is in
     488              :    register class CL and has mode MODE.  If found, return an rtx
     489              :    of that oldest register, otherwise return NULL.  */
     490              : 
     491              : static rtx
     492     80949716 : find_oldest_value_reg (enum reg_class cl, rtx reg, struct value_data *vd, bool frame_related)
     493              : {
     494     80949716 :   unsigned int regno = REGNO (reg);
     495     80949716 :   machine_mode mode = GET_MODE (reg);
     496     80949716 :   unsigned int i;
     497              : 
     498     80949716 :   gcc_assert (regno < FIRST_PSEUDO_REGISTER);
     499              : 
     500              :   /* If we are accessing REG in some mode other that what we set it in,
     501              :      make sure that the replacement is valid.  In particular, consider
     502              :         (set (reg:DI r11) (...))
     503              :         (set (reg:SI r9) (reg:SI r11))
     504              :         (set (reg:SI r10) (...))
     505              :         (set (...) (reg:DI r9))
     506              :      Replacing r9 with r11 is invalid.  */
     507     80949716 :   if (mode != vd->e[regno].mode
     508     80949716 :       && (REG_NREGS (reg) > hard_regno_nregs (regno, vd->e[regno].mode)
     509      4224366 :           || !REG_CAN_CHANGE_MODE_P (regno, mode, vd->e[regno].mode)))
     510     35893994 :     return NULL_RTX;
     511              : 
     512     45622609 :   for (i = vd->e[regno].oldest_regno; i != regno; i = vd->e[i].next_regno)
     513              :     {
     514      2000643 :       machine_mode oldmode = vd->e[i].mode;
     515      2000643 :       rtx new_rtx;
     516              : 
     517      2000643 :       if (!in_hard_reg_set_p (reg_class_contents[cl], mode, i))
     518       558538 :         continue;
     519              : 
     520      1442105 :       if (incompatible_frame_status (frame_related, vd->e[i].frame_related))
     521            0 :         continue;
     522              : 
     523      1442105 :       new_rtx = maybe_mode_change (oldmode, vd->e[regno].mode, mode, i, regno);
     524      1442105 :       if (new_rtx)
     525              :         {
     526              :           /* NEW_RTX may be the global stack pointer rtx, in which case we
     527              :              must not modify it's attributes.  */
     528      1433756 :           if (new_rtx != stack_pointer_rtx)
     529              :             {
     530      1425483 :               ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (reg);
     531      1425483 :               REG_ATTRS (new_rtx) = REG_ATTRS (reg);
     532      1425483 :               REG_POINTER (new_rtx) = REG_POINTER (reg);
     533              :             }
     534      1433756 :           return new_rtx;
     535              :         }
     536              :     }
     537              : 
     538              :   return NULL_RTX;
     539              : }
     540              : 
     541              : /* If possible, replace the register at *LOC with the oldest register
     542              :    in register class CL.  Return true if successfully replaced.  */
     543              : 
     544              : static bool
     545     64575018 : replace_oldest_value_reg (rtx *loc, enum reg_class cl, rtx_insn *insn,
     546              :                           struct value_data *vd)
     547              : {
     548     64585634 :   rtx new_rtx = find_oldest_value_reg (cl, *loc, vd, RTX_FRAME_RELATED_P (insn));
     549     64575018 :   if (new_rtx && (!DEBUG_INSN_P (insn) || !skip_debug_insn_p))
     550              :     {
     551      1124428 :       if (DEBUG_INSN_P (insn))
     552              :         {
     553       585917 :           struct queued_debug_insn_change *change;
     554              : 
     555       585917 :           if (dump_file)
     556            2 :             fprintf (dump_file, "debug_insn %u: queued replacing reg %u with %u\n",
     557            2 :                      INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
     558              : 
     559       585917 :           change = queued_debug_insn_change_pool.allocate ();
     560       585917 :           change->next = vd->e[REGNO (new_rtx)].debug_insn_changes;
     561       585917 :           change->insn = insn;
     562       585917 :           change->loc = loc;
     563       585917 :           change->new_rtx = new_rtx;
     564       585917 :           vd->e[REGNO (new_rtx)].debug_insn_changes = change;
     565       585917 :           ++vd->n_debug_insn_changes;
     566       585917 :           return true;
     567              :         }
     568       538511 :       if (dump_file)
     569           25 :         fprintf (dump_file, "insn %u: replaced reg %u with %u\n",
     570           25 :                  INSN_UID (insn), REGNO (*loc), REGNO (new_rtx));
     571              : 
     572       538511 :       validate_change (insn, loc, new_rtx, 1);
     573       538511 :       return true;
     574              :     }
     575              :   return false;
     576              : }
     577              : 
     578              : /* Similar to replace_oldest_value_reg, but *LOC contains an address.
     579              :    Adapted from find_reloads_address_1.  CL is INDEX_REG_CLASS or
     580              :    BASE_REG_CLASS depending on how the register is being considered.  */
     581              : 
     582              : static bool
     583     97742455 : replace_oldest_value_addr (rtx *loc, enum reg_class cl,
     584              :                            machine_mode mode, addr_space_t as,
     585              :                            rtx_insn *insn, struct value_data *vd)
     586              : {
     587     97742455 :   rtx x = *loc;
     588     97742455 :   RTX_CODE code = GET_CODE (x);
     589     97742455 :   const char *fmt;
     590     97742455 :   int i, j;
     591     97742455 :   bool changed = false;
     592              : 
     593     97742455 :   switch (code)
     594              :     {
     595     28067552 :     case PLUS:
     596     28067552 :       if (DEBUG_INSN_P (insn))
     597              :         break;
     598              : 
     599     22138085 :       {
     600     22138085 :         rtx orig_op0 = XEXP (x, 0);
     601     22138085 :         rtx orig_op1 = XEXP (x, 1);
     602     22138085 :         RTX_CODE code0 = GET_CODE (orig_op0);
     603     22138085 :         RTX_CODE code1 = GET_CODE (orig_op1);
     604     22138085 :         rtx op0 = orig_op0;
     605     22138085 :         rtx op1 = orig_op1;
     606     22138085 :         rtx *locI = NULL;
     607     22138085 :         rtx *locB = NULL;
     608     22138085 :         enum rtx_code index_code = SCRATCH;
     609              : 
     610     22138085 :         if (GET_CODE (op0) == SUBREG)
     611              :           {
     612            0 :             op0 = SUBREG_REG (op0);
     613            0 :             code0 = GET_CODE (op0);
     614              :           }
     615              : 
     616     22138085 :         if (GET_CODE (op1) == SUBREG)
     617              :           {
     618            0 :             op1 = SUBREG_REG (op1);
     619            0 :             code1 = GET_CODE (op1);
     620              :           }
     621              : 
     622     22138085 :         if (code0 == MULT || code0 == SIGN_EXTEND || code0 == TRUNCATE
     623     21618789 :             || code0 == ZERO_EXTEND || code1 == MEM)
     624              :           {
     625       519296 :             locI = &XEXP (x, 0);
     626       519296 :             locB = &XEXP (x, 1);
     627       519296 :             index_code = GET_CODE (*locI);
     628              :           }
     629     21618789 :         else if (code1 == MULT || code1 == SIGN_EXTEND || code1 == TRUNCATE
     630     21617380 :                  || code1 == ZERO_EXTEND || code0 == MEM)
     631              :           {
     632         1409 :             locI = &XEXP (x, 1);
     633         1409 :             locB = &XEXP (x, 0);
     634         1409 :             index_code = GET_CODE (*locI);
     635              :           }
     636     21617380 :         else if (code0 == CONST_INT || code0 == CONST
     637     21617380 :                  || code0 == SYMBOL_REF || code0 == LABEL_REF)
     638              :           {
     639       746433 :             locB = &XEXP (x, 1);
     640       746433 :             index_code = GET_CODE (XEXP (x, 0));
     641              :           }
     642     20870947 :         else if (code1 == CONST_INT || code1 == CONST
     643              :                  || code1 == SYMBOL_REF || code1 == LABEL_REF)
     644              :           {
     645     19754381 :             locB = &XEXP (x, 0);
     646     19754381 :             index_code = GET_CODE (XEXP (x, 1));
     647              :           }
     648      1116566 :         else if (code0 == REG && code1 == REG)
     649              :           {
     650       922298 :             int index_op;
     651       922298 :             unsigned regno0 = REGNO (op0), regno1 = REGNO (op1);
     652              : 
     653          401 :             if (REGNO_OK_FOR_INDEX_P (regno1)
     654       922298 :                 && regno_ok_for_base_p (regno0, mode, as, PLUS, REG))
     655              :               index_op = 1;
     656            0 :             else if (REGNO_OK_FOR_INDEX_P (regno0)
     657          401 :                      && regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
     658              :               index_op = 0;
     659            0 :             else if (regno_ok_for_base_p (regno0, mode, as, PLUS, REG)
     660            0 :                      || REGNO_OK_FOR_INDEX_P (regno1))
     661              :               index_op = 1;
     662            0 :             else if (regno_ok_for_base_p (regno1, mode, as, PLUS, REG))
     663              :               index_op = 0;
     664              :             else
     665       921897 :               index_op = 1;
     666              : 
     667       922298 :             locI = &XEXP (x, index_op);
     668       922298 :             locB = &XEXP (x, !index_op);
     669       922298 :             index_code = GET_CODE (*locI);
     670              :           }
     671       194268 :         else if (code0 == REG)
     672              :           {
     673            0 :             locI = &XEXP (x, 0);
     674            0 :             locB = &XEXP (x, 1);
     675            0 :             index_code = GET_CODE (*locI);
     676              :           }
     677       194268 :         else if (code1 == REG)
     678              :           {
     679       194268 :             locI = &XEXP (x, 1);
     680       194268 :             locB = &XEXP (x, 0);
     681       194268 :             index_code = GET_CODE (*locI);
     682              :           }
     683              : 
     684     22138085 :         if (locI)
     685      1637271 :           changed |= replace_oldest_value_addr (locI, INDEX_REG_CLASS,
     686              :                                                 mode, as, insn, vd);
     687     22138085 :         if (locB)
     688     22138085 :           changed |= replace_oldest_value_addr (locB,
     689              :                                                 base_reg_class (mode, as, PLUS,
     690              :                                                                 index_code),
     691              :                                                 mode, as, insn, vd);
     692              :         return changed;
     693              :       }
     694              : 
     695              :     case POST_INC:
     696              :     case POST_DEC:
     697              :     case POST_MODIFY:
     698              :     case PRE_INC:
     699              :     case PRE_DEC:
     700              :     case PRE_MODIFY:
     701              :       return false;
     702              : 
     703      1907717 :     case MEM:
     704      1907717 :       return replace_oldest_value_mem (x, insn, vd);
     705              : 
     706     37435213 :     case REG:
     707     37435213 :       return replace_oldest_value_reg (loc, cl, insn, vd);
     708              : 
     709              :     default:
     710              :       break;
     711              :     }
     712              : 
     713     31902804 :   fmt = GET_RTX_FORMAT (code);
     714     74744620 :   for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
     715              :     {
     716     42841816 :       if (fmt[i] == 'e')
     717     16554948 :         changed |= replace_oldest_value_addr (&XEXP (x, i), cl, mode, as,
     718              :                                               insn, vd);
     719     26286868 :       else if (fmt[i] == 'E')
     720       323438 :         for (j = XVECLEN (x, i) - 1; j >= 0; j--)
     721       182477 :           changed |= replace_oldest_value_addr (&XVECEXP (x, i, j), cl,
     722              :                                                 mode, as, insn, vd);
     723              :     }
     724              : 
     725              :   return changed;
     726              : }
     727              : 
     728              : /* Similar to replace_oldest_value_reg, but X contains a memory.  */
     729              : 
     730              : static bool
     731     30352107 : replace_oldest_value_mem (rtx x, rtx_insn *insn, struct value_data *vd)
     732              : {
     733     30352107 :   enum reg_class cl;
     734              : 
     735     30352107 :   if (DEBUG_INSN_P (insn))
     736              :     cl = ALL_REGS;
     737              :   else
     738     28444390 :     cl = base_reg_class (GET_MODE (x), MEM_ADDR_SPACE (x), MEM, SCRATCH);
     739              : 
     740     30352107 :   return replace_oldest_value_addr (&XEXP (x, 0), cl,
     741     30352107 :                                     GET_MODE (x), MEM_ADDR_SPACE (x),
     742     30352107 :                                     insn, vd);
     743              : }
     744              : 
     745              : /* Apply all queued updates for DEBUG_INSNs that change some reg to
     746              :    register REGNO.  */
     747              : 
     748              : static void
     749       179697 : apply_debug_insn_changes (struct value_data *vd, unsigned int regno)
     750              : {
     751       179697 :   struct queued_debug_insn_change *change;
     752       179697 :   rtx_insn *last_insn = vd->e[regno].debug_insn_changes->insn;
     753              : 
     754       179697 :   for (change = vd->e[regno].debug_insn_changes;
     755       521942 :        change;
     756       342245 :        change = change->next)
     757              :     {
     758       342245 :       if (last_insn != change->insn)
     759              :         {
     760       158619 :           apply_change_group ();
     761       158619 :           last_insn = change->insn;
     762              :         }
     763       342245 :       validate_change (change->insn, change->loc, change->new_rtx, 1);
     764              :     }
     765       179697 :   apply_change_group ();
     766       179697 : }
     767              : 
     768              : /* Called via note_uses, for all used registers in a real insn
     769              :    apply DEBUG_INSN changes that change registers to the used
     770              :    registers.  */
     771              : 
     772              : static void
     773       953777 : cprop_find_used_regs (rtx *loc, void *data)
     774              : {
     775       953777 :   struct value_data *const vd = (struct value_data *) data;
     776       953777 :   subrtx_iterator::array_type array;
     777      3526180 :   FOR_EACH_SUBRTX (iter, array, *loc, NONCONST)
     778              :     {
     779      2572403 :       const_rtx x = *iter;
     780      2572403 :       if (REG_P (x))
     781              :         {
     782       880575 :           unsigned int regno = REGNO (x);
     783       880575 :           if (vd->e[regno].debug_insn_changes)
     784              :             {
     785       156385 :               apply_debug_insn_changes (vd, regno);
     786       156385 :               free_debug_insn_changes (vd, regno);
     787              :             }
     788              :         }
     789              :     }
     790       953777 : }
     791              : 
     792              : /* Apply clobbers of INSN in PATTERN and C_I_F_U to value_data VD.  */
     793              : 
     794              : static void
     795     73362352 : kill_clobbered_values (rtx_insn *insn, struct value_data *vd)
     796              : {
     797            0 :   note_stores (insn, kill_clobbered_value, vd);
     798        91845 : }
     799              : 
     800              : /* Perform the forward copy propagation on basic block BB.  */
     801              : 
     802              : static bool
     803     12266020 : copyprop_hardreg_forward_1 (basic_block bb, struct value_data *vd)
     804              : {
     805     12266020 :   bool anything_changed = false;
     806     12266020 :   rtx_insn *insn, *next;
     807              : 
     808     12266020 :   for (insn = BB_HEAD (bb); ; insn = next)
     809              :     {
     810    156569897 :       int n_ops, i, predicated;
     811    156569897 :       bool is_asm, any_replacements;
     812    156569897 :       rtx set;
     813    156569897 :       rtx link;
     814    156569897 :       bool changed = false;
     815    156569897 :       struct kill_set_value_data ksvd;
     816              : 
     817    156569897 :       next = NEXT_INSN (insn);
     818    156569897 :       if (!NONDEBUG_INSN_P (insn))
     819              :         {
     820     83113067 :           if (DEBUG_BIND_INSN_P (insn))
     821              :             {
     822     42368950 :               rtx loc = INSN_VAR_LOCATION_LOC (insn);
     823     42368950 :               if (!VAR_LOC_UNKNOWN_P (loc))
     824     23652189 :                 replace_oldest_value_addr (&INSN_VAR_LOCATION_LOC (insn),
     825     23652189 :                                            ALL_REGS, GET_MODE (loc),
     826              :                                            ADDR_SPACE_GENERIC, insn, vd);
     827              :             }
     828              : 
     829     83113067 :           if (insn == BB_END (bb))
     830              :             break;
     831              :           else
     832     82869982 :             continue;
     833              :         }
     834              : 
     835     73456830 :       set = single_set (insn);
     836              : 
     837              :       /* Detect noop sets and remove them before processing side effects.  */
     838     73456830 :       if (set && REG_P (SET_DEST (set)) && REG_P (SET_SRC (set)))
     839              :         {
     840      6328174 :           unsigned int regno = REGNO (SET_SRC (set));
     841      6328174 :           rtx r1 = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     842              :                                           SET_DEST (set), vd, false);
     843      6328174 :           rtx r2 = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     844              :                                           SET_SRC (set), vd, false);
     845      6328174 :           if (rtx_equal_p (r1 ? r1 : SET_DEST (set), r2 ? r2 : SET_SRC (set)))
     846              :             {
     847        63008 :               bool last = insn == BB_END (bb);
     848        63008 :               delete_insn (insn);
     849        63008 :               if (last)
     850              :                 break;
     851        60887 :               continue;
     852        60887 :             }
     853              :         }
     854              : 
     855              :       /* Detect obviously dead sets (via REG_UNUSED notes) and remove them.  */
     856              :       if (set
     857     67439639 :           && !RTX_FRAME_RELATED_P (insn)
     858     63509998 :           && NONJUMP_INSN_P (insn)
     859     53351520 :           && !may_trap_p (set)
     860     46388015 :           && find_reg_note (insn, REG_UNUSED, SET_DEST (set))
     861       248885 :           && !side_effects_p (SET_SRC (set))
     862       123315 :           && !side_effects_p (SET_DEST (set)))
     863              :         {
     864       123315 :           bool last = insn == BB_END (bb);
     865       123315 :           delete_insn_and_edges (insn);
     866       123315 :           if (last)
     867              :             break;
     868       123312 :           continue;
     869       123312 :         }
     870              : 
     871              : 
     872     73270507 :       extract_constrain_insn (insn);
     873     73270507 :       preprocess_constraints (insn);
     874     73270507 :       const operand_alternative *op_alt = which_op_alt ();
     875     73270507 :       n_ops = recog_data.n_operands;
     876     73270507 :       is_asm = asm_noperands (PATTERN (insn)) >= 0;
     877              : 
     878              :       /* Simplify the code below by promoting OP_OUT to OP_INOUT
     879              :          in predicated instructions.  */
     880              : 
     881     73270507 :       predicated = GET_CODE (PATTERN (insn)) == COND_EXEC;
     882    226473329 :       for (i = 0; i < n_ops; ++i)
     883              :         {
     884    153202822 :           int matches = op_alt[i].matches;
     885    153202822 :           if (matches >= 0 || op_alt[i].matched >= 0
     886    135883775 :               || (predicated && recog_data.operand_type[i] == OP_OUT))
     887     17319047 :             recog_data.operand_type[i] = OP_INOUT;
     888              :         }
     889              : 
     890              :       /* Apply changes to earlier DEBUG_INSNs if possible.  */
     891     73270507 :       if (vd->n_debug_insn_changes)
     892       705995 :         note_uses (&PATTERN (insn), cprop_find_used_regs, vd);
     893              : 
     894              :       /* For each earlyclobber operand, zap the value data.  */
     895    226473329 :       for (i = 0; i < n_ops; i++)
     896    153202822 :         if (op_alt[i].earlyclobber)
     897        12465 :           kill_value (recog_data.operand[i], vd);
     898              : 
     899              :       /* Within asms, a clobber cannot overlap inputs or outputs.
     900              :          I wouldn't think this were true for regular insns, but
     901              :          scan_rtx treats them like that...  */
     902     73270507 :       kill_clobbered_values (insn, vd);
     903              : 
     904              :       /* Kill all auto-incremented values.  */
     905              :       /* ??? REG_INC is useless, since stack pushes aren't done that way.  */
     906     73270507 :       kill_autoinc_value (insn, vd);
     907              : 
     908              :       /* Kill all early-clobbered operands.  */
     909    299743836 :       for (i = 0; i < n_ops; i++)
     910    153202822 :         if (op_alt[i].earlyclobber)
     911        12465 :           kill_value (recog_data.operand[i], vd);
     912              : 
     913              :       /* If we have dead sets in the insn, then we need to note these as we
     914              :          would clobbers.  */
     915    141687507 :       for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
     916              :         {
     917     68417023 :           if (REG_NOTE_KIND (link) == REG_UNUSED)
     918              :             {
     919      9169813 :               kill_value (XEXP (link, 0), vd);
     920              :               /* Furthermore, if the insn looked like a single-set,
     921              :                  but the dead store kills the source value of that
     922              :                  set, then we can no-longer use the plain move
     923              :                  special case below.  */
     924      9169813 :               if (set
     925      9169813 :                   && reg_overlap_mentioned_p (XEXP (link, 0), SET_SRC (set)))
     926              :                 set = NULL;
     927              :             }
     928              : 
     929              :           /* We need to keep CFI info correct, and the same on all paths,
     930              :              so we cannot normally replace the registers REG_CFA_REGISTER
     931              :              refers to.  Bail.  */
     932     68417023 :           if (REG_NOTE_KIND (link) == REG_CFA_REGISTER)
     933           23 :             goto did_replacement;
     934              :         }
     935              : 
     936              :       /* Special-case plain move instructions, since we may well
     937              :          be able to do the move from a different register class.  */
     938     73270484 :       if (set && REG_P (SET_SRC (set)))
     939              :         {
     940     16423290 :           rtx src = SET_SRC (set);
     941     16423290 :           rtx dest = SET_DEST (set);
     942     16423290 :           unsigned int regno = REGNO (src);
     943     16423290 :           machine_mode mode = GET_MODE (src);
     944     16423290 :           unsigned int i;
     945     16423290 :           rtx new_rtx;
     946              : 
     947              :           /* If we are accessing SRC in some mode other that what we
     948              :              set it in, make sure that the replacement is valid.  */
     949     16423290 :           if (mode != vd->e[regno].mode)
     950              :             {
     951      6556964 :               if (REG_NREGS (src)
     952      6556964 :                   > hard_regno_nregs (regno, vd->e[regno].mode))
     953      5238473 :                 goto no_move_special_case;
     954              : 
     955              :               /* And likewise, if we are narrowing on big endian the transformation
     956              :                  is also invalid.  */
     957      1318491 :               if (REG_NREGS (src) < hard_regno_nregs (regno, vd->e[regno].mode)
     958      1318491 :                   && maybe_ne (subreg_lowpart_offset (mode,
     959              :                                                       vd->e[regno].mode), 0U))
     960            0 :                 goto no_move_special_case;
     961              :             }
     962              : 
     963              :           /* If the destination is also a register, try to find a source
     964              :              register in the same class.  */
     965     11184817 :           if (REG_P (dest))
     966              :             {
     967     11155050 :               new_rtx = find_oldest_value_reg (REGNO_REG_CLASS (regno),
     968      3718350 :                                                src, vd, RTX_FRAME_RELATED_P (insn));
     969              : 
     970      3718350 :               if (new_rtx && validate_change (insn, &SET_SRC (set), new_rtx, 0))
     971              :                 {
     972        71094 :                   if (dump_file)
     973            2 :                     fprintf (dump_file,
     974              :                              "insn %u: replaced reg %u with %u\n",
     975            2 :                              INSN_UID (insn), regno, REGNO (new_rtx));
     976        71094 :                   changed = true;
     977        71094 :                   goto did_replacement;
     978              :                 }
     979              :               /* We need to re-extract as validate_change clobbers
     980              :                  recog_data.  */
     981      3647256 :               extract_constrain_insn (insn);
     982      3647256 :               preprocess_constraints (insn);
     983              :             }
     984              : 
     985              :           /* Otherwise, try all valid registers and see if its valid.  */
     986     11129210 :           for (i = vd->e[regno].oldest_regno; i != regno;
     987        15487 :                i = vd->e[i].next_regno)
     988              :             {
     989       288631 :               if (incompatible_frame_status (RTX_FRAME_RELATED_P (insn), vd->e[i].frame_related))
     990            0 :                 continue;
     991       288631 :               new_rtx = maybe_mode_change (vd->e[i].mode, vd->e[regno].mode,
     992              :                                        mode, i, regno);
     993       288631 :               if (new_rtx != NULL_RTX)
     994              :                 {
     995              :                   /* Don't propagate for a more expensive reg-reg move.  */
     996       286904 :                   if (REG_P (dest))
     997              :                     {
     998       133177 :                       enum reg_class from = REGNO_REG_CLASS (regno);
     999       133177 :                       enum reg_class to = REGNO_REG_CLASS (REGNO (dest));
    1000       133177 :                       enum reg_class new_from = REGNO_REG_CLASS (i);
    1001       133177 :                       unsigned int original_cost
    1002       133177 :                         = targetm.register_move_cost (mode, from, to);
    1003       133177 :                       unsigned int after_cost
    1004       133177 :                         = targetm.register_move_cost (mode, new_from, to);
    1005       133177 :                       if (after_cost > original_cost)
    1006         7897 :                         continue;
    1007              :                     }
    1008              : 
    1009       279007 :                   if (validate_change (insn, &SET_SRC (set), new_rtx, 0))
    1010              :                     {
    1011              :                       /* NEW_RTX may be the global stack pointer rtx, in which
    1012              :                          case we must not modify it's attributes.  */
    1013       273144 :                       if (new_rtx != stack_pointer_rtx)
    1014              :                         {
    1015       256806 :                           ORIGINAL_REGNO (new_rtx) = ORIGINAL_REGNO (src);
    1016       256806 :                           REG_ATTRS (new_rtx) = REG_ATTRS (src);
    1017       256806 :                           REG_POINTER (new_rtx) = REG_POINTER (src);
    1018              :                         }
    1019       273144 :                       if (dump_file)
    1020            1 :                         fprintf (dump_file,
    1021              :                                  "insn %u: replaced reg %u with %u\n",
    1022            1 :                                  INSN_UID (insn), regno, REGNO (new_rtx));
    1023       273144 :                       changed = true;
    1024       273144 :                       goto did_replacement;
    1025              :                     }
    1026              :                   /* We need to re-extract as validate_change clobbers
    1027              :                      recog_data.  */
    1028         5863 :                   extract_constrain_insn (insn);
    1029         5863 :                   preprocess_constraints (insn);
    1030              :                 }
    1031              :             }
    1032              :         }
    1033     56847194 :       no_move_special_case:
    1034              : 
    1035              :       any_replacements = false;
    1036              : 
    1037              :       /* For each input operand, replace a hard register with the
    1038              :          eldest live copy that's in an appropriate register class.  */
    1039    225440557 :       for (i = 0; i < n_ops; i++)
    1040              :         {
    1041    152514311 :           bool replaced = false;
    1042              : 
    1043              :           /* Don't scan match_operand here, since we've no reg class
    1044              :              information to pass down.  Any operands that we could
    1045              :              substitute in will be represented elsewhere.  */
    1046    152514311 :           if (recog_data.constraints[i][0] == '\0')
    1047     27512012 :             continue;
    1048              : 
    1049              :           /* Don't replace in asms intentionally referencing hard regs.  */
    1050       147010 :           if (is_asm && REG_P (recog_data.operand[i])
    1051    125132167 :               && (REGNO (recog_data.operand[i])
    1052       129868 :                   == ORIGINAL_REGNO (recog_data.operand[i])))
    1053         2018 :             continue;
    1054              : 
    1055    125000281 :           if (recog_data.operand_type[i] == OP_IN)
    1056              :             {
    1057     64688534 :               if (op_alt[i].is_address)
    1058      3225378 :                 replaced
    1059      3225378 :                   = replace_oldest_value_addr (recog_data.operand_loc[i],
    1060              :                                                alternative_class (op_alt, i),
    1061              :                                                VOIDmode, ADDR_SPACE_GENERIC,
    1062              :                                                insn, vd);
    1063     61463156 :               else if (REG_P (recog_data.operand[i]))
    1064     27139805 :                 replaced
    1065     27139805 :                   = replace_oldest_value_reg (recog_data.operand_loc[i],
    1066              :                                               alternative_class (op_alt, i),
    1067              :                                               insn, vd);
    1068     34323351 :               else if (MEM_P (recog_data.operand[i]))
    1069     14286921 :                 replaced = replace_oldest_value_mem (recog_data.operand[i],
    1070              :                                                      insn, vd);
    1071              :             }
    1072     60311747 :           else if (MEM_P (recog_data.operand[i]))
    1073     14157469 :             replaced = replace_oldest_value_mem (recog_data.operand[i],
    1074              :                                                  insn, vd);
    1075              : 
    1076              :           /* If we performed any replacement, update match_dups.  */
    1077     58809573 :           if (replaced)
    1078              :             {
    1079       537172 :               int j;
    1080       537172 :               rtx new_rtx;
    1081              : 
    1082       537172 :               new_rtx = *recog_data.operand_loc[i];
    1083       537172 :               recog_data.operand[i] = new_rtx;
    1084       564114 :               for (j = 0; j < recog_data.n_dups; j++)
    1085        26942 :                 if (recog_data.dup_num[j] == i)
    1086         9036 :                   validate_unshare_change (insn, recog_data.dup_loc[j], new_rtx, 1);
    1087              : 
    1088              :               any_replacements = true;
    1089              :             }
    1090              :         }
    1091              : 
    1092     72926246 :       if (any_replacements)
    1093              :         {
    1094       534067 :           if (! apply_change_group ())
    1095              :             {
    1096          350 :               if (dump_file)
    1097            0 :                 fprintf (dump_file,
    1098              :                          "insn %u: reg replacements not verified\n",
    1099            0 :                          INSN_UID (insn));
    1100              :             }
    1101              :           else
    1102              :             changed = true;
    1103              :         }
    1104              : 
    1105       344261 :     did_replacement:
    1106       344261 :       if (changed)
    1107              :         {
    1108       877955 :           anything_changed = true;
    1109              : 
    1110              :           /* If something changed, perhaps further changes to earlier
    1111              :              DEBUG_INSNs can be applied.  */
    1112       877955 :           if (vd->n_debug_insn_changes)
    1113       118009 :             note_uses (&PATTERN (insn), cprop_find_used_regs, vd);
    1114       877955 :           df_insn_rescan (insn);
    1115              :         }
    1116              : 
    1117     73270507 :       ksvd.vd = vd;
    1118     73270507 :       ksvd.ignore_set_reg = NULL_RTX;
    1119     73270507 :       ksvd.insn_is_frame_related = false;
    1120              : 
    1121              :       /* Clobber call-clobbered registers.  */
    1122     73270507 :       if (CALL_P (insn))
    1123              :         {
    1124      5473581 :           unsigned int set_regno = INVALID_REGNUM;
    1125      5473581 :           unsigned int set_nregs = 0;
    1126      5473581 :           unsigned int regno;
    1127      5473581 :           rtx exp;
    1128              : 
    1129     16098521 :           for (exp = CALL_INSN_FUNCTION_USAGE (insn); exp; exp = XEXP (exp, 1))
    1130              :             {
    1131     10716785 :               rtx x = XEXP (exp, 0);
    1132     10716785 :               if (GET_CODE (x) == SET)
    1133              :                 {
    1134        91845 :                   rtx dest = SET_DEST (x);
    1135        91845 :                   kill_value (dest, vd);
    1136        91845 :                   set_value_regno (REGNO (dest), GET_MODE (dest), vd);
    1137        91845 :                   copy_value (dest, SET_SRC (x), vd, false);
    1138        91845 :                   ksvd.ignore_set_reg = dest;
    1139        91845 :                   set_regno = REGNO (dest);
    1140        91845 :                   set_nregs = REG_NREGS (dest);
    1141        91845 :                   break;
    1142              :                 }
    1143              :             }
    1144              : 
    1145      5473581 :           function_abi callee_abi = insn_callee_abi (insn);
    1146    514516614 :           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1147    503569452 :             if (vd->e[regno].mode != VOIDmode
    1148     24439215 :                 && callee_abi.clobbers_reg_p (vd->e[regno].mode, regno)
    1149    518336307 :                 && (regno < set_regno || regno >= set_regno + set_nregs))
    1150     14675010 :               kill_value_regno (regno, 1, vd);
    1151              : 
    1152              :           /* If SET was seen in CALL_INSN_FUNCTION_USAGE, and SET_SRC
    1153              :              of the SET isn't clobbered by CALLEE_ABI, but instead among
    1154              :              CLOBBERs on the CALL_INSN, we could wrongly assume the
    1155              :              value in it is still live.  */
    1156      5473581 :           if (ksvd.ignore_set_reg)
    1157        91845 :             kill_clobbered_values (insn, vd);
    1158              :         }
    1159              : 
    1160    152682908 :       bool copy_p = (set
    1161     66997945 :                      && REG_P (SET_DEST (set))
    1162    118115565 :                      && REG_P (SET_SRC (set)));
    1163      6141915 :       bool noop_p = (copy_p
    1164      6141915 :                      && rtx_equal_p (SET_DEST (set), SET_SRC (set)));
    1165              : 
    1166              :       /* If a noop move is using narrower mode than we have recorded,
    1167              :          we need to either remove the noop move, or kill_set_value.  */
    1168        31793 :       if (noop_p
    1169        31793 :           && partial_subreg_p (GET_MODE (SET_DEST (set)),
    1170        31793 :                                vd->e[REGNO (SET_DEST (set))].mode))
    1171              :         {
    1172         1937 :           if (noop_move_p (insn))
    1173              :             {
    1174         1937 :               bool last = insn == BB_END (bb);
    1175         1937 :               delete_insn (insn);
    1176         1937 :               if (last)
    1177              :                 break;
    1178              :             }
    1179              :           else
    1180              :             noop_p = false;
    1181              :         }
    1182              : 
    1183     73270486 :       if (!noop_p)
    1184              :         {
    1185     73238714 :           ksvd.insn_is_frame_related = RTX_FRAME_RELATED_P (insn);
    1186              : 
    1187              :           /* Notice stores.  */
    1188     73238714 :           note_stores (insn, kill_set_value, &ksvd);
    1189              : 
    1190              :           /* Notice copies.  */
    1191     73238714 :           if (copy_p)
    1192              :             {
    1193      6110122 :               df_insn_rescan (insn);
    1194      6110122 :               copy_value (SET_DEST (set), SET_SRC (set), vd, RTX_FRAME_RELATED_P (insn));
    1195              :             }
    1196              :         }
    1197              : 
    1198     73270486 :       if (insn == BB_END (bb))
    1199              :         break;
    1200              :     }
    1201              : 
    1202     12266020 :   return anything_changed;
    1203              : }
    1204              : 
    1205              : /* Dump the value chain data to stderr.  */
    1206              : 
    1207              : DEBUG_FUNCTION void
    1208            0 : debug_value_data (struct value_data *vd)
    1209              : {
    1210            0 :   HARD_REG_SET set;
    1211            0 :   unsigned int i, j;
    1212              : 
    1213            0 :   CLEAR_HARD_REG_SET (set);
    1214              : 
    1215            0 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1216            0 :     if (vd->e[i].oldest_regno == i)
    1217              :       {
    1218            0 :         if (vd->e[i].mode == VOIDmode)
    1219              :           {
    1220            0 :             if (vd->e[i].next_regno != INVALID_REGNUM)
    1221            0 :               fprintf (stderr, "[%u] Bad next_regno for empty chain (%u)\n",
    1222              :                        i, vd->e[i].next_regno);
    1223            0 :             continue;
    1224              :           }
    1225              : 
    1226            0 :         SET_HARD_REG_BIT (set, i);
    1227            0 :         fprintf (stderr, "[%u %s] ", i, GET_MODE_NAME (vd->e[i].mode));
    1228              : 
    1229            0 :         for (j = vd->e[i].next_regno;
    1230            0 :              j != INVALID_REGNUM;
    1231            0 :              j = vd->e[j].next_regno)
    1232              :           {
    1233            0 :             if (TEST_HARD_REG_BIT (set, j))
    1234              :               {
    1235            0 :                 fprintf (stderr, "[%u] Loop in regno chain\n", j);
    1236            0 :                 return;
    1237              :               }
    1238              : 
    1239            0 :             if (vd->e[j].oldest_regno != i)
    1240              :               {
    1241            0 :                 fprintf (stderr, "[%u] Bad oldest_regno (%u)\n",
    1242              :                          j, vd->e[j].oldest_regno);
    1243            0 :                 return;
    1244              :               }
    1245            0 :             SET_HARD_REG_BIT (set, j);
    1246            0 :             fprintf (stderr, "[%u %s] ", j, GET_MODE_NAME (vd->e[j].mode));
    1247              :           }
    1248            0 :         fputc ('\n', stderr);
    1249              :       }
    1250              : 
    1251            0 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1252            0 :     if (! TEST_HARD_REG_BIT (set, i)
    1253            0 :         && (vd->e[i].mode != VOIDmode
    1254            0 :             || vd->e[i].oldest_regno != i
    1255            0 :             || vd->e[i].next_regno != INVALID_REGNUM))
    1256            0 :       fprintf (stderr, "[%u] Non-empty reg in chain (%s %u %i)\n",
    1257            0 :                i, GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
    1258              :                vd->e[i].next_regno);
    1259              : }
    1260              : 
    1261              : /* Do copyprop_hardreg_forward_1 for a single basic block BB.
    1262              :    DEBUG_INSN is skipped since we do not want to involve DF related
    1263              :    staff as how it is handled in function pass_cprop_hardreg::execute.
    1264              : 
    1265              :    NOTE: Currently it is only used for shrink-wrap.  Maybe extend it
    1266              :    to handle DEBUG_INSN for other uses.  */
    1267              : 
    1268              : void
    1269       357335 : copyprop_hardreg_forward_bb_without_debug_insn (basic_block bb)
    1270              : {
    1271       357335 :   struct value_data *vd;
    1272       357335 :   vd = XNEWVEC (struct value_data, 1);
    1273       357335 :   init_value_data (vd);
    1274              : 
    1275       357335 :   skip_debug_insn_p = true;
    1276       357335 :   copyprop_hardreg_forward_1 (bb, vd);
    1277       357335 :   free (vd);
    1278       357335 :   skip_debug_insn_p = false;
    1279       357335 : }
    1280              : 
    1281              : static void
    1282     90191451 : validate_value_data (struct value_data *vd)
    1283              : {
    1284     90191451 :   HARD_REG_SET set;
    1285     90191451 :   unsigned int i, j;
    1286              : 
    1287     90191451 :   CLEAR_HARD_REG_SET (set);
    1288              : 
    1289   8387804943 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1290   8297613492 :     if (vd->e[i].oldest_regno == i)
    1291              :       {
    1292   8269759536 :         if (vd->e[i].mode == VOIDmode)
    1293              :           {
    1294   7947578079 :             if (vd->e[i].next_regno != INVALID_REGNUM)
    1295            0 :               internal_error ("%qs: [%u] bad %<next_regno%> for empty chain (%u)",
    1296              :                               __func__, i, vd->e[i].next_regno);
    1297   7947578079 :             continue;
    1298              :           }
    1299              : 
    1300    322181457 :         SET_HARD_REG_BIT (set, i);
    1301              : 
    1302    322181457 :         for (j = vd->e[i].next_regno;
    1303    350035413 :              j != INVALID_REGNUM;
    1304     27853956 :              j = vd->e[j].next_regno)
    1305              :           {
    1306     27853956 :             if (TEST_HARD_REG_BIT (set, j))
    1307            0 :               internal_error ("%qs: loop in %<next_regno%> chain (%u)",
    1308              :                               __func__, j);
    1309     27853956 :             if (vd->e[j].oldest_regno != i)
    1310            0 :               internal_error ("%qs: [%u] bad %<oldest_regno%> (%u)",
    1311              :                               __func__, j, vd->e[j].oldest_regno);
    1312              : 
    1313     27853956 :             SET_HARD_REG_BIT (set, j);
    1314              :           }
    1315              :       }
    1316              : 
    1317   8387804943 :   for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i)
    1318   8297613492 :     if (! TEST_HARD_REG_BIT (set, i)
    1319   8297613492 :         && (vd->e[i].mode != VOIDmode
    1320   7947578079 :             || vd->e[i].oldest_regno != i
    1321   7947578079 :             || vd->e[i].next_regno != INVALID_REGNUM))
    1322            0 :       internal_error ("%qs: [%u] non-empty register in chain (%s %u %i)",
    1323              :                       __func__, i,
    1324            0 :                       GET_MODE_NAME (vd->e[i].mode), vd->e[i].oldest_regno,
    1325              :                       vd->e[i].next_regno);
    1326     90191451 : }
    1327              : 
    1328              : 
    1329              : namespace {
    1330              : 
    1331              : const pass_data pass_data_cprop_hardreg =
    1332              : {
    1333              :   RTL_PASS, /* type */
    1334              :   "cprop_hardreg", /* name */
    1335              :   OPTGROUP_NONE, /* optinfo_flags */
    1336              :   TV_CPROP_REGISTERS, /* tv_id */
    1337              :   0, /* properties_required */
    1338              :   0, /* properties_provided */
    1339              :   0, /* properties_destroyed */
    1340              :   0, /* todo_flags_start */
    1341              :   TODO_df_finish, /* todo_flags_finish */
    1342              : };
    1343              : 
    1344              : class pass_cprop_hardreg : public rtl_opt_pass
    1345              : {
    1346              : public:
    1347       285722 :   pass_cprop_hardreg (gcc::context *ctxt)
    1348       571444 :     : rtl_opt_pass (pass_data_cprop_hardreg, ctxt)
    1349              :   {}
    1350              : 
    1351              :   /* opt_pass methods: */
    1352      1471370 :   bool gate (function *) final override
    1353              :     {
    1354      1471370 :       return (optimize > 0 && (flag_cprop_registers));
    1355              :     }
    1356              : 
    1357              :   unsigned int execute (function *) final override;
    1358              : 
    1359              : }; // class pass_cprop_hardreg
    1360              : 
    1361              : static bool
    1362     11908685 : cprop_hardreg_bb (basic_block bb, struct value_data *all_vd, sbitmap visited)
    1363              : {
    1364     11908685 :   bitmap_set_bit (visited, bb->index);
    1365              : 
    1366              :   /* If a block has a single predecessor, that we've already
    1367              :      processed, begin with the value data that was live at
    1368              :      the end of the predecessor block.  */
    1369              :   /* ??? Ought to use more intelligent queuing of blocks.  */
    1370     11908685 :   if (single_pred_p (bb)
    1371      8817691 :       && bitmap_bit_p (visited, single_pred (bb)->index)
    1372     19208115 :       && ! (single_pred_edge (bb)->flags & (EDGE_ABNORMAL_CALL | EDGE_EH)))
    1373              :     {
    1374      7178073 :       all_vd[bb->index] = all_vd[single_pred (bb)->index];
    1375      7178073 :       if (all_vd[bb->index].n_debug_insn_changes)
    1376              :         {
    1377              :           unsigned int regno;
    1378              : 
    1379       503148 :           for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1380              :             {
    1381       503148 :               if (all_vd[bb->index].e[regno].debug_insn_changes)
    1382              :                 {
    1383              :                   struct queued_debug_insn_change *cur;
    1384       107875 :                   for (cur = all_vd[bb->index].e[regno].debug_insn_changes;
    1385       178757 :                        cur; cur = cur->next)
    1386       107875 :                     --all_vd[bb->index].n_debug_insn_changes;
    1387        70882 :                   all_vd[bb->index].e[regno].debug_insn_changes = NULL;
    1388        70882 :                   if (all_vd[bb->index].n_debug_insn_changes == 0)
    1389              :                     break;
    1390              :                 }
    1391              :             }
    1392              :         }
    1393              :     }
    1394              :   else
    1395      4730612 :     init_value_data (all_vd + bb->index);
    1396              : 
    1397     11908685 :   return copyprop_hardreg_forward_1 (bb, all_vd + bb->index);
    1398              : }
    1399              : 
    1400              : static void
    1401        49404 : cprop_hardreg_debug (function *fun, struct value_data *all_vd)
    1402              : {
    1403        49404 :   basic_block bb;
    1404              : 
    1405      3273246 :   FOR_EACH_BB_FN (bb, fun)
    1406      3223842 :     if (all_vd[bb->index].n_debug_insn_changes)
    1407              :       {
    1408        82020 :         unsigned int regno;
    1409        82020 :         bitmap live;
    1410              : 
    1411        82020 :         live = df_get_live_out (bb);
    1412       595635 :         for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
    1413       595635 :           if (all_vd[bb->index].e[regno].debug_insn_changes)
    1414              :             {
    1415        84637 :               if (REGNO_REG_SET_P (live, regno))
    1416        23312 :                 apply_debug_insn_changes (all_vd + bb->index, regno);
    1417              : 
    1418        84637 :               struct queued_debug_insn_change *cur;
    1419        84637 :               for (cur = all_vd[bb->index].e[regno].debug_insn_changes;
    1420       218991 :                    cur; cur = cur->next)
    1421       134354 :                 --all_vd[bb->index].n_debug_insn_changes;
    1422        84637 :               all_vd[bb->index].e[regno].debug_insn_changes = NULL;
    1423        84637 :               if (all_vd[bb->index].n_debug_insn_changes == 0)
    1424              :                 break;
    1425              :             }
    1426              :       }
    1427              : 
    1428        49404 :   queued_debug_insn_change_pool.release ();
    1429        49404 : }
    1430              : 
    1431              : unsigned int
    1432      1043682 : pass_cprop_hardreg::execute (function *fun)
    1433              : {
    1434      1043682 :   struct value_data *all_vd;
    1435      1043682 :   basic_block bb;
    1436              : 
    1437      1043682 :   all_vd = XNEWVEC (struct value_data, last_basic_block_for_fn (fun));
    1438              : 
    1439      1043682 :   auto_sbitmap visited (last_basic_block_for_fn (fun));
    1440      1043682 :   bitmap_clear (visited);
    1441              : 
    1442      1043682 :   auto_vec<int> worklist1, worklist2;
    1443      1043682 :   auto_vec<int> *curr = &worklist1;
    1444      1043682 :   auto_vec<int> *next = &worklist2;
    1445      1043682 :   bool any_debug_changes = false;
    1446              : 
    1447              :   /* We need accurate notes.  Earlier passes such as if-conversion may
    1448              :      leave notes in an inconsistent state.  */
    1449      1043682 :   df_note_add_problem ();
    1450      1043682 :   df_analyze ();
    1451              : 
    1452              :   /* It is tempting to set DF_LR_RUN_DCE, but DCE may choose to delete
    1453              :      an insn and this pass would not have visibility into the removal.
    1454              :      This pass would then potentially use the source of that
    1455              :      INSN for propagation purposes, generating invalid code.
    1456              : 
    1457              :      So we just ask for updated notes and handle trivial deletions
    1458              :      within this pass where we can update this passes internal
    1459              :      data structures appropriately.  */
    1460      1043682 :   df_set_flags (DF_DEFER_INSN_RESCAN);
    1461              : 
    1462     12478079 :   FOR_EACH_BB_FN (bb, fun)
    1463              :     {
    1464     11434397 :       if (cprop_hardreg_bb (bb, all_vd, visited))
    1465       470641 :         curr->safe_push (bb->index);
    1466     11434397 :       if (all_vd[bb->index].n_debug_insn_changes)
    1467        69895 :         any_debug_changes = true;
    1468              :     }
    1469              : 
    1470              :   /* We must call df_analyze here unconditionally to ensure that the
    1471              :      REG_UNUSED and REG_DEAD notes are consistent with and without -g.  */
    1472      1043682 :   df_analyze ();
    1473              : 
    1474      1043682 :   if (MAY_HAVE_DEBUG_BIND_INSNS && any_debug_changes)
    1475        40545 :     cprop_hardreg_debug (fun, all_vd);
    1476              : 
    1477              :   /* Repeat pass up to PASSES times, but only processing basic blocks
    1478              :      that have changed on the previous iteration.  CURR points to the
    1479              :      current worklist, and each iteration populates the NEXT worklist,
    1480              :      swapping pointers after each cycle.  */
    1481              : 
    1482      1043682 :   unsigned int passes = optimize > 1 ? 3 : 2;
    1483      1225218 :   for (unsigned int pass = 2; pass <= passes && !curr->is_empty (); pass++)
    1484              :     {
    1485       181536 :       any_debug_changes = false;
    1486       181536 :       bitmap_clear (visited);
    1487       181536 :       next->truncate (0);
    1488       655824 :       for (int index : *curr)
    1489              :         {
    1490       474288 :           bb = BASIC_BLOCK_FOR_FN (fun, index);
    1491       474288 :           if (cprop_hardreg_bb (bb, all_vd, visited))
    1492         4356 :             next->safe_push (bb->index);
    1493       474288 :           if (all_vd[bb->index].n_debug_insn_changes)
    1494        12125 :             any_debug_changes = true;
    1495              :         }
    1496              : 
    1497       181536 :       df_analyze ();
    1498       181536 :       if (MAY_HAVE_DEBUG_BIND_INSNS && any_debug_changes)
    1499         8859 :         cprop_hardreg_debug (fun, all_vd);
    1500       181536 :       std::swap (curr, next);
    1501              :     }
    1502              : 
    1503      1043682 :   free (all_vd);
    1504      1043682 :   return 0;
    1505      1043682 : }
    1506              : 
    1507              : } // anon namespace
    1508              : 
    1509              : rtl_opt_pass *
    1510       285722 : make_pass_cprop_hardreg (gcc::context *ctxt)
    1511              : {
    1512       285722 :   return new pass_cprop_hardreg (ctxt);
    1513              : }
        

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.