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

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

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ebotcazou at gcc dot gnu.org,
                   |                            |jakub at gcc dot gnu.org,
                   |                            |segher at gcc dot gnu.org

--- Comment #1 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The problem is that try_combine for:
(gdb) p debug_rtx (i2)
(insn 35 34 36 6 (set (reg:SI 95 [ iftmp.0_7 ])
        (zero_extend:SI (reg:QI 94 [ iftmp.0_7 ]))) "pr91720.c":12:5 88
{zero_extendqisi2}
     (nil))
(gdb) p debug_rtx (i3)
(insn 36 35 37 6 (set (reg:SI 96)
        (lshiftrt:SI (reg:SI 95 [ iftmp.0_7 ])
            (const_int 1 [0x1]))) "pr91720.c":12:5 152 {lshrsi3}
     (expr_list:REG_DEAD (reg:SI 95 [ iftmp.0_7 ])
        (nil)))
combine_simplify_rtx "simplifies"
(lshiftrt:SI (zero_extend:SI (reg:QI 94 [ iftmp.0_7 ]))
    (const_int 1 [0x1]))
into:
(lshiftrt:SI (subreg:SI (reg:QI 94 [ iftmp.0_7 ]) 0)
    (const_int 1 [0x1]))
which is not equivalent, because it pushes random undefined bits to the right.
expand_compound_operation has:
7437          tem = gen_lowpart (mode, XEXP (x, 0));
7438          if (!tem || GET_CODE (tem) == CLOBBER)
7439            return x;
7440          tem = simplify_shift_const (NULL_RTX, ASHIFT, mode,
7441                                      tem, modewidth - pos - len);
7442          tem = simplify_shift_const (NULL_RTX, unsignedp ? LSHIFTRT :
ASHIFTRT,
7443                                      mode, tem, modewidth - len);
and while the first simplify_shift_const (properly) returns
(ashift:SI (subreg:SI (reg:QI 94 [ iftmp.0_7 ]) 0)
    (const_int 24 [0x18]))
because the upper bits of the register are all shifted out, the second
simplify_shift_const returns the paradoxical subreg.
What is specific to this testcase is that reg:QI 94 has nonzero_bits equal to
128.
simplify_shift_const_1 then will simplify it to the (subreg:SI (reg:QI 94 [
iftmp.0_7 ]) 0) with desired AND outer operation and outer_const 128, that
still seems to be correct, but then
p debug_rtx (simplify_and_const_int (0, int_result_mode, x, 128))
(subreg:SI (reg:QI 94 [ iftmp.0_7 ]) 0)
where int_result_mode is SImode and this is already wrong, because paradoxical
subregs don't have defined content of the upper bits.

  /* See what bits may be nonzero in VAROP.  Unlike the general case of
     a call to nonzero_bits, here we don't care about bits outside
     MODE.  */

  nonzero = nonzero_bits (varop, mode) & GET_MODE_MASK (mode);

  /* Turn off all bits in the constant that are known to already be zero.
     Thus, if the AND isn't needed at all, we will have CONSTOP == NONZERO_BITS
     which is tested below.  */

  constop &= nonzero;

...
  /* If we are only masking insignificant bits, return VAROP.  */
  if (constop == nonzero)
    return varop;

So, the bug is either in nonzero_bits that it for the WORD_REGISTER_OPERATIONS
and load_extend_op (QImode) == ZERO_EXTEND returns 0s in the upper bits, or in
simplify_and_const_int trusting nonzero_bits even on paradoxical subregs, ...

Reply via email to