Welcome Guest ( Log In | Register )

Outline · [ Standard ] · Linear+

> Compare GCC, Clang, Go and Rust, according to Taras Tsugrii

views
     
TSFlierMate
post Jun 10 2021, 11:26 PM, updated 4d ago

Getting Started
**
Junior Member
187 posts

Joined: Nov 2020


Compile the following...
CODE
int isHtmlWhitespace(int ch) {
   return ch == 0x0009 || ch == 0x000A ||
           ch == 0x000C || ch == 0x000D ||
           ch == 0x0020;
}


GCC with enabled optimizations is able to produce:

CODE
isHtmlWhitespace(int):
       cmp     edi, 32; compare ch with 0x0020
       ja      .L42      ; and return false if ch is larger, since 32 is the largest possible match
       movabs  rax, 4294981120
       mov     ecx, edi
       shr     rax, cl
       and     eax, 1
       ret
.L42:
       xor     eax, eax
       ret


Clang generates different but still very compact and interesting Assembly:
CODE
isHtmlWhitespace(int):                  # @isHtmlWhitespace(int)
       lea     eax, [rdi - 9]
       cmp     eax, 5
       jae     .LBB2_3
       mov     ecx, 27
       bt      ecx, eax
       jb      .LBB2_2
.LBB2_3:
       xor     eax, eax
       cmp     edi, 32
       sete    al
       ret
.LBB2_2:
       mov     eax, 1
       ret


Unfortunately not all compilers are using this clever optimization. Unfortunately Go's compiler is one of such compilers:
CODE
func is_html_whitespace(ch int) bool {
   return ch == 0x0009 || ch == 0x000A ||
       ch == 0x000C || ch == 0x000D ||
       ch == 0x0020
}

...is translated into a set of IFs which is very unfortunate:

CODE
v14
   00003 (+4) MOVQ "".ch(SP), AX
v30
   00004 (4) CMPQ AX, $9
b1
   00005 (4) JNE 9
v29
   00006 (4) MOVL $1, AX
v28
   00007 (+4) MOVB AX, "".~r1+8(SP)
b8
   00008 (4) RET
v10
   00009 (4) CMPQ AX, $10
b2
   00010 (4) JEQ 6
v34
   00011 (+5) CMPQ AX, $12
b4
   00012 (5) JEQ 6
v31
   00013 (5) CMPQ AX, $13
b6
   00014 (5) JEQ 6
v7
   00015 (+6) CMPQ AX, $32
v24
   00016 (6) SETEQ AX
b9
   00017 (6) JMP 7


And what about Rust? Interestingly its Assembly is different from the one generated by Clang compiler for C++ code and impressively contains no branches:

CODE
is_html_whitespace:                     # @is_html_whitespace
# %bb.0:
                                       # kill: def $edi killed $edi def $rdi
   leal    -9(%rdi), %eax
   cmpl    $2, %eax
   setb    %al
   movl    %edi, %ecx
   andl    $-2, %ecx
   cmpl    $12, %ecx
   sete    %cl
   orb    %al, %cl
   cmpl    $32, %edi
   sete    %al
   orb    %cl, %al
   retq


Source: https://softwarebits.hashnode.dev/bit-testing

Which is the winner? Which is the loser? thumbup.gif

This post has been edited by FlierMate: Jun 10 2021, 11:28 PM

 

Change to:
| Lo-Fi Version
0.0152sec    1.04    5 queries    GZIP Disabled
Time is now: 14th June 2021 - 01:22 AM