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 "testing" 8 9 func TestDeadStore(t *testing.T) { 10 c := testConfig(t) 11 elemType := &TypeImpl{Size_: 1, Name: "testtype"} 12 ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr", Elem_: elemType} // dummy for testing 13 fun := Fun(c, "entry", 14 Bloc("entry", 15 Valu("start", OpInitMem, TypeMem, 0, nil), 16 Valu("sb", OpSB, TypeInvalid, 0, nil), 17 Valu("v", OpConstBool, TypeBool, 1, nil), 18 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), 19 Valu("addr2", OpAddr, ptrType, 0, nil, "sb"), 20 Valu("addr3", OpAddr, ptrType, 0, nil, "sb"), 21 Valu("zero1", OpZero, TypeMem, 1, nil, "addr3", "start"), 22 Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "zero1"), 23 Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"), 24 Valu("store3", OpStore, TypeMem, 1, nil, "addr1", "v", "store2"), 25 Valu("store4", OpStore, TypeMem, 1, nil, "addr3", "v", "store3"), 26 Goto("exit")), 27 Bloc("exit", 28 Exit("store3"))) 29 30 CheckFunc(fun.f) 31 dse(fun.f) 32 CheckFunc(fun.f) 33 34 v1 := fun.values["store1"] 35 if v1.Op != OpCopy { 36 t.Errorf("dead store not removed") 37 } 38 39 v2 := fun.values["zero1"] 40 if v2.Op != OpCopy { 41 t.Errorf("dead store (zero) not removed") 42 } 43 } 44 func TestDeadStorePhi(t *testing.T) { 45 // make sure we don't get into an infinite loop with phi values. 46 c := testConfig(t) 47 ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing 48 fun := Fun(c, "entry", 49 Bloc("entry", 50 Valu("start", OpInitMem, TypeMem, 0, nil), 51 Valu("sb", OpSB, TypeInvalid, 0, nil), 52 Valu("v", OpConstBool, TypeBool, 1, nil), 53 Valu("addr", OpAddr, ptrType, 0, nil, "sb"), 54 Goto("loop")), 55 Bloc("loop", 56 Valu("phi", OpPhi, TypeMem, 0, nil, "start", "store"), 57 Valu("store", OpStore, TypeMem, 1, nil, "addr", "v", "phi"), 58 If("v", "loop", "exit")), 59 Bloc("exit", 60 Exit("store"))) 61 62 CheckFunc(fun.f) 63 dse(fun.f) 64 CheckFunc(fun.f) 65 } 66 67 func TestDeadStoreTypes(t *testing.T) { 68 // Make sure a narrow store can't shadow a wider one. We test an even 69 // stronger restriction, that one store can't shadow another unless the 70 // types of the address fields are identical (where identicalness is 71 // decided by the CSE pass). 72 c := testConfig(t) 73 t1 := &TypeImpl{Size_: 8, Ptr: true, Name: "t1"} 74 t2 := &TypeImpl{Size_: 4, Ptr: true, Name: "t2"} 75 fun := Fun(c, "entry", 76 Bloc("entry", 77 Valu("start", OpInitMem, TypeMem, 0, nil), 78 Valu("sb", OpSB, TypeInvalid, 0, nil), 79 Valu("v", OpConstBool, TypeBool, 1, nil), 80 Valu("addr1", OpAddr, t1, 0, nil, "sb"), 81 Valu("addr2", OpAddr, t2, 0, nil, "sb"), 82 Valu("store1", OpStore, TypeMem, 1, nil, "addr1", "v", "start"), 83 Valu("store2", OpStore, TypeMem, 1, nil, "addr2", "v", "store1"), 84 Goto("exit")), 85 Bloc("exit", 86 Exit("store2"))) 87 88 CheckFunc(fun.f) 89 cse(fun.f) 90 dse(fun.f) 91 CheckFunc(fun.f) 92 93 v := fun.values["store1"] 94 if v.Op == OpCopy { 95 t.Errorf("store %s incorrectly removed", v) 96 } 97 } 98 99 func TestDeadStoreUnsafe(t *testing.T) { 100 // Make sure a narrow store can't shadow a wider one. The test above 101 // covers the case of two different types, but unsafe pointer casting 102 // can get to a point where the size is changed but type unchanged. 103 c := testConfig(t) 104 ptrType := &TypeImpl{Size_: 8, Ptr: true, Name: "testptr"} // dummy for testing 105 fun := Fun(c, "entry", 106 Bloc("entry", 107 Valu("start", OpInitMem, TypeMem, 0, nil), 108 Valu("sb", OpSB, TypeInvalid, 0, nil), 109 Valu("v", OpConstBool, TypeBool, 1, nil), 110 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"), 111 Valu("store1", OpStore, TypeMem, 8, nil, "addr1", "v", "start"), // store 8 bytes 112 Valu("store2", OpStore, TypeMem, 1, nil, "addr1", "v", "store1"), // store 1 byte 113 Goto("exit")), 114 Bloc("exit", 115 Exit("store2"))) 116 117 CheckFunc(fun.f) 118 cse(fun.f) 119 dse(fun.f) 120 CheckFunc(fun.f) 121 122 v := fun.values["store1"] 123 if v.Op == OpCopy { 124 t.Errorf("store %s incorrectly removed", v) 125 } 126 } 127