Commit e06829b9 authored by David Chase's avatar David Chase

cmd/compile: preserve statement marks in branch elimination

This reduces the number of missing-statement lines.

Change-Id: Iefa56c2a253220d17d8b53210c8c6af78ee68756
Reviewed-on: https://go-review.googlesource.com/c/go/+/198483
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarJeremy Faller <jeremy@golang.org>
parent 86ea7d51
......@@ -4,6 +4,8 @@
package ssa
import "cmd/internal/src"
// branchelim tries to eliminate branches by
// generating CondSelect instructions.
//
......@@ -174,12 +176,98 @@ func elimIf(f *Func, loadAddr *sparseSet, dom *Block) bool {
e.b.Preds[e.i].b = dom
}
for i := range simple.Values {
simple.Values[i].Block = dom
// Try really hard to preserve statement marks attached to blocks.
simplePos := simple.Pos
postPos := post.Pos
simpleStmt := simplePos.IsStmt() == src.PosIsStmt
postStmt := postPos.IsStmt() == src.PosIsStmt
for _, v := range simple.Values {
v.Block = dom
}
for i := range post.Values {
post.Values[i].Block = dom
for _, v := range post.Values {
v.Block = dom
}
// findBlockPos determines if b contains a stmt-marked value
// that has the same line number as the Pos for b itself.
// (i.e. is the position on b actually redundant?)
findBlockPos := func(b *Block) bool {
pos := b.Pos
for _, v := range b.Values {
// See if there is a stmt-marked value already that matches simple.Pos (and perhaps post.Pos)
if pos.SameFileAndLine(v.Pos) && v.Pos.IsStmt() == src.PosIsStmt {
return true
}
}
return false
}
if simpleStmt {
simpleStmt = !findBlockPos(simple)
if !simpleStmt && simplePos.SameFileAndLine(postPos) {
postStmt = false
}
}
if postStmt {
postStmt = !findBlockPos(post)
}
// If simpleStmt and/or postStmt are still true, then try harder
// to find the corresponding statement marks new homes.
// setBlockPos determines if b contains a can-be-statement value
// that has the same line number as the Pos for b itself, and
// puts a statement mark on it, and returns whether it succeeded
// in this operation.
setBlockPos := func (b *Block) bool {
pos := b.Pos
for _, v := range b.Values {
if pos.SameFileAndLine(v.Pos) && !isPoorStatementOp(v.Op) {
v.Pos = v.Pos.WithIsStmt()
return true
}
}
return false
}
// If necessary and possible, add a mark to a value in simple
if simpleStmt {
if setBlockPos(simple) && simplePos.SameFileAndLine(postPos) {
postStmt = false
}
}
// If necessary and possible, add a mark to a value in post
if postStmt {
postStmt = !setBlockPos(post)
}
// Before giving up (this was added because it helps), try the end of "dom", and if that is not available,
// try the values in the successor block if it is uncomplicated.
if postStmt {
if dom.Pos.IsStmt() != src.PosIsStmt {
dom.Pos = postPos
} else {
// Try the successor block
if len(dom.Succs) == 1 && len(dom.Succs[0].Block().Preds) == 1 {
succ := dom.Succs[0].Block()
for _, v := range succ.Values {
if isPoorStatementOp(v.Op) {
continue
}
if postPos.SameFileAndLine(v.Pos) {
v.Pos = v.Pos.WithIsStmt()
}
postStmt = false
break
}
// If postStmt still true, tag the block itself if possible
if postStmt && succ.Pos.IsStmt() != src.PosIsStmt {
succ.Pos = postPos
}
}
}
}
dom.Values = append(dom.Values, simple.Values...)
dom.Values = append(dom.Values, post.Values...)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment