https://godbolt.org/z/6n7G8q

I'm actually not sure how good this assembly is, it would be
interesting to hear from you, but it looks promising.

вт, 1 сент. 2020 г. в 22:54, Oliver Smith <[email protected]>:
>
> In the process of developing a piece of middleware, I need to translate from 
> a bit-array into a bitmask. I am struggling to find a way to express this in 
> go that doesn't result in terrible performance.
>
> The approaches I would try in most other languages were along the lines of:
>
> ```
> mask = (bool1 << bitno1) | (bool2 << bitno2);
> // or
> mask = (bool1 ? value1 : 0) | (bool2 ? value2 : 0);
> ```
>
> but instead, after reading several old (circa 1.5) posts, I'd landed at
>
> ```
> func maskIfTrue(mask uint, predicate bool) uint {
>   if predicate {
>     return mask
>   }
>   return 0
> }
>
> mask = maskIfTrue(mask1, bool1) | maskIfTrue(mask2, bool2)
> ```
>
> Here is a (boiled-down & reduced) comparison of the go implementation vs a 
> simple C implementation compiled with -O0 and -Os:
>
> The go version is branch-crazy.
>
> Is there some way I can write this that will produce simpler/efficient code 
> and also not be code salad? I don't have control over the relative ordering 
> of the bools or the bitfield values, and this is a hot path?
>
> Go branchiness:
> ```
>         nop
>         cmpb    1(AX), $0
>         jeq     featToMask_pc94
>         movl    $2, DX
> featToMask_pc19:
>         nop
>         cmpb    2(AX), $0
>         jeq     featToMask_pc90
>         movl    $4, BX
> featToMask_pc30:
>         nop
> ```
>
> The "FeatToMask" C transliteration when compiled with optimization *disabled* 
> (-O0) looks similar, but even -O1 fixes that:
> ```
> FeatToMask:
>         mov     eax, edi
>         movzx   eax, ah
>         mov     esi, edi
>         shr     esi, 16
>         mov     ecx, edi
>         shr     ecx, 24
>         mov     rdx, rdi
>         shr     rdx, 32
>         shr     rdi, 40
>         or      eax, esi
>         or      eax, ecx
>         or      eax, edx
>         or      eax, edi
>         movzx   eax, al
>         ret
> ```
>
> and with -Os you get down to something better than the naive-C-implementation 
> at the top of the source
>
> ```
> FeatToMask:
>         mov     QWORD PTR [rsp-8], rdi
>         mov     al, BYTE PTR [rsp-7]
>         or      al, BYTE PTR [rsp-6]
>         or      al, BYTE PTR [rsp-5]
>         or      eax, DWORD PTR [rsp-4]
>         or      al, BYTE PTR [rsp-3]
>         movzx   eax, al
>         ret
> ```
>
> --
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to [email protected].
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/ea364cef-3998-469c-8742-3bc794733535n%40googlegroups.com.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/CAMteYTaMuRmdq0%3DGiGXJ%3DYVP%2BcamdCssGwSxAcAubY4T0DOMiw%40mail.gmail.com.

Reply via email to