https://gcc.gnu.org/g:bf3037e923e9f91d93ab64bdf73a37f64f659fb9

commit r16-2051-gbf3037e923e9f91d93ab64bdf73a37f64f659fb9
Author: Richard Sandiford <richard.sandif...@arm.com>
Date:   Mon Jul 7 09:10:38 2025 +0100

    ext-dce: Fix subreg_lsb is_constant assumption
    
    ext-dce had:
    
              if (SUBREG_P (dst) && SUBREG_BYTE (dst).is_constant ())
                {
                  bit = subreg_lsb (dst).to_constant ();
                  if (bit >= HOST_BITS_PER_WIDE_INT)
                    bit = HOST_BITS_PER_WIDE_INT - 1;
                  dst = SUBREG_REG (dst);
    
    But a constant SUBREG_BYTE doesn't guarantee a constant subreg_lsb.
    If the SUBREG_REG is a pair of N-bit registers on a big-endian target,
    the most significant end has a SUBREG_BYTE of 0 but a subreg_lsb of N.
    This N would then be non-constant for variable-length registers.
    
    The patch fixes gcc.dg/torture/pr120276.c and other failures on
    aarch64_be-elf.
    
    gcc/
            * ext-dce.cc (ext_dce_process_uses): Apply is_constant directly
            to the subreg_lsb.

Diff:
---
 gcc/ext-dce.cc | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/gcc/ext-dce.cc b/gcc/ext-dce.cc
index afe7afe21fd7..e7635fb7a394 100644
--- a/gcc/ext-dce.cc
+++ b/gcc/ext-dce.cc
@@ -651,9 +651,8 @@ ext_dce_process_uses (rtx_insn *insn, rtx obj,
 
          /* ?!? How much of this should mirror SET handling, potentially
             being shared?   */
-         if (SUBREG_P (dst) && SUBREG_BYTE (dst).is_constant ())
+         if (SUBREG_P (dst) && subreg_lsb (dst).is_constant (&bit))
            {
-             bit = subreg_lsb (dst).to_constant ();
              if (bit >= HOST_BITS_PER_WIDE_INT)
                bit = HOST_BITS_PER_WIDE_INT - 1;
              dst = SUBREG_REG (dst);

Reply via email to