github.com/zebozhuang/go@v0.0.0-20200207033046-f8a98f6f5c5d/src/cmd/compile/internal/ssa/deadstore_test.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 import ( 8 "cmd/compile/internal/types" 9 "testing" 10 ) 11 12 func TestDeadStore(t *testing.T) { 13 c := testConfig(t) 14 ptrType := c.config.Types.BytePtr 15 t.Logf("PTRTYPE %v", ptrType) 16 fun := c.Fun("entry", 17 Bloc("entry", 18 Valu("start", OpInitMem, types.TypeMem, 0, nil), 19 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 20 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil), 21 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), 22 Valu("addr2", OpAddr, ptrType, 0, nil, "sb"), 23 Valu("addr3", OpAddr, ptrType, 0, nil, "sb"), 24 Valu("zero1", OpZero, types.TypeMem, 1, c.config.Types.Bool, "addr3", "start"), 25 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "zero1"), 26 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"), 27 Valu("store3", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store2"), 28 Valu("store4", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr3", "v", "store3"), 29 Goto("exit")), 30 Bloc("exit", 31 Exit("store3"))) 32 33 CheckFunc(fun.f) 34 dse(fun.f) 35 CheckFunc(fun.f) 36 37 v1 := fun.values["store1"] 38 if v1.Op != OpCopy { 39 t.Errorf("dead store not removed") 40 } 41 42 v2 := fun.values["zero1"] 43 if v2.Op != OpCopy { 44 t.Errorf("dead store (zero) not removed") 45 } 46 } 47 func TestDeadStorePhi(t *testing.T) { 48 // make sure we don't get into an infinite loop with phi values. 49 c := testConfig(t) 50 ptrType := c.config.Types.BytePtr 51 fun := c.Fun("entry", 52 Bloc("entry", 53 Valu("start", OpInitMem, types.TypeMem, 0, nil), 54 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 55 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil), 56 Valu("addr", OpAddr, ptrType, 0, nil, "sb"), 57 Goto("loop")), 58 Bloc("loop", 59 Valu("phi", OpPhi, types.TypeMem, 0, nil, "start", "store"), 60 Valu("store", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr", "v", "phi"), 61 If("v", "loop", "exit")), 62 Bloc("exit", 63 Exit("store"))) 64 65 CheckFunc(fun.f) 66 dse(fun.f) 67 CheckFunc(fun.f) 68 } 69 70 func TestDeadStoreTypes(t *testing.T) { 71 // Make sure a narrow store can't shadow a wider one. We test an even 72 // stronger restriction, that one store can't shadow another unless the 73 // types of the address fields are identical (where identicalness is 74 // decided by the CSE pass). 75 c := testConfig(t) 76 t1 := c.config.Types.UInt64.PtrTo() 77 t2 := c.config.Types.UInt32.PtrTo() 78 fun := c.Fun("entry", 79 Bloc("entry", 80 Valu("start", OpInitMem, types.TypeMem, 0, nil), 81 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 82 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil), 83 Valu("addr1", OpAddr, t1, 0, nil, "sb"), 84 Valu("addr2", OpAddr, t2, 0, nil, "sb"), 85 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "start"), 86 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"), 87 Goto("exit")), 88 Bloc("exit", 89 Exit("store2"))) 90 91 CheckFunc(fun.f) 92 cse(fun.f) 93 dse(fun.f) 94 CheckFunc(fun.f) 95 96 v := fun.values["store1"] 97 if v.Op == OpCopy { 98 t.Errorf("store %s incorrectly removed", v) 99 } 100 } 101 102 func TestDeadStoreUnsafe(t *testing.T) { 103 // Make sure a narrow store can't shadow a wider one. The test above 104 // covers the case of two different types, but unsafe pointer casting 105 // can get to a point where the size is changed but type unchanged. 106 c := testConfig(t) 107 ptrType := c.config.Types.UInt64.PtrTo() 108 fun := c.Fun("entry", 109 Bloc("entry", 110 Valu("start", OpInitMem, types.TypeMem, 0, nil), 111 Valu("sb", OpSB, types.TypeInvalid, 0, nil), 112 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil), 113 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), 114 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "addr1", "v", "start"), // store 8 bytes 115 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store1"), // store 1 byte 116 Goto("exit")), 117 Bloc("exit", 118 Exit("store2"))) 119 120 CheckFunc(fun.f) 121 cse(fun.f) 122 dse(fun.f) 123 CheckFunc(fun.f) 124 125 v := fun.values["store1"] 126 if v.Op == OpCopy { 127 t.Errorf("store %s incorrectly removed", v) 128 } 129 }