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, ...