internal/cpu: add a detection for Neoverse(N2, V2) cores

The memmove implementation relies on the variable
runtime.arm64UseAlignedLoads to select fastest code
path. Considering Neoverse N2 and V2 cores prefer aligned
loads, this patch adds code to detect them for
memmove performance.

And this patch uses a new variable ARM64.IsNeoverse to
represent all Neoverse cores, removing the more specific
versions.

Change-Id: I9e06eae01a0325a0b604ac6af1e55711dd6133f7
Reviewed-on: https://go-review.googlesource.com/c/go/+/487815
Reviewed-by: Joel Sing <joel@sing.id.au>
Reviewed-by: Dmitri Shuralyov <dmitshur@google.com>
Run-TryBot: Fannie Zhang <Fannie.Zhang@arm.com>
Reviewed-by: Cherry Mui <cherryyz@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
This commit is contained in:
fanzha02 2023-04-20 07:28:50 +00:00 committed by Joel Sing
parent a1284d0185
commit e4b03f9425
4 changed files with 24 additions and 24 deletions

View file

@ -57,18 +57,17 @@ var ARM struct {
// The booleans in ARM64 contain the correspondingly named cpu feature bit. // The booleans in ARM64 contain the correspondingly named cpu feature bit.
// The struct is padded to avoid false sharing. // The struct is padded to avoid false sharing.
var ARM64 struct { var ARM64 struct {
_ CacheLinePad _ CacheLinePad
HasAES bool HasAES bool
HasPMULL bool HasPMULL bool
HasSHA1 bool HasSHA1 bool
HasSHA2 bool HasSHA2 bool
HasSHA512 bool HasSHA512 bool
HasCRC32 bool HasCRC32 bool
HasATOMICS bool HasATOMICS bool
HasCPUID bool HasCPUID bool
IsNeoverseN1 bool IsNeoverse bool
IsNeoverseV1 bool _ CacheLinePad
_ CacheLinePad
} }
var MIPS64X struct { var MIPS64X struct {

View file

@ -19,8 +19,7 @@ func doinit() {
{Name: "crc32", Feature: &ARM64.HasCRC32}, {Name: "crc32", Feature: &ARM64.HasCRC32},
{Name: "atomics", Feature: &ARM64.HasATOMICS}, {Name: "atomics", Feature: &ARM64.HasATOMICS},
{Name: "cpuid", Feature: &ARM64.HasCPUID}, {Name: "cpuid", Feature: &ARM64.HasCPUID},
{Name: "isNeoverseN1", Feature: &ARM64.IsNeoverseN1}, {Name: "isNeoverse", Feature: &ARM64.IsNeoverse},
{Name: "isNeoverseV1", Feature: &ARM64.IsNeoverseV1},
} }
// arm64 uses different ways to detect CPU features at runtime depending on the operating system. // arm64 uses different ways to detect CPU features at runtime depending on the operating system.

View file

@ -39,22 +39,24 @@ func hwcapInit(os string) {
// TODO(elias.naur): Only disable the optimization on bad chipsets on android. // TODO(elias.naur): Only disable the optimization on bad chipsets on android.
ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && os != "android" ARM64.HasATOMICS = isSet(HWCap, hwcap_ATOMICS) && os != "android"
// Check to see if executing on a NeoverseN1 and in order to do that, // Check to see if executing on a Neoverse core and in order to do that,
// check the AUXV for the CPUID bit. The getMIDR function executes an // check the AUXV for the CPUID bit. The getMIDR function executes an
// instruction which would normally be an illegal instruction, but it's // instruction which would normally be an illegal instruction, but it's
// trapped by the kernel, the value sanitized and then returned. Without // trapped by the kernel, the value sanitized and then returned.
// the CPUID bit the kernel will not trap the instruction and the process // Without the CPUID bit the kernel will not trap the instruction and the
// will be terminated with SIGILL. // process will be terminated with SIGILL.
if ARM64.HasCPUID { if ARM64.HasCPUID {
midr := getMIDR() midr := getMIDR()
part_num := uint16((midr >> 4) & 0xfff) part_num := uint16((midr >> 4) & 0xfff)
implementor := byte((midr >> 24) & 0xff) implementor := byte((midr >> 24) & 0xff)
if implementor == 'A' && part_num == 0xd0c { // d0c - NeoverseN1
ARM64.IsNeoverseN1 = true // d40 - NeoverseV1
} // d49 - NeoverseN2
if implementor == 'A' && part_num == 0xd40 { // d4f - NeoverseV2
ARM64.IsNeoverseV1 = true if implementor == 'A' && (part_num == 0xd0c || part_num == 0xd40 ||
part_num == 0xd49 || part_num == 0xd4f) {
ARM64.IsNeoverse = true
} }
} }
} }

View file

@ -11,7 +11,7 @@ import (
var arm64UseAlignedLoads bool var arm64UseAlignedLoads bool
func init() { func init() {
if cpu.ARM64.IsNeoverseN1 || cpu.ARM64.IsNeoverseV1 { if cpu.ARM64.IsNeoverse {
arm64UseAlignedLoads = true arm64UseAlignedLoads = true
} }
} }