simd: create a single file for simd types shared by stubs and emulation (Should be) no changes to generated anything, just better organization Change-Id: I4d00c9f17b5aad7f49bafce64b8af6841d21c32a Reviewed-on: https://go-review.googlesource.com/c/go/+/789662 TryBot-Bypass: David Chase <drchase@google.com> Reviewed-by: Cherry Mui <cherryyz@google.com>
diff --git a/src/simd/archsimd/_gen/midway/intersect_simd_ops.go b/src/simd/archsimd/_gen/midway/intersect_simd_ops.go index de8f070..e91c527 100644 --- a/src/simd/archsimd/_gen/midway/intersect_simd_ops.go +++ b/src/simd/archsimd/_gen/midway/intersect_simd_ops.go
@@ -218,6 +218,7 @@ return recvType } + // Record existing emulated methods emulated := make(map[TypeMethod]bool) f, err := parser.ParseFile(fset, emulatedFile, nil, parser.ParseComments) if err != nil { @@ -327,17 +328,122 @@ } } - intersectionByElem := make(map[string][]string) + type ElemMethod struct { + e, m string + } - doWrites := func(w io.Writer) { + intersectionByElem := make(map[string][]string) + signatureByElemMethod := make(map[ElemMethod]*ast.FuncDecl) + + // elems is a slice of stems of vector types. + elems := []string{"Int8", "Int16", "Int32", "Int64", "Uint8", "Uint16", "Uint32", "Uint64", "Float32", "Float64", "Mask8", "Mask16", "Mask32", "Mask64"} + + for _, elem := range elems { + type128 := map128[elem] + type256 := map256[elem] + type512 := map512[elem] + + methods128w := methodsByType[combine("wasm", type128)] + methods128n := methodsByType[combine("arm64", type128)] + methods128 := methodsByType[combine("amd64", type128)] + methods256 := methodsByType[combine("amd64", type256)] + methods512 := methodsByType[combine("amd64", type512)] + + var intersection []string + var missingNames []string + for m := range allMethodNames { + if wasm128, arm128, amd128, amd256, amd512 := + methods128w[m] == nil, methods128n[m] == nil, methods128[m] == nil, methods256[m] == nil, methods512[m] == nil; !wasm128 && !arm128 && !amd128 && !amd256 && !amd512 { + intersection = append(intersection, m) + signatureByElemMethod[ElemMethod{elem, m}] = methods512[m] // Use 512-bit signature (arbitrary choice, they should match) + } else if !(wasm128 && arm128 && amd128 && amd256 && amd512) { + missing[m] = whyMissing{wasm128, arm128, amd128, amd256, amd512} + missingNames = append(missingNames, m) + } + } + sort.Strings(missingNames) + + for _, m := range missingNames { + pv("Missing implementation for %ss.%s on %s\n", elem, m, missing[m].String()) + } + + sort.Strings(intersection) + + intersectionByElem[elem] = intersection + } + + // xlateType translates a type by replacing instances of types with keys in knownReceivers with their values, + // and generates the string representation of the resulting type. E.g., []Int8x32 -> []Int8s + // (because Int8x32 -> Int8s in knownReceivers + var xlateType func(ast.Expr) string + xlateType = func(e ast.Expr) string { + switch t := e.(type) { + case *ast.Ident: + if mapped, ok := knownReceivers[t.Name]; ok { + return mapped + } + return t.Name + case *ast.StarExpr: + return "*" + xlateType(t.X) + case *ast.ArrayType: + lenStr := "" + if t.Len != nil { + var buf strings.Builder + format.Node(&buf, token.NewFileSet(), t.Len) + lenStr = buf.String() + } + return "[" + lenStr + "]" + xlateType(t.Elt) + case *ast.SelectorExpr: + return xlateType(t.X) + "." + t.Sel.Name + case *ast.Ellipsis: + return "..." + xlateType(t.Elt) + default: + var buf strings.Builder + format.Node(&buf, token.NewFileSet(), t) + return buf.String() + } + } + + toScalar := func(s string) string { + if strings.HasPrefix(s, "Mask") { + return "int" + s[4:] + } + return strings.ToLower(s) + } + + doTypes := func(w io.Writer) { + + pf := func(f string, s ...any) { fmt.Fprintf(w, f, s...) } + + fmt.Fprintln(w, + `// Code generated by 'go run -C $GOROOT/src/simd/archsimd/_gen/midway'; DO NOT EDIT. + +//go:build goexperiment.simd + +// Scalable vector types for rewriting and emulation + +package simd + +import "simd/internal/bridge" + +// internal SIMD marker, and hard dependence on simd/internal/bridge +type _simd bridge.ZeroSized +`) + + for _, elem := range elems { + if c := comments.Types[elem+"s"]; c != "" { + pf("// %s\n", c) + } + pf("type %ss struct {\n\t_ _simd\n\ta, b uint64 // the actual vector size may be larger.\n}\n", elem) + } + } + + doMethods := func(w io.Writer) { p := func(s ...any) { fmt.Fprint(w, s...) } pf := func(f string, s ...any) { fmt.Fprintf(w, f, s...) } nl := func() { fmt.Fprintln(w) } - // elems is a slice of stems of vector types. - elems := []string{"Int8", "Int16", "Int32", "Int64", "Uint8", "Uint16", "Uint32", "Uint64", "Float32", "Float64", "Mask8", "Mask16", "Mask32", "Mask64"} - fmt.Fprintln(w, `// Code generated by 'go run -C $GOROOT/src/simd/archsimd/_gen/midway'; DO NOT EDIT. @@ -347,90 +453,10 @@ package simd -import "simd/internal/bridge" - -// internal SIMD marker, and hard dependence on simd/internal/bridge -type _simd bridge.ZeroSized `) - sigForMethod := make(map[string]*ast.FuncDecl) - - // xlateType translates a type by replacing instances of types with keys in knownReceivers with their values, - // and generates the string representation of the resulting type. E.g., []Int8x32 -> []Int8s - // (because Int8x32 -> Int8s in knownReceivers - var xlateType func(ast.Expr) string - xlateType = func(e ast.Expr) string { - switch t := e.(type) { - case *ast.Ident: - if mapped, ok := knownReceivers[t.Name]; ok { - return mapped - } - return t.Name - case *ast.StarExpr: - return "*" + xlateType(t.X) - case *ast.ArrayType: - lenStr := "" - if t.Len != nil { - var buf strings.Builder - format.Node(&buf, token.NewFileSet(), t.Len) - lenStr = buf.String() - } - return "[" + lenStr + "]" + xlateType(t.Elt) - case *ast.SelectorExpr: - return xlateType(t.X) + "." + t.Sel.Name - case *ast.Ellipsis: - return "..." + xlateType(t.Elt) - default: - var buf strings.Builder - format.Node(&buf, token.NewFileSet(), t) - return buf.String() - } - } - - toScalar := func(s string) string { - if strings.HasPrefix(s, "Mask") { - return "int" + s[4:] - } - return strings.ToLower(s) - } - for _, elem := range elems { - type128 := map128[elem] - type256 := map256[elem] - type512 := map512[elem] - - methods128w := methodsByType[combine("wasm", type128)] - methods128n := methodsByType[combine("arm64", type128)] - methods128 := methodsByType[combine("amd64", type128)] - methods256 := methodsByType[combine("amd64", type256)] - methods512 := methodsByType[combine("amd64", type512)] - - var intersection []string - var missingNames []string - for m := range allMethodNames { - if wasm128, arm128, amd128, amd256, amd512 := - methods128w[m] == nil, methods128n[m] == nil, methods128[m] == nil, methods256[m] == nil, methods512[m] == nil; !wasm128 && !arm128 && !amd128 && !amd256 && !amd512 { - intersection = append(intersection, m) - sigForMethod[m] = methods512[m] // Use 512-bit signature (arbitrary choice, they should match) - } else if !(wasm128 && arm128 && amd128 && amd256 && amd512) { - missing[m] = whyMissing{wasm128, arm128, amd128, amd256, amd512} - missingNames = append(missingNames, m) - } - } - sort.Strings(missingNames) - - for _, m := range missingNames { - pv("Missing implementation for %ss.%s on %s\n", elem, m, missing[m].String()) - } - - sort.Strings(intersection) - - intersectionByElem[elem] = intersection - - if c := comments.Types[elem+"s"]; c != "" { - pf("// %s\n", c) - } - pf("type %ss struct {\n\t_ _simd\n\tatLeast [2]uint64 // the actual vector size may be larger.\n}\n", elem) + intersection := intersectionByElem[elem] if elem[0] != 'M' { // cannot load masks @@ -461,11 +487,10 @@ pf("// %s\n", broadcastComment) } pf("func Broadcast%ss(%s) %ss\n", elem, toScalar(elem), elem) - } for _, m := range intersection { - fd := sigForMethod[m] + fd := signatureByElemMethod[ElemMethod{elem, m}] elems := elem + "s" methodComment := "" if typeMethods, ok := comments.Methods[elem+"s"]; ok { @@ -532,7 +557,10 @@ } } } - formatAndWrite(*goRoot+"/src/simd/simd.go", doWrites) + + formatAndWrite(*goRoot+"/src/simd/simd_types.go", doTypes) + formatAndWrite(*goRoot+"/src/simd/simd_stubs.go", doMethods) + var extraMocks []TypeMethod for x := range emulated { extraMocks = append(extraMocks, x) @@ -548,8 +576,6 @@ pw("%s contains %s.%s missing from intersected methods\n", emulatedFile, x.t, x.m) } - elems := []string{"Int8", "Int16", "Int32", "Int64", "Uint8", "Uint16", "Uint32", "Uint64", "Float32", "Float64", "Mask8", "Mask16", "Mask32", "Mask64"} - for _, aaf := range archAndFiles { arch := aaf.arch doArchWrites := func(w io.Writer) {
diff --git a/src/simd/simd_emulated.go b/src/simd/simd_emulated.go index f23c5c4..d6d5607 100644 --- a/src/simd/simd_emulated.go +++ b/src/simd/simd_emulated.go
@@ -10,7 +10,6 @@ "fmt" "math" "math/bits" - "simd/internal/bridge" ) // VectorSize returns the bit length of the emulated vector (fixed to 128). @@ -33,14 +32,6 @@ return false } -type _simd bridge.ZeroSized - -// Int8s represents a 128-bit vector of 16 int8 elements. -type Int8s struct { - _ _simd - a, b uint64 -} - // LoadInt8s loads a slice of int8 into an Int8s vector. func LoadInt8s(s []int8) Int8s { var a, b uint64 @@ -355,12 +346,6 @@ return Uint8s{a: x.a, b: x.b} } -// Int16s represents a 128-bit vector of 8 int16 elements. -type Int16s struct { - _ _simd - a, b uint64 -} - // LoadInt16s loads a slice of int16 into an Int16s vector. func LoadInt16s(s []int16) Int16s { var a, b uint64 @@ -717,12 +702,6 @@ return Uint16s{a: x.a, b: x.b} } -// Int32s represents a 128-bit vector of 4 int32 elements. -type Int32s struct { - _ _simd - a, b uint64 -} - // LoadInt32s loads a slice of int32 into an Int32s vector. func LoadInt32s(s []int32) Int32s { var a, b uint64 @@ -1056,12 +1035,6 @@ return Uint32s{a: x.a, b: x.b} } -// Int64s represents a 128-bit vector of 2 int64 elements. -type Int64s struct { - _ _simd - a, b uint64 -} - // LoadInt64s loads a slice of int64 into an Int64s vector. func LoadInt64s(s []int64) Int64s { var a, b uint64 @@ -1293,12 +1266,6 @@ return Uint64s{a: x.a, b: x.b} } -// Uint8s represents a 128-bit vector of 16 uint8 elements. -type Uint8s struct { - _ _simd - a, b uint64 -} - // LoadUint8s loads a slice of uint8 into an Uint8s vector. func LoadUint8s(s []uint8) Uint8s { var a, b uint64 @@ -1556,12 +1523,6 @@ return Uint64s{a: x.a, b: x.b} } -// Uint16s represents a 128-bit vector of 8 uint16 elements. -type Uint16s struct { - _ _simd - a, b uint64 -} - // LoadUint16s loads a slice of uint16 into an Uint16s vector. func LoadUint16s(s []uint16) Uint16s { var a, b uint64 @@ -1905,12 +1866,6 @@ return Uint8s{a: x.a, b: x.b} } -// Uint32s represents a 128-bit vector of 4 uint32 elements. -type Uint32s struct { - _ _simd - a, b uint64 -} - // LoadUint32s loads a slice of uint32 into an Uint32s vector. func LoadUint32s(s []uint32) Uint32s { var a, b uint64 @@ -2221,12 +2176,6 @@ return Uint8s{a: x.a, b: x.b} } -// Uint64s represents a 128-bit vector of 2 uint64 elements. -type Uint64s struct { - _ _simd - a, b uint64 -} - // LoadUint64s loads a slice of uint64 into an Uint64s vector. func LoadUint64s(s []uint64) Uint64s { var a, b uint64 @@ -2463,12 +2412,6 @@ return Uint8s{a: x.a, b: x.b} } -// Float32s represents a 128-bit vector of 4 float32 elements. -type Float32s struct { - _ _simd - a, b uint64 -} - // LoadFloat32s loads a slice of float32 into an Float32s vector. func LoadFloat32s(s []float32) Float32s { var a, b uint64 @@ -2751,12 +2694,6 @@ return Uint32s{a: x.a, b: x.b} } -// Float64s represents a 128-bit vector of 2 float64 elements. -type Float64s struct { - _ _simd - a, b uint64 -} - // LoadFloat64s loads a slice of float64 into an Float64s vector. func LoadFloat64s(s []float64) Float64s { var a, b uint64 @@ -3020,12 +2957,6 @@ return Uint64s{a: x.a, b: x.b} } -// Mask8s represents a 128-bit mask vector for 16 int8/uint8 elements. -type Mask8s struct { - _ _simd - a, b uint64 -} - func (x *Mask8s) set(i int, v bool) { if v { if i < 8 { @@ -3058,12 +2989,6 @@ return Int8s{a: x.a, b: x.b} } -// Mask16s represents a 128-bit mask vector for 8 int16/uint16 elements. -type Mask16s struct { - _ _simd - a, b uint64 -} - func (x *Mask16s) set(i int, v bool) { if v { if i < 4 { @@ -3096,12 +3021,6 @@ return Int16s{a: x.a, b: x.b} } -// Mask32s represents a 128-bit mask vector for 4 int32/uint32/float32 elements. -type Mask32s struct { - _ _simd - a, b uint64 -} - func (x *Mask32s) set(i int, v bool) { if v { if i < 2 { @@ -3134,12 +3053,6 @@ return Int32s{a: x.a, b: x.b} } -// Mask64s represents a 128-bit mask vector for 2 int64/uint64/float64 elements. -type Mask64s struct { - _ _simd - a, b uint64 -} - func (x *Mask64s) set(i int, v bool) { if v { if i == 0 {
diff --git a/src/simd/simd.go b/src/simd/simd_stubs.go similarity index 93% rename from src/simd/simd.go rename to src/simd/simd_stubs.go index d390e45..6cb5921 100644 --- a/src/simd/simd.go +++ b/src/simd/simd_stubs.go
@@ -6,17 +6,6 @@ package simd -import "simd/internal/bridge" - -// internal SIMD marker, and hard dependence on simd/internal/bridge -type _simd bridge.ZeroSized - -// Int8s represents a vector of 8-bit signed integers. -type Int8s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadInt8 loads a slice of int8 into an Int8s vector. func LoadInt8s([]int8) Int8s @@ -113,12 +102,6 @@ // Xor returns the bitwise XOR of x and y. func (x Int8s) Xor(y Int8s) Int8s -// Int16s represents a vector of 16-bit signed integers. -type Int16s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadInt16 loads a slice of int16 into an Int16s vector. func LoadInt16s([]int16) Int16s @@ -227,12 +210,6 @@ // Xor returns the bitwise XOR of x and y. func (x Int16s) Xor(y Int16s) Int16s -// Int32s represents a vector of 32-bit signed integers. -type Int32s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadInt32 loads a slice of int32 into an Int32s vector. func LoadInt32s([]int32) Int32s @@ -338,12 +315,6 @@ // Xor returns the bitwise XOR of x and y. func (x Int32s) Xor(y Int32s) Int32s -// Int64s represents a vector of 64-bit signed integers. -type Int64s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadInt64 loads a slice of int64 into an Int64s vector. func LoadInt64s([]int64) Int64s @@ -431,12 +402,6 @@ // Xor returns the bitwise XOR of x and y. func (x Int64s) Xor(y Int64s) Int64s -// Uint8s represents a vector of 8-bit unsigned integers. -type Uint8s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadUint8 loads a slice of uint8 into an Uint8s vector. func LoadUint8s([]uint8) Uint8s @@ -524,12 +489,6 @@ // Xor returns the bitwise XOR of x and y. func (x Uint8s) Xor(y Uint8s) Uint8s -// Uint16s represents a vector of 16-bit unsigned integers. -type Uint16s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadUint16 loads a slice of uint16 into an Uint16s vector. func LoadUint16s([]uint16) Uint16s @@ -641,12 +600,6 @@ // Xor returns the bitwise XOR of x and y. func (x Uint16s) Xor(y Uint16s) Uint16s -// Uint32s represents a vector of 32-bit unsigned integers. -type Uint32s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadUint32 loads a slice of uint32 into an Uint32s vector. func LoadUint32s([]uint32) Uint32s @@ -752,12 +705,6 @@ // Xor returns the bitwise XOR of x and y. func (x Uint32s) Xor(y Uint32s) Uint32s -// Uint64s represents a vector of 64-bit unsigned integers. -type Uint64s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadUint64 loads a slice of uint64 into an Uint64s vector. func LoadUint64s([]uint64) Uint64s @@ -886,12 +833,6 @@ // Xor returns the bitwise XOR of x and y. func (x Uint64s) Xor(y Uint64s) Uint64s -// Float32s represents a vector of 32-bit floating-point numbers. -type Float32s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadFloat32 loads a slice of float32 into an Float32s vector. func LoadFloat32s([]float32) Float32s @@ -973,12 +914,6 @@ // ToBits reinterprets the vector bits as an unsigned integer vector. func (x Float32s) ToBits() Uint32s -// Float64s represents a vector of 64-bit floating-point numbers. -type Float64s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // LoadFloat64 loads a slice of float64 into an Float64s vector. func LoadFloat64s([]float64) Float64s @@ -1057,12 +992,6 @@ // ToBits reinterprets the vector bits as an unsigned integer vector. func (x Float64s) ToBits() Uint64s -// Mask8s represents a boolean mask for Int8s/Uint8s vectors. -type Mask8s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // And returns the bitwise AND of x and y. func (x Mask8s) And(y Mask8s) Mask8s @@ -1075,12 +1004,6 @@ // ToInt8s converts the mask to an Int8s vector. func (x Mask8s) ToInt8s() (to Int8s) -// Mask16s represents a boolean mask for Int16s/Uint16s vectors. -type Mask16s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // And returns the bitwise AND of x and y. func (x Mask16s) And(y Mask16s) Mask16s @@ -1093,12 +1016,6 @@ // ToInt16s converts the mask to an Int16s vector. func (x Mask16s) ToInt16s() (to Int16s) -// Mask32s represents a boolean mask for Int32s/Uint32s vectors. -type Mask32s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // And returns the bitwise AND of x and y. func (x Mask32s) And(y Mask32s) Mask32s @@ -1111,12 +1028,6 @@ // ToInt32s converts the mask to an Int32s vector. func (x Mask32s) ToInt32s() (to Int32s) -// Mask64s represents a boolean mask for Int64s/Uint64s vectors. -type Mask64s struct { - _ _simd - atLeast [2]uint64 // the actual vector size may be larger. -} - // And returns the bitwise AND of x and y. func (x Mask64s) And(y Mask64s) Mask64s
diff --git a/src/simd/simd_types.go b/src/simd/simd_types.go new file mode 100644 index 0000000..fccaa2a --- /dev/null +++ b/src/simd/simd_types.go
@@ -0,0 +1,96 @@ +// Code generated by 'go run -C $GOROOT/src/simd/archsimd/_gen/midway'; DO NOT EDIT. + +//go:build goexperiment.simd + +// Scalable vector types for rewriting and emulation + +package simd + +import "simd/internal/bridge" + +// internal SIMD marker, and hard dependence on simd/internal/bridge +type _simd bridge.ZeroSized + +// Int8s represents a vector of 8-bit signed integers. +type Int8s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Int16s represents a vector of 16-bit signed integers. +type Int16s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Int32s represents a vector of 32-bit signed integers. +type Int32s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Int64s represents a vector of 64-bit signed integers. +type Int64s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Uint8s represents a vector of 8-bit unsigned integers. +type Uint8s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Uint16s represents a vector of 16-bit unsigned integers. +type Uint16s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Uint32s represents a vector of 32-bit unsigned integers. +type Uint32s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Uint64s represents a vector of 64-bit unsigned integers. +type Uint64s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Float32s represents a vector of 32-bit floating-point numbers. +type Float32s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Float64s represents a vector of 64-bit floating-point numbers. +type Float64s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Mask8s represents a boolean mask for Int8s/Uint8s vectors. +type Mask8s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Mask16s represents a boolean mask for Int16s/Uint16s vectors. +type Mask16s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Mask32s represents a boolean mask for Int32s/Uint32s vectors. +type Mask32s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +} + +// Mask64s represents a boolean mask for Int64s/Uint64s vectors. +type Mask64s struct { + _ _simd + a, b uint64 // the actual vector size may be larger. +}