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

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.