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

--- Comment #4 from Peter Damianov <peter0x44 at disroot dot org> ---
>From what I can tell this applies to all integers:

bool f (int c)
{
    return (0xc0000000 & c) == 0x80000000;
}

has the same transformation applied

What clang does is valid because the function is checking the following bit
pattern:
10XXXXXX
the biggest value satisfying this bit pattern is:
10111111
which is -64

And the other end of the range doesn't need to be considered, because:
10000000 is INT8_MIN

Clang 19 generates the slightly different:
f(char):
        and     dil, -64
        neg     dil
        seto    al
        ret

Which still spares doing a comparison, but is a little bigger
I think it's doing the mask, then negating and checking for overflow
Only INT_MIN will overflow if negated, so INT_MIN is the only value that will
satisfy the bit pattern after all the other bits are masked off.

This second transformation is probably generalizable to more circumstances.
I don't know if it's worth filing a separate bug for that one.

GCC doesn't do either of these things.

I did try searching for dups and couldn't find any, but I have a vague memory
of reading something similar here before...

Reply via email to