Skip to content

Commit b0f513d

Browse files
JunyangShaogopherbot
authored andcommitted
internal/simdgen: complete the godef code gen
This generator supports generating the godefs of SIMD instructions with some shape constraints, please check gen_utility.go for the details. Change-Id: I87151740e161919c67c3f20c0258de6611e4955e Reviewed-on: https://go-review.googlesource.com/c/arch/+/667155 LUCI-TryBot-Result: Go LUCI <[email protected]> Auto-Submit: Junyang Shao <[email protected]> Reviewed-by: Junyang Shao <[email protected]> Reviewed-by: David Chase <[email protected]>
1 parent 3022628 commit b0f513d

25 files changed

+2817
-328
lines changed

internal/simdgen/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testdata/*

internal/simdgen/categories.yaml

Lines changed: 115 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,118 @@
11
!sum
22
- go: Add
3-
category: binary
4-
- go: AddSaturated
5-
category: binary
3+
commutative: "true"
4+
extension: "AVX.*"
5+
- go: SaturatedAdd
6+
commutative: "true"
7+
extension: "AVX.*"
8+
- go: MaskedAdd
9+
masked: "true"
10+
commutative: "true"
11+
extension: "AVX.*"
12+
- go: MaskedSaturatedAdd
13+
masked: "true"
14+
commutative: "true"
15+
extension: "AVX.*"
616
- go: Sub
7-
category: binary
17+
commutative: "true"
18+
extension: "AVX.*"
19+
- go: SaturatedSub
20+
commutative: "true"
21+
extension: "AVX.*"
22+
- go: MaskedSub
23+
masked: "true"
24+
commutative: "true"
25+
extension: "AVX.*"
26+
- go: MaskedSaturatedSub
27+
masked: "true"
28+
commutative: "true"
29+
extension: "AVX.*"
30+
- go: And
31+
commutative: "true"
32+
extension: "AVX.*"
33+
- go: MaskedAnd
34+
masked: "true"
35+
commutative: "true"
36+
extension: "AVX.*"
37+
- go: Or
38+
commutative: "true"
39+
extension: "AVX.*"
40+
- go: MaskedOr
41+
masked: "true"
42+
commutative: "true"
43+
extension: "AVX.*"
44+
- go: AndNot
45+
commutative: "true"
46+
extension: "AVX.*"
47+
- go: MaskedAndNot
48+
masked: "true"
49+
commutative: "true"
50+
extension: "AVX.*"
51+
- go: Xor
52+
commutative: "true"
53+
extension: "AVX.*"
54+
- go: MaskedXor
55+
masked: "true"
56+
commutative: "true"
57+
extension: "AVX.*"
58+
# We also have PTEST and VPTERNLOG, those should be hidden from the users
59+
# and only appear in rewrite rules.
60+
- go: Equal
61+
constImm: 0
62+
commutative: "true"
63+
extension: "AVX.*"
64+
- go: Greater
65+
constImm: 6
66+
commutative: "false"
67+
extension: "AVX.*"
68+
- go: MaskedEqual
69+
constImm: 0
70+
masked: "true"
71+
commutative: "true"
72+
extension: "AVX.*"
73+
- go: MaskedGreater
74+
constImm: 6
75+
masked: "true"
76+
commutative: "false"
77+
extension: "AVX.*"
78+
- go: Div
79+
commutative: "true"
80+
extension: "AVX.*"
81+
- go: MaskedDiv
82+
commutative: "true"
83+
masked: "true"
84+
extension: "AVX.*"
85+
- go: Mul
86+
commutative: "true"
87+
extension: "AVX.*"
88+
- go: MulEvenWiden
89+
commutative: "true"
90+
extension: "AVX.*"
91+
documentation: "Multiplies the even index elements from the two sources of size X at index i, store the result of size 2X at index i/2"
92+
- go: MulHigh
93+
commutative: "true"
94+
extension: "AVX.*"
95+
documentation: "Multiplies the elements from the two sources of size X at index i, store the high X bits of the result of size 2X at index i"
96+
- go: MulLow
97+
commutative: "true"
98+
extension: "AVX.*"
99+
documentation: "Multiplies the elements from the two sources of size X at index i, store the low X bits of the result of size 2X at index i"
100+
- go: MaskedMul
101+
masked: "true"
102+
commutative: "true"
103+
extension: "AVX.*"
104+
- go: MaskedMulEvenWiden
105+
masked: "true"
106+
commutative: "true"
107+
extension: "AVX.*"
108+
documentation: "Multiplies the even index elements from the two sources of size X at index i, store the result of size 2X at index i/2"
109+
- go: MaskedMulHigh
110+
masked: "true"
111+
commutative: "true"
112+
extension: "AVX.*"
113+
documentation: "Multiplies the elements from the two sources of size X at index i, store the high X bits of the result of size 2X at index i"
114+
- go: MaskedMulLow
115+
masked: "true"
116+
commutative: "true"
117+
extension: "AVX.*"
118+
documentation: "Multiplies the elements from the two sources of size X at index i, store the low X bits of the result of size 2X at index i"
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
"sort"
10+
)
11+
12+
const simdGenericOpsTmpl = `// 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.
13+
package main
14+
15+
func simdGenericOps() []opData {
16+
return []opData{
17+
{{- range . }}
18+
{name: "{{.OpName}}", argLength: {{.OpInLen}}, commutative: {{.Comm}}},
19+
{{- end }}
20+
}
21+
}
22+
`
23+
24+
// writeSIMDGenericOps generates the generic ops and writes it to simdAMD64ops.go
25+
// within the specified directory.
26+
func writeSIMDGenericOps(directory string, ops []Operation) error {
27+
file, t, err := openFileAndPrepareTemplate(directory, "src/cmd/compile/internal/ssa/_gen/simdgenericOps.go", simdGenericOpsTmpl)
28+
if err != nil {
29+
return err
30+
}
31+
defer file.Close()
32+
type genericOpsData struct {
33+
sortKey string
34+
OpName string
35+
OpInLen int
36+
Comm string
37+
}
38+
opsData := make([]genericOpsData, 0)
39+
for _, op := range ops {
40+
_, _, _, _, _, gOp, err := op.shape()
41+
if err != nil {
42+
return err
43+
}
44+
genericNames := gOp.Go + *gOp.In[0].Go
45+
opsData = append(opsData, genericOpsData{*gOp.In[0].Go + gOp.Go, genericNames, len(gOp.In), op.Commutative})
46+
}
47+
sort.Slice(opsData, func(i, j int) bool {
48+
return opsData[i].sortKey < opsData[j].sortKey
49+
})
50+
51+
err = t.Execute(file, opsData)
52+
if err != nil {
53+
return fmt.Errorf("failed to execute template: %w", err)
54+
}
55+
56+
return nil
57+
}
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// Copyright 2025 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package main
6+
7+
import (
8+
"fmt"
9+
)
10+
11+
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.
12+
package ssagen
13+
14+
import (
15+
"cmd/compile/internal/ir"
16+
"cmd/compile/internal/ssa"
17+
"cmd/compile/internal/types"
18+
"cmd/internal/sys"
19+
)
20+
21+
func simdIntrinsics(addF func(pkg, fn string, b intrinsicBuilder, archFamilies ...sys.ArchFamily)) {
22+
{{- range .OpsLen1}}
23+
addF("internal/simd", "{{(index .In 0).Go}}.{{.Go}}", opLen1(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
24+
{{- end}}
25+
{{- range .OpsLen2}}
26+
addF("internal/simd", "{{(index .In 0).Go}}.{{.Go}}", opLen2(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
27+
{{- end}}
28+
{{- range .OpsLen3}}
29+
addF("internal/simd", "{{(index .In 0).Go}}.{{.Go}}", opLen3(ssa.Op{{.Go}}{{(index .In 0).Go}}, {{.GoArch}}), sys.AMD64)
30+
{{- end}}
31+
32+
{{- range .VectorConversions }}
33+
addF("internal/simd", "{{.Tsrc.Name}}.As{{.Tdst.Name}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
34+
{{- end}}
35+
36+
{{- range $size, $ts := .TypeMap }}
37+
{{- range $t := $ts }}
38+
addF("internal/simd", "Load{{$t.Name}}", simdLoad(), sys.AMD64)
39+
addF("internal/simd", "{{$t.Name}}.Store", simdStore(), sys.AMD64)
40+
{{- end}}
41+
{{- end}}
42+
{{- range .Masks }}
43+
addF("internal/simd", "{{.Name}}.As{{.VectorCounterpart}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
44+
addF("internal/simd", "{{.VectorCounterpart}}.As{{.Name}}", func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value { return args[0] }, sys.AMD64)
45+
addF("internal/simd", "{{.Name}}.And", opLen2(ssa.OpAnd{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64)
46+
addF("internal/simd", "{{.Name}}.Or", opLen2(ssa.OpOr{{.ReshapedVectorWithAndOr}}, types.TypeVec{{.Size}}), sys.AMD64)
47+
{{- end}}
48+
}
49+
50+
func opLen1(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
51+
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
52+
return s.newValue1(op, t, args[0])
53+
}
54+
}
55+
56+
func opLen2(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
57+
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
58+
return s.newValue2(op, t, args[0], args[1])
59+
}
60+
}
61+
62+
func opLen3(op ssa.Op, t *types.Type) func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
63+
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
64+
return s.newValue3(op, t, args[0], args[1], args[2])
65+
}
66+
}
67+
68+
func simdLoad() func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
69+
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
70+
return s.newValue2(ssa.OpLoad, n.Type(), args[0], s.mem())
71+
}
72+
}
73+
74+
func simdStore() func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
75+
return func(s *state, n *ir.CallExpr, args []*ssa.Value) *ssa.Value {
76+
s.store(args[0].Type, args[1], args[0])
77+
return nil
78+
}
79+
}
80+
`
81+
82+
// writeSIMDIntrinsics generates the intrinsic mappings and writes it to simdintrinsics.go
83+
// within the specified directory.
84+
func writeSIMDIntrinsics(directory string, ops []Operation, typeMap simdTypeMap) error {
85+
file, t, err := openFileAndPrepareTemplate(directory, "src/cmd/compile/internal/ssagen/simdintrinsics.go", simdIntrinsicsTmpl)
86+
if err != nil {
87+
return err
88+
}
89+
defer file.Close()
90+
opsLen1, opsLen2, opsLen3, err := genericOpsByLen(ops)
91+
if err != nil {
92+
return err
93+
}
94+
95+
type templateData struct {
96+
OpsLen1 []Operation
97+
OpsLen2 []Operation
98+
OpsLen3 []Operation
99+
TypeMap simdTypeMap
100+
VectorConversions []simdTypePair
101+
Masks []simdType
102+
}
103+
err = t.Execute(file, templateData{opsLen1, opsLen2, opsLen3, typeMap, vConvertFromTypeMap(typeMap), masksFromTypeMap(typeMap)})
104+
if err != nil {
105+
return fmt.Errorf("failed to execute template: %w", err)
106+
}
107+
108+
return nil
109+
}

0 commit comments

Comments
 (0)