<div dir="ltr"><div dir="ltr"><div>Thanks for reporting this and other perf opportunities. As I mentioned before, if you could file bug reports for these, that's probably the only way they're ever going to get fixed (unless you're planning to fix them yourself). It's not an ideal situation, but that's how this project works in my experience. <br></div><div><br></div><div>Someone filed 1 of your examples on your behalf here:<br></div><div><a href="https://bugs.llvm.org/show_bug.cgi?id=39793">https://bugs.llvm.org/show_bug.cgi?id=39793</a><br></div><div><br></div><div>Please do consider following that model for your other problems. Without that kind of report, your code examples are likely to be forgotten.<br></div><div><br></div><div>Finally, sending mail to llvm-bugs is practically useless. I don't know of anyone that is tracking mails to that list rather than actual bug reports.<br></div></div></div><br><div class="gmail_quote"><div dir="ltr">On Tue, Nov 27, 2018 at 4:37 PM Stefan Kanthak <<a href="mailto:stefan.kanthak@nexgo.de">stefan.kanthak@nexgo.de</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">"Sanjay Patel" <<a href="mailto:spatel@rotateright.com" target="_blank">spatel@rotateright.com</a>> wrote:<br>
<br>
> IIUC, you want to use x86-specific bit-hacks (sbb masking) in cases like<br>
> this:<br>
> unsigned int foo(unsigned int crc) {<br>
>    if (crc & 0x80000000)<br>
>      crc <<= 1, crc ^= 0xEDB88320;<br>
>    else<br>
>      crc <<= 1;<br>
>    return crc;<br>
> }<br>
<br>
To document this for x86 too: rewrite the function slightly<br>
<br>
unsigned int foo(unsigned int crc, unsigned int poly) {<br>
    if (crc & 0x80000000)<br>
        crc <<= 1, crc ^= poly;<br>
    else<br>
        crc <<= 1;<br>
    return crc;<br>
}<br>
<br>
unsigned int bar(unsigned int crc, unsigned int poly) {<br>
    if (crc & 1)<br>
        crc >>= 1, crc ^= poly;<br>
    else<br>
        crc >>= 1;<br>
    return crc;<br>
}<br>
<br>
and you get the perfect code for the left-shifting case!<br>
<br>
foo: # @foo<br>
    lea eax, [rdi + rdi]<br>
    sar edi, 31<br>
    and edi, esi<br>
    xor eax, edi<br>
    ret<br>
<br>
The right-shifting case leaves but still room for improvement!<br>
<br>
bar: # @bar                | bar: # @bar<br>
    mov eax, edi           |<br>
    and eax, 1             |<br>
    neg eax                |<br>
    shr edi                |     shr edi<br>
                           |     sbb eax, eax<br>
    and eax, esi           |     and eax, esi<br>
    xor eax, edi           |     xor eax, edi<br>
    ret                    |     ret<br>
<br>
See <<a href="https://godbolt.org/z/aPKweG" rel="noreferrer" target="_blank">https://godbolt.org/z/aPKweG</a>><br>
<br>
regards<br>
Stefan Kanthak<br>
<br>
> Which is this in LLVM IR:<br>
> define i32 @foo(i32 %x) {<br>
>  %t2 = icmp slt i32 %x, 0<br>
>  %t3 = shl i32 %x, 1<br>
>  %t4 = xor i32 %t3, -306674912<br>
>  %t5 = select i1 %t2, i32 %t4, i32 %t3<br>
>  ret i32 %t5<br>
> }<br>
> <br>
> Please a file a bug report for the x86 backend (including performance<br>
> numbers if you have that data).<br>
> <br>
> On Wed, Nov 7, 2018 at 5:24 PM Stefan Kanthak via llvm-dev <<br>
> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a>> wrote:<br>
> <br>
>> Hi @ll,<br>
>><br>
>> while clang/LLVM recognizes common bit-twiddling idioms/expressions<br>
>> like<br>
>><br>
>> unsigned int rotate(unsigned int x, unsigned int n)<br>
>> {<br>
>>     return (x << n) | (x >> (32 - n));<br>
>> }<br>
>><br>
>> and typically generates "rotate" machine instructions for this<br>
>> expression, it fails to recognize other also common bit-twiddling<br>
>> idioms/expressions.<br>
>><br>
>> The standard IEEE CRC-32 for "big endian" alias "network" byte order<br>
>> (see <<a href="https://tools.ietf.org/html/rfc1952#section-8" rel="noreferrer" target="_blank">https://tools.ietf.org/html/rfc1952#section-8</a>> for example):<br>
>><br>
>> unsigned int crc32be(unsigned char const *octets, unsigned int count)<br>
>> {<br>
>>     unsigned int crc = 0L;<br>
>>     unsigned int i;<br>
>><br>
>>     while (count--) {<br>
>>         crc ^= *octets++ << 24;<br>
>>         for (i = 8; i > 0; i--)<br>
>>             if (crc & 0x80000000L)             // the code generated<br>
>>                 crc <<= 1, crc ^= 0xEDB88320L; // for Intel x86 from<br>
>>             else                               // these 4 lines is<br>
>>                 crc <<= 1;                     // rather poor!<br>
>>     }<br>
>>     return crc;<br>
>> }<br>
>><br>
>> The same function for "little endian" byte order, using the "inverse"<br>
>> or "mirrored" polynom:<br>
>><br>
>> unsigned int crc32le(unsigned char const *octets, unsigned int count)<br>
>> {<br>
>>     unsigned int crc = ~0L;<br>
>>     unsigned int i;<br>
>><br>
>>     while (count--) {<br>
>>         crc ^= *octets++;<br>
>>         for (i = 8; i > 0; i--)<br>
>>             if (crc & 1L)                      // the code generated<br>
>>                 crc >>= 1, crc ^= 0x04C11DB7L; // for Intel x86 from<br>
>>             else                               // these 4 lines is<br>
>>                 crc >>= 1;                     // rather poor!<br>
>>     }<br>
>>     return ~crc;<br>
>> }<br>
>><br>
>> See <<a href="https://godbolt.org/z/eYJeWt" rel="noreferrer" target="_blank">https://godbolt.org/z/eYJeWt</a>> (-O1) and <<a href="https://godbolt.org/z/zeExHm" rel="noreferrer" target="_blank">https://godbolt.org/z/zeExHm</a>><br>
>> (-O2)<br>
>><br>
>> crc32be: # @crc32be<br>
>>         xor    eax, eax<br>
>>         test   esi, esi<br>
>>         jne    .LBB0_2<br>
>>         jmp    .LBB0_5<br>
>> .LBB0_4: # in Loop: Header=BB0_2 Depth=1<br>
>>         add    rdi, 1<br>
>>         test   esi, esi<br>
>>         je    .LBB0_5<br>
>> .LBB0_2: # =>This Loop Header: Depth=1<br>
>>         add    esi, -1<br>
>>         movzx  edx, byte ptr [rdi]<br>
>>         shl    edx, 24<br>
>>         xor    edx, eax<br>
>>         mov    ecx, -8<br>
>>         mov    eax, edx<br>
>> .LBB0_3: # Parent Loop BB0_2 Depth=1   | # 4 instructions instead of 6, r8<br>
>> not clobbered!<br>
>>         lea    r8d, [rax + rax]        |     add   eax, eax<br>
>>         mov    edx, r8d                | # CF is set from the MSB of EAX<br>
>>         xor    edx, -306674912         |     sbb   edx, edx<br>
>>         test   eax, eax                | # EDX is 0xFFFFFFFF if CF set,<br>
>> else 0<br>
>>         mov    eax, edx                |     and   edx, -306674912<br>
>>         cmovns eax, r8d                |     xor   eax, edx<br>
>>         add    ecx, 1<br>
>>         jne    .LBB0_3<br>
>>         jmp    .LBB0_4<br>
>> .LBB0_5:<br>
>>         ret<br>
>> crc32le: # @crc32le<br>
>>         test   esi, esi<br>
>>         je    .LBB1_1<br>
>>         mov    eax, -1<br>
>> .LBB1_4: # =>This Loop Header: Depth=1<br>
>>         add    esi, -1<br>
>>         movzx  ecx, byte ptr [rdi]<br>
>>         xor    eax, ecx<br>
>>         mov    r8d, -8<br>
>> .LBB1_5: # Parent Loop BB1_4 Depth=1   | # 4 instructions instead of 7, and<br>
>>         mov    edx, eax                | #  neither r8 nor rcx clobbered!<br>
>>         shr    edx                     |     shr   eax, 1<br>
>>         mov    ecx, edx                | # CF is set from the LSB of EAX<br>
>>         xor    ecx, 79764919           |     sbb   edx, edx<br>
>>         test   al, 1                   | # EDX is 0xFFFFFFFF if CF set,<br>
>> else 0<br>
>>         mov    eax, ecx                |     and   edx, 79764919<br>
>>         cmove  eax, edx                |     xor   eax, edx<br>
>>         add    r8d, 1<br>
>>         jne    .LBB1_5<br>
>>         add    rdi, 1<br>
>>         test   esi, esi<br>
>>         jne    .LBB1_4<br>
>>         not    eax<br>
>>         ret<br>
>> .LBB1_1:<br>
>>         xor    eax, eax<br>
>>         ret<br>
>><br>
>> JFTR: with -O2, the inner loop gets unrolled, using the same non-optimal<br>
>>       code sequence with 6 and 7 instructions; this accounts for a total<br>
>>       of 16 and 24 superfluous instructions respectively.<br>
>> _______________________________________________<br>
>> LLVM Developers mailing list<br>
>> <a href="mailto:llvm-dev@lists.llvm.org" target="_blank">llvm-dev@lists.llvm.org</a><br>
>> <a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-dev</a><br>
>><br>
><br>
</blockquote></div>