LCOV - code coverage report
Current view: top level - gcc - fwprop.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 90.9 % 374 340
Test Date: 2024-03-23 14:05:01 Functions: 96.6 % 29 28
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* RTL-based forward propagation pass for GNU compiler.
       2                 :             :    Copyright (C) 2005-2024 Free Software Foundation, Inc.
       3                 :             :    Contributed by Paolo Bonzini and Steven Bosscher.
       4                 :             : 
       5                 :             : This file is part of GCC.
       6                 :             : 
       7                 :             : GCC is free software; you can redistribute it and/or modify it under
       8                 :             : the terms of the GNU General Public License as published by the Free
       9                 :             : Software Foundation; either version 3, or (at your option) any later
      10                 :             : version.
      11                 :             : 
      12                 :             : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13                 :             : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14                 :             : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15                 :             : for more details.
      16                 :             : 
      17                 :             : You should have received a copy of the GNU General Public License
      18                 :             : along with GCC; see the file COPYING3.  If not see
      19                 :             : <http://www.gnu.org/licenses/>.  */
      20                 :             : 
      21                 :             : #define INCLUDE_ALGORITHM
      22                 :             : #define INCLUDE_FUNCTIONAL
      23                 :             : #include "config.h"
      24                 :             : #include "system.h"
      25                 :             : #include "coretypes.h"
      26                 :             : #include "backend.h"
      27                 :             : #include "rtl.h"
      28                 :             : #include "rtlanal.h"
      29                 :             : #include "df.h"
      30                 :             : #include "rtl-ssa.h"
      31                 :             : 
      32                 :             : #include "predict.h"
      33                 :             : #include "cfgrtl.h"
      34                 :             : #include "cfgcleanup.h"
      35                 :             : #include "cfgloop.h"
      36                 :             : #include "tree-pass.h"
      37                 :             : #include "rtl-iter.h"
      38                 :             : #include "target.h"
      39                 :             : 
      40                 :             : /* This pass does simple forward propagation and simplification when an
      41                 :             :    operand of an insn can only come from a single def.  This pass uses
      42                 :             :    RTL SSA, so it is global.  However, we only do limited analysis of
      43                 :             :    available expressions.
      44                 :             : 
      45                 :             :    1) The pass tries to propagate the source of the def into the use,
      46                 :             :    and checks if the result is independent of the substituted value.
      47                 :             :    For example, the high word of a (zero_extend:DI (reg:SI M)) is always
      48                 :             :    zero, independent of the source register.
      49                 :             : 
      50                 :             :    In particular, we propagate constants into the use site.  Sometimes
      51                 :             :    RTL expansion did not put the constant in the same insn on purpose,
      52                 :             :    to satisfy a predicate, and the result will fail to be recognized;
      53                 :             :    but this happens rarely and in this case we can still create a
      54                 :             :    REG_EQUAL note.  For multi-word operations, this
      55                 :             : 
      56                 :             :       (set (subreg:SI (reg:DI 120) 0) (const_int 0))
      57                 :             :       (set (subreg:SI (reg:DI 120) 4) (const_int -1))
      58                 :             :       (set (subreg:SI (reg:DI 122) 0)
      59                 :             :          (ior:SI (subreg:SI (reg:DI 119) 0) (subreg:SI (reg:DI 120) 0)))
      60                 :             :       (set (subreg:SI (reg:DI 122) 4)
      61                 :             :          (ior:SI (subreg:SI (reg:DI 119) 4) (subreg:SI (reg:DI 120) 4)))
      62                 :             : 
      63                 :             :    can be simplified to the much simpler
      64                 :             : 
      65                 :             :       (set (subreg:SI (reg:DI 122) 0) (subreg:SI (reg:DI 119)))
      66                 :             :       (set (subreg:SI (reg:DI 122) 4) (const_int -1))
      67                 :             : 
      68                 :             :    This particular propagation is also effective at putting together
      69                 :             :    complex addressing modes.  We are more aggressive inside MEMs, in
      70                 :             :    that all definitions are propagated if the use is in a MEM; if the
      71                 :             :    result is a valid memory address we check address_cost to decide
      72                 :             :    whether the substitution is worthwhile.
      73                 :             : 
      74                 :             :    2) The pass propagates register copies.  This is not as effective as
      75                 :             :    the copy propagation done by CSE's canon_reg, which works by walking
      76                 :             :    the instruction chain, it can help the other transformations.
      77                 :             : 
      78                 :             :    We should consider removing this optimization, and instead reorder the
      79                 :             :    RTL passes, because GCSE does this transformation too.  With some luck,
      80                 :             :    the CSE pass at the end of rest_of_handle_gcse could also go away.
      81                 :             : 
      82                 :             :    3) The pass looks for paradoxical subregs that are actually unnecessary.
      83                 :             :    Things like this:
      84                 :             : 
      85                 :             :      (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
      86                 :             :      (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
      87                 :             :      (set (reg:SI 122) (plus:SI (subreg:SI (reg:QI 120) 0)
      88                 :             :                                 (subreg:SI (reg:QI 121) 0)))
      89                 :             : 
      90                 :             :    are very common on machines that can only do word-sized operations.
      91                 :             :    For each use of a paradoxical subreg (subreg:WIDER (reg:NARROW N) 0),
      92                 :             :    if it has a single def and it is (subreg:NARROW (reg:WIDE M) 0),
      93                 :             :    we can replace the paradoxical subreg with simply (reg:WIDE M).  The
      94                 :             :    above will simplify this to
      95                 :             : 
      96                 :             :      (set (reg:QI 120) (subreg:QI (reg:SI 118) 0))
      97                 :             :      (set (reg:QI 121) (subreg:QI (reg:SI 119) 0))
      98                 :             :      (set (reg:SI 122) (plus:SI (reg:SI 118) (reg:SI 119)))
      99                 :             : 
     100                 :             :    where the first two insns are now dead.  */
     101                 :             : 
     102                 :             : using namespace rtl_ssa;
     103                 :             : 
     104                 :             : static int num_changes;
     105                 :             : 
     106                 :             : /* Do not try to replace constant addresses or addresses of local and
     107                 :             :    argument slots.  These MEM expressions are made only once and inserted
     108                 :             :    in many instructions, as well as being used to control symbol table
     109                 :             :    output.  It is not safe to clobber them.
     110                 :             : 
     111                 :             :    There are some uncommon cases where the address is already in a register
     112                 :             :    for some reason, but we cannot take advantage of that because we have
     113                 :             :    no easy way to unshare the MEM.  In addition, looking up all stack
     114                 :             :    addresses is costly.  */
     115                 :             : 
     116                 :             : static bool
     117                 :     1620588 : can_simplify_addr (rtx addr)
     118                 :             : {
     119                 :     1620588 :   rtx reg;
     120                 :             : 
     121                 :     1620588 :   if (CONSTANT_ADDRESS_P (addr))
     122                 :             :     return false;
     123                 :             : 
     124                 :     1620588 :   if (GET_CODE (addr) == PLUS)
     125                 :      869033 :     reg = XEXP (addr, 0);
     126                 :             :   else
     127                 :             :     reg = addr;
     128                 :             : 
     129                 :     1620588 :   return (!REG_P (reg)
     130                 :     1620588 :           || (REGNO (reg) != FRAME_POINTER_REGNUM
     131                 :             :               && REGNO (reg) != HARD_FRAME_POINTER_REGNUM
     132                 :             :               && REGNO (reg) != ARG_POINTER_REGNUM));
     133                 :             : }
     134                 :             : 
     135                 :             : /* MEM is the result of an address simplification, and temporarily
     136                 :             :    undoing changes OLD_NUM_CHANGES onwards restores the original address.
     137                 :             :    Return whether it is good to use the new address instead of the
     138                 :             :    old one.  INSN is the containing instruction.  */
     139                 :             : 
     140                 :             : static bool
     141                 :     1512696 : should_replace_address (int old_num_changes, rtx mem, rtx_insn *insn)
     142                 :             : {
     143                 :     1512696 :   int gain;
     144                 :             : 
     145                 :             :   /* Prefer the new address if it is less expensive.  */
     146                 :     1512696 :   bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn));
     147                 :     1512696 :   temporarily_undo_changes (old_num_changes);
     148                 :     1512696 :   gain = address_cost (XEXP (mem, 0), GET_MODE (mem),
     149                 :     1512696 :                        MEM_ADDR_SPACE (mem), speed);
     150                 :     1512696 :   redo_changes (old_num_changes);
     151                 :     1512696 :   gain -= address_cost (XEXP (mem, 0), GET_MODE (mem),
     152                 :     1512696 :                         MEM_ADDR_SPACE (mem), speed);
     153                 :             : 
     154                 :             :   /* If the addresses have equivalent cost, prefer the new address
     155                 :             :      if it has the highest `set_src_cost'.  That has the potential of
     156                 :             :      eliminating the most insns without additional costs, and it
     157                 :             :      is the same that cse.cc used to do.  */
     158                 :     1512696 :   if (gain == 0)
     159                 :             :     {
     160                 :      251369 :       gain = set_src_cost (XEXP (mem, 0), VOIDmode, speed);
     161                 :      251369 :       temporarily_undo_changes (old_num_changes);
     162                 :      251369 :       gain -= set_src_cost (XEXP (mem, 0), VOIDmode, speed);
     163                 :      251369 :       redo_changes (old_num_changes);
     164                 :             :     }
     165                 :             : 
     166                 :     1512696 :   return (gain > 0);
     167                 :             : }
     168                 :             : 
     169                 :             : 
     170                 :             : namespace
     171                 :             : {
     172                 :             :   class fwprop_propagation : public insn_propagation
     173                 :             :   {
     174                 :             :   public:
     175                 :             :     static const uint16_t CHANGED_MEM = FIRST_SPARE_RESULT;
     176                 :             :     static const uint16_t CONSTANT = FIRST_SPARE_RESULT << 1;
     177                 :             :     static const uint16_t PROFITABLE = FIRST_SPARE_RESULT << 2;
     178                 :             : 
     179                 :             :     fwprop_propagation (insn_info *, set_info *, rtx, rtx);
     180                 :             : 
     181                 :    47589802 :     bool changed_mem_p () const { return result_flags & CHANGED_MEM; }
     182                 :             :     bool folded_to_constants_p () const;
     183                 :             :     bool likely_profitable_p () const;
     184                 :             : 
     185                 :             :     bool check_mem (int, rtx) final override;
     186                 :             :     void note_simplification (int, uint16_t, rtx, rtx) final override;
     187                 :             :     uint16_t classify_result (rtx, rtx);
     188                 :             : 
     189                 :             :   private:
     190                 :             :     const bool single_use_p;
     191                 :             :     const bool single_ebb_p;
     192                 :             :   };
     193                 :             : }
     194                 :             : 
     195                 :             : /* Prepare to replace FROM with TO in USE_INSN.  */
     196                 :             : 
     197                 :    30213356 : fwprop_propagation::fwprop_propagation (insn_info *use_insn,
     198                 :    30213356 :                                         set_info *def, rtx from, rtx to)
     199                 :             :   : insn_propagation (use_insn->rtl (), from, to),
     200                 :    30213356 :     single_use_p (def->single_nondebug_use ()),
     201                 :    30213356 :     single_ebb_p (use_insn->ebb () == def->ebb ())
     202                 :             : {
     203                 :    30213356 :   should_check_mems = true;
     204                 :    30213356 :   should_note_simplifications = true;
     205                 :    30213356 : }
     206                 :             : 
     207                 :             : /* MEM is the result of an address simplification, and temporarily
     208                 :             :    undoing changes OLD_NUM_CHANGES onwards restores the original address.
     209                 :             :    Return true if the propagation should continue, false if it has failed.  */
     210                 :             : 
     211                 :             : bool
     212                 :     2787988 : fwprop_propagation::check_mem (int old_num_changes, rtx mem)
     213                 :             : {
     214                 :     5575976 :   if (!memory_address_addr_space_p (GET_MODE (mem), XEXP (mem, 0),
     215                 :     2787988 :                                     MEM_ADDR_SPACE (mem)))
     216                 :             :     {
     217                 :     1167400 :       failure_reason = "would create an invalid MEM";
     218                 :     1167400 :       return false;
     219                 :             :     }
     220                 :             : 
     221                 :     1620588 :   temporarily_undo_changes (old_num_changes);
     222                 :     1620588 :   bool can_simplify = can_simplify_addr (XEXP (mem, 0));
     223                 :     1620588 :   redo_changes (old_num_changes);
     224                 :     1620588 :   if (!can_simplify)
     225                 :             :     {
     226                 :          66 :       failure_reason = "would replace a frame address";
     227                 :          66 :       return false;
     228                 :             :     }
     229                 :             : 
     230                 :             :   /* Copy propagations are always ok.  Otherwise check the costs.  */
     231                 :     1620522 :   if (!(REG_P (from) && REG_P (to))
     232                 :     3133218 :       && !should_replace_address (old_num_changes, mem, insn))
     233                 :             :     {
     234                 :      349970 :       failure_reason = "would increase the cost of a MEM";
     235                 :      349970 :       return false;
     236                 :             :     }
     237                 :             : 
     238                 :     1270552 :   result_flags |= CHANGED_MEM;
     239                 :     1270552 :   return true;
     240                 :             : }
     241                 :             : 
     242                 :             : /* OLDX has been simplified to NEWX.  Describe the change in terms of
     243                 :             :    result_flags.  */
     244                 :             : 
     245                 :             : uint16_t
     246                 :     3287543 : fwprop_propagation::classify_result (rtx old_rtx, rtx new_rtx)
     247                 :             : {
     248                 :     3287543 :   if (CONSTANT_P (new_rtx))
     249                 :             :     {
     250                 :             :       /* If OLD_RTX is a LO_SUM, then it presumably exists for a reason,
     251                 :             :          and NEW_RTX is likely not a legitimate address.  We want it to
     252                 :             :          disappear if it is invalid.
     253                 :             : 
     254                 :             :          ??? Using the mode of the LO_SUM as the mode of the address
     255                 :             :          seems odd, but it was what the pre-SSA code did.  */
     256                 :      607794 :       if (GET_CODE (old_rtx) == LO_SUM
     257                 :      607794 :           && !memory_address_p (GET_MODE (old_rtx), new_rtx))
     258                 :           0 :         return CONSTANT;
     259                 :      607794 :       return CONSTANT | PROFITABLE;
     260                 :             :     }
     261                 :             : 
     262                 :             :   /* Allow replacements that simplify operations on a vector or complex
     263                 :             :      value to a component.  The most prominent case is
     264                 :             :      (subreg ([vec_]concat ...)).   */
     265                 :     2679749 :   if (REG_P (new_rtx)
     266                 :      137443 :       && !HARD_REGISTER_P (new_rtx)
     267                 :      137204 :       && (VECTOR_MODE_P (GET_MODE (from))
     268                 :      104300 :           || COMPLEX_MODE_P (GET_MODE (from)))
     269                 :     2745557 :       && GET_MODE (new_rtx) == GET_MODE_INNER (GET_MODE (from)))
     270                 :             :     return PROFITABLE;
     271                 :             : 
     272                 :             :   /* Allow (subreg (mem)) -> (mem) simplifications with the following
     273                 :             :      exceptions:
     274                 :             :      1) Propagating (mem)s into multiple uses is not profitable.
     275                 :             :      2) Propagating (mem)s across EBBs may not be profitable if the source EBB
     276                 :             :         runs less frequently.
     277                 :             :      3) Propagating (mem)s into paradoxical (subreg)s is not profitable.
     278                 :             :      4) Creating new (mem/v)s is not correct, since DCE will not remove the old
     279                 :             :         ones.  */
     280                 :     2652555 :   if (single_use_p
     281                 :     1421706 :       && single_ebb_p
     282                 :     1421688 :       && SUBREG_P (old_rtx)
     283                 :      139933 :       && !paradoxical_subreg_p (old_rtx)
     284                 :      136752 :       && MEM_P (new_rtx)
     285                 :     2702657 :       && !MEM_VOLATILE_P (new_rtx))
     286                 :       50102 :     return PROFITABLE;
     287                 :             : 
     288                 :             :   return 0;
     289                 :             : }
     290                 :             : 
     291                 :             : /* Record that OLD_RTX has been simplified to NEW_RTX.  OLD_NUM_CHANGES
     292                 :             :    is the number of unrelated changes that had been made before processing
     293                 :             :    OLD_RTX and its subrtxes.  OLD_RESULT_FLAGS is the value that result_flags
     294                 :             :    had at that point.  */
     295                 :             : 
     296                 :             : void
     297                 :     3287543 : fwprop_propagation::note_simplification (int old_num_changes,
     298                 :             :                                          uint16_t old_result_flags,
     299                 :             :                                          rtx old_rtx, rtx new_rtx)
     300                 :             : {
     301                 :     3287543 :   result_flags &= ~(CONSTANT | PROFITABLE);
     302                 :     3287543 :   uint16_t new_flags = classify_result (old_rtx, new_rtx);
     303                 :     3287543 :   if (old_num_changes)
     304                 :       13682 :     new_flags &= old_result_flags;
     305                 :     3287543 :   result_flags |= new_flags;
     306                 :     3287543 : }
     307                 :             : 
     308                 :             : /* Return true if all substitutions eventually folded to constants.  */
     309                 :             : 
     310                 :             : bool
     311                 :    12613887 : fwprop_propagation::folded_to_constants_p () const
     312                 :             : {
     313                 :             :   /* If we're propagating a HIGH, require it to be folded with a
     314                 :             :      partnering LO_SUM.  For example, a REG_EQUAL note with a register
     315                 :             :      replaced by an unfolded HIGH is not useful.  */
     316                 :    12613887 :   if (CONSTANT_P (to) && GET_CODE (to) != HIGH)
     317                 :             :     return true;
     318                 :    11130442 :   return !(result_flags & UNSIMPLIFIED) && (result_flags & CONSTANT);
     319                 :             : }
     320                 :             : 
     321                 :             : 
     322                 :             : /* Return true if it is worth keeping the result of the propagation,
     323                 :             :    false if it would increase the complexity of the pattern too much.  */
     324                 :             : 
     325                 :             : bool
     326                 :    23267417 : fwprop_propagation::likely_profitable_p () const
     327                 :             : {
     328                 :    23267417 :   if (changed_mem_p ())
     329                 :             :     return true;
     330                 :             : 
     331                 :    22002777 :   if (!(result_flags & UNSIMPLIFIED)
     332                 :             :       && (result_flags & PROFITABLE))
     333                 :             :     return true;
     334                 :             : 
     335                 :    21778782 :   if (REG_P (to))
     336                 :             :     return true;
     337                 :             : 
     338                 :    19949684 :   if (GET_CODE (to) == SUBREG
     339                 :     1109235 :       && REG_P (SUBREG_REG (to))
     340                 :    21058191 :       && !paradoxical_subreg_p (to))
     341                 :             :     return true;
     342                 :             : 
     343                 :    18857676 :   if (CONSTANT_P (to))
     344                 :     1467604 :     return true;
     345                 :             : 
     346                 :             :   return false;
     347                 :             : }
     348                 :             : 
     349                 :             : /* Check that X has a single def.  */
     350                 :             : 
     351                 :             : static bool
     352                 :    74676933 : reg_single_def_p (rtx x)
     353                 :             : {
     354                 :    74676933 :   return REG_P (x) && crtl->ssa->single_dominating_def (REGNO (x));
     355                 :             : }
     356                 :             : 
     357                 :             : /* Try to substitute (set DEST SRC), which defines DEF, into note NOTE of
     358                 :             :    USE_INSN.  Return the number of substitutions on success, otherwise return
     359                 :             :    -1 and leave USE_INSN unchanged.
     360                 :             : 
     361                 :             :    If REQUIRE_CONSTANT is true, require all substituted occurrences of SRC
     362                 :             :    to fold to a constant, so that the note does not use any more registers
     363                 :             :    than it did previously.  If REQUIRE_CONSTANT is false, also allow the
     364                 :             :    substitution if it's something we'd normally allow for the main
     365                 :             :    instruction pattern.  */
     366                 :             : 
     367                 :             : static int
     368                 :     3238206 : try_fwprop_subst_note (insn_info *use_insn, set_info *def,
     369                 :             :                        rtx note, rtx dest, rtx src, bool require_constant)
     370                 :             : {
     371                 :     3238206 :   rtx_insn *use_rtl = use_insn->rtl ();
     372                 :     3238206 :   insn_info *def_insn = def->insn ();
     373                 :             : 
     374                 :     3238206 :   insn_change_watermark watermark;
     375                 :     3238206 :   fwprop_propagation prop (use_insn, def, dest, src);
     376                 :     3238206 :   if (!prop.apply_to_rvalue (&XEXP (note, 0)))
     377                 :             :     {
     378                 :       16783 :       if (dump_file && (dump_flags & TDF_DETAILS))
     379                 :           0 :         fprintf (dump_file, "cannot propagate from insn %d into"
     380                 :             :                  " notes of insn %d: %s\n", def_insn->uid (),
     381                 :             :                  use_insn->uid (), prop.failure_reason);
     382                 :       16783 :       return -1;
     383                 :             :     }
     384                 :             : 
     385                 :     3221423 :   if (prop.num_replacements == 0)
     386                 :             :     return 0;
     387                 :             : 
     388                 :      504710 :   if (require_constant)
     389                 :             :     {
     390                 :      495545 :       if (!prop.folded_to_constants_p ())
     391                 :             :         {
     392                 :      454993 :           if (dump_file && (dump_flags & TDF_DETAILS))
     393                 :           0 :             fprintf (dump_file, "cannot propagate from insn %d into"
     394                 :             :                      " notes of insn %d: %s\n", def_insn->uid (),
     395                 :             :                      use_insn->uid (), "wouldn't fold to constants");
     396                 :      454993 :           return -1;
     397                 :             :         }
     398                 :             :     }
     399                 :             :   else
     400                 :             :     {
     401                 :        9165 :       if (!prop.folded_to_constants_p () && !prop.likely_profitable_p ())
     402                 :             :         {
     403                 :           5 :           if (dump_file && (dump_flags & TDF_DETAILS))
     404                 :           0 :             fprintf (dump_file, "cannot propagate from insn %d into"
     405                 :             :                      " notes of insn %d: %s\n", def_insn->uid (),
     406                 :             :                      use_insn->uid (), "would increase complexity of node");
     407                 :           5 :           return -1;
     408                 :             :         }
     409                 :             :     }
     410                 :             : 
     411                 :       49712 :   if (dump_file && (dump_flags & TDF_DETAILS))
     412                 :             :     {
     413                 :           0 :       fprintf (dump_file, "\nin notes of insn %d, replacing:\n  ",
     414                 :           0 :                INSN_UID (use_rtl));
     415                 :           0 :       temporarily_undo_changes (0);
     416                 :           0 :       print_inline_rtx (dump_file, note, 2);
     417                 :           0 :       redo_changes (0);
     418                 :           0 :       fprintf (dump_file, "\n with:\n  ");
     419                 :           0 :       print_inline_rtx (dump_file, note, 2);
     420                 :           0 :       fprintf (dump_file, "\n");
     421                 :             :     }
     422                 :       49712 :   watermark.keep ();
     423                 :       49712 :   return prop.num_replacements;
     424                 :     3238206 : }
     425                 :             : 
     426                 :             : /* Try to substitute (set DEST SRC), which defines DEF, into location LOC of
     427                 :             :    USE_INSN's pattern.  Return true on success, otherwise leave USE_INSN
     428                 :             :    unchanged.  */
     429                 :             : 
     430                 :             : static bool
     431                 :    26975150 : try_fwprop_subst_pattern (obstack_watermark &attempt, insn_change &use_change,
     432                 :             :                           set_info *def, rtx *loc, rtx dest, rtx src)
     433                 :             : {
     434                 :    26975150 :   insn_info *use_insn = use_change.insn ();
     435                 :    26975150 :   rtx_insn *use_rtl = use_insn->rtl ();
     436                 :    26975150 :   insn_info *def_insn = def->insn ();
     437                 :             : 
     438                 :    26975150 :   insn_change_watermark watermark;
     439                 :    26975150 :   fwprop_propagation prop (use_insn, def, dest, src);
     440                 :    26975150 :   if (!prop.apply_to_pattern (loc))
     441                 :             :     {
     442                 :     1512363 :       if (dump_file && (dump_flags & TDF_DETAILS))
     443                 :           0 :         fprintf (dump_file, "cannot propagate from insn %d into"
     444                 :             :                  " insn %d: %s\n", def_insn->uid (), use_insn->uid (),
     445                 :             :                  prop.failure_reason);
     446                 :     1512363 :       return false;
     447                 :             :     }
     448                 :             : 
     449                 :    25462787 :   if (prop.num_replacements == 0)
     450                 :             :     return false;
     451                 :             : 
     452                 :    21732859 :   if (!prop.likely_profitable_p ()
     453                 :    21732859 :       && (prop.changed_mem_p ()
     454                 :    17073277 :           || contains_mem_rtx_p (src)
     455                 :    11181836 :           || use_insn->is_asm ()
     456                 :    11181043 :           || !single_set (use_rtl)))
     457                 :             :     {
     458                 :     6668540 :       if (dump_file && (dump_flags & TDF_DETAILS))
     459                 :           0 :         fprintf (dump_file, "cannot propagate from insn %d into"
     460                 :             :                  " insn %d: %s\n", def_insn->uid (), use_insn->uid (),
     461                 :             :                  "would increase complexity of pattern");
     462                 :     6668540 :       return false;
     463                 :             :     }
     464                 :             : 
     465                 :    15064319 :   if (dump_file && (dump_flags & TDF_DETAILS))
     466                 :             :     {
     467                 :           0 :       fprintf (dump_file, "\npropagating insn %d into insn %d, replacing:\n",
     468                 :             :                def_insn->uid (), use_insn->uid ());
     469                 :           0 :       temporarily_undo_changes (0);
     470                 :           0 :       print_rtl_single (dump_file, PATTERN (use_rtl));
     471                 :           0 :       redo_changes (0);
     472                 :             :     }
     473                 :             : 
     474                 :             :   /* ??? In theory, it should be better to use insn costs rather than
     475                 :             :      set_src_costs here.  That would involve replacing this code with
     476                 :             :      change_is_worthwhile.  */
     477                 :    15064319 :   bool ok = recog (attempt, use_change);
     478                 :    15064319 :   if (ok && !prop.changed_mem_p () && !use_insn->is_asm ())
     479                 :     6016414 :     if (rtx use_set = single_set (use_rtl))
     480                 :             :       {
     481                 :     5664443 :         bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_rtl));
     482                 :     5664443 :         temporarily_undo_changes (0);
     483                 :    11328886 :         auto old_cost = set_src_cost (SET_SRC (use_set),
     484                 :     5664443 :                                       GET_MODE (SET_DEST (use_set)), speed);
     485                 :     5664443 :         redo_changes (0);
     486                 :    11328886 :         auto new_cost = set_src_cost (SET_SRC (use_set),
     487                 :     5664443 :                                       GET_MODE (SET_DEST (use_set)), speed);
     488                 :     5664443 :         if (new_cost > old_cost
     489                 :     5664443 :             || (new_cost == old_cost && !prop.likely_profitable_p ()))
     490                 :             :           {
     491                 :     4293966 :             if (dump_file)
     492                 :          69 :               fprintf (dump_file, "change not profitable"
     493                 :             :                        " (cost %d -> cost %d)\n", old_cost, new_cost);
     494                 :             :             ok = false;
     495                 :             :           }
     496                 :             :       }
     497                 :             : 
     498                 :    10770353 :   if (!ok)
     499                 :             :     {
     500                 :             :       /* The pattern didn't match, but if all uses of SRC folded to
     501                 :             :          constants, we can add a REG_EQUAL note for the result, if there
     502                 :             :          isn't one already.  */
     503                 :    12109177 :       if (!prop.folded_to_constants_p ())
     504                 :             :         return false;
     505                 :             : 
     506                 :             :       /* Test this first to avoid creating an unnecessary copy of SRC.  */
     507                 :     1443648 :       if (find_reg_note (use_rtl, REG_EQUAL, NULL_RTX))
     508                 :             :         return false;
     509                 :             : 
     510                 :      669167 :       rtx set = set_for_reg_notes (use_rtl);
     511                 :      669167 :       if (!set || !REG_P (SET_DEST (set)))
     512                 :             :         return false;
     513                 :             : 
     514                 :      392112 :       rtx value = copy_rtx (SET_SRC (set));
     515                 :      392112 :       cancel_changes (0);
     516                 :             : 
     517                 :             :       /* If there are any paradoxical SUBREGs, drop the REG_EQUAL note,
     518                 :             :          because the bits in there can be anything and so might not
     519                 :             :          match the REG_EQUAL note content.  See PR70574.  */
     520                 :      392112 :       if (contains_paradoxical_subreg_p (SET_SRC (set)))
     521                 :             :         return false;
     522                 :             : 
     523                 :      392085 :       if (dump_file && (dump_flags & TDF_DETAILS))
     524                 :           0 :         fprintf (dump_file, " Setting REG_EQUAL note\n");
     525                 :             : 
     526                 :      392085 :       return set_unique_reg_note (use_rtl, REG_EQUAL, value);
     527                 :             :     }
     528                 :             : 
     529                 :     2955142 :   rtx *note_ptr = &REG_NOTES (use_rtl);
     530                 :     5695308 :   while (rtx note = *note_ptr)
     531                 :             :     {
     532                 :     2740166 :       if ((REG_NOTE_KIND (note) == REG_EQUAL
     533                 :     2740166 :            || REG_NOTE_KIND (note) == REG_EQUIV)
     534                 :     2740166 :           && try_fwprop_subst_note (use_insn, def, note, dest, src, false) < 0)
     535                 :             :         {
     536                 :           5 :           *note_ptr = XEXP (note, 1);
     537                 :           5 :           free_EXPR_LIST_node (note);
     538                 :             :         }
     539                 :             :       else
     540                 :     2740161 :         note_ptr = &XEXP (note, 1);
     541                 :             :     }
     542                 :             : 
     543                 :     2955142 :   confirm_change_group ();
     544                 :     2955142 :   crtl->ssa->change_insn (use_change);
     545                 :     2955142 :   num_changes++;
     546                 :     2955142 :   return true;
     547                 :    26975150 : }
     548                 :             : 
     549                 :             : /* Try to substitute (set DEST SRC), which defines DEF, into USE_INSN's notes,
     550                 :             :    given that it was not possible to do this for USE_INSN's main pattern.
     551                 :             :    Return true on success, otherwise leave USE_INSN unchanged.  */
     552                 :             : 
     553                 :             : static bool
     554                 :    23632173 : try_fwprop_subst_notes (insn_info *use_insn, set_info *def,
     555                 :             :                         rtx dest, rtx src)
     556                 :             : {
     557                 :    23632173 :   rtx_insn *use_rtl = use_insn->rtl ();
     558                 :    68776580 :   for (rtx note = REG_NOTES (use_rtl); note; note = XEXP (note, 1))
     559                 :    45184959 :     if ((REG_NOTE_KIND (note) == REG_EQUAL
     560                 :    45184959 :          || REG_NOTE_KIND (note) == REG_EQUIV)
     561                 :    45184959 :         && try_fwprop_subst_note (use_insn, def, note, dest, src, true) > 0)
     562                 :             :       {
     563                 :       40552 :         confirm_change_group ();
     564                 :       40552 :         return true;
     565                 :             :       }
     566                 :             : 
     567                 :             :   return false;
     568                 :             : }
     569                 :             : 
     570                 :             : /* Check whether we could validly substitute (set DEST SRC), which defines DEF,
     571                 :             :    into USE.  If so, first try performing the substitution in location LOC
     572                 :             :    of USE->insn ()'s pattern.  If that fails, try instead to substitute
     573                 :             :    into the notes.
     574                 :             : 
     575                 :             :    Return true on success, otherwise leave USE_INSN unchanged.  */
     576                 :             : 
     577                 :             : static bool
     578                 :    41285067 : try_fwprop_subst (use_info *use, set_info *def,
     579                 :             :                   rtx *loc, rtx dest, rtx src)
     580                 :             : {
     581                 :    41285067 :   insn_info *use_insn = use->insn ();
     582                 :    41285067 :   insn_info *def_insn = def->insn ();
     583                 :             : 
     584                 :    41285067 :   auto attempt = crtl->ssa->new_change_attempt ();
     585                 :    41285067 :   use_array src_uses = remove_note_accesses (attempt, def_insn->uses ());
     586                 :             : 
     587                 :             :   /* ??? Not really a meaningful test: it means we can propagate arithmetic
     588                 :             :      involving hard registers but not bare references to them.  A better
     589                 :             :      test would be to iterate over src_uses looking for hard registers
     590                 :             :      that are not fixed.  */
     591                 :    41285067 :   if (REG_P (src) && HARD_REGISTER_P (src))
     592                 :             :     return false;
     593                 :             : 
     594                 :             :   /* ??? It would be better to make this EBB-based instead.  That would
     595                 :             :      involve checking for equal EBBs rather than equal BBs and trying
     596                 :             :      to make the uses available at use_insn->ebb ()->first_bb ().  */
     597                 :    32233539 :   if (def_insn->bb () != use_insn->bb ())
     598                 :             :     {
     599                 :     6855655 :       src_uses = crtl->ssa->make_uses_available (attempt, src_uses,
     600                 :             :                                                  use_insn->bb (),
     601                 :     6855655 :                                                  use_insn->is_debug_insn ());
     602                 :     6855655 :       if (!src_uses.is_valid ())
     603                 :             :         return false;
     604                 :             :     }
     605                 :             : 
     606                 :    29784569 :   insn_change use_change (use_insn);
     607                 :    29784569 :   use_change.new_uses = merge_access_arrays (attempt, use_change.new_uses,
     608                 :             :                                              src_uses);
     609                 :    67686107 :   if (!use_change.new_uses.is_valid ())
     610                 :             :     return false;
     611                 :             : 
     612                 :             :   /* ??? We could allow movement within the EBB by adding:
     613                 :             : 
     614                 :             :      use_change.move_range = use_insn->ebb ()->insn_range ();  */
     615                 :    28221481 :   if (!restrict_movement (use_change))
     616                 :             :     return false;
     617                 :             : 
     618                 :    26975150 :   return (try_fwprop_subst_pattern (attempt, use_change, def, loc, dest, src)
     619                 :    26975150 :           || try_fwprop_subst_notes (use_insn, def, dest, src));
     620                 :    41285067 : }
     621                 :             : 
     622                 :             : /* For the given single_set INSN, containing SRC known to be a
     623                 :             :    ZERO_EXTEND or SIGN_EXTEND of a register, return true if INSN
     624                 :             :    is redundant due to the register being set by a LOAD_EXTEND_OP
     625                 :             :    load from memory.  */
     626                 :             : 
     627                 :             : static bool
     628                 :       15618 : free_load_extend (rtx src, insn_info *insn)
     629                 :             : {
     630                 :       15618 :   rtx reg = XEXP (src, 0);
     631                 :       15618 :   if (load_extend_op (GET_MODE (reg)) != GET_CODE (src))
     632                 :             :     return false;
     633                 :             : 
     634                 :           0 :   def_info *def = nullptr;
     635                 :           0 :   for (use_info *use : insn->uses ())
     636                 :           0 :     if (use->regno () == REGNO (reg))
     637                 :             :       {
     638                 :           0 :         def = use->def ();
     639                 :           0 :         break;
     640                 :             :       }
     641                 :             : 
     642                 :           0 :   if (!def)
     643                 :             :     return false;
     644                 :             : 
     645                 :           0 :   insn_info *def_insn = def->insn ();
     646                 :           0 :   if (def_insn->is_artificial ())
     647                 :             :     return false;
     648                 :             : 
     649                 :           0 :   rtx_insn *def_rtl = def_insn->rtl ();
     650                 :           0 :   if (NONJUMP_INSN_P (def_rtl))
     651                 :             :     {
     652                 :           0 :       rtx patt = PATTERN (def_rtl);
     653                 :             : 
     654                 :           0 :       if (GET_CODE (patt) == SET
     655                 :           0 :           && GET_CODE (SET_SRC (patt)) == MEM
     656                 :           0 :           && rtx_equal_p (SET_DEST (patt), reg))
     657                 :             :         return true;
     658                 :             :     }
     659                 :             :   return false;
     660                 :             : }
     661                 :             : 
     662                 :             : /* Subroutine of forward_propagate_subreg that handles a use of DEST
     663                 :             :    in REF.  The other parameters are the same.  */
     664                 :             : 
     665                 :             : static bool
     666                 :       95815 : forward_propagate_subreg (use_info *use, set_info *def,
     667                 :             :                           rtx dest, rtx src, df_ref ref)
     668                 :             : {
     669                 :       95815 :   scalar_int_mode int_use_mode, src_mode;
     670                 :             : 
     671                 :             :   /* Only consider subregs... */
     672                 :       95815 :   rtx use_reg = DF_REF_REG (ref);
     673                 :       95815 :   machine_mode use_mode = GET_MODE (use_reg);
     674                 :       95815 :   if (GET_CODE (use_reg) != SUBREG
     675                 :       95752 :       || GET_MODE (SUBREG_REG (use_reg)) != GET_MODE (dest))
     676                 :             :     return false;
     677                 :             : 
     678                 :             :   /* ??? Replacing throughout the pattern would help for match_dups.  */
     679                 :       95752 :   rtx *loc = DF_REF_LOC (ref);
     680                 :       95752 :   if (paradoxical_subreg_p (use_reg))
     681                 :             :     {
     682                 :             :       /* If this is a paradoxical SUBREG, we have no idea what value the
     683                 :             :          extra bits would have.  However, if the operand is equivalent to
     684                 :             :          a SUBREG whose operand is the same as our mode, and all the modes
     685                 :             :          are within a word, we can just use the inner operand because
     686                 :             :          these SUBREGs just say how to treat the register.  */
     687                 :        1684 :       if (GET_CODE (src) == SUBREG
     688                 :        1649 :           && REG_P (SUBREG_REG (src))
     689                 :        1609 :           && REGNO (SUBREG_REG (src)) >= FIRST_PSEUDO_REGISTER
     690                 :        1609 :           && GET_MODE (SUBREG_REG (src)) == use_mode
     691                 :        1684 :           && subreg_lowpart_p (src))
     692                 :           0 :         return try_fwprop_subst (use, def, loc, use_reg, SUBREG_REG (src));
     693                 :             :     }
     694                 :             : 
     695                 :             :   /* If this is a SUBREG of a ZERO_EXTEND or SIGN_EXTEND, and the SUBREG
     696                 :             :      is the low part of the reg being extended then just use the inner
     697                 :             :      operand.  Don't do this if the ZERO_EXTEND or SIGN_EXTEND insn will
     698                 :             :      be removed due to it matching a LOAD_EXTEND_OP load from memory,
     699                 :             :      or due to the operation being a no-op when applied to registers.
     700                 :             :      For example, if we have:
     701                 :             : 
     702                 :             :          A: (set (reg:DI X) (sign_extend:DI (reg:SI Y)))
     703                 :             :          B: (... (subreg:SI (reg:DI X)) ...)
     704                 :             : 
     705                 :             :      and mode_rep_extended says that Y is already sign-extended,
     706                 :             :      the backend will typically allow A to be combined with the
     707                 :             :      definition of Y or, failing that, allow A to be deleted after
     708                 :             :      reload through register tying.  Introducing more uses of Y
     709                 :             :      prevents both optimisations.  */
     710                 :       94068 :   else if (is_a <scalar_int_mode> (use_mode, &int_use_mode)
     711                 :       83586 :            && subreg_lowpart_p (use_reg))
     712                 :             :     {
     713                 :       79054 :       if ((GET_CODE (src) == ZERO_EXTEND
     714                 :       79054 :            || GET_CODE (src) == SIGN_EXTEND)
     715                 :       60026 :           && is_a <scalar_int_mode> (GET_MODE (src), &src_mode)
     716                 :       60016 :           && REG_P (XEXP (src, 0))
     717                 :       19735 :           && REGNO (XEXP (src, 0)) >= FIRST_PSEUDO_REGISTER
     718                 :       19735 :           && GET_MODE (XEXP (src, 0)) == use_mode
     719                 :       15618 :           && !free_load_extend (src, def->insn ())
     720                 :       94672 :           && (targetm.mode_rep_extended (int_use_mode, src_mode)
     721                 :       15618 :               != (int) GET_CODE (src)))
     722                 :       15618 :         return try_fwprop_subst (use, def, loc, use_reg, XEXP (src, 0));
     723                 :             :     }
     724                 :             : 
     725                 :             :   return false;
     726                 :             : }
     727                 :             : 
     728                 :             : /* Try to substitute (set DEST SRC), which defines DEF, into USE and simplify
     729                 :             :    the result, handling cases where DEST is used in a subreg and where
     730                 :             :    applying that subreg to SRC results in a useful simplification.  */
     731                 :             : 
     732                 :             : static bool
     733                 :    47688904 : forward_propagate_subreg (use_info *use, set_info *def, rtx dest, rtx src)
     734                 :             : {
     735                 :    47688904 :   if (!use->includes_subregs () || !REG_P (dest))
     736                 :             :     return false;
     737                 :             : 
     738                 :     1570226 :   if (GET_CODE (src) != SUBREG
     739                 :     1540438 :       && GET_CODE (src) != ZERO_EXTEND
     740                 :     1484021 :       && GET_CODE (src) != SIGN_EXTEND)
     741                 :             :     return false;
     742                 :             : 
     743                 :       92627 :   rtx_insn *use_rtl = use->insn ()->rtl ();
     744                 :       92627 :   df_ref ref;
     745                 :             : 
     746                 :      242887 :   FOR_EACH_INSN_USE (ref, use_rtl)
     747                 :      164532 :     if (DF_REF_REGNO (ref) == use->regno ()
     748                 :      164532 :         && forward_propagate_subreg (use, def, dest, src, ref))
     749                 :             :       return true;
     750                 :             : 
     751                 :       83269 :   FOR_EACH_INSN_EQ_USE (ref, use_rtl)
     752                 :        4916 :     if (DF_REF_REGNO (ref) == use->regno ()
     753                 :        4916 :         && forward_propagate_subreg (use, def, dest, src, ref))
     754                 :             :       return true;
     755                 :             : 
     756                 :             :   return false;
     757                 :             : }
     758                 :             : 
     759                 :             : /* Try to substitute (set DEST SRC), which defines DEF, into USE and
     760                 :             :    simplify the result.  */
     761                 :             : 
     762                 :             : static bool
     763                 :    51058159 : forward_propagate_and_simplify (use_info *use, set_info *def,
     764                 :             :                                 rtx dest, rtx src)
     765                 :             : {
     766                 :    51058159 :   insn_info *use_insn = use->insn ();
     767                 :    51058159 :   rtx_insn *use_rtl = use_insn->rtl ();
     768                 :    51058159 :   insn_info *def_insn = def->insn ();
     769                 :             : 
     770                 :             :   /* ??? This check seems unnecessary.  We should be able to propagate
     771                 :             :      into any kind of instruction, regardless of whether it's a single set.
     772                 :             :      It seems odd to be more permissive with asms than normal instructions.  */
     773                 :    51058159 :   bool need_single_set = (!use_insn->is_asm () && !use_insn->is_debug_insn ());
     774                 :    51058159 :   rtx use_set = single_set (use_rtl);
     775                 :    51058159 :   if (need_single_set && !use_set)
     776                 :             :     return false;
     777                 :             : 
     778                 :             :   /* Do not propagate into PC etc.
     779                 :             : 
     780                 :             :      ??? This too seems unnecessary.  The current code should work correctly
     781                 :             :      without it, including cases where jumps become unconditional.  */
     782                 :    46760259 :   if (use_set && GET_MODE (SET_DEST (use_set)) == VOIDmode)
     783                 :             :     return false;
     784                 :             : 
     785                 :             :   /* In __asm don't replace if src might need more registers than
     786                 :             :      reg, as that could increase register pressure on the __asm.  */
     787                 :    42496630 :   if (use_insn->is_asm () && def_insn->uses ().size () > 1)
     788                 :        1928 :     return false;
     789                 :             : 
     790                 :             :   /* Check if the def is loading something from the constant pool; in this
     791                 :             :      case we would undo optimization such as compress_float_constant.
     792                 :             :      Still, we can set a REG_EQUAL note.  */
     793                 :    42494702 :   if (MEM_P (src) && MEM_READONLY_P (src))
     794                 :             :     {
     795                 :     1225253 :       rtx x = avoid_constant_pool_reference (src);
     796                 :     1225253 :       rtx note_set;
     797                 :     1225253 :       if (x != src
     798                 :      853501 :           && (note_set = set_for_reg_notes (use_rtl))
     799                 :      585361 :           && REG_P (SET_DEST (note_set))
     800                 :     1792422 :           && !contains_paradoxical_subreg_p (SET_SRC (note_set)))
     801                 :             :         {
     802                 :      548342 :           rtx note = find_reg_note (use_rtl, REG_EQUAL, NULL_RTX);
     803                 :      548342 :           rtx old_rtx = note ? XEXP (note, 0) : SET_SRC (note_set);
     804                 :      548342 :           rtx new_rtx = simplify_replace_rtx (old_rtx, src, x);
     805                 :      548342 :           if (old_rtx != new_rtx)
     806                 :           7 :             set_unique_reg_note (use_rtl, REG_EQUAL, copy_rtx (new_rtx));
     807                 :             :         }
     808                 :     1225253 :       return false;
     809                 :             :     }
     810                 :             : 
     811                 :             :   /* ??? Unconditionally propagating into PATTERN would work better
     812                 :             :      for instructions that have match_dups.  */
     813                 :    41269449 :   rtx *loc = need_single_set ? &use_set : &PATTERN (use_rtl);
     814                 :    41269449 :   return try_fwprop_subst (use, def, loc, dest, src);
     815                 :             : }
     816                 :             : 
     817                 :             : /* Given a use USE of an insn, if it has a single reaching
     818                 :             :    definition, try to forward propagate it into that insn.
     819                 :             :    Return true if something changed.
     820                 :             : 
     821                 :             :    REG_PROP_ONLY is true if we should only propagate register copies.  */
     822                 :             : 
     823                 :             : static bool
     824                 :   141985923 : forward_propagate_into (use_info *use, bool reg_prop_only = false)
     825                 :             : {
     826                 :   141985923 :   if (use->includes_read_writes ())
     827                 :             :     return false;
     828                 :             : 
     829                 :             :   /* Disregard uninitialized uses.  */
     830                 :   134719996 :   set_info *def = use->def ();
     831                 :   134719996 :   if (!def)
     832                 :             :     return false;
     833                 :             : 
     834                 :             :   /* Only consider single-register definitions.  This could be relaxed,
     835                 :             :      but it should rarely be needed before RA.  */
     836                 :   134710629 :   def = look_through_degenerate_phi (def);
     837                 :   134710629 :   if (def->includes_multiregs ())
     838                 :             :     return false;
     839                 :             : 
     840                 :             :   /* Only consider uses whose definition comes from a real instruction.  */
     841                 :   134188029 :   insn_info *def_insn = def->insn ();
     842                 :   134188029 :   if (def_insn->is_artificial ())
     843                 :             :     return false;
     844                 :             : 
     845                 :   100029913 :   rtx_insn *def_rtl = def_insn->rtl ();
     846                 :   100029913 :   if (!NONJUMP_INSN_P (def_rtl))
     847                 :             :     return false;
     848                 :             :   /* ??? This seems an unnecessary restriction.  We can easily tell
     849                 :             :      which set the definition comes from.  */
     850                 :    97406165 :   if (multiple_sets (def_rtl))
     851                 :             :     return false;
     852                 :    96705681 :   rtx def_set = simple_regno_set (PATTERN (def_rtl), def->regno ());
     853                 :    96705681 :   if (!def_set)
     854                 :             :     return false;
     855                 :             : 
     856                 :    96399027 :   rtx dest = SET_DEST (def_set);
     857                 :    96399027 :   rtx src = SET_SRC (def_set);
     858                 :    96399027 :   if (volatile_refs_p (src))
     859                 :             :     return false;
     860                 :             : 
     861                 :             :   /* Allow propagations into a loop only for reg-to-reg copies, since
     862                 :             :      replacing one register by another shouldn't increase the cost.
     863                 :             :      Propagations from inner loop to outer loop should also be ok.  */
     864                 :    95426490 :   struct loop *def_loop = def_insn->bb ()->cfg_bb ()->loop_father;
     865                 :   190852980 :   struct loop *use_loop = use->bb ()->cfg_bb ()->loop_father;
     866                 :    95426490 :   if ((reg_prop_only
     867                 :    51650798 :        || (def_loop != use_loop
     868                 :     1971546 :            && !flow_loop_nested_p (use_loop, def_loop)))
     869                 :    97076664 :       && (!reg_single_def_p (dest) || !reg_single_def_p (src)))
     870                 :             :     return false;
     871                 :             : 
     872                 :             :   /* Don't substitute into a non-local goto, this confuses CFG.  */
     873                 :    51058842 :   insn_info *use_insn = use->insn ();
     874                 :    51058842 :   rtx_insn *use_rtl = use_insn->rtl ();
     875                 :    51058842 :   if (JUMP_P (use_rtl)
     876                 :    51058842 :       && find_reg_note (use_rtl, REG_NON_LOCAL_GOTO, NULL_RTX))
     877                 :             :     return false;
     878                 :             : 
     879                 :    51058159 :   if (forward_propagate_and_simplify (use, def, dest, src)
     880                 :    51058159 :       || forward_propagate_subreg (use, def, dest, src))
     881                 :     3383529 :     return true;
     882                 :             : 
     883                 :             :   return false;
     884                 :             : }
     885                 :             : 
     886                 :             : static void
     887                 :     1955630 : fwprop_init (void)
     888                 :             : {
     889                 :     1955630 :   num_changes = 0;
     890                 :     1955630 :   calculate_dominance_info (CDI_DOMINATORS);
     891                 :             : 
     892                 :             :   /* We do not always want to propagate into loops, so we have to find
     893                 :             :      loops and be careful about them.  Avoid CFG modifications so that
     894                 :             :      we don't have to update dominance information afterwards for
     895                 :             :      build_single_def_use_links.  */
     896                 :     1955630 :   loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
     897                 :             : 
     898                 :     1955630 :   df_analyze ();
     899                 :     1955630 :   crtl->ssa = new rtl_ssa::function_info (cfun);
     900                 :     1955630 : }
     901                 :             : 
     902                 :             : static void
     903                 :     1955630 : fwprop_done (void)
     904                 :             : {
     905                 :     1955630 :   loop_optimizer_finalize ();
     906                 :             : 
     907                 :     1955630 :   crtl->ssa->perform_pending_updates ();
     908                 :     1955630 :   free_dominance_info (CDI_DOMINATORS);
     909                 :     1955630 :   cleanup_cfg (0);
     910                 :             : 
     911                 :     1955630 :   delete crtl->ssa;
     912                 :     1955630 :   crtl->ssa = nullptr;
     913                 :             : 
     914                 :     1955630 :   delete_trivially_dead_insns (get_insns (), max_reg_num ());
     915                 :             : 
     916                 :     1955630 :   if (dump_file)
     917                 :          63 :     fprintf (dump_file,
     918                 :             :              "\nNumber of successful forward propagations: %d\n\n",
     919                 :             :              num_changes);
     920                 :     1955630 : }
     921                 :             : 
     922                 :             : /* Try to optimize INSN, returning true if something changes.
     923                 :             :    FWPROP_ADDR_P is true if we are running fwprop_addr rather than
     924                 :             :    the full fwprop.  */
     925                 :             : 
     926                 :             : static bool
     927                 :   187066380 : fwprop_insn (insn_info *insn, bool fwprop_addr_p)
     928                 :             : {
     929                 :   353913151 :   for (use_info *use : insn->uses ())
     930                 :             :     {
     931                 :   170230300 :       if (use->is_mem ())
     932                 :    24751011 :         continue;
     933                 :             :       /* ??? The choices here follow those in the pre-SSA code.  */
     934                 :   145479289 :       if (!use->includes_address_uses ())
     935                 :             :         {
     936                 :   118102384 :           if (forward_propagate_into (use, fwprop_addr_p))
     937                 :     3383529 :             return true;
     938                 :             :         }
     939                 :             :       else
     940                 :             :         {
     941                 :    27376905 :           struct loop *loop = insn->bb ()->cfg_bb ()->loop_father;
     942                 :             :           /* The outermost loop is not really a loop.  */
     943                 :    27376905 :           if (loop == NULL || loop_outer (loop) == NULL)
     944                 :             :             {
     945                 :    20225581 :               if (forward_propagate_into (use, fwprop_addr_p))
     946                 :             :                 return true;
     947                 :             :             }
     948                 :     7151324 :           else if (fwprop_addr_p)
     949                 :             :             {
     950                 :     3657958 :               if (forward_propagate_into (use, false))
     951                 :             :                 return true;
     952                 :             :             }
     953                 :             :         }
     954                 :             :     }
     955                 :             :   return false;
     956                 :             : }
     957                 :             : 
     958                 :             : /* Main entry point.  */
     959                 :             : 
     960                 :             : static bool
     961                 :     2839490 : gate_fwprop (void)
     962                 :             : {
     963                 :     1955726 :   return optimize > 0 && flag_forward_propagate;
     964                 :             : }
     965                 :             : 
     966                 :             : static unsigned int
     967                 :     1955630 : fwprop (bool fwprop_addr_p)
     968                 :             : {
     969                 :     1955630 :   fwprop_init ();
     970                 :             : 
     971                 :             :   /* Go through all the instructions (including debug instructions) looking
     972                 :             :      for uses that we could propagate into.
     973                 :             : 
     974                 :             :      Do not forward propagate addresses into loops until after unrolling.
     975                 :             :      CSE did so because it was able to fix its own mess, but we are not.  */
     976                 :             : 
     977                 :     1955630 :   insn_info *next;
     978                 :             : 
     979                 :             :   /* ??? This code uses a worklist in order to preserve the behavior
     980                 :             :      of the pre-SSA implementation.  It would be better to instead
     981                 :             :      iterate on each instruction until no more propagations are
     982                 :             :      possible, then move on to the next.  */
     983                 :     1955630 :   auto_vec<insn_info *> worklist;
     984                 :   246899249 :   for (insn_info *insn = crtl->ssa->first_insn (); insn; insn = next)
     985                 :             :     {
     986                 :   244943619 :       next = insn->next_any_insn ();
     987                 :   244943619 :       if (insn->can_be_optimized () || insn->is_debug_insn ())
     988                 :   183682851 :         if (fwprop_insn (insn, fwprop_addr_p))
     989                 :     3170967 :           worklist.safe_push (insn);
     990                 :             :     }
     991                 :     9110876 :   for (unsigned int i = 0; i < worklist.length (); ++i)
     992                 :             :     {
     993                 :     3383529 :       insn_info *insn = worklist[i];
     994                 :     3383529 :       if (fwprop_insn (insn, fwprop_addr_p))
     995                 :      212562 :         worklist.safe_push (insn);
     996                 :             :     }
     997                 :             : 
     998                 :     1955630 :   fwprop_done ();
     999                 :     1955630 :   return 0;
    1000                 :     1955630 : }
    1001                 :             : 
    1002                 :             : namespace {
    1003                 :             : 
    1004                 :             : const pass_data pass_data_rtl_fwprop =
    1005                 :             : {
    1006                 :             :   RTL_PASS, /* type */
    1007                 :             :   "fwprop1", /* name */
    1008                 :             :   OPTGROUP_NONE, /* optinfo_flags */
    1009                 :             :   TV_FWPROP, /* tv_id */
    1010                 :             :   0, /* properties_required */
    1011                 :             :   0, /* properties_provided */
    1012                 :             :   0, /* properties_destroyed */
    1013                 :             :   0, /* todo_flags_start */
    1014                 :             :   TODO_df_finish, /* todo_flags_finish */
    1015                 :             : };
    1016                 :             : 
    1017                 :             : class pass_rtl_fwprop : public rtl_opt_pass
    1018                 :             : {
    1019                 :             : public:
    1020                 :      285617 :   pass_rtl_fwprop (gcc::context *ctxt)
    1021                 :      571234 :     : rtl_opt_pass (pass_data_rtl_fwprop, ctxt)
    1022                 :             :   {}
    1023                 :             : 
    1024                 :             :   /* opt_pass methods: */
    1025                 :     1419745 :   bool gate (function *) final override { return gate_fwprop (); }
    1026                 :      977815 :   unsigned int execute (function *) final override { return fwprop (false); }
    1027                 :             : 
    1028                 :             : }; // class pass_rtl_fwprop
    1029                 :             : 
    1030                 :             : } // anon namespace
    1031                 :             : 
    1032                 :             : rtl_opt_pass *
    1033                 :      285617 : make_pass_rtl_fwprop (gcc::context *ctxt)
    1034                 :             : {
    1035                 :      285617 :   return new pass_rtl_fwprop (ctxt);
    1036                 :             : }
    1037                 :             : 
    1038                 :             : namespace {
    1039                 :             : 
    1040                 :             : const pass_data pass_data_rtl_fwprop_addr =
    1041                 :             : {
    1042                 :             :   RTL_PASS, /* type */
    1043                 :             :   "fwprop2", /* name */
    1044                 :             :   OPTGROUP_NONE, /* optinfo_flags */
    1045                 :             :   TV_FWPROP, /* tv_id */
    1046                 :             :   0, /* properties_required */
    1047                 :             :   0, /* properties_provided */
    1048                 :             :   0, /* properties_destroyed */
    1049                 :             :   0, /* todo_flags_start */
    1050                 :             :   TODO_df_finish, /* todo_flags_finish */
    1051                 :             : };
    1052                 :             : 
    1053                 :             : class pass_rtl_fwprop_addr : public rtl_opt_pass
    1054                 :             : {
    1055                 :             : public:
    1056                 :      285617 :   pass_rtl_fwprop_addr (gcc::context *ctxt)
    1057                 :      571234 :     : rtl_opt_pass (pass_data_rtl_fwprop_addr, ctxt)
    1058                 :             :   {}
    1059                 :             : 
    1060                 :             :   /* opt_pass methods: */
    1061                 :     1419745 :   bool gate (function *) final override { return gate_fwprop (); }
    1062                 :      977815 :   unsigned int execute (function *) final override { return fwprop (true); }
    1063                 :             : 
    1064                 :             : }; // class pass_rtl_fwprop_addr
    1065                 :             : 
    1066                 :             : } // anon namespace
    1067                 :             : 
    1068                 :             : rtl_opt_pass *
    1069                 :      285617 : make_pass_rtl_fwprop_addr (gcc::context *ctxt)
    1070                 :             : {
    1071                 :      285617 :   return new pass_rtl_fwprop_addr (ctxt);
    1072                 :             : }
        

Generated by: LCOV version 2.0-1

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.