aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/ssa/numberlines.go
diff options
context:
space:
mode:
authorDavid Chase <drchase@google.com>2019-05-02 13:35:07 -0400
committerDavid Chase <drchase@google.com>2019-05-16 03:26:42 +0000
commitfba60669751a5362c43e3bdee8455bed3fa275b2 (patch)
tree8984a0981070c2ccd4bfa20a3cfeae2aa1f2b63d /src/cmd/compile/internal/ssa/numberlines.go
parentf2694534cf3591191a125815bae24cd12ea07022 (diff)
downloadgo-fba60669751a5362c43e3bdee8455bed3fa275b2.tar.gz
go-fba60669751a5362c43e3bdee8455bed3fa275b2.zip
cmd/compile: add debugging and stats output to numberlines
This is useful for debugging line number assignment and also for making sense of pathological line number inputs. Activated with -gcflags=-d=ssa/number_lines/stats=1 (the bit matters) -gcflags=-d=ssa/number_lines/debug Stats: "SUM_LINE_RANGE", SUM for f in files {MAX line in f {line}-MIN line in f {line}} "MAXMIN_LINE_RANGE", MAX for f in files {MAX line in f {line}} - MIN for f in files {MIN line in f {line}} "MAXFILE", maxfile, MAX for f in files {f} "NFILES", len(entries) | files | Change-Id: I8a7336e6370452fe2e3a62de17606db9bd6a6fd3 Reviewed-on: https://go-review.googlesource.com/c/go/+/174947 Run-TryBot: David Chase <drchase@google.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/numberlines.go')
-rw-r--r--src/cmd/compile/internal/ssa/numberlines.go75
1 files changed, 74 insertions, 1 deletions
diff --git a/src/cmd/compile/internal/ssa/numberlines.go b/src/cmd/compile/internal/ssa/numberlines.go
index 6ff337ce6f..4807da731c 100644
--- a/src/cmd/compile/internal/ssa/numberlines.go
+++ b/src/cmd/compile/internal/ssa/numberlines.go
@@ -7,6 +7,8 @@ package ssa
import (
"cmd/internal/obj"
"cmd/internal/src"
+ "fmt"
+ "sort"
)
func isPoorStatementOp(op Op) bool {
@@ -82,6 +84,32 @@ func (b *Block) FirstPossibleStmtValue() *Value {
return nil
}
+func flc(p src.XPos) string {
+ if p == src.NoXPos {
+ return "none"
+ }
+ return fmt.Sprintf("(%d):%d:%d", p.FileIndex(), p.Line(), p.Col())
+}
+
+type fileAndPair struct {
+ f int32
+ lp lineRange
+}
+
+type fileAndPairs []fileAndPair
+
+func (fap fileAndPairs) Len() int {
+ return len(fap)
+}
+func (fap fileAndPairs) Less(i, j int) bool {
+ return fap[i].f < fap[j].f
+}
+func (fap fileAndPairs) Swap(i, j int) {
+ fap[i], fap[j] = fap[j], fap[i]
+}
+
+// -d=ssa/number_lines/stats=1 (that bit) for line and file distribution statistics
+// -d=ssa/number_lines/debug for information about why particular values are marked as statements.
func numberLines(f *Func) {
po := f.Postorder()
endlines := make(map[ID]src.XPos)
@@ -131,6 +159,9 @@ func numberLines(f *Func) {
if b.Pos.IsStmt() != src.PosNotStmt {
b.Pos = b.Pos.WithIsStmt()
endlines[b.ID] = b.Pos
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt effectively-empty-block %s %s %s\n", f.Name, b, flc(b.Pos))
+ }
continue
}
line := src.NoXPos
@@ -153,11 +184,18 @@ func numberLines(f *Func) {
// check predecessors for any difference; if firstPos differs, then it is a boundary.
if len(b.Preds) == 0 { // Don't forget the entry block
b.Values[firstPosIndex].Pos = firstPos.WithIsStmt()
- } else {
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt entry-block %s %s %s %s\n", f.Name, b, b.Values[firstPosIndex], flc(firstPos))
+ }
+ } else { // differing pred
for _, p := range b.Preds {
pbi := p.Block().ID
if endlines[pbi].Line() != firstPos.Line() || !endlines[pbi].SameFile(firstPos) {
b.Values[firstPosIndex].Pos = firstPos.WithIsStmt()
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt differing-pred %s %s %s %s, different=%s ending %s\n",
+ f.Name, b, b.Values[firstPosIndex], flc(firstPos), p.Block(), flc(endlines[pbi]))
+ }
break
}
}
@@ -173,6 +211,9 @@ func numberLines(f *Func) {
i = nextGoodStatementIndex(v, i, b)
v = b.Values[i]
if v.Pos.Line() != firstPos.Line() || !v.Pos.SameFile(firstPos) {
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt new line %s %s %s %s prev pos = %s\n", f.Name, b, v, flc(v.Pos), flc(firstPos))
+ }
firstPos = v.Pos
v.Pos = v.Pos.WithIsStmt()
} else {
@@ -180,11 +221,43 @@ func numberLines(f *Func) {
}
}
if b.Pos.IsStmt() != src.PosNotStmt && (b.Pos.Line() != firstPos.Line() || !b.Pos.SameFile(firstPos)) {
+ if f.pass.debug > 0 {
+ fmt.Printf("Mark stmt end of block differs %s %s %s prev pos = %s\n", f.Name, b, flc(b.Pos), flc(firstPos))
+ }
b.Pos = b.Pos.WithIsStmt()
firstPos = b.Pos
}
endlines[b.ID] = firstPos
}
+ if f.pass.stats&1 != 0 {
+ // Report summary statistics on the shape of the sparse map about to be constructed
+ // TODO use this information to make sparse maps faster.
+ var entries fileAndPairs
+ for k, v := range ranges {
+ entries = append(entries, fileAndPair{int32(k), v})
+ }
+ sort.Sort(entries)
+ total := uint64(0) // sum over files of maxline(file) - minline(file)
+ maxfile := int32(0) // max(file indices)
+ minline := uint32(0xffffffff) // min over files of minline(file)
+ maxline := uint32(0) // max over files of maxline(file)
+ for _, v := range entries {
+ if f.pass.stats > 1 {
+ f.LogStat("file", v.f, "low", v.lp.first, "high", v.lp.last)
+ }
+ total += uint64(v.lp.last - v.lp.first)
+ if maxfile < v.f {
+ maxfile = v.f
+ }
+ if minline > v.lp.first {
+ minline = v.lp.first
+ }
+ if maxline < v.lp.last {
+ maxline = v.lp.last
+ }
+ }
+ f.LogStat("SUM_LINE_RANGE", total, "MAXMIN_LINE_RANGE", maxline-minline, "MAXFILE", maxfile, "NFILES", len(entries))
+ }
// cachedLineStarts is an empty sparse map for values that are included within ranges.
f.cachedLineStarts = newXposmap(ranges)
}