Commit b14b8d6b authored by Todd Neal's avatar Todd Neal

[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/13256Reviewed-by: 's avatarDavid Chase <drchase@google.com>
parent 0fb818a4
......@@ -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] {
......
......@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment