https://gcc.gnu.org/bugzilla/show_bug.cgi?id=92903
Bug ID: 92903
Summary: Cannot elide byteswap when only needed to compare to
multiple constants
Product: gcc
Version: 8.3.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c
Assignee: unassigned at gcc dot gnu.org
Reporter: jwerner at chromium dot org
Target Milestone: ---
I compiled the following test code on GCC 8.3.0:
int test(int a)
{
const int swapped = __builtin_bswap32(a);
if (swapped == 0x12345678 || swapped == 0x23456789)
return 1;
return 0;
}
On x86_64, I get:
0000000000000000 <test> (File Offset: 0x40):
0: 0f cf bswap %edi
2: 81 ff 78 56 34 12 cmp $0x12345678,%edi
8: 0f 94 c0 sete %al
b: 81 ff 89 67 45 23 cmp $0x23456789,%edi
11: 0f 94 c2 sete %dl
14: 09 d0 or %edx,%eax
16: 0f b6 c0 movzbl %al,%eax
19: c3 retq
And on aarch64, I get:
0000000000000000 <test> (File Offset: 0x40):
0: 528acf01 mov w1, #0x5678 // #22136
4: 5ac00800 rev w0, w0
8: 72a24681 movk w1, #0x1234, lsl #16
c: 6b01001f cmp w0, w1
10: 528cf121 mov w1, #0x6789 // #26505
14: 72a468a1 movk w1, #0x2345, lsl #16
18: 7a411004 ccmp w0, w1, #0x4, ne
1c: 1a9f17e0 cset w0, eq
20: d65f03c0 ret
In both of those cases it would have been better to omit the byteswap
instruction and instead embed the constants to compare to in their swapped form
right away. This works correctly when comparing to a single constant, like
this:
int test(int a)
{
const int swapped = __builtin_bswap32(a);
if (swapped == 0x12345678)
return 1;
return 0;
}
0000000000000000 <test> (File Offset: 0x40):
0: 52868241 mov w1, #0x3412 // #13330
4: 72af0ac1 movk w1, #0x7856, lsl #16
8: 6b01001f cmp w0, w1
c: 1a9f17e0 cset w0, eq
10: d65f03c0 ret
But comparing the swapped value to more than one constant somehow makes GCC
miss this optimization, even if neither the swapped value nor the constants are
used for anything else.