1
0
mirror of https://github.com/golang/go synced 2024-11-23 16:20:04 -07:00

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: David Chase <drchase@google.com>
This commit is contained in:
Josh Bleecher Snyder 2018-03-24 16:18:07 -07:00
parent 360c19157a
commit 8623503fe5
2 changed files with 5217 additions and 23770 deletions

File diff suppressed because it is too large Load Diff

View File

@ -145,26 +145,16 @@ func main() {
fmt.Fprintf(w, "// Code generated by gen/arithConstGen.go. DO NOT EDIT.\n\n") fmt.Fprintf(w, "// Code generated by gen/arithConstGen.go. DO NOT EDIT.\n\n")
fmt.Fprintf(w, "package main;\n") fmt.Fprintf(w, "package main;\n")
fmt.Fprintf(w, "import \"fmt\"\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 `//go:noinline
func {{.Name}}_{{.Type_}}_{{.FNumber}}_ssa(a {{.Type_}}) {{.Type_}} { func {{.Name}}_{{.Type_}}_{{.FNumber}}(a {{.Type_}}) {{.Type_}} { return a {{.Symbol}} {{.Number}} }
return a {{.Symbol}} {{.Number}} `))
} fncCnst2 := template.Must(template.New("fnc").Parse(
`)
if err != nil {
panic(err)
}
fncCnst2, err := template.New("fnc").Parse(
`//go:noinline `//go:noinline
func {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa(a {{.Type_}}) {{.Type_}} { func {{.Name}}_{{.FNumber}}_{{.Type_}}(a {{.Type_}}) {{.Type_}} { return {{.Number}} {{.Symbol}} a }
return {{.Number}} {{.Symbol}} a `))
}
`)
if err != nil {
panic(err)
}
type fncData struct { type fncData struct {
Name, Type_, Symbol, FNumber, Number string Name, Type_, Symbol, FNumber, Number string
@ -216,31 +206,30 @@ func main() {
} }
} }
fmt.Fprintf(w, "var failed bool\n\n") vrf1 := template.Must(template.New("vrf1").Parse(`
fmt.Fprintf(w, "func main() {\n\n") test_{{.Size}}{fn: {{.Name}}_{{.FNumber}}_{{.Type_}}, fnname: "{{.Name}}_{{.FNumber}}_{{.Type_}}", in: {{.Input}}, want: {{.Ans}}},`))
vrf1, _ := template.New("vrf1").Parse(` vrf2 := template.Must(template.New("vrf2").Parse(`
if got := {{.Name}}_{{.FNumber}}_{{.Type_}}_ssa({{.Input}}); got != {{.Ans}} { test_{{.Size}}{fn: {{.Name}}_{{.Type_}}_{{.FNumber}}, fnname: "{{.Name}}_{{.Type_}}_{{.FNumber}}", in: {{.Input}}, want: {{.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
}
`)
type cfncData struct { type cfncData struct {
Name, Type_, Symbol, FNumber, Number string Size, Name, Type_, Symbol, FNumber, Number string
Ans, Input string Ans, Input string
} }
for _, s := range szs { 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 { if len(s.u) > 0 {
for _, o := range ops { 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 { for _, i := range s.u {
fd.Number = fmt.Sprintf("%d", i) fd.Number = fmt.Sprintf("%d", i)
fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1)
@ -251,8 +240,7 @@ func main() {
if o.name != "mod" && o.name != "div" || j != 0 { if o.name != "mod" && o.name != "div" || j != 0 {
fd.Ans = ansU(i, j, s.name, o.symbol) fd.Ans = ansU(i, j, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j) fd.Input = fmt.Sprintf("%d", j)
err = vrf1.Execute(w, fd) if err := vrf1.Execute(w, fd); err != nil {
if err != nil {
panic(err) panic(err)
} }
} }
@ -260,8 +248,7 @@ func main() {
if o.name != "mod" && o.name != "div" || i != 0 { if o.name != "mod" && o.name != "div" || i != 0 {
fd.Ans = ansU(j, i, s.name, o.symbol) fd.Ans = ansU(j, i, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j) fd.Input = fmt.Sprintf("%d", j)
err = vrf2.Execute(w, fd) if err := vrf2.Execute(w, fd); err != nil {
if err != nil {
panic(err) panic(err)
} }
} }
@ -279,7 +266,7 @@ func main() {
if o.name == "lsh" || o.name == "rsh" { if o.name == "lsh" || o.name == "rsh" {
continue continue
} }
fd := cfncData{o.name, s.name, o.symbol, "", "", "", ""} fd := cfncData{s.name, o.name, s.name, o.symbol, "", "", "", ""}
for _, i := range s.i { for _, i := range s.i {
fd.Number = fmt.Sprintf("%d", i) fd.Number = fmt.Sprintf("%d", i)
fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1) fd.FNumber = strings.Replace(fd.Number, "-", "Neg", -1)
@ -287,8 +274,7 @@ func main() {
if o.name != "mod" && o.name != "div" || j != 0 { if o.name != "mod" && o.name != "div" || j != 0 {
fd.Ans = ansS(i, j, s.name, o.symbol) fd.Ans = ansS(i, j, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j) fd.Input = fmt.Sprintf("%d", j)
err = vrf1.Execute(w, fd) if err := vrf1.Execute(w, fd); err != nil {
if err != nil {
panic(err) panic(err)
} }
} }
@ -296,8 +282,7 @@ func main() {
if o.name != "mod" && o.name != "div" || i != 0 { if o.name != "mod" && o.name != "div" || i != 0 {
fd.Ans = ansS(j, i, s.name, o.symbol) fd.Ans = ansS(j, i, s.name, o.symbol)
fd.Input = fmt.Sprintf("%d", j) fd.Input = fmt.Sprintf("%d", j)
err = vrf2.Execute(w, fd) if err := vrf2.Execute(w, fd); err != nil {
if err != nil {
panic(err) panic(err)
} }
} }
@ -307,13 +292,33 @@ func main() {
} }
} }
fmt.Fprintf(w, "}\n\n")
} }
fmt.Fprintf(w, `if failed { fmt.Fprint(w, `
panic("tests failed") 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 // gofmt result
b := w.Bytes() b := w.Bytes()