https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115092
--- Comment #7 from Segher Boessenkool <segher at gcc dot gnu.org> --- (In reply to Jakub Jelinek from comment #5) > 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. Yeah, that look like it is missing some test. That needs to be fixed of course, but independent of that, this should really have been completely folded away earlier already?