Created
March 17, 2017 19:59
Star
You must be signed in to star a gist
Benchmark of different ways to guard the POPCNT instruction
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Requires https://go-review.googlesource.com/c/38320 | |
package popcnt | |
import ( | |
"math/bits" | |
"testing" | |
) | |
var sink interface{} | |
func BenchmarkUnguarded(b *testing.B) { | |
var sum int | |
for i := uint64(0); i < uint64(b.N); i++ { | |
sum += bits.OnesCount64(i) | |
} | |
sink = sum | |
} | |
var havePopcount = true | |
func BenchmarkGlobal(b *testing.B) { | |
// Test a global with a call as the slow path. | |
var sum int | |
for i := uint64(0); i < uint64(b.N); i++ { | |
var pop int | |
if havePopcount { | |
pop = bits.OnesCount64(i) | |
} else { | |
pop = slowOnesCount64(i) | |
} | |
sum += pop | |
} | |
sink = sum | |
} | |
var popcountFunc = bits.OnesCount64 | |
func BenchmarkIndirect(b *testing.B) { | |
// Call through a global function pointer. | |
var sum int | |
for i := uint64(0); i < uint64(b.N); i++ { | |
sum += popcountFunc(i) | |
} | |
sink = sum | |
} | |
func BenchmarkCodegen(b *testing.B) { | |
// Simulate calling out to a generated code page. | |
var sum int | |
for i := uint64(0); i < uint64(b.N); i++ { | |
sum += popcountCodePage(i) | |
} | |
sink = sum | |
} | |
func slowOnesCount64(x uint64) int { | |
const m = 1<<64 - 1 | |
const m0 = 0x5555555555555555 // 01010101 ... | |
const m1 = 0x3333333333333333 // 00110011 ... | |
const m2 = 0x0f0f0f0f0f0f0f0f // 00001111 ... | |
const m3 = 0x00ff00ff00ff00ff // etc. | |
const m4 = 0x0000ffff0000ffff | |
x = x>>1&(m0&m) + x&(m0&m) | |
x = x>>2&(m1&m) + x&(m1&m) | |
x = (x>>4 + x) & (m2 & m) | |
x += x >> 8 | |
x += x >> 16 | |
x += x >> 32 | |
return int(x) & (1<<7 - 1) | |
} | |
//go:noinline | |
func popcountCodePage(x uint64) int { | |
return bits.OnesCount64(x) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment