Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/go/build/deps_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,8 @@ var depsRules = `
internal/strconv,
internal/trace/tracev2,
math/bits,
structs
structs,
simd/archsimd
< internal/bytealg
< internal/stringslite
< internal/unsafeheader
Expand Down
24 changes: 4 additions & 20 deletions src/internal/runtime/maps/memhash_386.s
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
#include "textflag.h"

// hash function using AES hardware instructions
TEXT ·MemHash32(SB),NOSPLIT,$0-12
CMPB ·UseAeshash(SB), $0
JEQ noaes
TEXT ·memHash32AES(SB),NOSPLIT,$0-12
MOVL p+0(FP), AX // ptr to data
MOVL h+4(FP), X0 // seed
PINSRD $1, (AX), X0 // data
Expand All @@ -16,12 +14,8 @@ TEXT ·MemHash32(SB),NOSPLIT,$0-12
AESENC ·aeskeysched+32(SB), X0
MOVL X0, ret+8(FP)
RET
noaes:
JMP ·memHash32Fallback(SB)

TEXT ·MemHash64(SB),NOSPLIT,$0-12
CMPB ·UseAeshash(SB), $0
JEQ noaes
TEXT ·memHash64AES(SB),NOSPLIT,$0-12
MOVL p+0(FP), AX // ptr to data
MOVQ (AX), X0 // data
PINSRD $2, h+4(FP), X0 // seed
Expand All @@ -30,29 +24,19 @@ TEXT ·MemHash64(SB),NOSPLIT,$0-12
AESENC ·aeskeysched+32(SB), X0
MOVL X0, ret+8(FP)
RET
noaes:
JMP ·memHash64Fallback(SB)

TEXT ·MemHash(SB),NOSPLIT,$0-16
CMPB ·UseAeshash(SB), $0
JEQ noaes
TEXT ·memHashAES(SB),NOSPLIT,$0-16
MOVL p+0(FP), AX // ptr to data
MOVL s+8(FP), BX // size
LEAL ret+12(FP), DX
JMP ·aeshashbody<>(SB)
noaes:
JMP ·memHashFallback(SB)

TEXT ·StrHash(SB),NOSPLIT,$0-12
CMPB ·UseAeshash(SB), $0
JEQ noaes
TEXT ·strHashAES(SB),NOSPLIT,$0-12
MOVL p+0(FP), AX // ptr to string object
MOVL 4(AX), BX // length of string
MOVL (AX), AX // string data
LEAL ret+8(FP), DX
JMP ·aeshashbody<>(SB)
noaes:
JMP ·strHashFallback(SB)

// AX: data
// BX: length
Expand Down
34 changes: 26 additions & 8 deletions src/internal/runtime/maps/memhash_aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,32 @@ import (
"unsafe"
)

//go:noescape
func MemHash(p unsafe.Pointer, h, s uintptr) uintptr
const memHashAESImplemented = true

//go:noescape
func MemHash32(p unsafe.Pointer, h uintptr) uintptr
func MemHash(p unsafe.Pointer, h, s uintptr) uintptr {
if UseAeshash {
return memHashAES(p, h, s)
}
return memHashFallback(p, h, s)
}

//go:noescape
func MemHash64(p unsafe.Pointer, h uintptr) uintptr
func MemHash32(p unsafe.Pointer, h uintptr) uintptr {
if UseAeshash {
return memHash32AES(p, h)
}
return memHash32Fallback(p, h)
}

//go:noescape
func StrHash(p unsafe.Pointer, h uintptr) uintptr
func MemHash64(p unsafe.Pointer, h uintptr) uintptr {
if UseAeshash {
return memHash64AES(p, h)
}
return memHash64Fallback(p, h)
}

func StrHash(p unsafe.Pointer, h uintptr) uintptr {
if UseAeshash {
return strHashAES(p, h)
}
return strHashFallback(p, h)
}
27 changes: 27 additions & 0 deletions src/internal/runtime/maps/memhash_aes_asm.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build (amd64 && !goexperiment.simd) || arm64 || 386

package maps

import (
"unsafe"
)

const memHashUsesVAES = false

// stabs for assembly implementations
//
//go:noescape
func memHashAES(p unsafe.Pointer, h, s uintptr) uintptr

//go:noescape
func memHash32AES(p unsafe.Pointer, h uintptr) uintptr

//go:noescape
func memHash64AES(p unsafe.Pointer, h uintptr) uintptr

//go:noescape
func strHashAES(p unsafe.Pointer, h uintptr) uintptr
52 changes: 52 additions & 0 deletions src/internal/runtime/maps/memhash_aes_simd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build amd64 && goexperiment.simd

package maps

import (
"simd/archsimd"
"unsafe"
)

const memHashUsesVAES = true

func memHash32AES(p unsafe.Pointer, seed uintptr) uintptr {
var state archsimd.Uint64x2
state = state.SetElem(0, uint64(seed)).SetElem(1, uint64(*(*uint32)(p)))

hash := state.
AsUint8x16().
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[0])))).
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[16])))).
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[32])))).
AsUint64x2().
GetElem(0)
return uintptr(hash)
}

func memHash64AES(p unsafe.Pointer, seed uintptr) uintptr {
var state archsimd.Uint64x2
state = state.SetElem(0, uint64(seed)).SetElem(1, *(*uint64)(p))

hash := state.
AsUint8x16().
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[0])))).
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[16])))).
AESEncryptOneRound(archsimd.LoadUint32x4((*[4]uint32)(unsafe.Pointer(&aeskeysched[32])))).
AsUint64x2().
GetElem(0)
return uintptr(hash)
}

// TODO: Both strHashAES and memHashAES use aeshashbody that is quite large.
// So there is no point in rewriting them using simd intrinsics, since they won't be inlinable.
// Maybe in future we can do it for better maitanability.
//
//go:noescape
func memHashAES(p unsafe.Pointer, h, s uintptr) uintptr

//go:noescape
func strHashAES(p unsafe.Pointer, h uintptr) uintptr
50 changes: 4 additions & 46 deletions src/internal/runtime/maps/memhash_amd64.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,63 +4,21 @@

#include "textflag.h"

// func MemHash32(p unsafe.Pointer, h uintptr) uintptr
// ABIInternal for performance.
TEXT ·MemHash32<ABIInternal>(SB),NOSPLIT,$0-24
// AX = ptr to data
// BX = seed
CMPB ·UseAeshash(SB), $0
JEQ noaes
MOVQ BX, X0 // X0 = seed
PINSRD $2, (AX), X0 // data
AESENC ·aeskeysched+0(SB), X0
AESENC ·aeskeysched+16(SB), X0
AESENC ·aeskeysched+32(SB), X0
MOVQ X0, AX // return X0
RET
noaes:
JMP ·memHash32Fallback<ABIInternal>(SB)

// func MemHash64(p unsafe.Pointer, h uintptr) uintptr
// ABIInternal for performance.
TEXT ·MemHash64<ABIInternal>(SB),NOSPLIT,$0-24
// AX = ptr to data
// BX = seed
CMPB ·UseAeshash(SB), $0
JEQ noaes
MOVQ BX, X0 // X0 = seed
PINSRQ $1, (AX), X0 // data
AESENC ·aeskeysched+0(SB), X0
AESENC ·aeskeysched+16(SB), X0
AESENC ·aeskeysched+32(SB), X0
MOVQ X0, AX // return X0
RET
noaes:
JMP ·memHash64Fallback<ABIInternal>(SB)

// func MemHash(p unsafe.Pointer, h, s uintptr) uintptr
// func memHashAES(p unsafe.Pointer, h, s uintptr) uintptr
// hash function using AES hardware instructions
TEXT ·MemHash<ABIInternal>(SB),NOSPLIT,$0-32
TEXT ·memHashAES<ABIInternal>(SB),NOSPLIT,$0-32
// AX = ptr to data
// BX = seed
// CX = size
CMPB ·UseAeshash(SB), $0
JEQ noaes
JMP ·aeshashbody<>(SB)
noaes:
JMP ·memHashFallback<ABIInternal>(SB)

// func strhash(p unsafe.Pointer, h uintptr) uintptr
TEXT ·StrHash<ABIInternal>(SB),NOSPLIT,$0-24
// func strhashAES(p unsafe.Pointer, h uintptr) uintptr
TEXT ·strHashAES<ABIInternal>(SB),NOSPLIT,$0-24
// AX = ptr to string struct
// BX = seed
CMPB ·UseAeshash(SB), $0
JEQ noaes
MOVQ 8(AX), CX // length of string
MOVQ (AX), AX // string data
JMP ·aeshashbody<>(SB)
noaes:
JMP ·strHashFallback<ABIInternal>(SB)

// AX: data
// BX: hash seed
Expand Down
32 changes: 8 additions & 24 deletions src/internal/runtime/maps/memhash_arm64.s
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,8 @@

#include "textflag.h"

// func MemHash32(p unsafe.Pointer, h uintptr) uintptr
TEXT ·MemHash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
MOVB ·UseAeshash(SB), R10
CBZ R10, noaes
// func memHash32AES(p unsafe.Pointer, h uintptr) uintptr
TEXT ·memHash32AES<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
MOVD $·aeskeysched+0(SB), R3

VEOR V0.B16, V0.B16, V0.B16
Expand All @@ -23,13 +21,9 @@ TEXT ·MemHash32<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24

VMOV V0.D[0], R0
RET
noaes:
B ·memHash32Fallback<ABIInternal>(SB)

// func MemHash64(p unsafe.Pointer, h uintptr) uintptr
TEXT ·MemHash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
MOVB ·UseAeshash(SB), R10
CBZ R10, noaes
// func memHash64AES(p unsafe.Pointer, h uintptr) uintptr
TEXT ·memHash64AES<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
MOVD $·aeskeysched+0(SB), R3

VEOR V0.B16, V0.B16, V0.B16
Expand All @@ -45,25 +39,15 @@ TEXT ·MemHash64<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24

VMOV V0.D[0], R0
RET
noaes:
B ·memHash64Fallback<ABIInternal>(SB)

// func MemHash(p unsafe.Pointer, h, size uintptr) uintptr
TEXT ·MemHash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
MOVB ·UseAeshash(SB), R10
CBZ R10, noaes
// func memHashAES(p unsafe.Pointer, h, size uintptr) uintptr
TEXT ·memHashAES<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-32
B ·aeshashbody<>(SB)
noaes:
B ·memHashFallback<ABIInternal>(SB)

// func StrHash(p unsafe.Pointer, h uintptr) uintptr
TEXT ·StrHash<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
MOVB ·UseAeshash(SB), R10
CBZ R10, noaes
// func strHashAES(p unsafe.Pointer, h uintptr) uintptr
TEXT ·strHashAES<ABIInternal>(SB),NOSPLIT|NOFRAME,$0-24
LDP (R0), (R0, R2) // string data / length
B ·aeshashbody<>(SB)
noaes:
B ·strHashFallback<ABIInternal>(SB)

// R0: data
// R1: seed data
Expand Down
15 changes: 15 additions & 0 deletions src/internal/runtime/maps/memhash_noaes.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,21 @@ import (
)

// AES hashing not implemented for these architectures
const memHashAESImplemented = false
const memHashUsesVAES = false

func memHash32AES(p unsafe.Pointer, h uintptr) uintptr {
panic("memHash32AES not implemented")
}

func memHash64AES(p unsafe.Pointer, h uintptr) uintptr {
panic("memHash64AES not implemented")
}

func strHashAES(p unsafe.Pointer, h uintptr) uintptr {
panic("strHashAES not implemented")
}

func MemHash(p unsafe.Pointer, h, s uintptr) uintptr {
return memHashFallback(p, h, s)
}
Expand Down
33 changes: 33 additions & 0 deletions src/internal/runtime/maps/memhash_nosimd_amd64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !goexperiment.simd

#include "textflag.h"

// func memHash32AES(p unsafe.Pointer, h uintptr) uintptr
// ABIInternal for performance.
TEXT ·memHash32AES<ABIInternal>(SB),NOSPLIT,$0-24
// AX = ptr to data
// BX = seed
MOVQ BX, X0 // X0 = seed
PINSRD $2, (AX), X0 // data
AESENC ·aeskeysched+0(SB), X0
AESENC ·aeskeysched+16(SB), X0
AESENC ·aeskeysched+32(SB), X0
MOVQ X0, AX // return X0
RET

// func memHash64AES(p unsafe.Pointer, h uintptr) uintptr
// ABIInternal for performance.
TEXT ·memHash64AES<ABIInternal>(SB),NOSPLIT,$0-24
// AX = ptr to data
// BX = seed
MOVQ BX, X0 // X0 = seed
PINSRQ $1, (AX), X0 // data
AESENC ·aeskeysched+0(SB), X0
AESENC ·aeskeysched+16(SB), X0
AESENC ·aeskeysched+32(SB), X0
MOVQ X0, AX // return X0
RET
Loading
Loading