aboutsummaryrefslogtreecommitdiff
path: root/src/simd/genfiles.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/simd/genfiles.go')
-rw-r--r--src/simd/genfiles.go155
1 files changed, 155 insertions, 0 deletions
diff --git a/src/simd/genfiles.go b/src/simd/genfiles.go
index 80234ac9f8..be23b127c8 100644
--- a/src/simd/genfiles.go
+++ b/src/simd/genfiles.go
@@ -254,6 +254,15 @@ package simd
`, s)
}
+func ssaPrologue(s string, out io.Writer) {
+ fmt.Fprintf(out,
+ `// Code generated by '%s'; DO NOT EDIT.
+
+package ssa
+
+`, s)
+}
+
func unsafePrologue(s string, out io.Writer) {
fmt.Fprintf(out,
`// Code generated by '%s'; DO NOT EDIT.
@@ -806,6 +815,7 @@ func (x {{.VType}}) String() string {
`)
const TD = "internal/simd_test/"
+const SSA = "../cmd/compile/internal/ssa/"
func main() {
sl := flag.String("sl", "slice_gen_amd64.go", "file name for slice operations")
@@ -867,6 +877,115 @@ func main() {
if *cmh != "" {
one(*cmh, curryTestPrologue("simd methods that compare two operands under a mask"), compareMaskedTemplate)
}
+
+ nonTemplateRewrites(SSA+"tern_helpers.go", ssaPrologue, classifyBooleanSIMD, ternOpForLogical)
+
+}
+
+func ternOpForLogical(out io.Writer) {
+ fmt.Fprintf(out, `
+func ternOpForLogical(op Op) Op {
+ switch op {
+`)
+
+ intShapes.forAllShapes(func(seq int, t, upperT string, w, c int, out io.Writer) {
+ wt, ct := w, c
+ if wt < 32 {
+ wt = 32
+ ct = (w * c) / wt
+ }
+ fmt.Fprintf(out, "case OpAndInt%[1]dx%[2]d, OpOrInt%[1]dx%[2]d, OpXorInt%[1]dx%[2]d,OpAndNotInt%[1]dx%[2]d: return OpternInt%dx%d\n", w, c, wt, ct)
+ fmt.Fprintf(out, "case OpAndUint%[1]dx%[2]d, OpOrUint%[1]dx%[2]d, OpXorUint%[1]dx%[2]d,OpAndNotUint%[1]dx%[2]d: return OpternUint%dx%d\n", w, c, wt, ct)
+ }, out)
+
+ fmt.Fprintf(out, `
+ }
+ return op
+}
+`)
+
+}
+
+func classifyBooleanSIMD(out io.Writer) {
+ fmt.Fprintf(out, `
+type SIMDLogicalOP uint8
+const (
+ // boolean simd operations, for reducing expression to VPTERNLOG* instructions
+ // sloInterior is set for non-root nodes in logical-op expression trees.
+ sloInterior SIMDLogicalOP = 1
+ sloNone SIMDLogicalOP = 2 * iota
+ sloAnd
+ sloOr
+ sloAndNot
+ sloXor
+ sloNot
+)
+func classifyBooleanSIMD(v *Value) SIMDLogicalOP {
+ switch v.Op {
+ case `)
+ intShapes.forAllShapes(func(seq int, t, upperT string, w, c int, out io.Writer) {
+ op := "And"
+ if seq > 0 {
+ fmt.Fprintf(out, ",Op%s%s%dx%d", op, upperT, w, c)
+ } else {
+ fmt.Fprintf(out, "Op%s%s%dx%d", op, upperT, w, c)
+ }
+ seq++
+ }, out)
+
+ fmt.Fprintf(out, `:
+ return sloAnd
+
+ case `)
+ intShapes.forAllShapes(func(seq int, t, upperT string, w, c int, out io.Writer) {
+ op := "Or"
+ if seq > 0 {
+ fmt.Fprintf(out, ",Op%s%s%dx%d", op, upperT, w, c)
+ } else {
+ fmt.Fprintf(out, "Op%s%s%dx%d", op, upperT, w, c)
+ }
+ seq++
+ }, out)
+
+ fmt.Fprintf(out, `:
+ return sloOr
+
+ case `)
+ intShapes.forAllShapes(func(seq int, t, upperT string, w, c int, out io.Writer) {
+ op := "AndNot"
+ if seq > 0 {
+ fmt.Fprintf(out, ",Op%s%s%dx%d", op, upperT, w, c)
+ } else {
+ fmt.Fprintf(out, "Op%s%s%dx%d", op, upperT, w, c)
+ }
+ seq++
+ }, out)
+
+ fmt.Fprintf(out, `:
+ return sloAndNot
+`)
+
+ // "Not" is encoded as x.Xor(x.Equal(x).AsInt8x16())
+ // i.e. xor.Args[0] == x, xor.Args[1].Op == As...
+ // but AsInt8x16 is a pun/passthrough.
+
+ intShapes.forAllShapes(
+ func(seq int, t, upperT string, w, c int, out io.Writer) {
+ fmt.Fprintf(out, "case OpXor%s%dx%d: ", upperT, w, c)
+ fmt.Fprintf(out, `
+ if y := v.Args[1]; y.Op == OpEqual%s%dx%d &&
+ y.Args[0] == y.Args[1] {
+ return sloNot
+ }
+ `, upperT, w, c)
+ fmt.Fprintf(out, "return sloXor\n")
+ }, out)
+
+ fmt.Fprintf(out, `
+ }
+ return sloNone
+}
+`)
}
// numberLines takes a slice of bytes, and returns a string where each line
@@ -881,6 +1000,42 @@ func numberLines(data []byte) string {
return buf.String()
}
+func nonTemplateRewrites(filename string, prologue func(s string, out io.Writer), rewrites ...func(out io.Writer)) {
+ if filename == "" {
+ return
+ }
+
+ ofile := os.Stdout
+
+ if filename != "-" {
+ var err error
+ ofile, err = os.Create(filename)
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "Could not create the output file %s for the generated code, %v", filename, err)
+ os.Exit(1)
+ }
+ }
+
+ out := new(bytes.Buffer)
+
+ prologue("go run genfiles.go", out)
+ for _, rewrite := range rewrites {
+ rewrite(out)
+ }
+
+ b, err := format.Source(out.Bytes())
+ if err != nil {
+ fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
+ fmt.Fprintf(os.Stderr, "%s\n", numberLines(out.Bytes()))
+ fmt.Fprintf(os.Stderr, "There was a problem formatting the generated code for %s, %v\n", filename, err)
+ os.Exit(1)
+ } else {
+ ofile.Write(b)
+ ofile.Close()
+ }
+
+}
+
func one(filename string, prologue func(s string, out io.Writer), sats ...shapeAndTemplate) {
if filename == "" {
return