]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: preserve statement marks in branch elimination
authorDavid Chase <drchase@google.com>
Tue, 1 Oct 2019 15:08:46 +0000 (11:08 -0400)
committerDavid Chase <drchase@google.com>
Fri, 4 Oct 2019 20:19:44 +0000 (20:19 +0000)
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: Jeremy Faller <jeremy@golang.org>
src/cmd/compile/internal/ssa/branchelim.go

index c79b913d724d7ed2535fd9cec1b61e340f6ce5f7..298eed362ac66cc1c6aff35b626d7a884d980102 100644 (file)
@@ -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...)