aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2021-04-12 20:53:03 -0400
committerDavid Chase <drchase@google.com>2021-04-14 18:46:08 +0000
commit4df3d0e4df734283911cf3c428d9638c9dc5af4e (patch)
tree65a4040cb386e4309172a234259139792eb7537b /src
parent4480c822ba37ea3795fa4dbb56d13578d7961d88 (diff)
downloadgo-4df3d0e4df734283911cf3c428d9638c9dc5af4e.tar.xz
cmd/compile: rescue stmt boundaries from OpArgXXXReg and OpSelectN.
Fixes this failure: go test cmd/compile/internal/ssa -run TestStmtLines -v === RUN TestStmtLines stmtlines_test.go:115: Saw too many (amd64, > 1%) lines without statement marks, total=88263, nostmt=1930 ('-run TestStmtLines -v' lists failing lines) The failure has two causes. One is that the first-line adjuster in code generation was relocating "first lines" to instructions that would either not have any code generated, or would have the statment marker removed by a different believed-good heuristic. The other was that statement boundaries were getting attached to register values (that with the old ABI were loads from the stack, hence real instructions). The register values disappear at code generation. The fixes are to (1) note that certain instructions are not good choices for "first value" and skip them, and (2) in an expandCalls post-pass, look for register valued instructions and under appropriate conditions move their statement marker to a compatible use. Also updates TestStmtLines to always log the score, for easier comparison of minor compiler changes. Updates #40724. Change-Id: I485573ce900e292d7c44574adb7629cdb4695c3f Reviewed-on: https://go-review.googlesource.com/c/go/+/309649 Trust: David Chase <drchase@google.com> Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
Diffstat (limited to 'src')
-rw-r--r--src/cmd/compile/internal/dwarfgen/scope_test.go8
-rw-r--r--src/cmd/compile/internal/ssa/expand_calls.go25
-rw-r--r--src/cmd/compile/internal/ssa/stmtlines_test.go1
-rw-r--r--src/cmd/compile/internal/ssagen/ssa.go10
4 files changed, 35 insertions, 9 deletions
diff --git a/src/cmd/compile/internal/dwarfgen/scope_test.go b/src/cmd/compile/internal/dwarfgen/scope_test.go
index fcfcf85f84..3df4c345c3 100644
--- a/src/cmd/compile/internal/dwarfgen/scope_test.go
+++ b/src/cmd/compile/internal/dwarfgen/scope_test.go
@@ -181,17 +181,17 @@ var testfile = []testline{
{line: " fi(p)", scopes: []int{1}},
{line: " }"},
{line: "}"},
- {line: "func TestCaptureVar(flag bool) func() int {"},
- {line: " a := 1", vars: []string{"arg flag bool", "arg ~r1 func() int", "var a int"}},
+ {line: "var fglob func() int"},
+ {line: "func TestCaptureVar(flag bool) {"},
+ {line: " a := 1", vars: []string{"arg flag bool", "var a int"}}, // TODO(register args) restore "arg ~r1 func() int",
{line: " if flag {"},
{line: " b := 2", scopes: []int{1}, vars: []string{"var b int", "var f func() int"}},
{line: " f := func() int {", scopes: []int{1, 0}},
{line: " return b + 1"},
{line: " }"},
- {line: " return f", scopes: []int{1}},
+ {line: " fglob = f", scopes: []int{1}},
{line: " }"},
{line: " f1(a)"},
- {line: " return nil"},
{line: "}"},
{line: "func main() {"},
{line: " TestNestedFor()"},
diff --git a/src/cmd/compile/internal/ssa/expand_calls.go b/src/cmd/compile/internal/ssa/expand_calls.go
index d947443cb2..b2b2b5d877 100644
--- a/src/cmd/compile/internal/ssa/expand_calls.go
+++ b/src/cmd/compile/internal/ssa/expand_calls.go
@@ -1478,6 +1478,31 @@ func expandCalls(f *Func) {
}
}
}
+
+ // Rewriting can attach lines to values that are unlikely to survive code generation, so move them to a use.
+ for _, b := range f.Blocks {
+ for _, v := range b.Values {
+ for _, a := range v.Args {
+ if a.Pos.IsStmt() != src.PosIsStmt {
+ continue
+ }
+ if a.Type.IsMemory() {
+ continue
+ }
+ if a.Pos.Line() != v.Pos.Line() {
+ continue
+ }
+ if !a.Pos.SameFile(v.Pos) {
+ continue
+ }
+ switch a.Op {
+ case OpArgIntReg, OpArgFloatReg, OpSelectN:
+ v.Pos = v.Pos.WithIsStmt()
+ a.Pos = a.Pos.WithDefaultStmt()
+ }
+ }
+ }
+ }
}
// rewriteArgToMemOrRegs converts OpArg v in-place into the register version of v,
diff --git a/src/cmd/compile/internal/ssa/stmtlines_test.go b/src/cmd/compile/internal/ssa/stmtlines_test.go
index f5ff3a5927..a510d0b3d0 100644
--- a/src/cmd/compile/internal/ssa/stmtlines_test.go
+++ b/src/cmd/compile/internal/ssa/stmtlines_test.go
@@ -117,6 +117,7 @@ func TestStmtLines(t *testing.T) {
} else if len(nonStmtLines)*100 > 2*len(lines) { // expect 98% elsewhere.
t.Errorf("Saw too many (not amd64, > 2%%) lines without statement marks, total=%d, nostmt=%d ('-run TestStmtLines -v' lists failing lines)\n", len(lines), len(nonStmtLines))
}
+ t.Logf("Saw %d out of %d lines without statement marks", len(nonStmtLines), len(lines))
if testing.Verbose() {
sort.Slice(nonStmtLines, func(i, j int) bool {
if nonStmtLines[i].File != nonStmtLines[j].File {
diff --git a/src/cmd/compile/internal/ssagen/ssa.go b/src/cmd/compile/internal/ssagen/ssa.go
index 60a849db23..b970451624 100644
--- a/src/cmd/compile/internal/ssagen/ssa.go
+++ b/src/cmd/compile/internal/ssagen/ssa.go
@@ -6638,15 +6638,15 @@ func genssa(f *ssa.Func, pp *objw.Progs) {
inlMarksByPos[pos] = append(inlMarksByPos[pos], p)
default:
+ // Special case for first line in function; move it to the start (which cannot be a register-valued instruction)
+ if firstPos != src.NoXPos && v.Op != ssa.OpArgIntReg && v.Op != ssa.OpArgFloatReg && v.Op != ssa.OpLoadReg && v.Op != ssa.OpStoreReg {
+ s.SetPos(firstPos)
+ firstPos = src.NoXPos
+ }
// Attach this safe point to the next
// instruction.
s.pp.NextLive = s.livenessMap.Get(v)
- // Special case for first line in function; move it to the start.
- if firstPos != src.NoXPos {
- s.SetPos(firstPos)
- firstPos = src.NoXPos
- }
// let the backend handle it
Arch.SSAGenValue(&s, v)
}