internal/simdgen: remove map-iteration dependence from output This makes checking for (lack of) effects from changes much easier. Change-Id: I0b8c49381798d924541abb95bbfcbe8281d37950 Reviewed-on: https://go-review.googlesource.com/c/arch/+/680178 Reviewed-by: Cherry Mui <cherryyz@google.com> LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
diff --git a/internal/simdgen/gen_simdTypes.go b/internal/simdgen/gen_simdTypes.go index d19c8d2..0405c58 100644 --- a/internal/simdgen/gen_simdTypes.go +++ b/internal/simdgen/gen_simdTypes.go
@@ -6,6 +6,8 @@ import ( "fmt" + "slices" + "sort" "strings" ) @@ -20,6 +22,14 @@ Size int // The size of the type } +func compareSimdTypes(x, y simdType) int { + c := strings.Compare(x.Name, y.Name) + if c != 0 { + return c + } + return strings.Compare(x.Type, y.Type) +} + type simdTypeMap map[int][]simdType type simdTypePair struct { @@ -27,44 +37,51 @@ Tdst simdType } -const simdTypesTmpl = `// Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. +func compareSimdTypePairs(x, y simdTypePair) int { + c := compareSimdTypes(x.Tsrc, y.Tsrc) + if c != 0 { + return c + } + return compareSimdTypes(x.Tdst, y.Tdst) +} + +const simdTypesTemplates = `{{define "fileHeader"}}// Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. //go:build goexperiment.simd package simd +{{end}} -{{- range $size, $ts := .TypeMap }} +{{define "sizeTmpl"}} +// v{{.}} is a tag type that tells the compiler that this is really {{.}}-bit SIMD +type v{{.}} struct { + _{{.}} struct{} +} +{{end}} -// v{{$size}} is a tag type that tells the compiler that this is really {{$size}}-bit SIMD -type v{{$size}} struct { - _{{$size}} struct{} +{{define "typeTmpl"}} +// {{.Name}} is a {{.Size}}-bit SIMD vector of {{.Lanes}} {{.Base}} +type {{.Name}} struct { +{{.Fields}} } -{{- range $i, $tsrc := $ts }} +{{- if ne .Type "mask"}} -// {{$tsrc.Name}} is a {{$size}}-bit SIMD vector of {{$tsrc.Lanes}} {{$tsrc.Base}} -type {{$tsrc.Name}} struct { -{{$tsrc.Fields}} -} +// Len returns the number of elements in a {{.Name}} +func (x {{.Name}}) Len() int { return {{.Lanes}} } -{{- if ne $tsrc.Type "mask"}} - -// Len returns the number of elements in a {{$tsrc.Name}} -func (x {{$tsrc.Name}}) Len() int { return {{$tsrc.Lanes}} } - -// Load{{$tsrc.Name}} loads a {{$tsrc.Name}} from an array +// Load{{.Name}} loads a {{.Name}} from an array // //go:noescape -func Load{{$tsrc.Name}}(y *[{{$tsrc.Lanes}}]{{$tsrc.Base}}) {{$tsrc.Name}} +func Load{{.Name}}(y *[{{.Lanes}}]{{.Base}}) {{.Name}} -// Store stores a {{$tsrc.Name}} to an array +// Store stores a {{.Name}} to an array // //go:noescape -func (x {{$tsrc.Name}}) Store(y *[{{$tsrc.Lanes}}]{{$tsrc.Base}}) +func (x {{.Name}}) Store(y *[{{.Lanes}}]{{.Base}}) {{- end}} -{{- end}} -{{- end}} +{{end}} ` const simdStubsTmpl = `// Code generated by x/arch/internal/simdgen using 'go run . -xedPath $XED_PATH -o godefs -goroot $GOROOT go.yaml types.yaml categories.yaml'; DO NOT EDIT. @@ -168,6 +185,7 @@ } } } + slices.SortFunc(v, compareSimdTypePairs) return v } @@ -180,25 +198,38 @@ } } } + slices.SortFunc(m, compareSimdTypes) return m } // writeSIMDTypes generates the simd vector type and writes it to types_amd64.go // within the specified directory. func writeSIMDTypes(directory string, typeMap simdTypeMap) error { - file, t, err := openFileAndPrepareTemplate(directory, "src/"+simdPackage+"/types_amd64.go", simdTypesTmpl) + file, t, err := openFileAndPrepareTemplate(directory, "src/"+simdPackage+"/types_amd64.go", simdTypesTemplates) if err != nil { return err } defer file.Close() - type templateData struct { - TypeMap simdTypeMap + if err := t.ExecuteTemplate(file, "fileHeader", nil); err != nil { + return fmt.Errorf("failed to execute fileHeader template: %w", err) } - err = t.Execute(file, templateData{typeMap}) - if err != nil { - return fmt.Errorf("failed to execute template: %w", err) + sizes := make([]int, 0, len(typeMap)) + for size := range typeMap { + sizes = append(sizes, size) + } + sort.Ints(sizes) + + for _, size := range sizes { + if err := t.ExecuteTemplate(file, "sizeTmpl", size); err != nil { + return fmt.Errorf("failed to execute size template for size %d: %w", size, err) + } + for _, typeDef := range typeMap[size] { + if err := t.ExecuteTemplate(file, "typeTmpl", typeDef); err != nil { + return fmt.Errorf("failed to execute type template for type %s: %w", typeDef.Name, err) + } + } } return nil
diff --git a/internal/simdgen/gen_utility.go b/internal/simdgen/gen_utility.go index 28a451d..7fcade6 100644 --- a/internal/simdgen/gen_utility.go +++ b/internal/simdgen/gen_utility.go
@@ -355,6 +355,7 @@ } deduped = append(deduped, dup[0]) } + slices.SortFunc(deduped, compareOperations) return deduped, nil }
diff --git a/internal/simdgen/godefs.go b/internal/simdgen/godefs.go index 2a611c9..9309e0c 100644 --- a/internal/simdgen/godefs.go +++ b/internal/simdgen/godefs.go
@@ -6,6 +6,8 @@ import ( "log" + "slices" + "strings" "golang.org/x/arch/internal/unify" ) @@ -30,6 +32,47 @@ Masked *string } +func compareStringPointers(x, y *string) int { + if x != nil && y != nil { + return strings.Compare(*x, *y) + } + if x == nil && y == nil { + return 0 + } + if x == nil { + return -1 + } + return 1 +} + +func compareOperations(x, y Operation) int { + if c := strings.Compare(x.Go, y.Go); c != 0 { + return c + } + if c := strings.Compare(x.GoArch, y.GoArch); c != 0 { + return c + } + if len(x.In) < len(y.In) { + return -1 + } + if len(x.In) > len(y.In) { + return 1 + } + if len(x.Out) < len(y.Out) { + return -1 + } + if len(x.Out) > len(y.Out) { + return 1 + } + for i := range x.In { + ox, oy := &x.In[i], y.In[i] + if c := compareStringPointers(ox.Go, oy.Go); c != 0 { + return c + } + } + return 0 +} + type Operand struct { Class string // One of "mask", "immediate", "vreg" and "mem" @@ -68,6 +111,7 @@ op.sortOperand() ops = append(ops, op) } + slices.SortFunc(ops, compareOperations) // The parsed XED data might contain duplicates, like // 512 bits VPADDP. deduped := dedup(ops)