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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/ea364cef-3998-469c-8742-3bc794733535n%40googlegroups.com.

Reply via email to