From: Todd Neal Date: Mon, 3 Aug 2015 23:08:22 +0000 (-0500) Subject: [dev.ssa] cmd/compile/ssa: don't perform nilcheck on OpAddr/OpAddPtr values X-Git-Tag: go1.7beta1~1623^2^2~295 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=b14b8d6bc7d55fdde87aa5de74d7c906ca53bfd0;p=gostls13.git [dev.ssa] cmd/compile/ssa: don't perform nilcheck on OpAddr/OpAddPtr values Don't nilcheck values that were constructed as a result of OpAddr or OpAddPtr. Change-Id: I38053e905d1b76a2a64e77f84e444d38a5217108 Reviewed-on: https://go-review.googlesource.com/13256 Reviewed-by: David Chase --- diff --git a/src/cmd/compile/internal/ssa/nilcheck.go b/src/cmd/compile/internal/ssa/nilcheck.go index b9964b2980..ac7af5c60d 100644 --- a/src/cmd/compile/internal/ssa/nilcheck.go +++ b/src/cmd/compile/internal/ssa/nilcheck.go @@ -53,6 +53,19 @@ func nilcheckelim(f *Func) { var pushRecPtr bool switch node.op { case Work: + // a value resulting from taking the address of a + // value, or a value constructed from an offset of a + // non-nil ptr (OpAddPtr) implies it is non-nil + for _, v := range node.block.Values { + if v.Op == OpAddr || v.Op == OpAddPtr { + // set this immediately instead of + // using SetPtr so we can potentially + // remove an OpIsNonNil check in the + // current work block + nonNilValues[v.ID] = true + } + } + if node.ptr != nil { // already have a nilcheck in the dominator path if nonNilValues[node.ptr.ID] { diff --git a/src/cmd/compile/internal/ssa/nilcheck_test.go b/src/cmd/compile/internal/ssa/nilcheck_test.go index 0ebf2bc801..e542df25c4 100644 --- a/src/cmd/compile/internal/ssa/nilcheck_test.go +++ b/src/cmd/compile/internal/ssa/nilcheck_test.go @@ -134,9 +134,8 @@ func TestNilcheckDomOrder(t *testing.T) { } } -//TODO: Disabled until we track OpAddr constructed values // TestNilcheckAddr verifies that nilchecks of OpAddr constructed values are removed. -func DISABLETestNilcheckAddr(t *testing.T) { +func TestNilcheckAddr(t *testing.T) { ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing c := NewConfig("amd64", DummyFrontend{t}) fun := Fun(c, "entry", @@ -168,6 +167,39 @@ func DISABLETestNilcheckAddr(t *testing.T) { } } +// TestNilcheckAddPtr verifies that nilchecks of OpAddPtr constructed values are removed. +func TestNilcheckAddPtr(t *testing.T) { + ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing + c := NewConfig("amd64", DummyFrontend{t}) + fun := Fun(c, "entry", + Bloc("entry", + Valu("mem", OpArg, TypeMem, 0, ".mem"), + Valu("sb", OpSB, TypeInvalid, 0, nil), + Goto("checkPtr")), + Bloc("checkPtr", + Valu("ptr1", OpAddPtr, ptrType, 0, nil, "sb"), + Valu("bool1", OpIsNonNil, TypeBool, 0, nil, "ptr1"), + If("bool1", "extra", "exit")), + Bloc("extra", + Goto("exit")), + Bloc("exit", + Exit("mem"))) + + CheckFunc(fun.f) + nilcheckelim(fun.f) + + // clean up the removed nil check + fuse(fun.f) + deadcode(fun.f) + + CheckFunc(fun.f) + for _, b := range fun.f.Blocks { + if b == fun.blocks["checkPtr"] && isNilCheck(b) { + t.Errorf("checkPtr was not eliminated") + } + } +} + // TestNilcheckKeepRemove verifies that dupliate checks of the same pointer // are removed, but checks of different pointers are not. func TestNilcheckKeepRemove(t *testing.T) {