]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: pick position of implicit break statements more carefully
authorDavid Chase <drchase@google.com>
Wed, 25 Sep 2019 19:20:10 +0000 (15:20 -0400)
committerDavid Chase <drchase@google.com>
Thu, 3 Oct 2019 21:07:45 +0000 (21:07 +0000)
The previous version used the position of the switch statement,
which makes for potentially jumpy stepping and introduces a large
number of statements repeating the line (tricky for inserting
breaks).  It also shared a single OBREAK node and this was not
really a syntax "tree".

This improves both the nostmt test (by 6 lines) and
reduces the total badness score from dwarf-goodness (by about 200).

Change-Id: I1f71b231a26f152bdb6ce9bc8f95828bb222f665
Reviewed-on: https://go-review.googlesource.com/c/go/+/188218
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Jeremy Faller <jeremy@golang.org>
src/cmd/compile/internal/gc/swt.go

index a97e9735da0b0cfe314554f03867168c69f13480..1381cdacba930e0853e5d6b86ce31a80b3f138b3 100644 (file)
@@ -268,7 +268,6 @@ func walkExprSwitch(sw *Node) {
                exprname: cond,
        }
 
-       br := nod(OBREAK, nil, nil)
        var defaultGoto *Node
        var body Nodes
        for _, ncase := range sw.List.Slice() {
@@ -290,13 +289,17 @@ func walkExprSwitch(sw *Node) {
                // Process body.
                body.Append(npos(ncase.Pos, nodSym(OLABEL, nil, label)))
                body.Append(ncase.Nbody.Slice()...)
-               if !hasFall(ncase.Nbody.Slice()) {
+               if fall, pos := hasFall(ncase.Nbody.Slice()); !fall {
+                       br := nod(OBREAK, nil, nil)
+                       br.Pos = pos
                        body.Append(br)
                }
        }
        sw.List.Set(nil)
 
        if defaultGoto == nil {
+               br := nod(OBREAK, nil, nil)
+               br.Pos = br.Pos.WithNotStmt()
                defaultGoto = br
        }
 
@@ -469,7 +472,7 @@ func allCaseExprsAreSideEffectFree(sw *Node) bool {
 }
 
 // hasFall reports whether stmts ends with a "fallthrough" statement.
-func hasFall(stmts []*Node) bool {
+func hasFall(stmts []*Node) (bool, src.XPos) {
        // Search backwards for the index of the fallthrough
        // statement. Do not assume it'll be in the last
        // position, since in some cases (e.g. when the statement
@@ -480,7 +483,10 @@ func hasFall(stmts []*Node) bool {
        for i >= 0 && stmts[i].Op == OVARKILL {
                i--
        }
-       return i >= 0 && stmts[i].Op == OFALL
+       if i < 0 {
+               return false, src.NoXPos
+       }
+       return stmts[i].Op == OFALL, stmts[i].Pos
 }
 
 // walkTypeSwitch generates an AST that implements sw, where sw is a