]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: extend ssa.go to handle 1-element array and 1-field struct
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 3 Sep 2019 16:24:35 +0000 (23:24 +0700)
committerMatthew Dempsky <mdempsky@google.com>
Tue, 3 Sep 2019 19:33:04 +0000 (19:33 +0000)
Assinging to 1-element array/1-field struct variable is considered clobbering
the whole variable. By emitting OpVarDef in this case, liveness analysis
can now know the variable is redefined.

Also, the isfat is not necessary anymore, and will be removed in follow up CL.

Fixes #33916

Change-Id: Iece0d90b05273f333d59d6ee5b12ee7dc71908c2
Reviewed-on: https://go-review.googlesource.com/c/go/+/192979
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/cmd/compile/internal/gc/ssa.go
test/live.go
test/live2.go

index ac7f3eb22bdee6c5a60b2ef87dfb50a494946a84..0706d95937dd9bb281ffe32dee96c0317385fb74 100644 (file)
@@ -2767,10 +2767,14 @@ func (s *state) assign(left *Node, right *ssa.Value, deref bool, skip skipMask)
                s.addNamedValue(left, right)
                return
        }
-       // Left is not ssa-able. Compute its address.
-       if left.Op == ONAME && left.Class() != PEXTERN && skip == 0 {
-               s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, left, s.mem(), !left.IsAutoTmp())
+
+       // If this assignment clobbers an entire local variable, then emit
+       // OpVarDef so liveness analysis knows the variable is redefined.
+       if base := clobberBase(left); base.Op == ONAME && base.Class() != PEXTERN && skip == 0 {
+               s.vars[&memVar] = s.newValue1Apos(ssa.OpVarDef, types.TypeMem, base, s.mem(), !base.IsAutoTmp())
        }
+
+       // Left is not ssa-able. Compute its address.
        addr := s.addr(left, false)
        if isReflectHeaderDataField(left) {
                // Package unsafe's documentation says storing pointers into
@@ -6210,3 +6214,13 @@ func (n *Node) StorageClass() ssa.StorageClass {
                return 0
        }
 }
+
+func clobberBase(n *Node) *Node {
+       if n.Op == ODOT && n.Left.Type.NumFields() == 1 {
+               return clobberBase(n.Left)
+       }
+       if n.Op == OINDEX && n.Left.Type.IsArray() && n.Left.Type.NumElem() == 1 {
+               return clobberBase(n.Left)
+       }
+       return n
+}
index ec51193725d100679b4b0324db62310d339e33eb..b6e6d93f5f8fc14c947820e454c77d8153ff5fcd 100644 (file)
@@ -659,7 +659,7 @@ func bad40() {
 
 func good40() {
        ret := T40{}              // ERROR "stack object ret T40$"
-       ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+ ret$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+       ret.m = make(map[int]int) // ERROR "live at call to fastrand: .autotmp_[0-9]+$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
        t := &ret
        printnl() // ERROR "live at call to printnl: ret$"
        // Note: ret is live at the printnl because the compiler moves &ret
@@ -704,3 +704,14 @@ func f42() {
 
 //go:noescape
 func f43(a []*int)
+
+// Assigning to a sub-element that makes up an entire local variable
+// should clobber that variable.
+func f44(f func() [2]*int) interface{} { // ERROR "live at entry to f44: f"
+       type T struct {
+               s [1][2]*int
+       }
+       ret := T{}
+       ret.s[0] = f()
+       return ret // ERROR "stack object .autotmp_5 T"
+}
index cea312f075187f2457bf5f36e4f0d9fb54aa8367..83a6cb7db60759dddff85f8ce4ba9542c19f0981 100644 (file)
@@ -27,14 +27,14 @@ func newT40() *T40 {
 }
 
 func bad40() {
-       t := newT40() // ERROR "live at call to makemap: ret$" "stack object ret T40$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+       t := newT40() // ERROR "stack object ret T40$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
        printnl()     // ERROR "live at call to printnl: ret$"
        useT40(t)
 }
 
 func good40() {
        ret := T40{}                  // ERROR "stack object ret T40$"
-       ret.m = make(map[int]int, 42) // ERROR "live at call to makemap: ret$" "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
+       ret.m = make(map[int]int, 42) // ERROR "stack object .autotmp_[0-9]+ map.hdr\[int\]int$"
        t := &ret
        printnl() // ERROR "live at call to printnl: ret$"
        useT40(t)