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.

Reply via email to