[dev.simd] internal/cpu: add AVX-512-CD and DQ, and derived "basic AVX-512"

This adds detection for the CD and DQ sub-features of x86 AVX-512.

Building on these, we also add a "derived" AVX-512 feature that
bundles together the basic usable subset of subfeatures. Despite the F
in AVX-512-F standing for "foundation", AVX-512-F+BW+DQ+VL together
really form the basic usable subset of AVX-512 functionality. These
have also all been supported together by almost every CPU, and are
guaranteed by GOAMD64=v4, so there's little point in separating them
out.

Change-Id: I34356502bd1853ba2372e48db0b10d55cffe07a1
Reviewed-on: https://go-review.googlesource.com/c/go/+/680899
Reviewed-by: Cherry Mui <cherryyz@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
Austin Clements 2025-06-12 15:24:22 -04:00
parent dfa6c74263
commit 9b9af3d638
2 changed files with 27 additions and 0 deletions

View file

@ -31,8 +31,11 @@ var X86 struct {
HasADX bool HasADX bool
HasAVX bool HasAVX bool
HasAVX2 bool HasAVX2 bool
HasAVX512 bool // Virtual feature: F+CD+BW+DQ+VL
HasAVX512F bool HasAVX512F bool
HasAVX512CD bool
HasAVX512BW bool HasAVX512BW bool
HasAVX512DQ bool
HasAVX512VL bool HasAVX512VL bool
HasBMI1 bool HasBMI1 bool
HasBMI2 bool HasBMI2 bool
@ -160,6 +163,10 @@ var RISCV64 struct {
//go:linkname S390X //go:linkname S390X
//go:linkname RISCV64 //go:linkname RISCV64
// doDerived, if non-nil, is called after processing GODEBUG to set "derived"
// feature flags.
var doDerived func()
// Initialize examines the processor and sets the relevant variables above. // Initialize examines the processor and sets the relevant variables above.
// This is called by the runtime package early in program initialization, // This is called by the runtime package early in program initialization,
// before normal init functions are run. env is set by runtime if the OS supports // before normal init functions are run. env is set by runtime if the OS supports
@ -167,6 +174,9 @@ var RISCV64 struct {
func Initialize(env string) { func Initialize(env string) {
doinit() doinit()
processOptions(env) processOptions(env)
if doDerived != nil {
doDerived()
}
} }
// options contains the cpu debug options that can be used in GODEBUG. // options contains the cpu debug options that can be used in GODEBUG.

View file

@ -36,7 +36,9 @@ const (
cpuid_BMI2 = 1 << 8 cpuid_BMI2 = 1 << 8
cpuid_ERMS = 1 << 9 cpuid_ERMS = 1 << 9
cpuid_AVX512F = 1 << 16 cpuid_AVX512F = 1 << 16
cpuid_AVX512DQ = 1 << 17
cpuid_ADX = 1 << 19 cpuid_ADX = 1 << 19
cpuid_AVX512CD = 1 << 28
cpuid_SHA = 1 << 29 cpuid_SHA = 1 << 29
cpuid_AVX512BW = 1 << 30 cpuid_AVX512BW = 1 << 30
cpuid_AVX512VL = 1 << 31 cpuid_AVX512VL = 1 << 31
@ -84,7 +86,9 @@ func doinit() {
// they can be turned off. // they can be turned off.
options = append(options, options = append(options,
option{Name: "avx512f", Feature: &X86.HasAVX512F}, option{Name: "avx512f", Feature: &X86.HasAVX512F},
option{Name: "avx512cd", Feature: &X86.HasAVX512CD},
option{Name: "avx512bw", Feature: &X86.HasAVX512BW}, option{Name: "avx512bw", Feature: &X86.HasAVX512BW},
option{Name: "avx512dq", Feature: &X86.HasAVX512DQ},
option{Name: "avx512vl", Feature: &X86.HasAVX512VL}, option{Name: "avx512vl", Feature: &X86.HasAVX512VL},
) )
} }
@ -149,7 +153,9 @@ func doinit() {
X86.HasAVX512F = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 X86.HasAVX512F = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512
if X86.HasAVX512F { if X86.HasAVX512F {
X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD)
X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW)
X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ)
X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL)
} }
@ -164,6 +170,17 @@ func doinit() {
_, _, _, edxExt1 := cpuid(0x80000001, 0) _, _, _, edxExt1 := cpuid(0x80000001, 0)
X86.HasRDTSCP = isSet(edxExt1, cpuid_RDTSCP) X86.HasRDTSCP = isSet(edxExt1, cpuid_RDTSCP)
doDerived = func() {
// Rather than carefully gating on fundamental AVX-512 features, we have
// a virtual "AVX512" feature that captures F+CD+BW+DQ+VL. BW, DQ, and
// VL have a huge effect on which AVX-512 instructions are available,
// and these have all been supported on everything except the earliest
// Phi chips with AVX-512. No CPU has had CD without F, so we include
// it. GOAMD64=v4 also implies exactly this set, and these are all
// included in AVX10.1.
X86.HasAVX512 = X86.HasAVX512F && X86.HasAVX512CD && X86.HasAVX512BW && X86.HasAVX512DQ && X86.HasAVX512VL
}
} }
func isSet(hwc uint32, value uint32) bool { func isSet(hwc uint32, value uint32) bool {