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, [email protected] 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, [email protected]
> <[email protected]>:
> >
> > 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 [email protected].
> > 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 [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/golang-nuts/4381cff4-a79e-4b91-bf04-c7a2c95af309n%40googlegroups.com.