Skip to content

Commit 2216956

Browse files
authored
Merge pull request #531 from RoaringBitmap/neon_opti
adding NEON optimizations
2 parents f9e9fab + 208a752 commit 2216956

4 files changed

Lines changed: 519 additions & 2 deletions

File tree

popcnt_generic.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
//go:build !amd64 || appengine
2-
// +build !amd64 appengine
1+
//go:build (!amd64 && !arm64) || appengine
2+
// +build !amd64,!arm64 appengine
33

44
package roaring
55

popcnt_neon_arm64.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
//go:build arm64 && !appengine
2+
// +build arm64,!appengine
3+
4+
package roaring
5+
6+
// The functions below are implemented in popcnt_neon_arm64.s using NEON
7+
// (Advanced SIMD). NEON is mandatory in the ARMv8-A baseline that every arm64
8+
// CPU implements, so — unlike the amd64 AVX2 path, which is gated on a runtime
9+
// _hasAVX2 check — these routines are always used on arm64. The pure-Go
10+
// fallbacks in popcnt_slices.go remain in use on other architectures and on
11+
// appengine builds, which compile popcnt_generic.go instead.
12+
13+
//go:noescape
14+
func _popcntSliceNEON(s []uint64) uint64
15+
16+
//go:noescape
17+
func _popcntMaskSliceNEON(s, m []uint64) uint64
18+
19+
//go:noescape
20+
func _popcntAndSliceNEON(s, m []uint64) uint64
21+
22+
//go:noescape
23+
func _popcntOrSliceNEON(s, m []uint64) uint64
24+
25+
//go:noescape
26+
func _popcntXorSliceNEON(s, m []uint64) uint64
27+
28+
// useNEON is always true on arm64; it exists so tests can force the scalar
29+
// fallback path and to mirror the amd64 dispatch structure.
30+
var useNEON = true
31+
32+
func popcntSlice(s []uint64) uint64 {
33+
if useNEON {
34+
return _popcntSliceNEON(s)
35+
}
36+
return popcntSliceGo(s)
37+
}
38+
39+
func popcntMaskSlice(s, m []uint64) uint64 {
40+
if useNEON {
41+
return _popcntMaskSliceNEON(s, m)
42+
}
43+
return popcntMaskSliceGo(s, m)
44+
}
45+
46+
func popcntAndSlice(s, m []uint64) uint64 {
47+
if useNEON {
48+
return _popcntAndSliceNEON(s, m)
49+
}
50+
return popcntAndSliceGo(s, m)
51+
}
52+
53+
func popcntOrSlice(s, m []uint64) uint64 {
54+
if useNEON {
55+
return _popcntOrSliceNEON(s, m)
56+
}
57+
return popcntOrSliceGo(s, m)
58+
}
59+
60+
func popcntXorSlice(s, m []uint64) uint64 {
61+
if useNEON {
62+
return _popcntXorSliceNEON(s, m)
63+
}
64+
return popcntXorSliceGo(s, m)
65+
}

0 commit comments

Comments
 (0)