diff options
author | Cherry Zhang <cherryyz@google.com> | 2016-08-17 21:23:36 -0400 |
---|---|---|
committer | Cherry Zhang <cherryyz@google.com> | 2016-08-18 16:38:56 +0000 |
commit | a7277e5494c696a4798b99e1e55d55acf61211de (patch) | |
tree | 1c701a099bcc800e67e0061f767654b3018c4e77 /src/cmd/compile/internal/ssa/deadstore_test.go | |
parent | 5b9ff11c3d50368c44ae7aa9cb4b58c67494e7bb (diff) | |
download | go-a7277e5494c696a4798b99e1e55d55acf61211de.tar.gz go-a7277e5494c696a4798b99e1e55d55acf61211de.zip |
cmd/compile: compare size in dead store elimination
Only remove stores that is shadowed by another store with same or
larger size. Normally we don't need this check because we did check
the types, but unsafe pointer casting can get around it.
Fixes #16769.
Change-Id: I3f7c6c57807b590a2f735007dec6c65a4fa01a34
Reviewed-on: https://go-review.googlesource.com/27320
Run-TryBot: Cherry Zhang <cherryyz@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/ssa/deadstore_test.go')
-rw-r--r-- | src/cmd/compile/internal/ssa/deadstore_test.go | 33 |
1 files changed, 31 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/ssa/deadstore_test.go b/src/cmd/compile/internal/ssa/deadstore_test.go index c38f1cdbaf..beb6de0637 100644 --- a/src/cmd/compile/internal/ssa/deadstore_test.go +++ b/src/cmd/compile/internal/ssa/deadstore_test.go @@ -8,7 +8,7 @@ import "testing" func TestDeadStore(t *testing.T) { c := testConfig(t) - elemType := &TypeImpl{Size_: 8, Name: "testtype"} + elemType := &TypeImpl{Size_: 1, Name: "testtype"} ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr", Elem_: elemType} // dummy for testing fun := Fun(c, "entry", Bloc("entry", @@ -18,7 +18,7 @@ func TestDeadStore(t *testing.T) { Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), Valu("addr2", OpAddr, ptrType, 0, nil, "sb"), Valu("addr3", OpAddr, ptrType, 0, nil, "sb"), - Valu("zero1", OpZero, TypeMem, 8, nil, "addr3", "start"), + Valu("zero1", OpZero, TypeMem, 1, nil, "addr3", "start"), Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "zero1"), Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"), Valu("store3", OpStore, TypeMem, 1, nil, "addr1", "v", "store2"), @@ -95,3 +95,32 @@ func TestDeadStoreTypes(t *testing.T) { t.Errorf("store %s incorrectly removed", v) } } + +func TestDeadStoreUnsafe(t *testing.T) { + // Make sure a narrow store can't shadow a wider one. The test above + // covers the case of two different types, but unsafe pointer casting + // can get to a point where the size is changed but type unchanged. + c := testConfig(t) + ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing + fun := Fun(c, "entry", + Bloc("entry", + Valu("start", OpInitMem, TypeMem, 0, nil), + Valu("sb", OpSB, TypeInvalid, 0, nil), + Valu("v", OpConstBool, TypeBool, 1, nil), + Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), + Valu("store1", OpStore, TypeMem, 8, nil, "addr1", "v", "start"), // store 8 bytes + Valu("store2", OpStore, TypeMem, 1, nil, "addr1", "v", "store1"), // store 1 byte + Goto("exit")), + Bloc("exit", + Exit("store2"))) + + CheckFunc(fun.f) + cse(fun.f) + dse(fun.f) + CheckFunc(fun.f) + + v := fun.values["store1"] + if v.Op == OpCopy { + t.Errorf("store %s incorrectly removed", v) + } +} |