Commit 8623503f authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile/internal/gc: speed up arith const tests

This change reduces the time to run this test on my machine from

real	0m2.491s
user	0m3.020s
sys	0m0.331s

to

real	0m0.237s
user	0m0.180s
sys	0m0.173s

This will make it reasonable to add more constants to the test.
I am also hopeful that it might help a bit with intermittent
cmd/compile/internal/gc test timeouts on the build dashboard
on the slower builders.

The time savings are entirely in compilation time,
by avoiding generating one giant func main.
Instead, generate tables of tests to be run,
which are translated into static data,
and then loop over those tests.

While we're here, do some minor cleanup:

* Remove the _ssa suffix on function names,
  as that was only needed during ssa bootstrapping.
* Clean up error handling during test generation.
* Make functions single-line, to reduce future diff sizes.
  Diffing giant files is slow.

Change-Id: Ic5fccdb71679169bea756c7d33c07d05e4801860
Reviewed-on: https://go-review.googlesource.com/102956
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 360c1915
......@@ -145,26 +145,16 @@ func main() {
fmt.Fprintf(w, "// Code generated by gen/arithConstGen.go. DO NOT EDIT.\n\n")
fmt.Fprintf(w, "package main;\n")
fmt.Fprintf(w, "import \"fmt\"\n")
fmt.Fprintf(w, "import \"os\"\n")
fncCnst1, err := template.New("fnc").Parse(
fncCnst1 := template.Must(template.New("fnc").Parse(
`//go:noinline
func {{.Name}}_{{.Type_}}_{{.FNumber}}_ssa(a {{.Type_}}) {{.Type_}} {
return a {{.Symbol}} {{.Number}}
}
`)
if err != nil {
panic(err)
}
fncCnst2, err := template.New("fnc").Parse(
func {{.Name}}_{{.Type_}}_{{.FNumber}}(a {{.Type_}}) {{.Type_}} { return a {{.Symbol}} {{.Number}} }
`))
fncCnst2 := template.Must(template.New("fnc").Parse(
`//go:noinline
func {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa(a {{.Type_}}) {{.Type_}} {
return {{.Number}} {{.Symbol}} a
}
`)
if err != nil {
panic(err)
}
func {{.Name}}_{{.FNumber}}_{{.Type_}}(a {{.Type_}}) {{.Type_}} { return {{.Number}} {{.Symbol}} a }
`))
type fncData struct {
Name, Type_, Symbol, FNumber, Number string
......@@ -216,31 +206,30 @@ func main() {
}
}
fmt.Fprintf(w, "var failed bool\n\n")
fmt.Fprintf(w, "func main() {\n\n")
vrf1 := template.Must(template.New("vrf1").Parse(`
test_{{.Size}}{fn: {{.Name}}_{{.FNumber}}_{{.Type_}}, fnname: "{{.Name}}_{{.FNumber}}_{{.Type_}}", in: {{.Input}}, want: {{.Ans}}},`))
vrf1, _ := template.New("vrf1").Parse(`
if got := {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa({{.Input}}); got != {{.Ans}} {
fmt.Printf("{{.Name}}_{{.Type_}} {{.Number}}%s{{.Input}} = %d, wanted {{.Ans}}\n", ` + "`{{.Symbol}}`" + `, got)
failed = true
}
`)
vrf2, _ := template.New("vrf2").Parse(`
if got := {{.Name}}_{{.Type_}}_{{.FNumber}}_ssa({{.Input}}); got != {{.Ans}} {
fmt.Printf("{{.Name}}_{{.Type_}} {{.Input}}%s{{.Number}} = %d, wanted {{.Ans}}\n", ` + "`{{.Symbol}}`" + `, got)
failed = true
}
`)
vrf2 := template.Must(template.New("vrf2").Parse(`
test_{{.Size}}{fn: {{.Name}}_{{.Type_}}_{{.FNumber}}, fnname: "{{.Name}}_{{.Type_}}_{{.FNumber}}", in: {{.Input}}, want: {{.Ans}}},`))
type cfncData struct {
Name, Type_, Symbol, FNumber, Number string
Size, Name, Type_, Symbol, FNumber, Number string
Ans, Input string
}
for _, s := range szs {
fmt.Fprintf(w, `
type test_%[1]s struct {
fn func (%[1]s) %[1]s
fnname string
in %[1]s
want %[1]s
}
`, s.name)
fmt.Fprintf(w, "var tests_%[1]s =[]test_%[1]s {\n\n", s.name)
if len(s.u) > 0 {
for _, o := range ops {
fd := cfncData{o.name, s.name, o.symbol, "", "", "", ""}
fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""}
for _, i := range s.u {
fd.Number = fmt.Sprintf("%d", i)
fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1)
......@@ -251,8 +240,7 @@ func main() {
if o.name != "mod" && o.name != "div" || j != 0 {
fd.Ans = ansU(i, j, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j)
err = vrf1.Execute(w, fd)
if err != nil {
if err := vrf1.Execute(w, fd); err != nil {
panic(err)
}
}
......@@ -260,8 +248,7 @@ func main() {
if o.name != "mod" && o.name != "div" || i != 0 {
fd.Ans = ansU(j, i, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j)
err = vrf2.Execute(w, fd)
if err != nil {
if err := vrf2.Execute(w, fd); err != nil {
panic(err)
}
}
......@@ -279,7 +266,7 @@ func main() {
if o.name == "lsh" || o.name == "rsh" {
continue
}
fd := cfncData{o.name, s.name, o.symbol, "", "", "", ""}
fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""}
for _, i := range s.i {
fd.Number = fmt.Sprintf("%d", i)
fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1)
......@@ -287,8 +274,7 @@ func main() {
if o.name != "mod" && o.name != "div" || j != 0 {
fd.Ans = ansS(i, j, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j)
err = vrf1.Execute(w, fd)
if err != nil {
if err := vrf1.Execute(w, fd); err != nil {
panic(err)
}
}
......@@ -296,8 +282,7 @@ func main() {
if o.name != "mod" && o.name != "div" || i != 0 {
fd.Ans = ansS(j, i, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j)
err = vrf2.Execute(w, fd)
if err != nil {
if err := vrf2.Execute(w, fd); err != nil {
panic(err)
}
}
......@@ -307,13 +292,33 @@ func main() {
}
}
fmt.Fprintf(w, "}\n\n")
}
fmt.Fprintf(w, `if failed {
panic("tests failed")
fmt.Fprint(w, `
var failed bool
func main() {
`)
for _, s := range szs {
fmt.Fprintf(w, `for _, test := range tests_%s {`, s.name)
// Use WriteString here to avoid a vet warning about formatting directives.
w.WriteString(`if got := test.fn(test.in); got != test.want {
fmt.Printf("%s(%d) = %d, want %d\n", test.fnname, test.in, got, test.want)
failed = true
}
}
`)
}
fmt.Fprint(w, `
if failed {
os.Exit(1)
}
}
`)
fmt.Fprintf(w, "}\n")
// gofmt result
b := w.Bytes()
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment