https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115092
--- Comment #5 from Jakub Jelinek <jakub at gcc dot gnu.org> --- I think the bug is in simplify_comparison. We have there GE (sign_extract:SI (reg/v:SI 101 [ g ]) (const_int 1 [0x1]) (const_int 0 [0])) (const_int -1 [0xffffffffffffffff]) That is first changed into GE (ashiftrt:SI (ashift:SI (reg/v:SI 101 [ g ]) (const_int 31 [0x1f])) (const_int 31 [0x1f])) (const_int -1 [0xffffffffffffffff]) Both are always true. But then the /* FALLTHROUGH */ case LSHIFTRT: /* If we have (compare (xshiftrt FOO N) (const_int C)) and the low order N bits of FOO are known to be zero, we can do this by comparing FOO with C shifted left N bits so long as no overflow occurs. Even if the low order N bits of FOO aren't known to be zero, if the comparison is >= or < we can use the same optimization and for > or <= by setting all the low order N bits in the comparison constant. */ optimization triggers and optimizes it into GE (ashift:SI (reg/v:SI 101 [ g ]) (const_int 31 [0x1f])) (const_int -2147483648 [0xffffffff80000000]) I think that is ok too. But then code = simplify_compare_const (code, raw_mode, &op0, &op1); simplifies that to NE and I think that step is wrong, because GE of anything >= INT_MIN is true. So, I think /* If we are comparing against a constant power of two and the value being compared can only have that single bit nonzero (e.g., it was `and'ed with that bit), we can replace this with a comparison with zero. */ if (const_op && (code == EQ || code == NE || code == GE || code == GEU || code == LT || code == LTU) && is_a <scalar_int_mode> (mode, &int_mode) && GET_MODE_PRECISION (int_mode) - 1 < HOST_BITS_PER_WIDE_INT && pow2p_hwi (const_op & GET_MODE_MASK (int_mode)) && (nonzero_bits (op0, int_mode) == (unsigned HOST_WIDE_INT) (const_op & GET_MODE_MASK (int_mode)))) { code = (code == EQ || code == GE || code == GEU ? NE : EQ); const_op = 0; } in simplify_compare_const is wrong if const_op is the most significant bit of int_mode.