]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: adjust is-statement on Pos's to improve debugging
authorDavid Chase <drchase@google.com>
Sat, 3 Mar 2018 01:33:15 +0000 (20:33 -0500)
committerDavid Chase <drchase@google.com>
Wed, 4 Apr 2018 22:14:59 +0000 (22:14 +0000)
Stores to auto tmp variables can be hoisted to places
where the line numbers make debugging look "jumpy".
Turning those instructions into ones with is_stmt = 0 in
the DWARF (accomplished by marking ssa nodes with NotStmt)
makes debugging look better while still attributing the
instructions with the correct line number.

The same is true for certain register allocator spills and
reloads.

Change-Id: I97a394eb522d4911cc40b4bf5bf76d3d7221f6c0
Reviewed-on: https://go-review.googlesource.com/98415
Run-TryBot: David Chase <drchase@google.com>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/regalloc.go
src/cmd/compile/internal/ssa/testdata/hist.gdb-opt.nexts
src/cmd/compile/internal/ssa/testdata/scopes.gdb-opt.nexts

index 909df12e5e48e4b2a3c94408553d76c6da1aaaa4..704278cd1e1a296945e3fcaf24966b8475a4874d 100644 (file)
@@ -419,6 +419,16 @@ func (s *state) newValue1A(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.V
        return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
 }
 
+// newValue1Apos adds a new value with one argument and an aux value to the current block.
+// isStmt determines whether the created values may be a statement or not
+// (i.e., false means never, yes means maybe).
+func (s *state) newValue1Apos(op ssa.Op, t *types.Type, aux interface{}, arg *ssa.Value, isStmt bool) *ssa.Value {
+       if isStmt {
+               return s.curBlock.NewValue1A(s.peekPos(), op, t, aux, arg)
+       }
+       return s.curBlock.NewValue1A(s.peekPos().WithNotStmt(), op, t, aux, arg)
+}
+
 // newValue1I adds a new value with one argument and an auxint value to the current block.
 func (s *state) newValue1I(op ssa.Op, t *types.Type, aux int64, arg *ssa.Value) *ssa.Value {
        return s.curBlock.NewValue1I(s.peekPos(), op, t, aux, arg)
@@ -449,6 +459,16 @@ func (s *state) newValue3A(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1
        return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
 }
 
+// newValue3Apos adds a new value with three arguments and an aux value to the current block.
+// isStmt determines whether the created values may be a statement or not
+// (i.e., false means never, yes means maybe).
+func (s *state) newValue3Apos(op ssa.Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *ssa.Value, isStmt bool) *ssa.Value {
+       if isStmt {
+               return s.curBlock.NewValue3A(s.peekPos(), op, t, aux, arg0, arg1, arg2)
+       }
+       return s.curBlock.NewValue3A(s.peekPos().WithNotStmt(), op, t, aux, arg0, arg1, arg2)
+}
+
 // newValue4 adds a new value with four arguments to the current block.
 func (s *state) newValue4(op ssa.Op, t *types.Type, arg0, arg1, arg2, arg3 *ssa.Value) *ssa.Value {
        return s.curBlock.NewValue4(s.peekPos(), op, t, arg0, arg1, arg2, arg3)
@@ -997,7 +1017,7 @@ func (s *state) stmt(n *Node) {
                // varkill in the store chain is enough to keep it correctly ordered
                // with respect to call ops.
                if !s.canSSA(n.Left) {
-                       s.vars[&memVar] = s.newValue1A(ssa.OpVarKill, types.TypeMem, n.Left, s.mem())
+                       s.vars[&memVar] = s.newValue1Apos(ssa.OpVarKill, types.TypeMem, n.Left, s.mem(), false)
                }
 
        case OVARLIVE:
@@ -2338,7 +2358,7 @@ func (s *state) append(n *Node, inplace bool) *ssa.Value {
        for i, arg := range args {
                addr := s.newValue2(ssa.OpPtrIndex, pt, p2, s.constInt(types.Types[TINT], int64(i)))
                if arg.store {
-                       s.storeType(et, addr, arg.v, 0)
+                       s.storeType(et, addr, arg.v, 0, true)
                } else {
                        s.move(et, addr, arg.v)
                }
@@ -2488,7 +2508,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
        // Left is not ssa-able. Compute its address.
        addr := s.addr(left, false)
        if left.Op == ONAME && left.Class() != PEXTERN && skip == 0 {
-               s.vars[&memVar] = s.newValue1A(ssa.OpVarDef, types.TypeMem, left, s.mem())
+               s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, left, s.mem(), !left.IsAutoTmp())
        }
        if isReflectHeaderDataField(left) {
                // Package unsafe's documentation says storing pointers into
@@ -2508,7 +2528,7 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
                return
        }
        // Treat as a store.
-       s.storeType(t, addr, right, skip)
+       s.storeType(t, addr, right, skip, !left.IsAutoTmp())
 }
 
 // zeroVal returns the zero value for type t.
@@ -3491,7 +3511,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value {
                        s.Fatalf("addr of undeclared ONAME %v. declared: %v", n, s.decladdrs)
                        return nil
                case PAUTO:
-                       return s.newValue1A(ssa.OpAddr, t, n, s.sp)
+                       return s.newValue1Apos(ssa.OpAddr, t, n, s.sp, !n.IsAutoTmp())
                case PPARAMOUT: // Same as PAUTO -- cannot generate LEA early.
                        // ensure that we reuse symbols for out parameters so
                        // that cse works on their addresses
@@ -3776,11 +3796,11 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*types.Type, args .
        return res
 }
 
-// do *left = right for type t.
-func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask) {
+/// do *left = right for type t.
+func (s *state) storeType(t *types.Type, left, right *ssa.Value, skip skipMask, leftIsStmt bool) {
        if skip == 0 && (!types.Haspointers(t) || ssa.IsStackAddr(left)) {
                // Known to not have write barrier. Store the whole type.
-               s.store(t, left, right)
+               s.vars[&memVar] = s.newValue3Apos(ssa.OpStore, types.TypeMem, t, left, right, s.mem(), leftIsStmt)
                return
        }
 
index 0839bba86dfa2483cd6987de23a3c8a0072f4a9c..3fe170ac55c981bcc93069e1f98415c147e08263 100644 (file)
@@ -444,7 +444,7 @@ func (s *regAllocState) makeSpill(v *Value, b *Block) *Value {
 // *Value which is either v or a copy of v allocated to the chosen register.
 func (s *regAllocState) allocValToReg(v *Value, mask regMask, nospill bool, pos src.XPos) *Value {
        vi := &s.values[v.ID]
-
+       pos = pos.WithNotStmt()
        // Check if v is already in a requested register.
        if mask&vi.regs != 0 {
                r := pickReg(mask & vi.regs)
@@ -1893,18 +1893,20 @@ func (e *edgeState) process() {
                        fmt.Printf("breaking cycle with v%d in %s:%s\n", vid, loc, c)
                }
                e.erase(r)
+               pos := d.pos.WithNotStmt()
                if _, isReg := loc.(*Register); isReg {
-                       c = e.p.NewValue1(d.pos, OpCopy, c.Type, c)
+                       c = e.p.NewValue1(pos, OpCopy, c.Type, c)
                } else {
-                       c = e.p.NewValue1(d.pos, OpLoadReg, c.Type, c)
+                       c = e.p.NewValue1(pos, OpLoadReg, c.Type, c)
                }
-               e.set(r, vid, c, false, d.pos)
+               e.set(r, vid, c, false, pos)
        }
 }
 
 // processDest generates code to put value vid into location loc. Returns true
 // if progress was made.
 func (e *edgeState) processDest(loc Location, vid ID, splice **Value, pos src.XPos) bool {
+       pos = pos.WithNotStmt()
        occupant := e.contents[loc]
        if occupant.vid == vid {
                // Value is already in the correct place.
index 79c65a928833b5216ea1855230f6498ce9a21aa2..69091d12ed7464bb9b8cff9c617bc3c17a603232 100644 (file)
@@ -116,54 +116,30 @@ scanner = (struct bufio.Scanner *) <A>
 a = 0
 n = 0
 t = 0
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 91:                    n += a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-90:                    t += i * a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 90:                    t += i * a
 92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-86:            for i, a := range hist {
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 87:                    if a == 0 { //gdb-opt=(a,n,t)
 a = 3
 n = 3
 t = 3
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 91:                    n += a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-90:                    t += i * a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 90:                    t += i * a
 92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-86:            for i, a := range hist {
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 87:                    if a == 0 { //gdb-opt=(a,n,t)
 a = 0
 n = 6
 t = 9
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 91:                    n += a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-90:                    t += i * a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 90:                    t += i * a
 92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-86:            for i, a := range hist {
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 87:                    if a == 0 { //gdb-opt=(a,n,t)
 a = 1
 n = 8
 t = 17
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 91:                    n += a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-90:                    t += i * a
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 90:                    t += i * a
 92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
-86:            for i, a := range hist {
-92:                    fmt.Fprintf(os.Stderr, "%d\t%d\t%d\t%d\t%d\n", i, a, n, i*a, t) //gdb-dbg=(n,i,t)
 87:                    if a == 0 { //gdb-opt=(a,n,t)
 a = 0
 n = 9
index 290f02fd92d760557ff26594b67a86ad0db239fa..0a09989f88b6ca20f6d551c4e7f26893d3383b00 100644 (file)
@@ -4,7 +4,6 @@
 20:            y := id(0)
 21:            fmt.Println(x)
 0:
-22:            for i := x; i < 3; i++ {
 23:                    x := i * i
 24:                    y += id(x) //gdb-dbg=(x,y)//gdb-opt=(x,y)
 x = 0
@@ -32,7 +31,6 @@ y = 1
 x = <optimized out>
 y = 1
 22:            for i := x; i < 3; i++ {
-27:            fmt.Println(x, y)
 26:            y = x + y //gdb-dbg=(x,y)//gdb-opt=(x,y)
 x = 0
 y = 1