Thank you Aleksey. That is indeed a working solution, and it works well.
 Here are the two functions I wrote as suggested:

func bool2int(b bool) int {
        if b {
                return 1
        }
        return 0
}

func testBitHack(v int) bool {
        return (bool2int(v==10) & bool2int(v==5) & bool2int(v==15)) == 0
}

Here is the Go assembly code of testBitHack

"".testBitHack STEXT nosplit size=47 args=0x10 locals=0x0
        0x0000 00000 (main.go:12)       TEXT    "".testBitHack(SB), 
NOSPLIT|ABIInternal, $0-16
        0x0000 00000 (main.go:12)       FUNCDATA        $0, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (main.go:12)       FUNCDATA        $1, 
gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
        0x0000 00000 (main.go:13)       MOVQ    "".v+8(SP), AX
        0x0005 00005 (main.go:13)       CMPQ    AX, $10
        0x0009 00009 (main.go:13)       SETEQ   CL
        0x000c 00012 (main.go:13)       CMPQ    AX, $5
        0x0010 00016 (main.go:13)       SETEQ   DL
        0x0013 00019 (main.go:13)       CMPQ    AX, $15
        0x0017 00023 (main.go:13)       SETEQ   AL
        0x001a 00026 (main.go:13)       MOVBLZX DL, DX
        0x001d 00029 (main.go:13)       MOVBLZX CL, CX
        0x0020 00032 (main.go:13)       ANDQ    DX, CX
        0x0023 00035 (main.go:13)       MOVBLZX AL, AX
        0x0026 00038 (main.go:13)       TESTQ   AX, CX
        0x0029 00041 (main.go:13)       SETEQ   "".~r1+16(SP)
        0x002e 00046 (main.go:13)       RET

The function bool2int and its condition were effectively optimized away by 
the Go compiler.  That’s awesome. Good job. It’s a nice trick.




Le samedi 21 novembre 2020 à 11:41:03 UTC+1, aleksey...@gmail.com a écrit :

> To me your example appears somewhat confusing, int(bool(int())) is the
> fishiest part IMO. I assume bool(int()) is just (v^v1 != 0) in
> disguise and this is essentially
>
> (v^v1 != 0) & (v^v2 != 0) & (v^v3 != 0)
>
> Am i right?
>
> Go can't & bools, so
>
> func bool2int(b bool) int { // This is what Go compiler can optimize well
> if b {
> return 1
> }
> return 0
> }
>
> And this leaves us with
>
> bool2int(v^v1 != 0) & bool2int(v^v2 != 0) & bool2int(v^v3 != 0)
>
> Is that correct?
>
> https://godbolt.org/z/jq368G
>
> I don't see branching in relevant parts. v == v1 || v == v2 will of
> course branch because || is a condition.
>
> Does that answer your question or maybe I am missing something?
>
> пт, 20 нояб. 2020 г. в 11:27, christoph...@gmail.com
> <christoph...@gmail.com>:
> >
> > Go has a strict type separation between int and bool. For a normal usage 
> this is OK. I guess it also ease assembly portability because there is not 
> always a machine instruction to do so.
> >
> > For bit hacking, this is an unfortunate limitation. A handy feature of 
> bool <-> int conversion is that true is converted to 1 and any integer 
> different of zero to true. As a consequence, when we write int(bool(x)) we 
> get 0 when x is 0, and 1 when x is not 0. I checked the math/bits package 
> and there is not an equivalent function.
> >
> > Is there a way around this that avoids the conditional branching ?
> >
> > The use case I have to test if an integer is in a quite small constant 
> set of integers. With bool <-> int conversion, we can use binary operation 
> like this for instance which would be valid in C
> >
> > r := int(bool(v^v1))&int(bool(v^v2))&int(bool(v^v3))
> >
> > This is to be compared with
> >
> > r := v==v1 || v==v2 || v==v3
> >
> > The second form is of course more readable, but will also have a 
> conditional branch at each ||. If most tested integers are different from 
> v1, v2 and v3, the first form seam to me more efficient due to pipelining. 
> Though branching prediction can mitigate the penalty.
> >
> > The best I could do as valid Go alternative is this
> >
> > r := (v^v1)*(v^v2)*(v^v3)
> >
> > but the multiplication is obviously not efficient.
> >
> > Did I miss something ?
> >
> > --
> > 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...@googlegroups.com.
> > To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/a2b743d7-011d-481f-9a0f-3f00f4507328n%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 golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/4381cff4-a79e-4b91-bf04-c7a2c95af309n%40googlegroups.com.

Reply via email to