https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82192

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |NEW
                 CC|                            |law at gcc dot gnu.org,
                   |                            |segher at gcc dot gnu.org
           Assignee|jakub at gcc dot gnu.org           |unassigned at gcc dot 
gnu.org

--- Comment #9 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
So, we call make_compound_extraction_int on
(and:HI (subreg:HI (lshiftrt:SI (subreg:SI (reg:DI 94 [ a ]) 0)
            (subreg:QI (reg:SI 97) 0)) 0)
    (const_int 8191 [0x1fff]))
and that calls make_extraction (SImode, (subreg:SI (reg:DI 94 [ a ]) 0),
0, (subreg:QI (reg:SI 97) 0), 13, 1, 0, false);
I'm afraid I have no idea what are the requirements/behavior of ZERO_EXTRACT or
make_extraction when POS + LEN is bigger than the bitsize of the operand and
therefore no idea where the bug is.
If there is a requirement that POS + LEN must be always <= bitsize of the
operand, then it is invalid to handle LSHIFTRT with variable shift count
through make_extraction, because we actually want to extract fewer than LEN
bits for some POS values and the rest are 0.  If POS + LEN may be larger than
bitsize and the remaining bits are zero, then it is invalid to 
  if (GET_CODE (inner) == SUBREG && subreg_lowpart_p (inner))
    {
      /* If going from (subreg:SI (mem:QI ...)) to (mem:QI ...),
         consider just the QI as the memory to extract from.
         The subreg adds or removes high bits; its mode is
         irrelevant to the meaning of this extraction,
         since POS and LEN count from the lsb.  */
      if (MEM_P (SUBREG_REG (inner)))
        is_mode = GET_MODE (SUBREG_REG (inner));
      inner = SUBREG_REG (inner);
    }
for non-paradoxical subregs and pos_rtx != NULL_RTX and non-constant or
constant, but with POS + LEN larger than original GET_MODE (inner).
We can (zero_extract:SI (subreg:SI (reg:DI 94 [ a ]) 0)
          (const_int 13 [0xd])
          (zero_extend:SI (subreg:QI (reg:SI 97) 0)))
but not (zero_extract:DI (reg:DI 94 [ a ])
          (const_int 13 [0xd])
          (zero_extend:SI (subreg:QI (reg:SI 97) 0)))
because for the pos_rtx larger than 32-13 the former extracts 12 to 1 bits out
of the SImode and zero extends that, while for the latter it always extracts 13
bits out of the 64-bit pseudo.

Reply via email to