blob: 377026b97f1e999b334393927db2637d54861cd6 [file]
// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package main
import (
"fmt"
)
const simdIntrinsicsTmpl = `// 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.
package ssagen
import (
"cmd/compile/internal/ir"
"cmd/compile/internal/ssa"
"cmd/compile/internal/types"
"cmd/internal/sys"
)
const simdPackage = "` + simdPackage + `"
func simdIntrinsics(addF func(pkg, fn string, b intrinsicBuilder, archFamilies ...sys.ArchFamily)) {
{{- range .OpsLen1}}
addF(simdPackage, "{{(index .In 0).Go}}.{{.Go}}", opLen1(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
{{- end}}
{{- range .OpsLen2}}
addF(simdPackage, "{{(index .In 0).Go}}.{{.Go}}", opLen2(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
{{- end}}
{{- range .OpsLen3}}
addF(simdPackage, "{{(index .In 0).Go}}.{{.Go}}", opLen3(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
{{- end}}
{{- range .VectorConversions }}
addF(simdPackage, "{{.Tsrc.Name}}.As{{.Tdst.Name}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
{{- end}}
{{- range $size, $ts := .TypeMap }}
{{- range $t := $ts }}
addF(simdPackage, "Load{{$t.Name}}", simdLoad(), sys.AMD64)
addF(simdPackage, "{{$t.Name}}.Store", simdStore(), sys.AMD64)
{{- end}}
{{- end}}
{{- range .Masks }}
addF(simdPackage, "{{.Name}}.As{{.VectorCounterpart}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
addF(simdPackage, "{{.VectorCounterpart}}.As{{.Name}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
addF(simdPackage, "{{.Name}}.And", opLen2(ssa.OpAnd{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64)
addF(simdPackage, "{{.Name}}.Or", opLen2(ssa.OpOr{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64)
{{- end}}
}
func opLen1(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue1(op, t, args[0])
}
}
func opLen2(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue2(op, t, args[0], args[1])
}
}
func opLen3(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue3(op, t, args[0], args[1], args[2])
}
}
func simdLoad() func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return s.newValue2(ssa.OpLoad, n.Type(), args[0], s.mem())
}
}
func simdStore() func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
s.store(args[0].Type, args[1], args[0])
return nil
}
}
`
// writeSIMDIntrinsics generates the intrinsic mappings and writes it to simdintrinsics.go
// within the specified directory.
func writeSIMDIntrinsics(directory string, ops []Operation, typeMap simdTypeMap) error {
file, t, err := openFileAndPrepareTemplate(directory, "src/cmd/compile/internal/ssagen/simdintrinsics.go", simdIntrinsicsTmpl)
if err != nil {
return err
}
defer file.Close()
opsLen1, opsLen2, opsLen3, err := genericOpsByLen(ops)
if err != nil {
return err
}
type templateData struct {
OpsLen1 []Operation
OpsLen2 []Operation
OpsLen3 []Operation
TypeMap simdTypeMap
VectorConversions []simdTypePair
Masks []simdType
}
err = t.Execute(file, templateData{opsLen1, opsLen2, opsLen3, typeMap, vConvertFromTypeMap(typeMap), masksFromTypeMap(typeMap)})
if err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}
return nil
}