From: Austin Clements Date: Thu, 12 Jun 2025 19:24:22 +0000 (-0400) Subject: internal/cpu: add AVX-512-CD and DQ, and derived "basic AVX-512" X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e73afaae69bb6f098e3c1dbd98cfe134843910a1;p=gostls13.git 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. This is a cherry-pick of CL 680899 from the dev.simd branch. Change-Id: I34356502bd1853ba2372e48db0b10d55cffe07a1 Reviewed-on: https://go-review.googlesource.com/c/go/+/693396 Reviewed-by: Cherry Mui Auto-Submit: Austin Clements LUCI-TryBot-Result: Go LUCI --- diff --git a/src/internal/cpu/cpu.go b/src/internal/cpu/cpu.go index 6017b1acc9..fca38532dc 100644 --- a/src/internal/cpu/cpu.go +++ b/src/internal/cpu/cpu.go @@ -31,9 +31,13 @@ var X86 struct { HasADX bool HasAVX bool HasAVX2 bool + HasAVX512 bool // Virtual feature: F+CD+BW+DQ+VL HasAVX512F bool + HasAVX512CD bool HasAVX512BW bool + HasAVX512DQ bool HasAVX512VL bool + HasAVX512VPCLMULQDQ bool HasBMI1 bool HasBMI2 bool HasERMS bool @@ -48,7 +52,6 @@ var X86 struct { HasSSSE3 bool HasSSE41 bool HasSSE42 bool - HasAVX512VPCLMULQDQ bool _ CacheLinePad } @@ -161,6 +164,10 @@ var RISCV64 struct { //go:linkname S390X //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. // 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 @@ -168,6 +175,9 @@ var RISCV64 struct { func Initialize(env string) { doinit() processOptions(env) + if doDerived != nil { + doDerived() + } } // options contains the cpu debug options that can be used in GODEBUG. diff --git a/src/internal/cpu/cpu_x86.go b/src/internal/cpu/cpu_x86.go index 69b9542ae2..315c26b0dd 100644 --- a/src/internal/cpu/cpu_x86.go +++ b/src/internal/cpu/cpu_x86.go @@ -36,7 +36,9 @@ const ( cpuid_BMI2 = 1 << 8 cpuid_ERMS = 1 << 9 cpuid_AVX512F = 1 << 16 + cpuid_AVX512DQ = 1 << 17 cpuid_ADX = 1 << 19 + cpuid_AVX512CD = 1 << 28 cpuid_SHA = 1 << 29 cpuid_AVX512BW = 1 << 30 cpuid_AVX512VL = 1 << 31 @@ -89,7 +91,9 @@ func doinit() { // they can be turned off. options = append(options, option{Name: "avx512f", Feature: &X86.HasAVX512F}, + option{Name: "avx512cd", Feature: &X86.HasAVX512CD}, option{Name: "avx512bw", Feature: &X86.HasAVX512BW}, + option{Name: "avx512dq", Feature: &X86.HasAVX512DQ}, option{Name: "avx512vl", Feature: &X86.HasAVX512VL}, ) } @@ -154,7 +158,9 @@ func doinit() { X86.HasAVX512F = isSet(ebx7, cpuid_AVX512F) && osSupportsAVX512 if X86.HasAVX512F { + X86.HasAVX512CD = isSet(ebx7, cpuid_AVX512CD) X86.HasAVX512BW = isSet(ebx7, cpuid_AVX512BW) + X86.HasAVX512DQ = isSet(ebx7, cpuid_AVX512DQ) X86.HasAVX512VL = isSet(ebx7, cpuid_AVX512VL) X86.HasAVX512VPCLMULQDQ = isSet(ecx7, cpuid_AVX512VPCLMULQDQ) } @@ -170,6 +176,17 @@ func doinit() { _, _, _, edxExt1 := cpuid(0x80000001, 0) 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 {