From: David Chase Date: Tue, 1 Oct 2019 15:08:46 +0000 (-0400) Subject: cmd/compile: preserve statement marks in branch elimination X-Git-Tag: go1.14beta1~858 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e06829b9772ca3a7d5ba3c573b345699f51d69b0;p=gostls13.git 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 TryBot-Result: Gobot Gobot Reviewed-by: Jeremy Faller --- diff --git a/src/cmd/compile/internal/ssa/branchelim.go b/src/cmd/compile/internal/ssa/branchelim.go index c79b913d72..298eed362a 100644 --- a/src/cmd/compile/internal/ssa/branchelim.go +++ b/src/cmd/compile/internal/ssa/branchelim.go @@ -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...)