1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/types"
9 "cmd/internal/src"
10 "testing"
11 )
12
13 func TestDeadStore(t *testing.T) {
14 c := testConfig(t)
15 ptrType := c.config.Types.BytePtr
16 t.Logf("PTRTYPE %v", ptrType)
17 fun := c.Fun("entry",
18 Bloc("entry",
19 Valu("start", OpInitMem, types.TypeMem, 0, nil),
20 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
21 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
22 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
23 Valu("addr2", OpAddr, ptrType, 0, nil, "sb"),
24 Valu("addr3", OpAddr, ptrType, 0, nil, "sb"),
25 Valu("zero1", OpZero, types.TypeMem, 1, c.config.Types.Bool, "addr3", "start"),
26 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "zero1"),
27 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"),
28 Valu("store3", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store2"),
29 Valu("store4", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr3", "v", "store3"),
30 Goto("exit")),
31 Bloc("exit",
32 Exit("store3")))
33
34 CheckFunc(fun.f)
35 dse(fun.f)
36 CheckFunc(fun.f)
37
38 v1 := fun.values["store1"]
39 if v1.Op != OpCopy {
40 t.Errorf("dead store not removed")
41 }
42
43 v2 := fun.values["zero1"]
44 if v2.Op != OpCopy {
45 t.Errorf("dead store (zero) not removed")
46 }
47 }
48
49 func TestDeadStorePhi(t *testing.T) {
50
51 c := testConfig(t)
52 ptrType := c.config.Types.BytePtr
53 fun := c.Fun("entry",
54 Bloc("entry",
55 Valu("start", OpInitMem, types.TypeMem, 0, nil),
56 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
57 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
58 Valu("addr", OpAddr, ptrType, 0, nil, "sb"),
59 Goto("loop")),
60 Bloc("loop",
61 Valu("phi", OpPhi, types.TypeMem, 0, nil, "start", "store"),
62 Valu("store", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr", "v", "phi"),
63 If("v", "loop", "exit")),
64 Bloc("exit",
65 Exit("store")))
66
67 CheckFunc(fun.f)
68 dse(fun.f)
69 CheckFunc(fun.f)
70 }
71
72 func TestDeadStoreTypes(t *testing.T) {
73
74
75
76
77 c := testConfig(t)
78 t1 := c.config.Types.UInt64.PtrTo()
79 t2 := c.config.Types.UInt32.PtrTo()
80 fun := c.Fun("entry",
81 Bloc("entry",
82 Valu("start", OpInitMem, types.TypeMem, 0, nil),
83 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
84 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
85 Valu("addr1", OpAddr, t1, 0, nil, "sb"),
86 Valu("addr2", OpAddr, t2, 0, nil, "sb"),
87 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "start"),
88 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr2", "v", "store1"),
89 Goto("exit")),
90 Bloc("exit",
91 Exit("store2")))
92
93 CheckFunc(fun.f)
94 cse(fun.f)
95 dse(fun.f)
96 CheckFunc(fun.f)
97
98 v := fun.values["store1"]
99 if v.Op == OpCopy {
100 t.Errorf("store %s incorrectly removed", v)
101 }
102 }
103
104 func TestDeadStoreUnsafe(t *testing.T) {
105
106
107
108 c := testConfig(t)
109 ptrType := c.config.Types.UInt64.PtrTo()
110 fun := c.Fun("entry",
111 Bloc("entry",
112 Valu("start", OpInitMem, types.TypeMem, 0, nil),
113 Valu("sb", OpSB, c.config.Types.Uintptr, 0, nil),
114 Valu("v", OpConstBool, c.config.Types.Bool, 1, nil),
115 Valu("addr1", OpAddr, ptrType, 0, nil, "sb"),
116 Valu("store1", OpStore, types.TypeMem, 0, c.config.Types.Int64, "addr1", "v", "start"),
117 Valu("store2", OpStore, types.TypeMem, 0, c.config.Types.Bool, "addr1", "v", "store1"),
118 Goto("exit")),
119 Bloc("exit",
120 Exit("store2")))
121
122 CheckFunc(fun.f)
123 cse(fun.f)
124 dse(fun.f)
125 CheckFunc(fun.f)
126
127 v := fun.values["store1"]
128 if v.Op == OpCopy {
129 t.Errorf("store %s incorrectly removed", v)
130 }
131 }
132
133 func TestDeadStoreSmallStructInit(t *testing.T) {
134 c := testConfig(t)
135 ptrType := c.config.Types.BytePtr
136 typ := types.NewStruct([]*types.Field{
137 types.NewField(src.NoXPos, &types.Sym{Name: "A"}, c.config.Types.Int),
138 types.NewField(src.NoXPos, &types.Sym{Name: "B"}, c.config.Types.Int),
139 })
140 name := c.Temp(typ)
141 fun := c.Fun("entry",
142 Bloc("entry",
143 Valu("start", OpInitMem, types.TypeMem, 0, nil),
144 Valu("sp", OpSP, c.config.Types.Uintptr, 0, nil),
145 Valu("zero", OpConst64, c.config.Types.Int, 0, nil),
146 Valu("v6", OpLocalAddr, ptrType, 0, name, "sp", "start"),
147 Valu("v3", OpOffPtr, ptrType, 8, nil, "v6"),
148 Valu("v22", OpOffPtr, ptrType, 0, nil, "v6"),
149 Valu("zerostore1", OpStore, types.TypeMem, 0, c.config.Types.Int, "v22", "zero", "start"),
150 Valu("zerostore2", OpStore, types.TypeMem, 0, c.config.Types.Int, "v3", "zero", "zerostore1"),
151 Valu("v8", OpLocalAddr, ptrType, 0, name, "sp", "zerostore2"),
152 Valu("v23", OpOffPtr, ptrType, 8, nil, "v8"),
153 Valu("v25", OpOffPtr, ptrType, 0, nil, "v8"),
154 Valu("zerostore3", OpStore, types.TypeMem, 0, c.config.Types.Int, "v25", "zero", "zerostore2"),
155 Valu("zerostore4", OpStore, types.TypeMem, 0, c.config.Types.Int, "v23", "zero", "zerostore3"),
156 Goto("exit")),
157 Bloc("exit",
158 Exit("zerostore4")))
159
160 fun.f.Name = "smallstructinit"
161 CheckFunc(fun.f)
162 cse(fun.f)
163 dse(fun.f)
164 CheckFunc(fun.f)
165
166 v1 := fun.values["zerostore1"]
167 if v1.Op != OpCopy {
168 t.Errorf("dead store not removed")
169 }
170 v2 := fun.values["zerostore2"]
171 if v2.Op != OpCopy {
172 t.Errorf("dead store not removed")
173 }
174 }
175
View as plain text