diff options
author | Todd Neal <todd@tneal.org> | 2015-09-06 16:00:01 -0400 |
---|---|---|
committer | Todd Neal <todd@tneal.org> | 2015-09-07 20:04:59 +0000 |
commit | 6bf383c7b31c990231c2a6c148b98e035b3b1b53 (patch) | |
tree | 6d83910097bf45d498387ced5034e5c15de065be /src/cmd/compile/internal/ssa/nilcheck_test.go | |
parent | 1fc52b61f24c210514d4b14e9cc2f8e0aa3f3d9b (diff) | |
download | go-6bf383c7b31c990231c2a6c148b98e035b3b1b53.tar.gz go-6bf383c7b31c990231c2a6c148b98e035b3b1b53.zip |
[dev.ssa] cmd/compile: clean up nilcheck logic
Be more clear about the two conditions that we care about:
1) a block that performs a nil check (OpIsNonNil), which may be removed
2) a block that is the non-nil sucessor for an OpIsNonNil block
Now we only care about removing nilchecks for two scenarios:
- a type 1 block is dominated by a type 2 block for the same value
- a block is both type 1 and type 2 for the same value
Fixes math/big.
Change-Id: I50018a4014830461ddfe2a2daf588468e4a8f0b4
Reviewed-on: https://go-review.googlesource.com/14325
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/nilcheck_test.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/nilcheck_test.go | 45 |
1 files changed, 45 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/ssa/nilcheck_test.go b/src/cmd/compile/internal/ssa/nilcheck_test.go index 1d048fbb34..cbd17e0093 100644 --- a/src/cmd/compile/internal/ssa/nilcheck_test.go +++ b/src/cmd/compile/internal/ssa/nilcheck_test.go @@ -382,3 +382,48 @@ func TestNilcheckUser(t *testing.T) { } } } + +// TestNilcheckBug reproduces a bug in nilcheckelim found by compiling math/big +func TestNilcheckBug(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", OpConstPtr, ptrType, 0, nil, "sb"), + Valu("nilptr", OpConstNil, ptrType, 0, nil, "sb"), + Valu("bool1", OpNeqPtr, TypeBool, 0, nil, "ptr1", "nilptr"), + If("bool1", "secondCheck", "couldBeNil")), + Bloc("couldBeNil", + Goto("secondCheck")), + Bloc("secondCheck", + Valu("bool2", OpIsNonNil, TypeBool, 0, nil, "ptr1"), + If("bool2", "extra", "exit")), + Bloc("extra", + Goto("exit")), + Bloc("exit", + Exit("mem"))) + + CheckFunc(fun.f) + // we need the opt here to rewrite the user nilcheck + opt(fun.f) + nilcheckelim(fun.f) + + // clean up the removed nil check + fuse(fun.f) + deadcode(fun.f) + + CheckFunc(fun.f) + foundSecondCheck := false + for _, b := range fun.f.Blocks { + if b == fun.blocks["secondCheck"] && isNilCheck(b) { + foundSecondCheck = true + } + } + if !foundSecondCheck { + t.Errorf("secondCheck was eliminated, but shouldn't have") + } +} |