...
1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/ir"
9 "cmd/compile/internal/types"
10 )
11
12
13
14
15
16 func dse(f *Func) {
17 var stores []*Value
18 loadUse := f.newSparseSet(f.NumValues())
19 defer f.retSparseSet(loadUse)
20 storeUse := f.newSparseSet(f.NumValues())
21 defer f.retSparseSet(storeUse)
22 shadowed := f.newSparseMap(f.NumValues())
23 defer f.retSparseMap(shadowed)
24 for _, b := range f.Blocks {
25
26
27
28 loadUse.clear()
29 storeUse.clear()
30 stores = stores[:0]
31 for _, v := range b.Values {
32 if v.Op == OpPhi {
33
34 continue
35 }
36 if v.Type.IsMemory() {
37 stores = append(stores, v)
38 for _, a := range v.Args {
39 if a.Block == b && a.Type.IsMemory() {
40 storeUse.add(a.ID)
41 if v.Op != OpStore && v.Op != OpZero && v.Op != OpVarDef {
42
43
44 loadUse.add(a.ID)
45 }
46 }
47 }
48 } else {
49 for _, a := range v.Args {
50 if a.Block == b && a.Type.IsMemory() {
51 loadUse.add(a.ID)
52 }
53 }
54 }
55 }
56 if len(stores) == 0 {
57 continue
58 }
59
60
61 var last *Value
62 for _, v := range stores {
63 if storeUse.contains(v.ID) {
64 continue
65 }
66 if last != nil {
67 b.Fatalf("two final stores - simultaneous live stores %s %s", last.LongString(), v.LongString())
68 }
69 last = v
70 }
71 if last == nil {
72 b.Fatalf("no last store found - cycle?")
73 }
74
75
76
77
78
79
80
81 shadowed.clear()
82 v := last
83
84 walkloop:
85 if loadUse.contains(v.ID) {
86
87
88 shadowed.clear()
89 }
90 if v.Op == OpStore || v.Op == OpZero {
91 ptr := v.Args[0]
92 var off int64
93 for ptr.Op == OpOffPtr {
94 off += ptr.AuxInt
95 ptr = ptr.Args[0]
96 }
97 var sz int64
98 if v.Op == OpStore {
99 sz = v.Aux.(*types.Type).Size()
100 } else {
101 sz = v.AuxInt
102 }
103 sr := shadowRange(shadowed.get(ptr.ID))
104 if sr.contains(off, off+sz) {
105
106
107 if v.Op == OpStore {
108
109 v.SetArgs1(v.Args[2])
110 } else {
111
112 v.SetArgs1(v.Args[1])
113 }
114 v.Aux = nil
115 v.AuxInt = 0
116 v.Op = OpCopy
117 } else {
118
119 shadowed.set(ptr.ID, int32(sr.merge(off, off+sz)))
120 }
121 }
122
123 if v.Op == OpPhi {
124
125
126
127
128 continue
129 }
130 for _, a := range v.Args {
131 if a.Block == b && a.Type.IsMemory() {
132 v = a
133 goto walkloop
134 }
135 }
136 }
137 }
138
139
140
141
142
143
144 type shadowRange int32
145
146 func (sr shadowRange) lo() int64 {
147 return int64(sr & 0xffff)
148 }
149 func (sr shadowRange) hi() int64 {
150 return int64((sr >> 16) & 0xffff)
151 }
152
153
154 func (sr shadowRange) contains(lo, hi int64) bool {
155 return lo >= sr.lo() && hi <= sr.hi()
156 }
157
158
159
160 func (sr shadowRange) merge(lo, hi int64) shadowRange {
161 if lo < 0 || hi > 0xffff {
162
163 return sr
164 }
165 if sr.lo() == sr.hi() {
166
167 return shadowRange(lo + hi<<16)
168 }
169 if hi < sr.lo() || lo > sr.hi() {
170
171
172
173 if sr.hi()-sr.lo() >= hi-lo {
174 return sr
175 }
176 return shadowRange(lo + hi<<16)
177 }
178
179 return shadowRange(min(lo, sr.lo()) + max(hi, sr.hi())<<16)
180 }
181
182
183
184
185
186 func elimDeadAutosGeneric(f *Func) {
187 addr := make(map[*Value]*ir.Name)
188 elim := make(map[*Value]*ir.Name)
189 var used ir.NameSet
190
191
192 visit := func(v *Value) (changed bool) {
193 args := v.Args
194 switch v.Op {
195 case OpAddr, OpLocalAddr:
196
197 n, ok := v.Aux.(*ir.Name)
198 if !ok || n.Class != ir.PAUTO {
199 return
200 }
201 if addr[v] == nil {
202 addr[v] = n
203 changed = true
204 }
205 return
206 case OpVarDef:
207
208 n, ok := v.Aux.(*ir.Name)
209 if !ok || n.Class != ir.PAUTO {
210 return
211 }
212 if elim[v] == nil {
213 elim[v] = n
214 changed = true
215 }
216 return
217 case OpVarLive:
218
219
220
221
222
223
224 n, ok := v.Aux.(*ir.Name)
225 if !ok || n.Class != ir.PAUTO {
226 return
227 }
228 if !used.Has(n) {
229 used.Add(n)
230 changed = true
231 }
232 return
233 case OpStore, OpMove, OpZero:
234
235 n, ok := addr[args[0]]
236 if ok && elim[v] == nil {
237 elim[v] = n
238 changed = true
239 }
240
241 args = args[1:]
242 }
243
244
245
246
247 if v.Op.SymEffect() != SymNone && v.Op != OpArg {
248 panic("unhandled op with sym effect")
249 }
250
251 if v.Uses == 0 && v.Op != OpNilCheck && !v.Op.IsCall() && !v.Op.HasSideEffects() || len(args) == 0 {
252
253
254 return
255 }
256
257
258
259
260 if v.Type.IsMemory() || v.Type.IsFlags() || v.Op == OpPhi || v.MemoryArg() != nil {
261 for _, a := range args {
262 if n, ok := addr[a]; ok {
263 if !used.Has(n) {
264 used.Add(n)
265 changed = true
266 }
267 }
268 }
269 return
270 }
271
272
273 var node *ir.Name
274 for _, a := range args {
275 if n, ok := addr[a]; ok && !used.Has(n) {
276 if node == nil {
277 node = n
278 } else if node != n {
279
280
281
282
283
284 used.Add(n)
285 changed = true
286 }
287 }
288 }
289 if node == nil {
290 return
291 }
292 if addr[v] == nil {
293
294 addr[v] = node
295 changed = true
296 return
297 }
298 if addr[v] != node {
299
300 used.Add(node)
301 changed = true
302 }
303 return
304 }
305
306 iterations := 0
307 for {
308 if iterations == 4 {
309
310 return
311 }
312 iterations++
313 changed := false
314 for _, b := range f.Blocks {
315 for _, v := range b.Values {
316 changed = visit(v) || changed
317 }
318
319 for _, c := range b.ControlValues() {
320 if n, ok := addr[c]; ok && !used.Has(n) {
321 used.Add(n)
322 changed = true
323 }
324 }
325 }
326 if !changed {
327 break
328 }
329 }
330
331
332 for v, n := range elim {
333 if used.Has(n) {
334 continue
335 }
336
337 v.SetArgs1(v.MemoryArg())
338 v.Aux = nil
339 v.AuxInt = 0
340 v.Op = OpCopy
341 }
342 }
343
344
345
346 func elimUnreadAutos(f *Func) {
347
348
349
350 var seen ir.NameSet
351 var stores []*Value
352 for _, b := range f.Blocks {
353 for _, v := range b.Values {
354 n, ok := v.Aux.(*ir.Name)
355 if !ok {
356 continue
357 }
358 if n.Class != ir.PAUTO {
359 continue
360 }
361
362 effect := v.Op.SymEffect()
363 switch effect {
364 case SymNone, SymWrite:
365
366
367
368 if !seen.Has(n) {
369 stores = append(stores, v)
370 }
371 default:
372
373
374
375
376
377 if v.Uses > 0 {
378 seen.Add(n)
379 }
380 }
381 }
382 }
383
384
385 for _, store := range stores {
386 n, _ := store.Aux.(*ir.Name)
387 if seen.Has(n) {
388 continue
389 }
390
391
392 store.SetArgs1(store.MemoryArg())
393 store.Aux = nil
394 store.AuxInt = 0
395 store.Op = OpCopy
396 }
397 }
398
View as plain text