aboutsummaryrefslogtreecommitdiff
path: root/src/simd/archsimd/_gen/simdgen/xed.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/simd/archsimd/_gen/simdgen/xed.go')
-rw-r--r--src/simd/archsimd/_gen/simdgen/xed.go125
1 files changed, 78 insertions, 47 deletions
diff --git a/src/simd/archsimd/_gen/simdgen/xed.go b/src/simd/archsimd/_gen/simdgen/xed.go
index 4ba6738e7e..5d6fac64d0 100644
--- a/src/simd/archsimd/_gen/simdgen/xed.go
+++ b/src/simd/archsimd/_gen/simdgen/xed.go
@@ -5,7 +5,6 @@
package main
import (
- "cmp"
"fmt"
"log"
"maps"
@@ -78,7 +77,7 @@ func loadXED(xedPath string) []*unify.Value {
switch {
case inst.RealOpcode == "N":
return // Skip unstable instructions
- case !(strings.HasPrefix(inst.Extension, "AVX") || strings.HasPrefix(inst.Extension, "SHA")):
+ case !(strings.HasPrefix(inst.Extension, "AVX") || strings.HasPrefix(inst.Extension, "SHA") || inst.Extension == "FMA"):
// We're only interested in AVX and SHA instructions.
return
}
@@ -210,16 +209,9 @@ func loadXED(xedPath string) []*unify.Value {
}
log.Printf("%d unhandled CPU features for %d instructions (use -v for details)", len(unknownFeatures), nInst)
} else {
- keys := slices.SortedFunc(maps.Keys(unknownFeatures), func(a, b cpuFeatureKey) int {
- return cmp.Or(cmp.Compare(a.Extension, b.Extension),
- cmp.Compare(a.ISASet, b.ISASet))
- })
+ keys := slices.Sorted(maps.Keys(unknownFeatures))
for _, key := range keys {
- if key.ISASet == "" || key.ISASet == key.Extension {
- log.Printf("unhandled Extension %s", key.Extension)
- } else {
- log.Printf("unhandled Extension %s and ISASet %s", key.Extension, key.ISASet)
- }
+ log.Printf("unhandled ISASet %s", key)
log.Printf(" opcodes: %s", slices.Sorted(maps.Keys(unknownFeatures[key])))
}
}
@@ -763,16 +755,24 @@ func instToUVal1(inst *xeddata.Inst, ops []operand, feature string, variant inst
// decodeCPUFeature returns the CPU feature name required by inst. These match
// the names of the "Has*" feature checks in the simd package.
func decodeCPUFeature(inst *xeddata.Inst) (string, bool) {
- key := cpuFeatureKey{
- Extension: inst.Extension,
- ISASet: isaSetStrip.ReplaceAllLiteralString(inst.ISASet, ""),
+ isaSet := inst.ISASet
+ if isaSet == "" {
+ // Older instructions don't have an ISA set. Use their "extension"
+ // instead.
+ isaSet = inst.Extension
}
- feat, ok := cpuFeatureMap[key]
+ // We require AVX512VL to use AVX512 at all, so strip off the vector length
+ // suffixes.
+ if strings.HasPrefix(isaSet, "AVX512") {
+ isaSet = isaSetVL.ReplaceAllLiteralString(isaSet, "")
+ }
+
+ feat, ok := cpuFeatureMap[isaSet]
if !ok {
- imap := unknownFeatures[key]
+ imap := unknownFeatures[isaSet]
if imap == nil {
imap = make(map[string]struct{})
- unknownFeatures[key] = imap
+ unknownFeatures[isaSet] = imap
}
imap[inst.Opcode()] = struct{}{}
return "", false
@@ -783,45 +783,76 @@ func decodeCPUFeature(inst *xeddata.Inst) (string, bool) {
return feat, true
}
-var isaSetStrip = regexp.MustCompile("_(128N?|256N?|512)$")
+var isaSetVL = regexp.MustCompile("_(128N?|256N?|512)$")
-type cpuFeatureKey struct {
- Extension, ISASet string
-}
-
-// cpuFeatureMap maps from XED's "EXTENSION" and "ISA_SET" to a CPU feature name
-// that can be used in the SIMD API.
-var cpuFeatureMap = map[cpuFeatureKey]string{
- {"SHA", "SHA"}: "SHA",
-
- {"AVX", ""}: "AVX",
- {"AVX_VNNI", "AVX_VNNI"}: "AVXVNNI",
- {"AVX2", ""}: "AVX2",
- {"AVXAES", ""}: "AVX, AES",
+// cpuFeatureMap maps from XED's "ISA_SET" (or "EXTENSION") to a CPU feature
+// name to expose in the SIMD feature check API.
+//
+// See XED's datafiles/*/cpuid.xed.txt for how ISA set names map to CPUID flags.
+var cpuFeatureMap = map[string]string{
+ "AVX": "AVX",
+ "AVX_VNNI": "AVXVNNI",
+ "AVX2": "AVX2",
+ "AVXAES": "AVXAES",
+ "SHA": "SHA",
+ "FMA": "FMA",
// AVX-512 foundational features. We combine all of these into one "AVX512" feature.
- {"AVX512EVEX", "AVX512F"}: "AVX512",
- {"AVX512EVEX", "AVX512CD"}: "AVX512",
- {"AVX512EVEX", "AVX512BW"}: "AVX512",
- {"AVX512EVEX", "AVX512DQ"}: "AVX512",
- // AVX512VL doesn't appear explicitly in the ISASet. I guess it's implied by
- // the vector length suffix.
+ "AVX512F": "AVX512",
+ "AVX512BW": "AVX512",
+ "AVX512CD": "AVX512",
+ "AVX512DQ": "AVX512",
+ // AVX512VL doesn't appear as its own ISASet; instead, the CPUID flag is
+ // required by the *_128 and *_256 ISASets. We fold it into "AVX512" anyway.
// AVX-512 extension features
- {"AVX512EVEX", "AVX512_BITALG"}: "AVX512BITALG",
- {"AVX512EVEX", "AVX512_GFNI"}: "AVX512GFNI",
- {"AVX512EVEX", "AVX512_VBMI2"}: "AVX512VBMI2",
- {"AVX512EVEX", "AVX512_VBMI"}: "AVX512VBMI",
- {"AVX512EVEX", "AVX512_VNNI"}: "AVX512VNNI",
- {"AVX512EVEX", "AVX512_VPOPCNTDQ"}: "AVX512VPOPCNTDQ",
- {"AVX512EVEX", "AVX512_VAES"}: "AVX512VAES",
- {"AVX512EVEX", "AVX512_VPCLMULQDQ"}: "AVX512VPCLMULQDQ",
+ "AVX512_BITALG": "AVX512BITALG",
+ "AVX512_GFNI": "AVX512GFNI",
+ "AVX512_VBMI": "AVX512VBMI",
+ "AVX512_VBMI2": "AVX512VBMI2",
+ "AVX512_VNNI": "AVX512VNNI",
+ "AVX512_VPOPCNTDQ": "AVX512VPOPCNTDQ",
+ "AVX512_VAES": "AVX512VAES",
+ "AVX512_VPCLMULQDQ": "AVX512VPCLMULQDQ",
// AVX 10.2 (not yet supported)
- {"AVX512EVEX", "AVX10_2_RC"}: "ignore",
+ "AVX10_2_RC": "ignore",
+}
+
+func init() {
+ // TODO: In general, Intel doesn't make any guarantees about what flags are
+ // set, so this means our feature checks need to ensure these, just to be
+ // sure.
+ var features = map[string]featureInfo{
+ "AVX2": {Implies: []string{"AVX"}},
+ "AVX512": {Implies: []string{"AVX2"}},
+
+ "AVXAES": {Virtual: true, Implies: []string{"AVX", "AES"}},
+ "FMA": {Implies: []string{"AVX"}},
+
+ // AVX-512 subfeatures.
+ "AVX512BITALG": {Implies: []string{"AVX512"}},
+ "AVX512GFNI": {Implies: []string{"AVX512"}},
+ "AVX512VBMI": {Implies: []string{"AVX512"}},
+ "AVX512VBMI2": {Implies: []string{"AVX512"}},
+ "AVX512VNNI": {Implies: []string{"AVX512"}},
+ "AVX512VPOPCNTDQ": {Implies: []string{"AVX512"}},
+ "AVX512VAES": {Implies: []string{"AVX512"}},
+
+ // AVX-VNNI and AVX-IFMA are "backports" of the AVX512-VNNI/IFMA
+ // instructions to VEX encoding, limited to 256 bit vectors. They're
+ // intended for lower end CPUs that want to support VNNI/IFMA without
+ // supporting AVX-512. As such, they're built on AVX2's VEX encoding.
+ "AVXVNNI": {Implies: []string{"AVX2"}},
+ "AVXIFMA": {Implies: []string{"AVX2"}},
+ }
+ registerFeatureInfo("amd64", goarchFeatures{
+ featureVar: "X86",
+ features: features,
+ })
}
-var unknownFeatures = map[cpuFeatureKey]map[string]struct{}{}
+var unknownFeatures = map[string]map[string]struct{}{}
// hasOptionalMask returns whether there is an optional mask operand in ops.
func hasOptionalMask(ops []operand) bool {