LCOV - code coverage report
Current view: top level - gcc - ext-dce.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 66.4 % 715 475
Test Date: 2026-08-22 16:33:35 Functions: 91.7 % 24 22
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* RTL dead zero/sign extension (code) elimination.
       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 under
       7              : the terms of the GNU General Public License as published by the Free
       8              : Software Foundation; either version 3, or (at your option) any later
       9              : version.
      10              : 
      11              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      12              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      13              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      14              : 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 "tree.h"
      26              : #include "memmodel.h"
      27              : #include "insn-config.h"
      28              : #include "emit-rtl.h"
      29              : #include "expr.h"
      30              : #include "recog.h"
      31              : #include "cfganal.h"
      32              : #include "tree-pass.h"
      33              : #include "cfgrtl.h"
      34              : #include "rtl-iter.h"
      35              : #include "df.h"
      36              : #include "print-rtl.h"
      37              : #include "dbgcnt.h"
      38              : #include "diagnostic-core.h"
      39              : #include "target.h"
      40              : 
      41              : /* These should probably move into a C++ class.  */
      42              : static vec<bitmap_head> livein;
      43              : static bitmap all_blocks;
      44              : static bitmap livenow;
      45              : static bitmap changed_pseudos;
      46              : static bool modify;
      47              : 
      48              : /* Chain detection for promotion: we defer promotions and only apply them
      49              :    when they form chains (one candidate's result feeds another's operand).
      50              :    Standalone promotions are skipped as they cause regressions on targets
      51              :    with free sign extension (e.g., RISC-V W-suffix instructions).  */
      52              : struct promotion_candidate_info {
      53              :   rtx_insn *insn;
      54              :   rtx set;
      55              : };
      56              : 
      57              : static vec<promotion_candidate_info> promotion_candidates;
      58              : static bitmap promotable_dests;
      59              : static bitmap consumed_by_candidate;
      60              : 
      61              : /* Copy pairs seen during the reverse scan (from optimized extensions).
      62              :    Used to propagate chain info transitively.  */
      63              : struct copy_info {
      64              :   unsigned int dest_regno;
      65              :   unsigned int src_regno;
      66              : };
      67              : static vec<copy_info> promotion_copies;
      68              : 
      69              : /* We consider four bit groups for liveness:
      70              :    bit 0..7   (least significant byte)
      71              :    bit 8..15  (second least significant byte)
      72              :    bit 16..31
      73              :    bit 32..BITS_PER_WORD-1  */
      74              : 
      75              : /* For the given REG, return the number of bit groups implied by the
      76              :    size of the REG's mode, up to a maximum of 4 (number of bit groups
      77              :    tracked by this pass).
      78              : 
      79              :    For partial integer and variable sized modes also return 4.  This
      80              :    could possibly be refined for something like PSI mode, but it
      81              :    does not seem worth the effort.  */
      82              : 
      83              : static int
      84    239792236 : group_limit (const_rtx reg)
      85              : {
      86    239792236 :   machine_mode mode = GET_MODE (reg);
      87              : 
      88    239792236 :   if (!GET_MODE_BITSIZE (mode).is_constant ())
      89              :     return 4;
      90              : 
      91    239792236 :   int size = GET_MODE_SIZE (mode).to_constant ();
      92              : 
      93    239792236 :   size = exact_log2 (size);
      94              : 
      95    239697873 :   if (size < 0)
      96              :     return 4;
      97              : 
      98    239697873 :   size++;
      99    239697873 :   return (size > 4 ? 4 : size);
     100              : }
     101              : 
     102              : /* Make all bit groups live for REGNO in bitmap BMAP.  For hard regs,
     103              :    we assume all groups are live.  For a pseudo we consider the size
     104              :    of the pseudo to avoid creating unnecessarily live chunks of data.  */
     105              : 
     106              : static void
     107      4810232 : make_reg_live (bitmap bmap, int regno)
     108              : {
     109      4810232 :   int limit;
     110              : 
     111              :   /* For pseudos we can use the mode to limit how many bit groups
     112              :      are marked as live since a pseudo only has one mode.  Hard
     113              :      registers have to be handled more conservatively.  */
     114      4810232 :   if (regno > FIRST_PSEUDO_REGISTER)
     115              :     {
     116       915977 :       rtx reg = regno_reg_rtx[regno];
     117       915977 :       limit = group_limit (reg);
     118              :     }
     119              :   else
     120              :     limit = 4;
     121              : 
     122     23717912 :   for (int i = 0; i < limit; i++)
     123     18907680 :     bitmap_set_bit (bmap, regno * 4 + i);
     124      4810232 : }
     125              : 
     126              : /* Note this pass could be used to narrow memory loads too.  It's
     127              :    not clear if that's profitable or not in general.  */
     128              : 
     129              : #define UNSPEC_P(X) (GET_CODE (X) == UNSPEC || GET_CODE (X) == UNSPEC_VOLATILE)
     130              : 
     131              : /* If we know the destination of CODE only uses some low bits
     132              :    (say just the QI bits of an SI operation), then return true
     133              :    if we can propagate the need for just the subset of bits
     134              :    from the destination to the sources.
     135              : 
     136              :    FIXME: This is safe for operands 1 and 2 of an IF_THEN_ELSE, but not
     137              :    operand 0.  Thus is likely would need some special casing to handle.  */
     138              : 
     139              : static bool
     140    145724946 : safe_for_live_propagation (rtx_code code)
     141              : {
     142              :   /* First handle rtx classes which as a whole are known to
     143              :      be either safe or unsafe.  */
     144    145724946 :   switch (GET_RTX_CLASS (code))
     145              :     {
     146              :       case RTX_OBJ:
     147              :       case RTX_CONST_OBJ:
     148              :         return true;
     149              : 
     150              :       case RTX_COMPARE:
     151              :       case RTX_COMM_COMPARE:
     152              :       case RTX_TERNARY:
     153              :         return false;
     154              : 
     155     75312072 :       default:
     156     75312072 :         break;
     157              :     }
     158              : 
     159              :   /* What's left are specific codes.  We only need to identify those
     160              :      which are safe.   */
     161     75312072 :   switch (code)
     162              :     {
     163              :     /* These are trivially safe.  */
     164              :     case SUBREG:
     165              :     case NOT:
     166              :     case ZERO_EXTEND:
     167              :     case SIGN_EXTEND:
     168              :     case TRUNCATE:
     169              :     case PLUS:
     170              :     case MINUS:
     171              :     case MULT:
     172              :     case SMUL_HIGHPART:
     173              :     case UMUL_HIGHPART:
     174              :     case AND:
     175              :     case IOR:
     176              :     case XOR:
     177              :       return true;
     178              : 
     179              :     /* We can propagate for the shifted operand, but not the shift
     180              :        count.  The count is handled specially.  */
     181              :     case ASHIFT:
     182              :     case LSHIFTRT:
     183              :     case ASHIFTRT:
     184              :     case SS_ASHIFT:
     185              :     case US_ASHIFT:
     186              :       return true;
     187              : 
     188              :     /* There may be other safe codes.  If so they can be added
     189              :        individually when discovered.  */
     190              :     default:
     191              :       return false;
     192              :     }
     193              : }
     194              : 
     195              : /* Clear bits in LIVENOW and set bits in LIVE_TMP for objects
     196              :    set/clobbered by OBJ contained in INSN.
     197              : 
     198              :    Conceptually it is always safe to ignore a particular destination
     199              :    here as that will result in more chunks of data being considered
     200              :    live.  That's what happens when we "continue" the main loop when
     201              :    we see something we don't know how to handle such as a vector
     202              :    mode destination.
     203              : 
     204              :    The more accurate we are in identifying what objects (and chunks
     205              :    within an object) are set by INSN, the more aggressive the
     206              :    optimization phase during use handling will be.  */
     207              : 
     208              : static bool
     209    140964819 : ext_dce_process_sets (rtx_insn *insn, rtx obj, bitmap live_tmp)
     210              : {
     211    140964819 :   bool skipped_dest = false;
     212              : 
     213    140964819 :   subrtx_iterator::array_type array;
     214    404229610 :   FOR_EACH_SUBRTX (iter, array, obj, NONCONST)
     215              :     {
     216    263264791 :       const_rtx x = *iter;
     217              : 
     218              :       /* An EXPR_LIST (from call fusage) ends in NULL_RTX.  */
     219    263264791 :       if (x == NULL_RTX)
     220      9773325 :         continue;
     221              : 
     222    253491466 :       if (UNSPEC_P (x))
     223       570787 :         continue;
     224              : 
     225    252920679 :       if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
     226              :         {
     227    145748718 :           unsigned bit = 0;
     228    145748718 :           x = SET_DEST (x);
     229              : 
     230              :           /* We don't support vector destinations or destinations
     231              :              wider than DImode.  */
     232    145748718 :           scalar_mode outer_mode;
     233    148955251 :           if (!is_a <scalar_mode> (GET_MODE (x), &outer_mode)
     234     92229418 :               || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
     235              :             {
     236              :               /* Skip the subrtxs of this destination.  There is
     237              :                  little value in iterating into the subobjects, so
     238              :                  just skip them for a bit of efficiency.  */
     239     56725833 :               skipped_dest = true;
     240     56725833 :               iter.skip_subrtxes ();
     241    263264791 :               continue;
     242              :             }
     243              : 
     244              :           /* We could have (strict_low_part (subreg ...)).  We can not just
     245              :              strip the STRICT_LOW_PART as that would result in clearing
     246              :              some bits in LIVENOW that are still live.  So process the
     247              :              STRICT_LOW_PART specially.  */
     248     89022885 :           if (GET_CODE (x) == STRICT_LOW_PART)
     249              :             {
     250            0 :               x = XEXP (x, 0);
     251              : 
     252              :               /* The only valid operand of a STRICT_LOW_PART is a non
     253              :                  paradoxical SUBREG.  */
     254            0 :               gcc_assert (SUBREG_P (x)
     255              :                           && !paradoxical_subreg_p (x)
     256              :                           && SUBREG_BYTE (x).is_constant ());
     257              : 
     258              :               /* I think we should always see a REG here.  But let's
     259              :                  be sure.  */
     260            0 :               gcc_assert (REG_P (SUBREG_REG (x)));
     261              : 
     262              :               /* The inner mode might be larger, just punt for
     263              :                  that case.  Remember, we can not just continue to process
     264              :                  the inner RTXs due to the STRICT_LOW_PART.  */
     265            0 :               if (!is_a <scalar_mode> (GET_MODE (SUBREG_REG (x)), &outer_mode)
     266            0 :                   || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
     267              :                 {
     268              :                   /* Skip the subrtxs of the STRICT_LOW_PART.  We can't
     269              :                      process them because it'll set objects as no longer
     270              :                      live when they are in fact still live.  */
     271            0 :                   skipped_dest = true;
     272            0 :                   iter.skip_subrtxes ();
     273            0 :                   continue;
     274              :                 }
     275              : 
     276              :               /* LIVE_TMP contains the set groups that are live-out and set in
     277              :                  this insn.  It is used to narrow the groups live-in for the
     278              :                  inputs of this insn.
     279              : 
     280              :                  The simple thing to do is mark all the groups as live, but
     281              :                  that will significantly inhibit optimization.
     282              : 
     283              :                  We also need to be careful in the case where we have an in-out
     284              :                  operand.  If we're not careful we'd clear LIVE_TMP
     285              :                  incorrectly.  */
     286            0 :               HOST_WIDE_INT rn = REGNO (SUBREG_REG (x));
     287            0 :               int limit = group_limit (SUBREG_REG (x));
     288            0 :               for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
     289            0 :                 if (bitmap_bit_p (livenow, i))
     290            0 :                   bitmap_set_bit (live_tmp, i);
     291              : 
     292            0 :               if (bitmap_empty_p (live_tmp))
     293            0 :                 make_reg_live (live_tmp, rn);
     294              : 
     295              :               /* The mode of the SUBREG tells us how many bits we can
     296              :                  clear.  */
     297            0 :               machine_mode mode = GET_MODE (x);
     298            0 :               HOST_WIDE_INT size
     299            0 :                 = exact_log2 (GET_MODE_SIZE (mode).to_constant ()) + 1;
     300            0 :               bitmap_clear_range (livenow, 4 * rn, size);
     301              : 
     302              :               /* We have fully processed this destination.  */
     303            0 :               iter.skip_subrtxes ();
     304            0 :               continue;
     305            0 :             }
     306              : 
     307              :           /* Phase one of destination handling.  First remove any wrapper
     308              :              such as SUBREG or ZERO_EXTRACT.  */
     309     89022885 :           unsigned HOST_WIDE_INT mask
     310     89022885 :             = GET_MODE_MASK (GET_MODE_INNER (GET_MODE (x)));
     311     89022885 :           if (SUBREG_P (x))
     312              :             {
     313              :               /* If we have a SUBREG destination that is too wide, just
     314              :                  skip the destination rather than continuing this iterator.
     315              :                  While continuing would be better, we'd need to strip the
     316              :                  subreg and restart within the SET processing rather than
     317              :                  the top of the loop which just complicates the flow even
     318              :                  more.  */
     319       587107 :               if (!is_a <scalar_mode> (GET_MODE (SUBREG_REG (x)), &outer_mode)
     320       587107 :                   || GET_MODE_BITSIZE (outer_mode) > HOST_BITS_PER_WIDE_INT)
     321              :                 {
     322       141556 :                   skipped_dest = true;
     323       141556 :                   iter.skip_subrtxes ();
     324       141556 :                   continue;
     325              :                 }
     326              : 
     327              :               /* We can safely strip a paradoxical subreg.  The inner mode will
     328              :                  be narrower than the outer mode.  We'll clear fewer bits in
     329              :                  LIVENOW than we'd like, but that's always safe.  */
     330       445551 :               if (paradoxical_subreg_p (x))
     331              :                 x = XEXP (x, 0);
     332       435210 :               else if (SUBREG_BYTE (x).is_constant ())
     333              :                 {
     334       435210 :                   bit = subreg_lsb (x).to_constant ();
     335       435210 :                   mask = GET_MODE_MASK (GET_MODE (SUBREG_REG (x))) << bit;
     336       435210 :                   gcc_assert (mask);
     337              :                   x = SUBREG_REG (x);
     338              :                 }
     339              :               else
     340              :                 gcc_unreachable ();
     341              :             }
     342              : 
     343     88881329 :           if (GET_CODE (x) == ZERO_EXTRACT)
     344              :             {
     345              :               /* Unlike a SUBREG destination, a set of a ZERO_EXTRACT only
     346              :                  modifies the bits referenced in the ZERO_EXTRACT, the rest
     347              :                  remain the same.  Thus we can not continue here, we must
     348              :                  either figure out what part of the destination is modified
     349              :                  or skip the sub-rtxs.  */
     350         3604 :               skipped_dest = true;
     351         3604 :               iter.skip_subrtxes ();
     352         3604 :               continue;
     353              :             }
     354              : 
     355              :           /* BIT >= 64 indicates something went horribly wrong.  */
     356     88877725 :           gcc_assert (bit <= HOST_BITS_PER_WIDE_INT - 1);
     357              : 
     358              :           /* Now handle the actual object that was changed.  */
     359     88877725 :           if (REG_P (x))
     360              :             {
     361              :               /* LIVE_TMP contains the set groups that are live-out and set in
     362              :                  this insn.  It is used to narrow the groups live-in for the
     363              :                  inputs of this insn.
     364              : 
     365              :                  The simple thing to do is mark all the groups as live, but
     366              :                  that will significantly inhibit optimization.
     367              : 
     368              :                  We also need to be careful in the case where we have an in-out
     369              :                  operand.  If we're not careful we'd clear LIVE_TMP
     370              :                  incorrectly.  */
     371     74611478 :               HOST_WIDE_INT rn = REGNO (x);
     372     74611478 :               int limit = group_limit (x);
     373    333834851 :               for (HOST_WIDE_INT i = 4 * rn; i < 4 * rn + limit; i++)
     374    259223373 :                 if (bitmap_bit_p (livenow, i))
     375    251571595 :                   bitmap_set_bit (live_tmp, i);
     376              : 
     377     74611478 :               if (bitmap_empty_p (live_tmp))
     378      1277705 :                 make_reg_live (live_tmp, rn);
     379              : 
     380              :               /* Now clear the bits known written by this instruction.
     381              :                  Note that BIT need not be a power of two, consider a
     382              :                  ZERO_EXTRACT destination.  */
     383     74611478 :               int start = (bit < 8 ? 0 : bit < 16 ? 1 : bit < 32 ? 2 : 3);
     384     79638764 :               int end = ((mask & ~HOST_WIDE_INT_UC (0xffffffff)) ? 4
     385     28322258 :                          : (mask & HOST_WIDE_INT_UC (0xffff0000)) ? 3
     386      5858195 :                          : (mask & 0xff00) ? 2 : 1);
     387     74611478 :               bitmap_clear_range (livenow, 4 * rn + start, end - start);
     388              :             }
     389              :           /* Some ports generate (clobber (const_int)).  */
     390     14266247 :           else if (CONST_INT_P (x))
     391            0 :             continue;
     392              :           else
     393     14266247 :             gcc_assert (CALL_P (insn)
     394              :                         || MEM_P (x)
     395              :                         || x == pc_rtx
     396              :                         || GET_CODE (x) == SCRATCH);
     397              : 
     398     88877725 :           iter.skip_subrtxes ();
     399     88877725 :         }
     400    107171961 :       else if (GET_CODE (x) == COND_EXEC)
     401              :         {
     402              :           /* This isn't ideal, but may not be so bad in practice.  */
     403            0 :           skipped_dest = true;
     404            0 :           iter.skip_subrtxes ();
     405              :         }
     406              :     }
     407    140964819 :   return skipped_dest;
     408    140964819 : }
     409              : 
     410              : /* INSN is a right shift and the second insn in a shift pair that is a
     411              :    sign or zero extension (SET is the single set associated with INSN).  
     412              : 
     413              :    Replace the source of SET with NEW_SRC which is a source register
     414              :    from NEW_SRC_INSN (the left shift in the pair).  This is effectively
     415              :    the same as the replacement we do for ZERO/SIGN extends on targets
     416              :    that support those insns.  */
     417              : static void
     418            0 : ext_dce_try_optimize_rshift (rtx_insn *insn, rtx set, rtx new_src, rtx_insn *new_src_insn)
     419              : {
     420              :   /* If the modes are not the same or one is a hard register, then
     421              :      conservatively do nothing.  */
     422            0 :   if (GET_MODE (SET_SRC (set)) != GET_MODE (new_src)
     423            0 :       || !REG_P (XEXP (SET_SRC (set), 0))
     424            0 :       || !REG_P (new_src)
     425            0 :       || REGNO (XEXP (SET_SRC (set), 0)) < FIRST_PSEUDO_REGISTER
     426            0 :       || REGNO (new_src) < FIRST_PSEUDO_REGISTER)
     427              :     return;
     428              : 
     429            0 :   if (dump_file)
     430              :     {
     431            0 :       fprintf (dump_file, "Processing insn:\n");
     432            0 :       dump_insn_slim (dump_file, insn);
     433            0 :       fprintf (dump_file, "Trying to simplify pattern:\n");
     434            0 :       print_rtl_single (dump_file, SET_SRC (set));
     435              :     }
     436              : 
     437              :   /* We decided to turn do the optimization but allow it to be rejected for
     438              :      bisection purposes.  */
     439            0 :   if (!dbg_cnt (::ext_dce))
     440              :     {
     441            0 :       if (dump_file)
     442            0 :         fprintf (dump_file, "Rejected due to debug counter.\n");
     443              :       return;
     444              :     }
     445              : 
     446              :   /* We're going to generate a fresh insn for the move, so put it
     447              :      into a sequence that we can emit after the current insn.   */
     448            0 :   start_sequence ();
     449            0 :   emit_move_insn (SET_DEST (set), new_src);
     450            0 :   rtx_insn *seq = end_sequence (); 
     451            0 :   emit_insn_after (seq, insn);
     452              : 
     453              :   /* Mark the destination as changed.  */
     454            0 :   rtx x = SET_DEST (set);
     455            0 :   while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
     456            0 :     x = XEXP (x, 0);
     457            0 :   gcc_assert (REG_P (x));
     458            0 :   bitmap_set_bit (changed_pseudos, REGNO (x));
     459              : 
     460            0 :   if (dump_file)
     461              :     {
     462            0 :       fprintf (dump_file, "Successfully transformed to:\n");
     463            0 :       print_rtl_single (dump_file, PATTERN (seq));
     464            0 :       fprintf (dump_file, "\n");
     465              :     }
     466              : 
     467            0 :   delete_insn (insn);
     468              : 
     469              :   /* If NEW_SRC died in its prior location, then we need to remove the
     470              :      death note and move it to the new location.  */
     471            0 :   rtx note = find_regno_note (new_src_insn, REG_DEAD, REGNO (new_src));
     472            0 :   if (note)
     473              :     {
     474            0 :       remove_note (new_src_insn, note);
     475            0 :       add_reg_note (insn, REG_DEAD, new_src);
     476              :     }
     477              : }
     478              : 
     479              : 
     480              : /* INSN has a sign/zero extended source inside SET that we will
     481              :    try to turn into a SUBREG.  If NEW_SRC is non-null, use that
     482              :    for the new source of INSN's set.  That scenario only happens
     483              :    when we're optimizing a shift pair.  */
     484              : static void
     485         8885 : ext_dce_try_optimize_extension (rtx_insn *insn, rtx set)
     486              : {
     487         8885 :   rtx src = SET_SRC (set);
     488         8885 :   rtx inner = XEXP (src, 0);
     489              : 
     490              :   /* For sign-extending loads from memory, try to replace with a
     491              :      zero-extending load when the upper bits are dead.  E.g. on RISC-V
     492              :      this turns lh+zext.h into just lhu.  */
     493         8885 :   if (MEM_P (inner) && GET_CODE (src) == SIGN_EXTEND)
     494              :     {
     495           36 :       if (dump_file)
     496              :         {
     497            0 :           fprintf (dump_file, "Processing insn:\n");
     498            0 :           dump_insn_slim (dump_file, insn);
     499            0 :           fprintf (dump_file, "Trying to narrow sign_extend to zero_extend:\n");
     500            0 :           print_rtl_single (dump_file, SET_SRC (set));
     501              :         }
     502              : 
     503           36 :       if (!dbg_cnt (::ext_dce))
     504              :         {
     505            0 :           if (dump_file)
     506            0 :             fprintf (dump_file, "Rejected due to debug counter.\n");
     507              :           return;
     508              :         }
     509              : 
     510           36 :       rtx new_pattern = gen_rtx_ZERO_EXTEND (GET_MODE (src), inner);
     511           36 :       int ok = validate_change (insn, &SET_SRC (set), new_pattern, false);
     512              : 
     513           36 :       rtx x = SET_DEST (set);
     514           36 :       while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
     515            0 :         x = XEXP (x, 0);
     516              : 
     517           36 :       gcc_assert (REG_P (x));
     518           36 :       if (ok)
     519              :         {
     520           36 :           bitmap_set_bit (changed_pseudos, REGNO (x));
     521           36 :           remove_reg_equal_equiv_notes (insn, false);
     522              :         }
     523              : 
     524           36 :       if (dump_file)
     525              :         {
     526            0 :           if (ok)
     527            0 :             fprintf (dump_file, "Successfully transformed to:\n");
     528              :           else
     529            0 :             fprintf (dump_file, "Failed transformation to:\n");
     530            0 :           print_rtl_single (dump_file, new_pattern);
     531            0 :           fprintf (dump_file, "\n");
     532              :         }
     533              :       return;
     534              :     }
     535              : 
     536              :   /* Avoid (subreg (mem)) and other constructs which may be valid RTL, but
     537              :      not useful for this optimization.  */
     538         8849 :   if (!(REG_P (inner) || (SUBREG_P (inner) && REG_P (SUBREG_REG (inner)))))
     539              :     return;
     540              : 
     541         5980 :   rtx new_pattern;
     542         5980 :   if (dump_file)
     543              :     {
     544            0 :       fprintf (dump_file, "Processing insn:\n");
     545            0 :       dump_insn_slim (dump_file, insn);
     546            0 :       fprintf (dump_file, "Trying to simplify pattern:\n");
     547            0 :       print_rtl_single (dump_file, SET_SRC (set));
     548              :     }
     549              : 
     550              :   /* We decided to turn do the optimization but allow it to be rejected for
     551              :      bisection purposes.  */
     552         5980 :   if (!dbg_cnt (::ext_dce))
     553              :     {
     554            0 :       if (dump_file)
     555            0 :         fprintf (dump_file, "Rejected due to debug counter.\n");
     556              :       return;
     557              :     }
     558              : 
     559        11960 :   new_pattern = simplify_gen_subreg (GET_MODE (src), inner,
     560         5980 :                                      GET_MODE (inner), 0);
     561              :   /* simplify_gen_subreg may fail in which case NEW_PATTERN will be NULL.
     562              :      We must not pass that as a replacement pattern to validate_change.  */
     563         5980 :   if (new_pattern)
     564              :     {
     565         5980 :       int ok = validate_change (insn, &SET_SRC (set), new_pattern, false);
     566              : 
     567         5980 :       rtx x = SET_DEST (set);
     568         5980 :       while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
     569            0 :         x = XEXP (x, 0);
     570              : 
     571         5980 :       gcc_assert (REG_P (x));
     572         5980 :       if (ok)
     573         5980 :         bitmap_set_bit (changed_pseudos, REGNO (x));
     574              : 
     575         5980 :       if (dump_file)
     576              :         {
     577            0 :           if (ok)
     578            0 :             fprintf (dump_file, "Successfully transformed to:\n");
     579              :           else
     580            0 :             fprintf (dump_file, "Failed transformation to:\n");
     581              : 
     582            0 :           print_rtl_single (dump_file, new_pattern);
     583            0 :           fprintf (dump_file, "\n");
     584              :         }
     585              : 
     586              :       /* INSN may have a REG_EQUAL note indicating that the value was
     587              :          sign or zero extended.  That note is no longer valid since we've
     588              :          just removed the extension.  Just wipe the notes.  */
     589         5980 :       if (ok)
     590         5980 :         remove_reg_equal_equiv_notes (insn, false);
     591              :     }
     592              :   else
     593              :     {
     594            0 :       if (dump_file)
     595            0 :         fprintf (dump_file, "Unable to generate valid SUBREG expression.\n");
     596              :     }
     597              : }
     598              : 
     599              : /* Try to promote a narrow-mode operation wrapped in a sign/zero extension
     600              :    to the wider mode when the extended bits are dead.  For example,
     601              :    (sign_extend:DI (plus:SI (x) (y))) -> (plus:DI (x') (y'))
     602              :    where x' and y' are the operands promoted to DI mode.
     603              : 
     604              :    This enables the combine pass to match wider-mode target patterns
     605              :    (e.g., sh2add on RISC-V) that cannot match the narrow-mode operation.  */
     606              : 
     607              : static void
     608            0 : ext_dce_try_promote_operation (rtx_insn *insn, rtx set)
     609              : {
     610            0 :   rtx src = SET_SRC (set);
     611              : 
     612              :   /* If the extension was already optimized away, nothing to do.  */
     613            0 :   if (GET_CODE (src) != SIGN_EXTEND && GET_CODE (src) != ZERO_EXTEND)
     614            0 :     return;
     615              : 
     616            0 :   machine_mode outer_mode = GET_MODE (src);
     617            0 :   rtx inner = XEXP (src, 0);
     618              : 
     619              :   /* Only handle binary and unary arithmetic/logic operations.  */
     620            0 :   if (!BINARY_P (inner) && !UNARY_P (inner))
     621              :     return;
     622              : 
     623            0 :   rtx_code inner_code = GET_CODE (inner);
     624              : 
     625              :   /* Restrict to operations whose result in the low bits is identical
     626              :      regardless of input width (i.e., no high-bit dependencies).  */
     627            0 :   switch (inner_code)
     628              :     {
     629            0 :     case PLUS:
     630            0 :     case MINUS:
     631            0 :     case MULT:
     632            0 :     case NEG:
     633            0 :     case AND:
     634            0 :     case IOR:
     635            0 :     case XOR:
     636            0 :     case NOT:
     637            0 :     case ASHIFT:
     638            0 :       break;
     639              :     default:
     640              :       return;
     641              :     }
     642              : 
     643              :   /* Promote each operand to the outer mode.  */
     644            0 :   int nops = BINARY_P (inner) ? 2 : 1;
     645            0 :   rtx new_ops[2];
     646              : 
     647            0 :   for (int i = 0; i < nops; i++)
     648              :     {
     649            0 :       rtx op = XEXP (inner, i);
     650              : 
     651            0 :       if (CONST_INT_P (op))
     652            0 :         new_ops[i] = op;
     653            0 :       else if (REG_P (op))
     654              :         {
     655            0 :           new_ops[i] = simplify_gen_subreg (outer_mode, op,
     656            0 :                                             GET_MODE (op), 0);
     657            0 :           if (!new_ops[i])
     658              :             return;
     659              :         }
     660            0 :       else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
     661              :         {
     662              :           /* The inner register may already be in the target mode
     663              :              (e.g., subreg:SI (reg:DI ...) 0).  Extract it directly
     664              :              rather than creating a paradoxical subreg of a subreg,
     665              :              which simplify_gen_subreg rejects.  */
     666            0 :           rtx inner_reg = SUBREG_REG (op);
     667            0 :           if (GET_MODE (inner_reg) == outer_mode)
     668            0 :             new_ops[i] = inner_reg;
     669              :           else
     670              :             {
     671            0 :               new_ops[i] = simplify_gen_subreg (outer_mode, inner_reg,
     672              :                                                 GET_MODE (inner_reg), 0);
     673            0 :               if (!new_ops[i])
     674              :                 return;
     675              :             }
     676              :         }
     677              :       else
     678              :         return;
     679              :     }
     680              : 
     681              :   /* Build the promoted operation.  */
     682            0 :   rtx new_src;
     683            0 :   if (BINARY_P (inner))
     684            0 :     new_src = gen_rtx_fmt_ee (inner_code, outer_mode,
     685              :                               new_ops[0], new_ops[1]);
     686              :   else
     687            0 :     new_src = gen_rtx_fmt_e (inner_code, outer_mode, new_ops[0]);
     688              : 
     689            0 :   if (dump_file)
     690              :     {
     691            0 :       fprintf (dump_file, "Processing insn:\n");
     692            0 :       dump_insn_slim (dump_file, insn);
     693            0 :       fprintf (dump_file, "Trying to promote to wider mode:\n");
     694            0 :       print_rtl_single (dump_file, new_src);
     695              :     }
     696              : 
     697              :   /* We decided to try the promotion but allow it to be rejected for
     698              :      bisection purposes.  */
     699            0 :   if (!dbg_cnt (::ext_dce))
     700              :     {
     701            0 :       if (dump_file)
     702            0 :         fprintf (dump_file, "Rejected due to debug counter.\n");
     703              :       return;
     704              :     }
     705              : 
     706            0 :   int ok = validate_change (insn, &SET_SRC (set), new_src, false);
     707              : 
     708            0 :   rtx x = SET_DEST (set);
     709            0 :   while (SUBREG_P (x) || GET_CODE (x) == ZERO_EXTRACT)
     710            0 :     x = XEXP (x, 0);
     711              : 
     712            0 :   gcc_assert (REG_P (x));
     713            0 :   if (ok)
     714            0 :     bitmap_set_bit (changed_pseudos, REGNO (x));
     715              : 
     716            0 :   if (dump_file)
     717              :     {
     718            0 :       if (ok)
     719            0 :         fprintf (dump_file, "Successfully promoted to:\n");
     720              :       else
     721            0 :         fprintf (dump_file, "Failed promotion to:\n");
     722            0 :       print_rtl_single (dump_file, new_src);
     723            0 :       fprintf (dump_file, "\n");
     724              :     }
     725              : 
     726            0 :   if (ok)
     727            0 :     remove_reg_equal_equiv_notes (insn, false);
     728              : }
     729              : 
     730              : /* Record INSN as a promotion candidate if it passes the same validity
     731              :    checks as ext_dce_try_promote_operation.  We defer actual promotion
     732              :    until we can determine whether the candidate is part of a chain.  */
     733              : 
     734              : static void
     735         2905 : ext_dce_record_promotion_candidate (rtx_insn *insn, rtx set)
     736              : {
     737         2905 :   rtx src = SET_SRC (set);
     738              : 
     739         2905 :   if (GET_CODE (src) != SIGN_EXTEND && GET_CODE (src) != ZERO_EXTEND)
     740              :     return;
     741              : 
     742         2905 :   machine_mode outer_mode = GET_MODE (src);
     743         2905 :   rtx inner = XEXP (src, 0);
     744              : 
     745         2905 :   if (!BINARY_P (inner) && !UNARY_P (inner))
     746              :     return;
     747              : 
     748         1850 :   rtx_code inner_code = GET_CODE (inner);
     749              : 
     750         1850 :   switch (inner_code)
     751              :     {
     752            0 :     case PLUS:
     753            0 :     case MINUS:
     754            0 :     case MULT:
     755            0 :     case NEG:
     756            0 :     case AND:
     757            0 :     case IOR:
     758            0 :     case XOR:
     759            0 :     case NOT:
     760            0 :     case ASHIFT:
     761            0 :       break;
     762              :     default:
     763              :       return;
     764              :     }
     765              : 
     766              :   /* Dry-run: check that all operands can be promoted.  */
     767            0 :   int nops = BINARY_P (inner) ? 2 : 1;
     768            0 :   for (int i = 0; i < nops; i++)
     769              :     {
     770            0 :       rtx op = XEXP (inner, i);
     771            0 :       if (CONST_INT_P (op))
     772            0 :         continue;
     773            0 :       else if (REG_P (op))
     774              :         {
     775            0 :           if (!simplify_gen_subreg (outer_mode, op, GET_MODE (op), 0))
     776              :             return;
     777              :         }
     778            0 :       else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
     779              :         {
     780            0 :           rtx inner_reg = SUBREG_REG (op);
     781            0 :           if (GET_MODE (inner_reg) != outer_mode
     782            0 :               && !simplify_gen_subreg (outer_mode, inner_reg,
     783              :                                        GET_MODE (inner_reg), 0))
     784              :             return;
     785              :         }
     786              :       else
     787              :         return;
     788              :     }
     789              : 
     790              :   /* Find the destination register.  */
     791            0 :   rtx dest = SET_DEST (set);
     792            0 :   while (SUBREG_P (dest) || GET_CODE (dest) == ZERO_EXTRACT)
     793            0 :     dest = XEXP (dest, 0);
     794            0 :   if (!REG_P (dest))
     795              :     return;
     796            0 :   unsigned int dest_regno = REGNO (dest);
     797              : 
     798              :   /* Record the candidate.  */
     799            0 :   promotion_candidates.safe_push ({insn, set});
     800            0 :   bitmap_set_bit (promotable_dests, dest_regno);
     801              : 
     802              :   /* Mark register operands as consumed by a candidate.  */
     803            0 :   for (int i = 0; i < nops; i++)
     804              :     {
     805            0 :       rtx op = XEXP (inner, i);
     806            0 :       if (REG_P (op))
     807            0 :         bitmap_set_bit (consumed_by_candidate, REGNO (op));
     808            0 :       else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
     809            0 :         bitmap_set_bit (consumed_by_candidate, REGNO (SUBREG_REG (op)));
     810              :     }
     811              : }
     812              : 
     813              : /* Promote candidates that form chains: a candidate whose result feeds
     814              :    into another candidate's operand, or whose operand comes from another
     815              :    candidate's result.  Skip standalone (isolated) promotions.  */
     816              : 
     817              : static void
     818     10027489 : ext_dce_promote_chained_candidates (void)
     819              : {
     820              :   /* Propagate chain info through copies recorded during the reverse scan.
     821              :      Since copies are recorded in reverse order, iterate forward to propagate
     822              :      promotable_dests (which was set late in the scan) through copies that
     823              :      were seen earlier.  */
     824     10027489 :   unsigned cix;
     825     10027489 :   copy_info *cp;
     826     10033469 :   FOR_EACH_VEC_ELT (promotion_copies, cix, cp)
     827              :     {
     828         5980 :       if (bitmap_bit_p (promotable_dests, cp->src_regno))
     829            0 :         bitmap_set_bit (promotable_dests, cp->dest_regno);
     830         5980 :       if (bitmap_bit_p (consumed_by_candidate, cp->dest_regno))
     831            0 :         bitmap_set_bit (consumed_by_candidate, cp->src_regno);
     832              :     }
     833              : 
     834              :   unsigned ix;
     835              :   promotion_candidate_info *cand;
     836              : 
     837     10027489 :   FOR_EACH_VEC_ELT (promotion_candidates, ix, cand)
     838              :     {
     839              :       /* Find destination register.  */
     840            0 :       rtx dest = SET_DEST (cand->set);
     841            0 :       while (SUBREG_P (dest) || GET_CODE (dest) == ZERO_EXTRACT)
     842            0 :         dest = XEXP (dest, 0);
     843            0 :       unsigned int dest_regno = REGNO (dest);
     844              : 
     845              :       /* Check if this candidate's result feeds into another candidate.  */
     846            0 :       bool is_chained = bitmap_bit_p (consumed_by_candidate, dest_regno);
     847              : 
     848              :       /* Check if any operand comes from another candidate's result.  */
     849            0 :       if (!is_chained)
     850              :         {
     851            0 :           rtx inner = XEXP (SET_SRC (cand->set), 0);
     852            0 :           int nops = BINARY_P (inner) ? 2 : 1;
     853            0 :           for (int i = 0; i < nops && !is_chained; i++)
     854              :             {
     855            0 :               rtx op = XEXP (inner, i);
     856            0 :               if (REG_P (op))
     857            0 :                 is_chained = bitmap_bit_p (promotable_dests, REGNO (op));
     858            0 :               else if (SUBREG_P (op) && REG_P (SUBREG_REG (op)))
     859            0 :                 is_chained = bitmap_bit_p (promotable_dests,
     860            0 :                                            REGNO (SUBREG_REG (op)));
     861              :             }
     862              :         }
     863              : 
     864            0 :       if (is_chained)
     865            0 :         ext_dce_try_promote_operation (cand->insn, cand->set);
     866            0 :       else if (dump_file)
     867              :         {
     868            0 :           fprintf (dump_file, "Skipping standalone promotion for insn:\n");
     869            0 :           dump_insn_slim (dump_file, cand->insn);
     870            0 :           fprintf (dump_file, "\n");
     871              :         }
     872              :     }
     873              : 
     874     10027489 :   promotion_candidates.truncate (0);
     875     10027489 :   promotion_copies.truncate (0);
     876     10027489 :   bitmap_clear (promotable_dests);
     877     10027489 :   bitmap_clear (consumed_by_candidate);
     878     10027489 : }
     879              : 
     880              : /* Some operators imply that their second operand is fully live,
     881              :    regardless of how many bits in the output are live.  An example
     882              :    would be the shift count on a target without SHIFT_COUNT_TRUNCATED
     883              :    defined.
     884              : 
     885              :    Return TRUE if CODE is such an operator.  FALSE otherwise.  */
     886              : 
     887              : static bool
     888     78385162 : binop_implies_op2_fully_live (rtx_code code)
     889              : {
     890            0 :   switch (code)
     891              :     {
     892              :     case ASHIFT:
     893              :     case LSHIFTRT:
     894              :     case ASHIFTRT:
     895              :     case ROTATE:
     896              :     case ROTATERT:
     897              :     case SS_ASHIFT:
     898              :     case US_ASHIFT:
     899              :       return !SHIFT_COUNT_TRUNCATED;
     900              : 
     901            0 :     default:
     902            0 :       return false;
     903              :     }
     904              : }
     905              : 
     906              : /* X, with code CODE, is an operation for which safe_for_live_propagation
     907              :    holds true, and bits set in MASK are live in the result.  Compute a
     908              :    mask of (potentially) live bits in the non-constant inputs.  In case of
     909              :    binop_implies_op2_fully_live (e.g. shifts), the computed mask may
     910              :    exclusively pertain to the first operand.
     911              : 
     912              :    This looks wrong as we may have some important operations embedded as
     913              :    operands of another operation.  For example, we might have an extension
     914              :    wrapping a shift.  It really feels like this needs to be recursing down
     915              :    into operands much more often.  */
     916              : 
     917              : unsigned HOST_WIDE_INT
     918     73127003 : carry_backpropagate (unsigned HOST_WIDE_INT mask, enum rtx_code code, rtx x)
     919              : {
     920     74824991 :   if (mask == 0)
     921              :     return 0;
     922              : 
     923              :   /* Consider a vector operation, the bits live are the element bits live
     924              :      broadcasted across the vector.  So there can be holes (consider a
     925              :      logical shift).
     926              : 
     927              :      Vector modes aren't likely to represent cases we can optimize with
     928              :      any regularity.  It seems sensible to just punt that case in a
     929              :      conservatively correct way.
     930              : 
     931              :      The conservatively corect choice here would be to return the mode
     932              :      mask for the outer mode.  We're already doing that for modes larger
     933              :      than HOST_BITS_PER_WIDE_INT, so it should be safe for larger vectors
     934              :      as well as something like V2HI.  */
     935     74824937 :   if (VECTOR_MODE_P (GET_MODE (x)) || COMPLEX_MODE_P (GET_MODE (x)))
     936      4050899 :     return GET_MODE_MASK (GET_MODE (x));
     937              :     
     938              : 
     939     70774038 :   enum machine_mode mode = GET_MODE (x);
     940     70774038 :   unsigned HOST_WIDE_INT mmask = GET_MODE_MASK (mode);
     941              : 
     942              :   /* While we don't try to optimize operations on types larger
     943              :      than 64 bits, we do want to make sure not to invoke undefined
     944              :      behavior when presented with such operations during use
     945              :      processing.  The safe thing to do is to just return mmask
     946              :      for that scenario indicating every possible chunk is life.  */
     947     70774038 :   scalar_int_mode smode;
     948     70774038 :   if (!is_a <scalar_int_mode> (mode, &smode)
     949     59043531 :       || GET_MODE_BITSIZE (smode) > HOST_BITS_PER_WIDE_INT)
     950              :     return mmask;
     951              : 
     952     58075678 :   switch (code)
     953              :     {
     954     16383102 :     case PLUS:
     955     16383102 :     case MINUS:
     956     16383102 :     case MULT:
     957     16383102 :       return (HOST_WIDE_INT_UC (2) << floor_log2 (mask)) - 1;
     958              : 
     959              :     /* We propagate for the shifted operand, but not the shift
     960              :        count.  The count is handled specially.  */
     961      1395542 :     case ASHIFT:
     962      1395542 :       if (CONST_INT_P (XEXP (x, 1))
     963      2719903 :           && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
     964      1324333 :         return (HOST_WIDE_INT) mask >> INTVAL (XEXP (x, 1));
     965        71209 :       return (HOST_WIDE_INT_UC (2) << floor_log2 (mask)) - 1;
     966              : 
     967              :     /* We propagate for the shifted operand, but not the shift
     968              :        count.  The count is handled specially.  */
     969       616209 :     case LSHIFTRT:
     970       616209 :       if (CONST_INT_P (XEXP (x, 1))
     971      1201929 :           && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
     972       585692 :         return mmask & (mask << INTVAL (XEXP (x, 1)));
     973              :       return mmask;
     974              : 
     975              :     /* We propagate for the shifted operand, but not the shift
     976              :        count.  The count is handled specially.  */
     977       308554 :     case ASHIFTRT:
     978       308554 :       if (CONST_INT_P (XEXP (x, 1))
     979       602430 :           && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
     980              :         {
     981       293876 :           HOST_WIDE_INT sign = 0;
     982       293876 :           if (HOST_BITS_PER_WIDE_INT - clz_hwi (mask) + INTVAL (XEXP (x, 1))
     983       293876 :               > GET_MODE_BITSIZE (smode))
     984       587752 :             sign = HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (smode) - 1);
     985       293876 :           return sign | (mmask & (mask << INTVAL (XEXP (x, 1))));
     986              :         }
     987              :       return mmask;
     988              : 
     989        43529 :     case SMUL_HIGHPART:
     990        43529 :     case UMUL_HIGHPART:
     991        43529 :       if (XEXP (x, 1) == const0_rtx)
     992              :         return 0;
     993        43529 :       if (XEXP (x, 1) == const1_rtx)
     994              :         return mmask;
     995        43529 :       if (CONST_INT_P (XEXP (x, 1)))
     996              :         {
     997            0 :           if (pow2p_hwi (INTVAL (XEXP (x, 1))))
     998            0 :             return mmask & (mask << (GET_MODE_BITSIZE (smode)
     999            0 :                                      - exact_log2 (INTVAL (XEXP (x, 1)))));
    1000              : 
    1001            0 :           int bits = (HOST_BITS_PER_WIDE_INT + GET_MODE_BITSIZE (smode)
    1002            0 :                       - clz_hwi (mask) - ctz_hwi (INTVAL (XEXP (x, 1))));
    1003            0 :           if (bits < GET_MODE_BITSIZE (smode))
    1004            0 :             return (HOST_WIDE_INT_1U << bits) - 1;
    1005              :         }
    1006              :       return mmask;
    1007              : 
    1008       574280 :     case SIGN_EXTEND:
    1009       574280 :       if (!GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
    1010       574280 :           || !GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))).is_constant ())
    1011              :         return -1;
    1012              : 
    1013              :       /* See note about vector modes near the start of this function.  */
    1014       574280 :       if (VECTOR_MODE_P (GET_MODE (XEXP (x, 0)))
    1015       574280 :           || COMPLEX_MODE_P (GET_MODE (XEXP (x, 0))))
    1016            0 :         return GET_MODE_MASK (GET_MODE (XEXP (x, 0)));
    1017              : 
    1018              :       /* We want the mode of the inner object.  We need to ensure its
    1019              :          sign bit is on in MASK.  */
    1020       574280 :       mode = GET_MODE_INNER (GET_MODE (XEXP (x, 0)));
    1021       574280 :       if (mask & ~GET_MODE_MASK (mode))
    1022       573755 :         mask |= HOST_WIDE_INT_1U << (GET_MODE_BITSIZE (mode).to_constant ()
    1023       573755 :                                      - 1);
    1024              : 
    1025              :       /* Recurse into the operand.  */
    1026       574280 :       return carry_backpropagate (mask, GET_CODE (XEXP (x, 0)), XEXP (x, 0));
    1027              : 
    1028      1123708 :     case ZERO_EXTEND:
    1029      1123708 :       if (!GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
    1030      1123708 :           || !GET_MODE_BITSIZE (GET_MODE (XEXP (x, 0))).is_constant ())
    1031              :         return -1;
    1032              : 
    1033              :       /* Recurse into the operand.  */
    1034      1123708 :       return carry_backpropagate (mask, GET_CODE (XEXP (x, 0)), XEXP (x, 0));
    1035              : 
    1036              :     /* If an AND/IOR unconditionally clears/sets bits in the output, then
    1037              :        we do not care about the liveness of those bits in the inputs.
    1038              : 
    1039              :        So AND MASK with the constant for AND and with the complemented constant
    1040              :        for IOR.  */
    1041      1343171 :     case AND:
    1042      1343171 :     case IOR:
    1043      1343171 :       if (CONST_INT_P (XEXP (x, 1)))
    1044       795240 :         mask &= (code == AND
    1045       795240 :                  ? UINTVAL (XEXP (x, 1))
    1046        96737 :                  : ~UINTVAL (XEXP (x, 1)));
    1047              :       return mask;
    1048              : 
    1049              :     /* We propagate for the shifted operand, but not the shift
    1050              :        count.  The count is handled specially.  */
    1051            0 :     case SS_ASHIFT:
    1052            0 :     case US_ASHIFT:
    1053            0 :       if (CONST_INT_P (XEXP (x, 1))
    1054            0 :           && UINTVAL (XEXP (x, 1)) < GET_MODE_BITSIZE (smode))
    1055              :         {
    1056            0 :           return ((mmask & ~((unsigned HOST_WIDE_INT) mmask
    1057            0 :                              >> (INTVAL (XEXP (x, 1))
    1058            0 :                                  + (XEXP (x, 1) != const0_rtx
    1059            0 :                                     && code == SS_ASHIFT))))
    1060            0 :                   | ((HOST_WIDE_INT) mask >> INTVAL (XEXP (x, 1))));
    1061              :         }
    1062              :       return mmask;
    1063              : 
    1064              :     default:
    1065              :       return mask;
    1066              :     }
    1067              : }
    1068              : 
    1069              : /* Process uses in INSN contained in OBJ.  Set appropriate bits in LIVENOW
    1070              :    for any chunks of pseudos that become live, potentially filtering using
    1071              :    bits from LIVE_TMP.
    1072              : 
    1073              :    If MODIFY is true, then optimize sign/zero extensions to SUBREGs when
    1074              :    the extended bits are never read and mark pseudos which had extensions
    1075              :    eliminated in CHANGED_PSEUDOS.  */
    1076              : 
    1077              : static void
    1078    140964819 : ext_dce_process_uses (rtx_insn *insn, rtx obj,
    1079              :                       bitmap live_tmp, bool skipped_dest)
    1080              : {
    1081    140964819 :   subrtx_var_iterator::array_type array_var;
    1082    771372583 :   FOR_EACH_SUBRTX_VAR (iter, array_var, obj, NONCONST)
    1083              :     {
    1084              :       /* An EXPR_LIST (from call fusage) ends in NULL_RTX.  */
    1085    630407764 :       rtx x = *iter;
    1086    630407764 :       if (x == NULL_RTX)
    1087      9773325 :         continue;
    1088              : 
    1089              :       /* So the basic idea in this FOR_EACH_SUBRTX_VAR loop is to
    1090              :          handle SETs explicitly, possibly propagating live information
    1091              :          into the uses.
    1092              : 
    1093              :          We may continue the loop at various points which will cause
    1094              :          iteration into the next level of RTL.  Breaking from the loop
    1095              :          is never safe as it can lead us to fail to process some of the
    1096              :          RTL and thus not make objects live when necessary.  */
    1097    620634439 :       enum rtx_code xcode = GET_CODE (x);
    1098    620634439 :       if (xcode == SET)
    1099              :         {
    1100    124623077 :           const_rtx dst = SET_DEST (x);
    1101    124623077 :           rtx src = SET_SRC (x);
    1102    124623077 :           const_rtx y;
    1103    124623077 :           unsigned HOST_WIDE_INT bit = 0;
    1104              : 
    1105              :           /* The code of the RHS of a SET.  */
    1106    124623077 :           enum rtx_code code = GET_CODE (src);
    1107              : 
    1108              :           /* ?!? How much of this should mirror SET handling, potentially
    1109              :              being shared?   */
    1110    124623077 :           if (SUBREG_P (dst) && subreg_lsb (dst).is_constant (&bit))
    1111              :             {
    1112       632305 :               if (bit >= HOST_BITS_PER_WIDE_INT)
    1113              :                 bit = HOST_BITS_PER_WIDE_INT - 1;
    1114       632305 :               dst = SUBREG_REG (dst);
    1115              :             }
    1116    123990772 :           else if (GET_CODE (dst) == STRICT_LOW_PART)
    1117        10540 :             dst = XEXP (dst, 0);
    1118              : 
    1119              :           /* Main processing of the uses.  Two major goals here.
    1120              : 
    1121              :              First, we want to try and propagate liveness (or the lack
    1122              :              thereof) from the destination register to the source
    1123              :              register(s).
    1124              : 
    1125              :              Second, if the source is an extension, try to optimize
    1126              :              it into a SUBREG.  The SUBREG form indicates we don't
    1127              :              care about the upper bits and will usually be copy
    1128              :              propagated away.
    1129              : 
    1130              :              If we fail to handle something in here, the expectation
    1131              :              is the iterator will dive into the sub-components and
    1132              :              mark all the chunks in any found REGs as live.  */
    1133    124623077 :           if (REG_P (dst) && safe_for_live_propagation (code))
    1134              :             {
    1135              :               /* Create a mask representing the bits of this output
    1136              :                  operand that are live after this insn.  We can use
    1137              :                  this information to refine the live in state of
    1138              :                  inputs to this insn in many cases.
    1139              : 
    1140              :                  We have to do this on a per SET basis, we might have
    1141              :                  an INSN with multiple SETS, some of which can narrow
    1142              :                  the source operand liveness, some of which may not.  */
    1143     73127003 :               unsigned HOST_WIDE_INT dst_mask = 0;
    1144     73127003 :               HOST_WIDE_INT rn = REGNO (dst);
    1145     73127003 :               unsigned HOST_WIDE_INT mask_array[]
    1146              :                 = { 0xff, 0xff00, HOST_WIDE_INT_UC (0xffff0000),
    1147              :                     -HOST_WIDE_INT_UC (0x100000000) };
    1148    365635015 :               for (int i = 0; i < 4; i++)
    1149    292508012 :                 if (bitmap_bit_p (live_tmp, 4 * rn + i))
    1150    234935178 :                   dst_mask |= mask_array[i];
    1151     73127003 :               dst_mask >>= bit;
    1152              : 
    1153              :               /* If we ignored a destination during set processing, then
    1154              :                  consider all the bits live.  */
    1155     73127003 :               if (skipped_dest)
    1156     25451576 :                 dst_mask = -1;
    1157              : 
    1158     73127003 :               dst_mask = carry_backpropagate (dst_mask, code, src);
    1159              : 
    1160              :               /* ??? Could also handle ZERO_EXTRACT / SIGN_EXTRACT
    1161              :                  of the source specially to improve optimization.  */
    1162     73127003 :               if (code == SIGN_EXTEND || code == ZERO_EXTEND)
    1163              :                 {
    1164      1725351 :                   rtx inner = XEXP (src, 0);
    1165      1725351 :                   unsigned HOST_WIDE_INT src_mask
    1166      1725351 :                     = GET_MODE_MASK (GET_MODE (inner));
    1167              : 
    1168              :                   /* DST_MASK could be zero if we had something in the SET
    1169              :                      that we couldn't handle.  */
    1170      1725351 :                   if (modify && !skipped_dest && (dst_mask & ~src_mask) == 0)
    1171              :                     {
    1172         8885 :                       ext_dce_try_optimize_extension (insn, x);
    1173              : 
    1174              :                       /* If the extension was optimized to a copy, propagate
    1175              :                          chain info through it: if the dest is consumed by a
    1176              :                          promotion candidate (seen later in reverse scan),
    1177              :                          the source register is transitively consumed too.  */
    1178         8885 :                       rtx opt_src = SET_SRC (x);
    1179         8885 :                       if (GET_CODE (opt_src) != SIGN_EXTEND
    1180         8885 :                           && GET_CODE (opt_src) != ZERO_EXTEND)
    1181              :                         {
    1182         5980 :                           rtx copy_dest = SET_DEST (x);
    1183         5980 :                           while (SUBREG_P (copy_dest)
    1184         5980 :                                  || GET_CODE (copy_dest) == ZERO_EXTRACT)
    1185            0 :                             copy_dest = XEXP (copy_dest, 0);
    1186              : 
    1187         5980 :                           rtx copy_src = opt_src;
    1188         5980 :                           if (SUBREG_P (copy_src))
    1189         5653 :                             copy_src = SUBREG_REG (copy_src);
    1190              : 
    1191         5980 :                           if (REG_P (copy_dest) && REG_P (copy_src))
    1192              :                             {
    1193         5980 :                               if (bitmap_bit_p (consumed_by_candidate,
    1194         5980 :                                                 REGNO (copy_dest)))
    1195            0 :                                 bitmap_set_bit (consumed_by_candidate,
    1196            0 :                                                 REGNO (copy_src));
    1197         5980 :                               if (bitmap_bit_p (promotable_dests,
    1198         5980 :                                                 REGNO (copy_src)))
    1199            0 :                                 bitmap_set_bit (promotable_dests,
    1200            0 :                                                 REGNO (copy_dest));
    1201         5980 :                               promotion_copies.safe_push (
    1202         5980 :                                 {REGNO (copy_dest), REGNO (copy_src)});
    1203              :                             }
    1204              :                         }
    1205              :                       else
    1206         2905 :                         ext_dce_record_promotion_candidate (insn, x);
    1207              :                     }
    1208              : 
    1209              :                   /* Stripping the extension here just seems wrong on multiple
    1210              :                      levels.  It's source side handling, so it seems like it
    1211              :                      belongs in the loop below.  Stripping here also makes it
    1212              :                      harder than necessary to properly handle live bit groups
    1213              :                      for (ANY_EXTEND (SUBREG)) where the SUBREG has
    1214              :                      SUBREG_PROMOTED state.  */
    1215      1725351 :                   dst_mask &= src_mask;
    1216      1725351 :                   src = XEXP (src, 0);
    1217      1725351 :                   code = GET_CODE (src);
    1218              :                 }
    1219              : 
    1220              :               /* Special case for (sub)targets that do not have extension
    1221              :                  insns (and thus use shifts).  We want to detect when we have
    1222              :                  a shift pair and treat the pair as-if was an extension.
    1223              : 
    1224              :                  Key on the right shift and use (for now) simplistic tests
    1225              :                  to find the corresponding left shift.  */
    1226     73127003 :               scalar_mode outer_mode;
    1227     73127003 :               if ((code == LSHIFTRT || code == ASHIFTRT)
    1228      1087246 :                   && CONST_INT_P (XEXP (src, 1))
    1229      1195267 :                   && (INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 8
    1230      1190953 :                       || INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 16
    1231      1024510 :                       || INTVAL (XEXP (src, 1)) == BITS_PER_WORD - 32)
    1232       127416 :                   && is_a <scalar_mode> (GET_MODE (src), &outer_mode)
    1233     74298944 :                   && GET_MODE_BITSIZE (outer_mode) <= HOST_BITS_PER_WIDE_INT)
    1234              :                 {
    1235              :                   /* So we have a right shift that could correspond to
    1236              :                      the second in a pair implementing QI, HI or SI -> DI
    1237              :                      extension.  See if we can find the left shift.  For
    1238              :                      now, just look one real instruction back.  */
    1239        84695 :                   rtx_insn *prev_insn = prev_nonnote_nondebug_insn_bb (insn);
    1240              : 
    1241              :                   /* The previous insn must be a left shift by the same
    1242              :                      amount.  */
    1243        84695 :                   rtx prev_set;
    1244        84695 :                   if (prev_insn
    1245        82150 :                       && (prev_set = single_set (prev_insn))
    1246              :                       /* The destination of the left shift must be the
    1247              :                          source of the right shift.  */
    1248        82071 :                       && SET_DEST (prev_set) == XEXP (src, 0)
    1249        45051 :                       && GET_CODE (SET_SRC (prev_set)) == ASHIFT
    1250          655 :                       && CONST_INT_P (XEXP (SET_SRC (prev_set), 1))
    1251              :                       /* The counts must match.  */
    1252        84695 :                       && (INTVAL (XEXP (src, 1))
    1253          641 :                           == INTVAL (XEXP (SET_SRC (prev_set), 1))))
    1254              :                     {
    1255           15 :                       unsigned HOST_WIDE_INT src_mask = GET_MODE_BITSIZE (GET_MODE (src)).to_constant ();
    1256           15 :                       src_mask -= INTVAL (XEXP (src, 1));
    1257           15 :                       src_mask = (HOST_WIDE_INT_1U << src_mask) - 1;
    1258              : 
    1259              :                       /* DST_MASK has been adjusted for INSN.  We need its original value.  */
    1260           15 :                       unsigned HOST_WIDE_INT tmp_mask = 0;
    1261           75 :                       for (int i = 0; i < 4; i++)
    1262           60 :                         if (bitmap_bit_p (live_tmp, 4 * rn + i))
    1263           15 :                           tmp_mask |= mask_array[i];
    1264           15 :                       tmp_mask >>= bit;
    1265              : 
    1266           15 :                       if (modify && !skipped_dest && (tmp_mask & ~src_mask) == 0)
    1267              :                         {
    1268            0 :                           ext_dce_try_optimize_rshift (insn, x, XEXP (SET_SRC (prev_set), 0), prev_insn);
    1269              : 
    1270              :                           /* These may not strictly be necessary, but we might as well try and be
    1271              :                              as accurate as possible.  The RHS is now a simple REG.  */
    1272            0 :                           dst_mask = src_mask;
    1273            0 :                           src = XEXP (SET_SRC (prev_set), 0);
    1274            0 :                           code = GET_CODE (src);
    1275              :                         }
    1276              :                     }
    1277              :                 }
    1278              : 
    1279              :               /* Optimization is done at this point.  We just want to make
    1280              :                  sure everything that should get marked as live is marked
    1281              :                  from here onward.  */
    1282              : 
    1283              :               /* We will handle the other operand of a binary operator
    1284              :                  at the bottom of the loop by resetting Y.  */
    1285     73127003 :               if (BINARY_P (src))
    1286     22820693 :                 y = XEXP (src, 0);
    1287              :               else
    1288              :                 y = src;
    1289              : 
    1290              :               /* We're inside a SET and want to process the source operands
    1291              :                  making things live.  Breaking from this loop will cause
    1292              :                  the iterator to work on sub-rtxs, so it is safe to break
    1293              :                  if we see something we don't know how to handle.
    1294              : 
    1295              :                  This code is just hokey as it really just handles trivial
    1296              :                  unary and binary cases.  Otherwise the loop exits and we
    1297              :                  continue iterating on sub-rtxs, but outside the set context.  */
    1298     73127003 :               unsigned HOST_WIDE_INT save_mask = dst_mask;
    1299    117750339 :               for (;;)
    1300              :                 {
    1301              :                   /* In general we want to restore DST_MASK before each loop
    1302              :                      iteration.  The exception is when the opcode implies that
    1303              :                      the other operand is fully live.  That's handled by
    1304              :                      changing SAVE_MASK below.  */
    1305     95438671 :                   dst_mask = save_mask;
    1306              :                   /* Strip an outer paradoxical subreg.  The bits outside
    1307              :                      the inner mode are don't cares.  So we can just strip
    1308              :                      and process the inner object.  */
    1309     95438671 :                   if (paradoxical_subreg_p (y))
    1310              :                     y = XEXP (y, 0);
    1311     95338723 :                   else if (SUBREG_P (y) && subreg_lsb (y).is_constant (&bit))
    1312              :                     {
    1313              :                       /* If !TRULY_NOOP_TRUNCATION_MODES_P, the mode
    1314              :                          change performed by Y would normally need to be a
    1315              :                          TRUNCATE rather than a SUBREG.  It is probably the
    1316              :                          guarantee provided by SUBREG_PROMOTED_VAR_P that
    1317              :                          allows the SUBREG in Y as an exception.  We must
    1318              :                          therefore preserve that guarantee and treat the
    1319              :                          upper bits of the inner register as live
    1320              :                          regardless of the outer code.  See PR 120050.  */
    1321      1981969 :                       if (!REG_P (SUBREG_REG (y))
    1322      1981969 :                           || (SUBREG_PROMOTED_VAR_P (y)
    1323        14138 :                               && (!TRULY_NOOP_TRUNCATION_MODES_P (
    1324              :                                     GET_MODE (y),
    1325              :                                     GET_MODE (SUBREG_REG (y))))))
    1326              :                         break;
    1327              : 
    1328              :                       /* If this is a wide object (more bits than we can fit
    1329              :                          in a HOST_WIDE_INT), then just break from the SET
    1330              :                          context.   That will cause the iterator to walk down
    1331              :                          into the subrtx and if we land on a REG we'll mark
    1332              :                          the whole think live.  */
    1333      1980953 :                       if (bit >= HOST_BITS_PER_WIDE_INT)
    1334              :                         break;
    1335              : 
    1336              :                       /* The SUBREG's mode determines the live width.  */
    1337      1769712 :                       if (dst_mask)
    1338              :                         {
    1339      1769540 :                           dst_mask <<= bit;
    1340      1769540 :                           if (!dst_mask)
    1341            0 :                             dst_mask = -HOST_WIDE_INT_UC (0x100000000);
    1342              :                         }
    1343      1769712 :                       y = SUBREG_REG (y);
    1344              :                     }
    1345              : 
    1346     95226414 :                   if (REG_P (y))
    1347              :                     {
    1348              :                       /* We have found the use of a register.  We need to mark
    1349              :                          the appropriate chunks of the register live.  The mode
    1350              :                          of the REG is a starting point.  We may refine that
    1351              :                          based on what chunks in the output were live.  */
    1352     50905826 :                       rn = 4 * REGNO (y);
    1353     50905826 :                       unsigned HOST_WIDE_INT tmp_mask = dst_mask;
    1354              : 
    1355              :                       /* If the RTX code for the SET_SRC is not one we can
    1356              :                          propagate destination liveness through, then just
    1357              :                          set the mask to the mode's mask.  */
    1358     50905826 :                       if (!safe_for_live_propagation (code))
    1359        34214 :                         tmp_mask = GET_MODE_MASK (GET_MODE (y));
    1360              : 
    1361     50905826 :                       if (tmp_mask & 0xff)
    1362     50437000 :                         bitmap_set_bit (livenow, rn);
    1363     50905826 :                       if (tmp_mask & 0xff00)
    1364     48571508 :                         bitmap_set_bit (livenow, rn + 1);
    1365     50905826 :                       if (tmp_mask & HOST_WIDE_INT_UC (0xffff0000))
    1366     48315824 :                         bitmap_set_bit (livenow, rn + 2);
    1367     50905826 :                       if (tmp_mask & -HOST_WIDE_INT_UC (0x100000000))
    1368     42146499 :                         bitmap_set_bit (livenow, rn + 3);
    1369              :                     }
    1370     44320588 :                   else if (!CONSTANT_P (y))
    1371              :                     break;
    1372              : 
    1373              :                   /* We might have (ashift (const_int 1) (reg...))
    1374              :                      By setting dst_mask we can continue iterating on the
    1375              :                      the next operand and it will be considered fully live.
    1376              : 
    1377              :                      Note that since we restore DST_MASK from SAVE_MASK at the
    1378              :                      top of the loop, we have to change SAVE_MASK to get the
    1379              :                      semantics we want.  */
    1380     78385162 :                   if (binop_implies_op2_fully_live (GET_CODE (src)))
    1381      2545975 :                     save_mask = -1;
    1382              : 
    1383              :                   /* If this was anything but a binary operand, break the inner
    1384              :                      loop.  This is conservatively correct as it will cause the
    1385              :                      iterator to look at the sub-rtxs outside the SET context.  */
    1386     78385162 :                   if (!BINARY_P (src))
    1387              :                     break;
    1388              : 
    1389              :                   /* We processed the first operand of a binary operator.  Now
    1390              :                      handle the second.  */
    1391     22311668 :                   y = XEXP (src, 1), src = pc_rtx;
    1392     22311668 :                 }
    1393              : 
    1394              :               /* These are leaf nodes, no need to iterate down into them.  */
    1395     73127003 :               if (REG_P (y) || CONSTANT_P (y))
    1396     56073494 :                 iter.skip_subrtxes ();
    1397              :             }
    1398              :         }
    1399              :       /* If we are reading the low part of a SUBREG, then we can
    1400              :          refine liveness of the input register, otherwise let the
    1401              :          iterator continue into SUBREG_REG.  */
    1402    496011362 :       else if (SUBREG_P (x)
    1403      1446074 :                && REG_P (SUBREG_REG (x))
    1404      1444238 :                && !paradoxical_subreg_p (x)
    1405      1416184 :                && subreg_lowpart_p (x)
    1406      1125348 :                && GET_MODE_BITSIZE (GET_MODE (x)).is_constant ()
    1407    498262058 :                && GET_MODE_BITSIZE (GET_MODE (x)).to_constant () <= 32)
    1408              :         {
    1409       564994 :           HOST_WIDE_INT size = GET_MODE_BITSIZE (GET_MODE (x)).to_constant ();
    1410       564994 :           HOST_WIDE_INT rn = 4 * REGNO (SUBREG_REG (x));
    1411              : 
    1412              :           /* If this is a promoted subreg, then more of it may be live than
    1413              :              is otherwise obvious.  */
    1414       564994 :           if (SUBREG_PROMOTED_VAR_P (x))
    1415         4688 :             size = GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))).to_constant ();
    1416              : 
    1417       564994 :           bitmap_set_bit (livenow, rn);
    1418       564994 :           if (size > 8)
    1419       390360 :             bitmap_set_bit (livenow, rn + 1);
    1420       390360 :           if (size > 16)
    1421       350165 :             bitmap_set_bit (livenow, rn + 2);
    1422       350165 :           if (size > 32)
    1423           74 :             bitmap_set_bit (livenow, rn + 3);
    1424       564994 :           iter.skip_subrtxes ();
    1425              :         }
    1426              :       /* If we have a register reference that is not otherwise handled,
    1427              :          just assume all the chunks are live.  */
    1428    495446368 :       else if (REG_P (x))
    1429    164264781 :         bitmap_set_range (livenow, REGNO (x) * 4, group_limit (x));
    1430              :     }
    1431    140964819 : }
    1432              : 
    1433              : /* Process a single basic block BB with current liveness information
    1434              :    in LIVENOW, returning updated liveness information.
    1435              : 
    1436              :    If MODIFY is true, then this is the last pass and unnecessary
    1437              :    extensions should be eliminated when possible.  If an extension
    1438              :    is removed, the source pseudo is marked in CHANGED_PSEUDOS.  */
    1439              : 
    1440              : static void
    1441     23453200 : ext_dce_process_bb (basic_block bb)
    1442              : {
    1443     23453200 :   rtx_insn *insn;
    1444              : 
    1445    318727550 :   FOR_BB_INSNS_REVERSE (bb, insn)
    1446              :     {
    1447    295274350 :       if (!NONDEBUG_INSN_P (insn))
    1448    164082856 :         continue;
    1449              : 
    1450              :       /* Live-out state of the destination of this insn.  We can
    1451              :          use this to refine the live-in state of the sources of
    1452              :          this insn in many cases.  */
    1453    131191494 :       bitmap live_tmp = BITMAP_ALLOC (NULL);
    1454              : 
    1455              :       /* First process any sets/clobbers in INSN.  */
    1456    131191494 :       bool skipped_dest = ext_dce_process_sets (insn, PATTERN (insn), live_tmp);
    1457              : 
    1458              :       /* CALL_INSNs need processing their fusage data.  */
    1459    131191494 :       if (CALL_P (insn))
    1460      9773325 :         skipped_dest |= ext_dce_process_sets (insn,
    1461              :                                               CALL_INSN_FUNCTION_USAGE (insn),
    1462              :                                               live_tmp);
    1463              : 
    1464              :       /* And now uses, optimizing away SIGN/ZERO extensions as we go.  */
    1465    131191494 :       ext_dce_process_uses (insn, PATTERN (insn), live_tmp, skipped_dest);
    1466              : 
    1467              :       /* A nonlocal goto implicitly uses the frame pointer.  */
    1468    131191494 :       if (JUMP_P (insn) && find_reg_note (insn, REG_NON_LOCAL_GOTO, NULL_RTX))
    1469              :         {
    1470         1130 :           bitmap_set_range (livenow, FRAME_POINTER_REGNUM * 4, 4);
    1471         1130 :           if (!HARD_FRAME_POINTER_IS_FRAME_POINTER)
    1472         1130 :             bitmap_set_range (livenow, HARD_FRAME_POINTER_REGNUM * 4, 4);
    1473              :         }
    1474              : 
    1475              :       /* And process fusage data for the use as well.  */
    1476    131191494 :       if (CALL_P (insn))
    1477              :         {
    1478      9773325 :           if (!FAKE_CALL_P (insn))
    1479      9773265 :             bitmap_set_range (livenow, STACK_POINTER_REGNUM * 4, 4);
    1480              : 
    1481              :           /* If this is not a call to a const function, then assume it
    1482              :              can read any global register.  */
    1483      9773325 :           if (!RTL_CONST_CALL_P (insn))
    1484    879908805 :             for (unsigned i = 0; i < FIRST_PSEUDO_REGISTER; i++)
    1485    870447420 :               if (global_regs[i])
    1486          230 :                 bitmap_set_range (livenow, i * 4, 4);
    1487              : 
    1488      9773325 :           ext_dce_process_uses (insn, CALL_INSN_FUNCTION_USAGE (insn), live_tmp, false);
    1489              :         }
    1490              : 
    1491    131191494 :       BITMAP_FREE (live_tmp);
    1492              :     }
    1493              : 
    1494     23453200 :   if (modify)
    1495     10027489 :     ext_dce_promote_chained_candidates ();
    1496     23453200 : }
    1497              : 
    1498              : /* SUBREG_PROMOTED_VAR_P is set by the gimple->rtl optimizers and
    1499              :    is usually helpful.  However, in some cases setting the value when
    1500              :    it not strictly needed can cause this pass to miss optimizations.
    1501              : 
    1502              :    Specifically consider (set (mem) (subreg (reg))).  If set in that
    1503              :    case it will cause more bit groups to be live for REG than would
    1504              :    be strictly necessary which in turn can inhibit extension removal.
    1505              : 
    1506              :    So do a pass over the IL wiping the SUBREG_PROMOTED_VAR_P when it
    1507              :    is obviously not needed.  */
    1508              : 
    1509              : static void
    1510       981310 : maybe_clear_subreg_promoted_p (void)
    1511              : {
    1512    126568188 :   for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
    1513              :     {
    1514    125586878 :       if (!NONDEBUG_INSN_P (insn))
    1515     69369421 :         continue;
    1516              : 
    1517     56217457 :       rtx set = single_set (insn);
    1518     56217457 :       if (!set)
    1519      3760330 :         continue;
    1520              : 
    1521              :       /* There may be other cases where we should clear, but for
    1522              :          now, this is the only known case where it causes problems.  */
    1523     52457127 :       if (MEM_P (SET_DEST (set)) && SUBREG_P (SET_SRC (set))
    1524        86046 :         && GET_MODE (SET_DEST (set)) <= GET_MODE (SUBREG_REG (SET_SRC (set))))
    1525        75693 :         SUBREG_PROMOTED_VAR_P (SET_SRC (set)) = 0;
    1526              :     }
    1527       981310 : }
    1528              : 
    1529              : /* Walk the IL and build the transitive closure of all the REGs tied
    1530              :    together by copies where either the source or destination is
    1531              :    marked in CHANGED_PSEUDOS.  */
    1532              : 
    1533              : static void
    1534       981310 : expand_changed_pseudos (void)
    1535              : {
    1536              :   /* Build a vector of registers related by a copy.  This is meant to
    1537              :      speed up the next step by avoiding full IL walks.  */
    1538       981310 :   struct copy_pair { rtx first; rtx second; };
    1539       981310 :   auto_vec<copy_pair> pairs;
    1540    126568188 :   for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
    1541              :     {
    1542    125586878 :       if (!NONDEBUG_INSN_P (insn))
    1543     69369421 :         continue;
    1544              : 
    1545     56217457 :       rtx pat = PATTERN (insn);
    1546              : 
    1547              :       /* Simple copies to a REG from another REG or SUBREG of a REG.  */
    1548     56217457 :       if (GET_CODE (pat) == SET
    1549     44370579 :           && REG_P (SET_DEST (pat))
    1550     31669372 :           && (REG_P (SET_SRC (pat))
    1551     22871817 :               || (SUBREG_P (SET_SRC (pat))
    1552       398574 :                   && REG_P (SUBREG_REG (SET_SRC (pat))))))
    1553              :         {
    1554       398136 :           rtx src = (REG_P (SET_SRC (pat))
    1555      9195691 :                      ? SET_SRC (pat)
    1556              :                      : SUBREG_REG (SET_SRC (pat)));
    1557      9195691 :           pairs.safe_push ({ SET_DEST (pat), src });
    1558              :         }
    1559              : 
    1560              :       /* Simple copies to a REG from another REG or SUBREG of a REG
    1561              :          held inside a PARALLEL.  */
    1562     56217457 :       if (GET_CODE (pat) == PARALLEL)
    1563              :         {
    1564     25492322 :           for (int i = XVECLEN (pat, 0) - 1; i >= 0; i--)
    1565              :             {
    1566     17118532 :               rtx elem = XVECEXP (pat, 0, i);
    1567              : 
    1568     17118532 :               if (GET_CODE (elem) == SET
    1569      8618944 :                   && REG_P (SET_DEST (elem))
    1570      8458113 :                   && (REG_P (SET_SRC (elem))
    1571      8458113 :                       || (SUBREG_P (SET_SRC (elem))
    1572            0 :                           && REG_P (SUBREG_REG (SET_SRC (elem))))))
    1573              :                 {
    1574            0 :                   rtx src = (REG_P (SET_SRC (elem))
    1575            0 :                              ? SET_SRC (elem)
    1576              :                              : SUBREG_REG (SET_SRC (elem)));
    1577            0 :                   pairs.safe_push ({ SET_DEST (elem), src });
    1578              :                 }
    1579              :             }
    1580      8373790 :           continue;
    1581      8373790 :         }
    1582              :     }
    1583              : 
    1584              :   /* Now we have a vector with copy pairs.  Iterate over that list
    1585              :      updating CHANGED_PSEUDOS as we go.  Eliminate copies from the
    1586              :      list as we go as they don't need further processing.  */
    1587              :   bool changed = true;
    1588      1962723 :   while (changed)
    1589              :     {
    1590              :       changed = false;
    1591              :       unsigned int i;
    1592              :       copy_pair *p;
    1593     11159949 :       FOR_EACH_VEC_ELT (pairs, i, p)
    1594              :         {
    1595      9197226 :           if (bitmap_bit_p (changed_pseudos, REGNO (p->second))
    1596      9197226 :               && bitmap_set_bit (changed_pseudos, REGNO (p->first)))
    1597              :             {
    1598          114 :               pairs.unordered_remove (i);
    1599          114 :               changed = true;
    1600              :             }
    1601              :         }
    1602              :     }
    1603       981310 : }
    1604              : 
    1605              : /* We optimize away sign/zero extensions in this pass and replace
    1606              :    them with SUBREGs indicating certain bits are don't cares.
    1607              : 
    1608              :    This changes the SUBREG_PROMOTED_VAR_P state of the object.
    1609              :    It is fairly painful to fix this on the fly, so we have
    1610              :    recorded which pseudos are affected and we look for SUBREGs
    1611              :    of those pseudos and fix them up.  */
    1612              : 
    1613              : static void
    1614       981310 : reset_subreg_promoted_p (void)
    1615              : {
    1616              :   /* This pass eliminates zero/sign extensions on pseudo regs found
    1617              :      in CHANGED_PSEUDOS.  Elimination of those extensions changes if
    1618              :      the pseudos are known to hold values extended to wider modes
    1619              :      via SUBREG_PROMOTED_VAR.  So we wipe the SUBREG_PROMOTED_VAR
    1620              :      state on all affected pseudos.
    1621              : 
    1622              :      But that is insufficient.  We might have a copy from one REG
    1623              :      to another (possibly with the source register wrapped with a
    1624              :      SUBREG).  We need to wipe SUBREG_PROMOTED_VAR on the transitive
    1625              :      closure of the original CHANGED_PSEUDOS and registers they're
    1626              :      connected to via copies.  So expand the set.  */
    1627       981310 :   expand_changed_pseudos ();
    1628              :     
    1629              :   /* If we removed an extension, that changed the promoted state
    1630              :      of the destination of that extension.  Thus we need to go
    1631              :      find any SUBREGs that reference that pseudo and adjust their
    1632              :      SUBREG_PROMOTED_P state.  */
    1633    126568188 :   for (rtx_insn *insn = get_insns(); insn; insn = NEXT_INSN (insn))
    1634              :     {
    1635    125586878 :       if (!NONDEBUG_INSN_P (insn))
    1636     69369421 :         continue;
    1637              : 
    1638     56217457 :       rtx pat = PATTERN (insn);
    1639     56217457 :       subrtx_var_iterator::array_type array;
    1640    358510925 :       FOR_EACH_SUBRTX_VAR (iter, array, pat, NONCONST)
    1641              :         {
    1642    302293468 :           rtx sub = *iter;
    1643              : 
    1644              :           /* We only care about SUBREGs.  */
    1645    302293468 :           if (GET_CODE (sub) != SUBREG)
    1646    300656844 :             continue;
    1647              : 
    1648      1636624 :           const_rtx x = SUBREG_REG (sub);
    1649              : 
    1650              :           /* We only care if the inner object is a REG.  */
    1651      1636624 :           if (!REG_P (x))
    1652          772 :             continue;
    1653              : 
    1654              :           /* And only if the SUBREG is a promoted var.  */
    1655      1635852 :           if (!SUBREG_PROMOTED_VAR_P (sub))
    1656      1630103 :             continue;
    1657              : 
    1658         5749 :           if (bitmap_bit_p (changed_pseudos, REGNO (x)))
    1659            0 :             SUBREG_PROMOTED_VAR_P (sub) = 0;
    1660              :         }
    1661     56217457 :     }
    1662       981310 : }
    1663              : 
    1664              : /* Initialization of the ext-dce pass.  Primarily this means
    1665              :    setting up the various bitmaps we utilize.  */
    1666              : 
    1667              : static void
    1668       981310 : ext_dce_init (void)
    1669              : {
    1670       981310 :   livein.create (last_basic_block_for_fn (cfun));
    1671       981310 :   livein.quick_grow_cleared (last_basic_block_for_fn (cfun));
    1672     13961543 :   for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
    1673     11998923 :     bitmap_initialize (&livein[i], &bitmap_default_obstack);
    1674              : 
    1675       981310 :   auto_bitmap refs (&bitmap_default_obstack);
    1676       981310 :   df_get_exit_block_use_set (refs);
    1677              : 
    1678       981310 :   unsigned i;
    1679       981310 :   bitmap_iterator bi;
    1680      4513837 :   EXECUTE_IF_SET_IN_BITMAP (refs, 0, i, bi)
    1681      3532527 :     make_reg_live (&livein[EXIT_BLOCK], i);
    1682              : 
    1683       981310 :   livenow = BITMAP_ALLOC (NULL);
    1684       981310 :   all_blocks = BITMAP_ALLOC (NULL);
    1685       981310 :   changed_pseudos = BITMAP_ALLOC (NULL);
    1686       981310 :   promotable_dests = BITMAP_ALLOC (NULL);
    1687       981310 :   consumed_by_candidate = BITMAP_ALLOC (NULL);
    1688              : 
    1689     12980233 :   for (int i = 0; i < last_basic_block_for_fn (cfun); i++)
    1690     11998923 :     if (i != ENTRY_BLOCK && i != EXIT_BLOCK)
    1691     10036303 :       bitmap_set_bit (all_blocks, i);
    1692              : 
    1693       981310 :   modify = false;
    1694       981310 : }
    1695              : 
    1696              : /* Finalization of the ext-dce pass.  Primarily this means
    1697              :    releasing up the various bitmaps we utilize.  */
    1698              : 
    1699              : static void
    1700       981310 : ext_dce_finish (void)
    1701              : {
    1702     12980233 :   for (unsigned i = 0; i < livein.length (); i++)
    1703     11998923 :     bitmap_clear (&livein[i]);
    1704       981310 :   livein.release ();
    1705              : 
    1706       981310 :   BITMAP_FREE (livenow);
    1707       981310 :   BITMAP_FREE (changed_pseudos);
    1708       981310 :   BITMAP_FREE (all_blocks);
    1709       981310 :   BITMAP_FREE (promotable_dests);
    1710       981310 :   BITMAP_FREE (consumed_by_candidate);
    1711       981310 :   promotion_candidates.release ();
    1712       981310 :   promotion_copies.release ();
    1713       981310 : }
    1714              : 
    1715              : /* Process block number BB_INDEX as part of the backward
    1716              :    simple dataflow analysis.  Return TRUE if something in
    1717              :    this block changed or FALSE otherwise.  */
    1718              : 
    1719              : static bool
    1720     27378440 : ext_dce_rd_transfer_n (int bb_index)
    1721              : {
    1722              :   /* The ENTRY/EXIT blocks never change.  */
    1723     27378440 :   if (bb_index == ENTRY_BLOCK || bb_index == EXIT_BLOCK)
    1724              :     return false;
    1725              : 
    1726     23453200 :   basic_block bb = BASIC_BLOCK_FOR_FN (cfun, bb_index);
    1727              : 
    1728              :   /* Make everything live that's live in the successors.  */
    1729     23453200 :   bitmap_clear (livenow);
    1730     23453200 :   edge_iterator ei;
    1731     23453200 :   edge e;
    1732              : 
    1733     58957286 :   FOR_EACH_EDGE (e, ei, bb->succs)
    1734     35504086 :     bitmap_ior_into (livenow, &livein[e->dest->index]);
    1735              : 
    1736     23453200 :   ext_dce_process_bb (bb);
    1737              : 
    1738              :   /* We only allow widening the set of objects live at the start
    1739              :      of a block.  Otherwise we run the risk of not converging.  */
    1740     23453200 :   return bitmap_ior_into (&livein[bb_index], livenow);
    1741              : }
    1742              : 
    1743              : /* Dummy function for the df_simple_dataflow API.  */
    1744     34136899 : static bool ext_dce_rd_confluence_n (edge) { return true; }
    1745              : 
    1746              : /* Use lifetime analysis to identify extensions that set bits that
    1747              :    are never read.  Turn such extensions into SUBREGs instead which
    1748              :    can often be propagated away.  */
    1749              : 
    1750              : void
    1751       981310 : ext_dce_execute (void)
    1752              : {
    1753              :   /* Limit the amount of memory we use for livein, with 4 bits per
    1754              :      reg per basic-block including overhead that maps to one byte
    1755              :      per reg per basic-block.  */
    1756       981310 :   uint64_t memory_request
    1757       981310 :     = (uint64_t)n_basic_blocks_for_fn (cfun) * max_reg_num ();
    1758       981310 :   if (memory_request / 1024 > (uint64_t)param_max_gcse_memory)
    1759              :     {
    1760            0 :       warning (OPT_Wdisabled_optimization,
    1761              :                "ext-dce disabled: %d basic blocks and %d registers; "
    1762              :                "increase %<--param max-gcse-memory%> above %wu",
    1763            0 :                n_basic_blocks_for_fn (cfun), max_reg_num (),
    1764              :                memory_request / 1024);
    1765            0 :       return;
    1766              :     }
    1767              : 
    1768              :   /* Some settings of SUBREG_PROMOTED_VAR_P are actively harmful
    1769              :      to this pass.  Clear it for those cases.  */
    1770       981310 :   maybe_clear_subreg_promoted_p ();
    1771       981310 :   df_analyze ();
    1772       981310 :   ext_dce_init ();
    1773              : 
    1774      3925240 :   do
    1775              :     {
    1776      1962620 :       df_simple_dataflow (DF_BACKWARD, NULL, NULL,
    1777              :                           ext_dce_rd_confluence_n, ext_dce_rd_transfer_n,
    1778              :                           all_blocks, df_get_postorder (DF_BACKWARD),
    1779              :                           df_get_n_blocks (DF_BACKWARD));
    1780      1962620 :       modify = !modify;
    1781              :     }
    1782              :   while (modify);
    1783              : 
    1784       981310 :   reset_subreg_promoted_p ();
    1785              : 
    1786       981310 :   ext_dce_finish ();
    1787              : }
    1788              : 
    1789              : 
    1790              : namespace {
    1791              : 
    1792              : const pass_data pass_data_ext_dce =
    1793              : {
    1794              :   RTL_PASS, /* type */
    1795              :   "ext_dce", /* name */
    1796              :   OPTGROUP_NONE, /* optinfo_flags */
    1797              :   TV_EXT_DCE, /* tv_id */
    1798              :   PROP_cfglayout, /* properties_required */
    1799              :   0, /* properties_provided */
    1800              :   0, /* properties_destroyed */
    1801              :   0, /* todo_flags_start */
    1802              :   TODO_df_finish, /* todo_flags_finish */
    1803              : };
    1804              : 
    1805              : class pass_ext_dce : public rtl_opt_pass
    1806              : {
    1807              : public:
    1808       294196 :   pass_ext_dce (gcc::context *ctxt)
    1809       588392 :     : rtl_opt_pass (pass_data_ext_dce, ctxt)
    1810              :   {}
    1811              : 
    1812              :   /* opt_pass methods: */
    1813      1515129 :   virtual bool gate (function *) { return flag_ext_dce && optimize > 0; }
    1814       981310 :   virtual unsigned int execute (function *)
    1815              :     {
    1816       981310 :       ext_dce_execute ();
    1817       981310 :       return 0;
    1818              :     }
    1819              : 
    1820              : }; // class pass_combine
    1821              : 
    1822              : } // anon namespace
    1823              : 
    1824              : rtl_opt_pass *
    1825       294196 : make_pass_ext_dce (gcc::context *ctxt)
    1826              : {
    1827       294196 :   return new pass_ext_dce (ctxt);
    1828              : }
        

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.