A very typical use of math/bits.TrailingZerosNN is to visit all set bits.
var sink int
func visitbits(x uint64) {
for x != 0 {
sink = bits.TrailingZeros64(x) // use result
x &= x - 1
}
}
(Among other things, I'd like to do this in some hot code in the runtime.)
This currently compiles on amd64 to:
"".visitbits STEXT nosplit size=40 args=0x8 locals=0x0
0x0000 00000 (x.go:7) TEXT "".visitbits(SB), NOSPLIT, $0-8
0x0000 00000 (x.go:7) FUNCDATA $0, gclocals·2a5305abe05176240e61b8620e19a815(SB)
0x0000 00000 (x.go:7) FUNCDATA $1, gclocals·33cdeccccebe80329f1fdbee7f5874cb(SB)
0x0000 00000 (x.go:7) MOVQ "".x+8(SP), AX
0x0005 00005 (x.go:8) JMP 34
0x0007 00007 (x.go:9) BSFQ AX, CX
0x000b 00011 (x.go:9) MOVL $64, DX
0x0010 00016 (x.go:9) CMOVQEQ DX, CX
0x0014 00020 (x.go:9) MOVQ CX, "".sink(SB)
0x001b 00027 (x.go:10) LEAQ -1(AX), CX
0x001f 00031 (x.go:10) ANDQ CX, AX
0x0022 00034 (x.go:8) TESTQ AX, AX
0x0025 00037 (x.go:8) JNE 7
0x0027 00039 (<unknown line number>) RET
However, since we know that x != 0 in the loop, we should be able to skip the CMOVEQ stuff and just use BSFQ directly. Similar (though less dramatic) optimizations apply for small int widths.
This seems like information that the prove pass has readily available. I haven't been able to figure out how to use it, though; the prove pass is complicated, and I'm not sure where best to make the change.
There seem like two reasonable options for encoding the information: Add new Ctz8NonZero ops, and change the value's op from Ctz8 to Ctz8NonZero, or giving Ctz8 an auxint indicating non-zero-ness. I weakly prefer the former.
@rasky any chance you could help out on this, if it is easy?
cc also @aclements
A very typical use of math/bits.TrailingZerosNN is to visit all set bits.
(Among other things, I'd like to do this in some hot code in the runtime.)
This currently compiles on amd64 to:
However, since we know that
x != 0in the loop, we should be able to skip the CMOVEQ stuff and just use BSFQ directly. Similar (though less dramatic) optimizations apply for small int widths.This seems like information that the prove pass has readily available. I haven't been able to figure out how to use it, though; the prove pass is complicated, and I'm not sure where best to make the change.
There seem like two reasonable options for encoding the information: Add new Ctz8NonZero ops, and change the value's op from Ctz8 to Ctz8NonZero, or giving Ctz8 an auxint indicating non-zero-ness. I weakly prefer the former.
@rasky any chance you could help out on this, if it is easy?
cc also @aclements