aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2015-10-26 17:34:06 -0400
committerDavid Chase <drchase@google.com>2015-10-30 20:35:20 +0000
commit729abfa35ca19a3ec9bd11a8c25eecac5eba6cc9 (patch)
treeabaf8863178d53eac8a613c27f44fded89c95db1 /src/cmd
parentcdc36252fe38cef9afa1fa1efa61897fae8a21a2 (diff)
downloadgo-729abfa35ca19a3ec9bd11a8c25eecac5eba6cc9.tar.xz
[dev.ssa] cmd/compile: default compile+test with SSA
Some tests disabled, some bifurcated into _ssa and not, with appropriate logging added to compiler. "tests/live.go" in particular needs attention. SSA-specific testing removed, since it's all SSA now. Added "-run_skips" option to tests/run.go to simplify checking whether a test still fails (or how it fails) on a skipped platform. The compiler now compiles with SSA by default. If you don't want SSA, specify GOSSAHASH=n (or N) as an environment variable. Function names ending in "_ssa" are always SSA-compiled. GOSSAFUNC=fname retains its "SSA for fname, log to ssa.html" GOSSAPKG=pkg only has an effect when GOSSAHASH=n GOSSAHASH=10101 etc retains its name-hash-matching behavior for purposes of debugging. See #13068 Change-Id: I8217bfeb34173533eaeb391b5f6935483c7d6b43 Reviewed-on: https://go-review.googlesource.com/16299 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: David Chase <drchase@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/gc/ssa.go48
-rw-r--r--src/cmd/compile/internal/ssa/config.go14
-rw-r--r--src/cmd/compile/internal/ssa/export_test.go8
-rw-r--r--src/cmd/compile/internal/ssa/nilcheck.go7
-rw-r--r--src/cmd/dist/test.go34
5 files changed, 58 insertions, 53 deletions
diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go
index b96661d15e..521e6d7ffa 100644
--- a/src/cmd/compile/internal/gc/ssa.go
+++ b/src/cmd/compile/internal/gc/ssa.go
@@ -34,10 +34,10 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
// 1. IF GOSSAFUNC == current function name THEN
// compile this function with SSA and log output to ssa.html
- // 2. IF GOSSAHASH == "y" or "Y" THEN
+ // 2. IF GOSSAHASH == "" THEN
// compile this function (and everything else) with SSA
- // 3. IF GOSSAHASH == "" THEN
+ // 3. IF GOSSAHASH == "n" or "N"
// IF GOSSAPKG == current package name THEN
// compile this function (and everything in this package) with SSA
// ELSE
@@ -49,9 +49,10 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
// ELSE
// compile this function with the old back end.
- // Plan is for 3 to be remove, and the 2) dependence on GOSSAHASH changes
- // from "y"/"Y" to empty -- then SSA is default, and is disabled by setting
- // GOSSAHASH to a value that is neither 0 nor 1 (e.g., "N" or "X")
+ // Plan is for 3 to be removed when the tests are revised.
+ // SSA is now default, and is disabled by setting
+ // GOSSAHASH to n or N, or selectively with strings of
+ // 0 and 1.
if usessa {
fmt.Println("generating SSA for", name)
@@ -183,10 +184,11 @@ func buildssa(fn *Node) (ssafn *ssa.Func, usessa bool) {
// Main call to ssa package to compile function
ssa.Compile(s.f)
- if usessa || gossahash == "y" || gossahash == "Y" {
+ // gossahash = "y" is historical/symmetric-with-"n" -- i.e., not really needed.
+ if usessa || gossahash == "" || gossahash == "y" || gossahash == "Y" {
return s.f, true
}
- if gossahash == "" {
+ if gossahash == "n" || gossahash == "N" {
if localpkg.Name != os.Getenv("GOSSAPKG") {
return s.f, false
}
@@ -298,9 +300,11 @@ func (s *state) label(sym *Sym) *ssaLabel {
return lab
}
-func (s *state) Logf(msg string, args ...interface{}) { s.config.Logf(msg, args...) }
-func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(msg, args...) }
-func (s *state) Unimplementedf(msg string, args ...interface{}) { s.config.Unimplementedf(msg, args...) }
+func (s *state) Logf(msg string, args ...interface{}) { s.config.Logf(msg, args...) }
+func (s *state) Fatalf(msg string, args ...interface{}) { s.config.Fatalf(msg, args...) }
+func (s *state) Unimplementedf(msg string, args ...interface{}) { s.config.Unimplementedf(msg, args...) }
+func (s *state) Warnl(line int, msg string, args ...interface{}) { s.config.Warnl(line, msg, args...) }
+func (s *state) Debug_checknil() bool { return s.config.Debug_checknil() }
var (
// dummy node for the memory variable
@@ -1997,7 +2001,7 @@ func (s *state) expr(n *Node) *ssa.Value {
if haspointers(et) {
// TODO: just one write barrier call for all of these writes?
// TODO: maybe just one writeBarrierEnabled check?
- s.insertWB(et, addr)
+ s.insertWB(et, addr, n.Lineno)
}
}
@@ -2044,7 +2048,7 @@ func (s *state) assign(left *Node, right *ssa.Value, wb bool) {
}
s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, t.Size(), addr, right, s.mem())
if wb {
- s.insertWB(left.Type, addr)
+ s.insertWB(left.Type, addr, left.Lineno)
}
}
@@ -2566,7 +2570,7 @@ func (s *state) rtcall(fn *Node, returns bool, results []*Type, args ...*ssa.Val
// been stored at location p. Tell the runtime about this write.
// Note: there must be no GC suspension points between the write and
// the call that this function inserts.
-func (s *state) insertWB(t *Type, p *ssa.Value) {
+func (s *state) insertWB(t *Type, p *ssa.Value, line int32) {
// if writeBarrierEnabled {
// typedmemmove_nostore(&t, p)
// }
@@ -2586,6 +2590,10 @@ func (s *state) insertWB(t *Type, p *ssa.Value) {
taddr := s.newValue1A(ssa.OpAddr, Types[TUINTPTR], &ssa.ExternSymbol{Types[TUINTPTR], typenamesym(t)}, s.sb)
s.rtcall(typedmemmove_nostore, true, nil, taddr, p)
+ if Debug_wb > 0 {
+ Warnl(int(line), "write barrier")
+ }
+
b.AddEdgeTo(s.curBlock)
}
@@ -2985,6 +2993,10 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
Fatalf("dottype needs a direct iface type %s", n.Type)
}
+ if Debug_typeassert > 0 {
+ Warnl(int(n.Lineno), "type assertion inlined")
+ }
+
// TODO: If we have a nonempty interface and its itab field is nil,
// then this test is redundant and ifaceType should just branch directly to bFail.
cond := s.newValue2(ssa.OpEqPtr, Types[TBOOL], typ, target)
@@ -4523,6 +4535,16 @@ func (e *ssaExport) Unimplementedf(msg string, args ...interface{}) {
e.unimplemented = true
}
+// Warnl reports a "warning", which is usually flag-triggered
+// logging output for the benefit of tests.
+func (e *ssaExport) Warnl(line int, fmt_ string, args ...interface{}) {
+ Warnl(line, fmt_, args...)
+}
+
+func (e *ssaExport) Debug_checknil() bool {
+ return Debug_checknil != 0
+}
+
func (n *Node) Typ() ssa.Type {
return n.Type
}
diff --git a/src/cmd/compile/internal/ssa/config.go b/src/cmd/compile/internal/ssa/config.go
index cfba10bc24..014c960267 100644
--- a/src/cmd/compile/internal/ssa/config.go
+++ b/src/cmd/compile/internal/ssa/config.go
@@ -49,6 +49,12 @@ type Logger interface {
// Unimplemented reports that the function cannot be compiled.
// It will be removed once SSA work is complete.
Unimplementedf(msg string, args ...interface{})
+
+ // Warnl writes compiler messages in the form expected by "errorcheck" tests
+ Warnl(line int, fmt_ string, args ...interface{})
+
+ // Fowards the Debug_checknil flag from gc
+ Debug_checknil() bool
}
type Frontend interface {
@@ -100,9 +106,11 @@ func (c *Config) NewFunc() *Func {
return &Func{Config: c, NamedValues: map[GCNode][]*Value{}}
}
-func (c *Config) Logf(msg string, args ...interface{}) { c.fe.Logf(msg, args...) }
-func (c *Config) Fatalf(msg string, args ...interface{}) { c.fe.Fatalf(msg, args...) }
-func (c *Config) Unimplementedf(msg string, args ...interface{}) { c.fe.Unimplementedf(msg, args...) }
+func (c *Config) Logf(msg string, args ...interface{}) { c.fe.Logf(msg, args...) }
+func (c *Config) Fatalf(msg string, args ...interface{}) { c.fe.Fatalf(msg, args...) }
+func (c *Config) Unimplementedf(msg string, args ...interface{}) { c.fe.Unimplementedf(msg, args...) }
+func (c *Config) Warnl(line int, msg string, args ...interface{}) { c.fe.Warnl(line, msg, args...) }
+func (c *Config) Debug_checknil() bool { return c.fe.Debug_checknil() }
// TODO(khr): do we really need a separate Config, or can we just
// store all its fields inside a Func?
diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go
index d0ba7b1c09..c37db75803 100644
--- a/src/cmd/compile/internal/ssa/export_test.go
+++ b/src/cmd/compile/internal/ssa/export_test.go
@@ -32,9 +32,11 @@ func (DummyFrontend) Auto(t Type) GCNode {
return nil
}
-func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
-func (d DummyFrontend) Fatalf(msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
-func (d DummyFrontend) Unimplementedf(msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
+func (d DummyFrontend) Logf(msg string, args ...interface{}) { d.t.Logf(msg, args...) }
+func (d DummyFrontend) Fatalf(msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
+func (d DummyFrontend) Unimplementedf(msg string, args ...interface{}) { d.t.Fatalf(msg, args...) }
+func (d DummyFrontend) Warnl(line int, msg string, args ...interface{}) { d.t.Logf(msg, args...) }
+func (d DummyFrontend) Debug_checknil() bool { return false }
func (d DummyFrontend) TypeBool() Type { return TypeBool }
func (d DummyFrontend) TypeInt8() Type { return TypeInt8 }
diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go
index 5b012a8551..f8caa7b042 100644
--- a/src/cmd/compile/internal/ssa/nilcheck.go
+++ b/src/cmd/compile/internal/ssa/nilcheck.go
@@ -88,6 +88,13 @@ func nilcheckelim(f *Func) {
// Eliminate the nil check.
// The deadcode pass will remove vestigial values,
// and the fuse pass will join this block with its successor.
+
+ // Logging in the style of the former compiler -- and omit line 1,
+ // which is usually in generated code.
+ if f.Config.Debug_checknil() && int(node.block.Control.Line) > 1 {
+ f.Config.Warnl(int(node.block.Control.Line), "removed nil check")
+ }
+
switch node.block.Kind {
case BlockIf:
node.block.Kind = BlockFirst
diff --git a/src/cmd/dist/test.go b/src/cmd/dist/test.go
index be6cdb5c0b..0afe4c6060 100644
--- a/src/cmd/dist/test.go
+++ b/src/cmd/dist/test.go
@@ -13,7 +13,6 @@ import (
"log"
"os"
"os/exec"
- "path"
"path/filepath"
"regexp"
"strconv"
@@ -276,31 +275,6 @@ func (t *tester) registerStdTest(pkg string) {
})
}
-// TODO: Remove when SSA codegen is used by default.
-func (t *tester) registerSSATest(pkg string) {
- t.tests = append(t.tests, distTest{
- name: "go_test_ssa:" + pkg,
- heading: "Testing packages with SSA codegen.",
- fn: func() error {
- args := []string{
- "test",
- "-short",
- t.timeout(180 * 3), // SSA generates slower code right now
- "-gcflags=" + os.Getenv("GO_GCFLAGS"),
- }
- if t.race {
- args = append(args, "-race")
- }
- args = append(args, pkg)
- cmd := exec.Command("go", args...)
- cmd.Env = mergeEnvLists([]string{"GOSSAPKG=" + path.Base(pkg)}, os.Environ())
- cmd.Stdout = os.Stdout
- cmd.Stderr = os.Stderr
- return cmd.Run()
- },
- })
-}
-
func (t *tester) registerRaceBenchTest(pkg string) {
testName := "go_test_bench:" + pkg
if t.runRx == nil || t.runRx.MatchString(testName) {
@@ -344,9 +318,6 @@ func (t *tester) registerTests() {
if strings.HasPrefix(name, "go_test_bench:") {
t.registerRaceBenchTest(strings.TrimPrefix(name, "go_test_bench:"))
}
- if t.goarch == "amd64" && strings.HasPrefix(name, "go_test_ssa:") {
- t.registerSSATest(strings.TrimPrefix(name, "go_test_ssa:"))
- }
}
} else {
// Use a format string to only list packages and commands that have tests.
@@ -363,11 +334,6 @@ func (t *tester) registerTests() {
for _, pkg := range pkgs {
t.registerStdTest(pkg)
}
- if t.goarch == "amd64" {
- for _, pkg := range pkgs {
- t.registerSSATest(pkg)
- }
- }
if t.race {
for _, pkg := range pkgs {
t.registerRaceBenchTest(pkg)