https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118206
--- Comment #7 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
Further reduced:
__attribute__((noipa)) int
foo (const void *x)
{
unsigned short b;
__builtin_memcpy (&b, x, sizeof (short));
if ((b & 15) != 8)
return 1;
if ((((unsigned char) b) >> 4) > 7)
return 1;
return 0;
}
int
main ()
{
unsigned char a[8] = { 0x78, 0x78 };
if (sizeof (short) == 2 && foo (a) != 0)
__builtin_abort ();
}
Both (b & 15) != 8 and (((unsigned char) b) >> 4) > 7 tests actually only care
about the first byte (on little endian), and the second could be simplified to
(b & 128) != 0.
So I think both tests actually can be combined into (b & 143) != 8.
But instead of that ifcombine combines that to
optimizing two comparisons to (_8 & 143) == 8 && (_9 & 15) == 0
where _8 is the low byte and _9 is the high byte. The old tests weren't
checking anything from the high byte before.