]> Cypherpunks.ru repositories - gostls13.git/commitdiff
cmd/compile: remove more nil ptr checks after newobject
authorKeith Randall <khr@golang.org>
Thu, 24 Aug 2017 22:23:27 +0000 (15:23 -0700)
committerKeith Randall <khr@golang.org>
Fri, 25 Aug 2017 03:26:58 +0000 (03:26 +0000)
For code like the following (where x escapes):

   x := []int{1}

We're currently generating a nil check.  The line above is really 3 operations:

t := new([1]int)
t[0] = 1
x := t[:]

We remove the nil check for t[0] = 1, but not for t[:].

Our current nil check removal rule is too strict about the possible
memory arguments of the nil check. Unlike zeroing or storing to the
result of runtime.newobject, the nilness of runtime.newobject is
always false, even after other stores have happened in the meantime.

Change-Id: I95fad4e3a59c27effdb37c43ea215e18f30b1e5f
Reviewed-on: https://go-review.googlesource.com/58711
Run-TryBot: Keith Randall <khr@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewritegeneric.go
test/nilptr3.go

index ea04b61b73eff3fa0394a7b4fbb3910dd27d83d2..1faf6b3857f2c9b6de3cf2c82cabddba15cca372 100644 (file)
        -> mem
 // nil checks just need to rewrite to something useless.
 // they will be deadcode eliminated soon afterwards.
-(NilCheck (Load (OffPtr [c] (SP)) mem) mem)
-       && mem.Op == OpStaticCall
-       && isSameSym(mem.Aux, "runtime.newobject")
+(NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
+       && isSameSym(sym, "runtime.newobject")
        && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
        && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
        -> (Invalid)
-(NilCheck (OffPtr (Load (OffPtr [c] (SP)) mem)) mem)
-       && mem.Op == OpStaticCall
-       && isSameSym(mem.Aux, "runtime.newobject")
+(NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
+       && isSameSym(sym, "runtime.newobject")
        && c == config.ctxt.FixedFrameSize() + config.RegSize // offset of return value
        && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
        -> (Invalid)
index bc78fdb6fb637156cc8b16a80b2b11fe070ecc8d..fdd4c1e1677d180145e9fea5aadf9797f361441d 100644 (file)
@@ -16833,8 +16833,8 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
                v.AddArg(mem)
                return true
        }
-       // match: (NilCheck (Load (OffPtr [c] (SP)) mem) mem)
-       // cond: mem.Op == OpStaticCall         && isSameSym(mem.Aux, "runtime.newobject")      && c == config.ctxt.FixedFrameSize() + config.RegSize   && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+       // match: (NilCheck (Load (OffPtr [c] (SP)) (StaticCall {sym} _)) _)
+       // cond: isSameSym(sym, "runtime.newobject")    && c == config.ctxt.FixedFrameSize() + config.RegSize   && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
        // result: (Invalid)
        for {
                _ = v.Args[1]
@@ -16852,18 +16852,19 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
                if v_0_0_0.Op != OpSP {
                        break
                }
-               mem := v_0.Args[1]
-               if mem != v.Args[1] {
+               v_0_1 := v_0.Args[1]
+               if v_0_1.Op != OpStaticCall {
                        break
                }
-               if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
+               sym := v_0_1.Aux
+               if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
                        break
                }
                v.reset(OpInvalid)
                return true
        }
-       // match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) mem)) mem)
-       // cond: mem.Op == OpStaticCall         && isSameSym(mem.Aux, "runtime.newobject")      && c == config.ctxt.FixedFrameSize() + config.RegSize   && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
+       // match: (NilCheck (OffPtr (Load (OffPtr [c] (SP)) (StaticCall {sym} _))) _)
+       // cond: isSameSym(sym, "runtime.newobject")    && c == config.ctxt.FixedFrameSize() + config.RegSize   && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")
        // result: (Invalid)
        for {
                _ = v.Args[1]
@@ -16885,11 +16886,12 @@ func rewriteValuegeneric_OpNilCheck_0(v *Value) bool {
                if v_0_0_0_0.Op != OpSP {
                        break
                }
-               mem := v_0_0.Args[1]
-               if mem != v.Args[1] {
+               v_0_0_1 := v_0_0.Args[1]
+               if v_0_0_1.Op != OpStaticCall {
                        break
                }
-               if !(mem.Op == OpStaticCall && isSameSym(mem.Aux, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
+               sym := v_0_0_1.Aux
+               if !(isSameSym(sym, "runtime.newobject") && c == config.ctxt.FixedFrameSize()+config.RegSize && warnRule(fe.Debug_checknil() && v.Pos.Line() > 1, v, "removed nil check")) {
                        break
                }
                v.reset(OpInvalid)
index 195c8ca043d0d451045f6d10f56a2a6db8ca6922..9a96bb53867341fb248a73c8b37e267d1fbc1e23 100644 (file)
@@ -259,3 +259,10 @@ func f7() (*Struct, float64) {
 func f8(t *[8]int) [8]int {
        return *t // ERROR "removed nil check"
 }
+
+func f9() []int {
+       x := new([1]int)
+       x[0] = 1  // ERROR "removed nil check"
+       y := x[:] // ERROR "removed nil check"
+       return y
+}