Skip to content

Commit f7f85bd

Browse files
committed
cmd/compile: refine statement marking in numberlines
1) An empty block is treated as not-a-statement unless its line differs from at least one of its predecessors (it might make sense to rearrange branches in predecessors, but that is a different issue). 2) When iterating forward to choose a "good" place for a statement, actually check that the chosen place is in fact good. 3) Refactor same line and same file into methods on XPos and Pos. This reduces the failure rate of ssa/stmtlines_test by 7-ish lines. (And interacts favorably with later debugging CLs.) Change-Id: Idb7cca7068f6fc9fbfdbe25bc0da15bcfc7b9d4a Reviewed-on: https://go-review.googlesource.com/c/go/+/188217 Run-TryBot: David Chase <drchase@google.com> Reviewed-by: Jeremy Faller <jeremy@golang.org>
1 parent 3ad3508 commit f7f85bd

File tree

3 files changed

+33
-18
lines changed

3 files changed

+33
-18
lines changed

src/cmd/compile/internal/ssa/numberlines.go

Lines changed: 25 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,20 @@ func nextGoodStatementIndex(v *Value, i int, b *Block) int {
4343
if i >= len(b.Values)-1 {
4444
return i
4545
}
46-
// Only consider the likely-ephemeral/fragile opcodes expected to vanish in a rewrite.
46+
// Skip the likely-ephemeral/fragile opcodes expected to vanish in a rewrite.
4747
if !isPoorStatementOp(v.Op) {
4848
return i
4949
}
5050
// Look ahead to see what the line number is on the next thing that could be a boundary.
5151
for j := i + 1; j < len(b.Values); j++ {
52-
if b.Values[j].Pos.IsStmt() == src.PosNotStmt { // ignore non-statements
52+
u := b.Values[j]
53+
if u.Pos.IsStmt() == src.PosNotStmt { // ignore non-statements
5354
continue
5455
}
55-
if b.Values[j].Pos.Line() == v.Pos.Line() && v.Pos.SameFile(b.Values[j].Pos) {
56+
if u.Pos.SameFileAndLine(v.Pos) {
57+
if isPoorStatementOp(u.Op) {
58+
continue // Keep looking, this is also not a good statement op
59+
}
5660
return j
5761
}
5862
return i
@@ -156,18 +160,10 @@ func numberLines(f *Func) {
156160
}
157161

158162
if firstPosIndex == -1 { // Effectively empty block, check block's own Pos, consider preds.
159-
if b.Pos.IsStmt() != src.PosNotStmt {
160-
b.Pos = b.Pos.WithIsStmt()
161-
endlines[b.ID] = b.Pos
162-
if f.pass.debug > 0 {
163-
fmt.Printf("Mark stmt effectively-empty-block %s %s %s\n", f.Name, b, flc(b.Pos))
164-
}
165-
continue
166-
}
167163
line := src.NoXPos
168164
for _, p := range b.Preds {
169165
pbi := p.Block().ID
170-
if endlines[pbi] != line {
166+
if !endlines[pbi].SameFileAndLine(line) {
171167
if line == src.NoXPos {
172168
line = endlines[pbi]
173169
continue
@@ -178,7 +174,20 @@ func numberLines(f *Func) {
178174

179175
}
180176
}
181-
endlines[b.ID] = line
177+
// If the block has no statement itself and is effectively empty, tag it w/ predecessor(s) but not as a statement
178+
if b.Pos.IsStmt() == src.PosNotStmt {
179+
b.Pos = line
180+
endlines[b.ID] = line
181+
continue
182+
}
183+
// If the block differs from its predecessors, mark it as a statement
184+
if line == src.NoXPos || !line.SameFileAndLine(b.Pos) {
185+
b.Pos = b.Pos.WithIsStmt()
186+
if f.pass.debug > 0 {
187+
fmt.Printf("Mark stmt effectively-empty-block %s %s %s\n", f.Name, b, flc(b.Pos))
188+
}
189+
}
190+
endlines[b.ID] = b.Pos
182191
continue
183192
}
184193
// check predecessors for any difference; if firstPos differs, then it is a boundary.
@@ -190,7 +199,7 @@ func numberLines(f *Func) {
190199
} else { // differing pred
191200
for _, p := range b.Preds {
192201
pbi := p.Block().ID
193-
if endlines[pbi].Line() != firstPos.Line() || !endlines[pbi].SameFile(firstPos) {
202+
if !endlines[pbi].SameFileAndLine(firstPos) {
194203
b.Values[firstPosIndex].Pos = firstPos.WithIsStmt()
195204
if f.pass.debug > 0 {
196205
fmt.Printf("Mark stmt differing-pred %s %s %s %s, different=%s ending %s\n",
@@ -210,7 +219,7 @@ func numberLines(f *Func) {
210219
// skip ahead if possible
211220
i = nextGoodStatementIndex(v, i, b)
212221
v = b.Values[i]
213-
if v.Pos.Line() != firstPos.Line() || !v.Pos.SameFile(firstPos) {
222+
if !v.Pos.SameFileAndLine(firstPos) {
214223
if f.pass.debug > 0 {
215224
fmt.Printf("Mark stmt new line %s %s %s %s prev pos = %s\n", f.Name, b, v, flc(v.Pos), flc(firstPos))
216225
}
@@ -220,7 +229,7 @@ func numberLines(f *Func) {
220229
v.Pos = v.Pos.WithDefaultStmt()
221230
}
222231
}
223-
if b.Pos.IsStmt() != src.PosNotStmt && (b.Pos.Line() != firstPos.Line() || !b.Pos.SameFile(firstPos)) {
232+
if b.Pos.IsStmt() != src.PosNotStmt && !b.Pos.SameFileAndLine(firstPos) {
224233
if f.pass.debug > 0 {
225234
fmt.Printf("Mark stmt end of block differs %s %s %s prev pos = %s\n", f.Name, b, flc(b.Pos), flc(firstPos))
226235
}

src/cmd/internal/src/pos.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -381,8 +381,9 @@ func makeLico(line, col uint) lico {
381381
return makeLicoRaw(line, col)
382382
}
383383

384-
func (x lico) Line() uint { return uint(x) >> lineShift }
385-
func (x lico) Col() uint { return uint(x) >> colShift & colMax }
384+
func (x lico) Line() uint { return uint(x) >> lineShift }
385+
func (x lico) SameLine(y lico) bool { return 0 == (x^y)&^lico(1 << lineShift-1) }
386+
func (x lico) Col() uint { return uint(x) >> colShift & colMax }
386387
func (x lico) IsStmt() uint {
387388
if x == 0 {
388389
return PosNotStmt

src/cmd/internal/src/xpos.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,11 @@ func (p XPos) SameFile(q XPos) bool {
3535
return p.index == q.index
3636
}
3737

38+
// SameFileAndLine reports whether p and q are positions on the same line in the same file.
39+
func (p XPos) SameFileAndLine(q XPos) bool {
40+
return p.index == q.index && p.lico.SameLine(q.lico)
41+
}
42+
3843
// After reports whether the position p comes after q in the source.
3944
// For positions with different bases, ordering is by base index.
4045
func (p XPos) After(q XPos) bool {

0 commit comments

Comments
 (0)