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
5package ssa
6
7import (
8	"cmd/internal/src"
9)
10
11// findlive returns the reachable blocks and live values in f.
12// The caller should call f.Cache.freeBoolSlice(live) when it is done with it.
13func findlive(f *Func) (reachable []bool, live []bool) {
14	reachable = ReachableBlocks(f)
15	var order []*Value
16	live, order = liveValues(f, reachable)
17	f.Cache.freeValueSlice(order)
18	return
19}
20
21// ReachableBlocks returns the reachable blocks in f.
22func ReachableBlocks(f *Func) []bool {
23	reachable := make([]bool, f.NumBlocks())
24	reachable[f.Entry.ID] = true
25	p := make([]*Block, 0, 64) // stack-like worklist
26	p = append(p, f.Entry)
27	for len(p) > 0 {
28		// Pop a reachable block
29		b := p[len(p)-1]
30		p = p[:len(p)-1]
31		// Mark successors as reachable
32		s := b.Succs
33		if b.Kind == BlockFirst {
34			s = s[:1]
35		}
36		for _, e := range s {
37			c := e.b
38			if int(c.ID) >= len(reachable) {
39				f.Fatalf("block %s >= f.NumBlocks()=%d?", c, len(reachable))
40			}
41			if !reachable[c.ID] {
42				reachable[c.ID] = true
43				p = append(p, c) // push
44			}
45		}
46	}
47	return reachable
48}
49
50// liveValues returns the live values in f and a list of values that are eligible
51// to be statements in reversed data flow order.
52// The second result is used to help conserve statement boundaries for debugging.
53// reachable is a map from block ID to whether the block is reachable.
54// The caller should call f.Cache.freeBoolSlice(live) and f.Cache.freeValueSlice(liveOrderStmts).
55// when they are done with the return values.
56func liveValues(f *Func, reachable []bool) (live []bool, liveOrderStmts []*Value) {
57	live = f.Cache.allocBoolSlice(f.NumValues())
58	liveOrderStmts = f.Cache.allocValueSlice(f.NumValues())[:0]
59
60	// After regalloc, consider all values to be live.
61	// See the comment at the top of regalloc.go and in deadcode for details.
62	if f.RegAlloc != nil {
63		for i := range live {
64			live[i] = true
65		}
66		return
67	}
68
69	// Record all the inline indexes we need
70	var liveInlIdx map[int]bool
71	pt := f.Config.ctxt.PosTable
72	for _, b := range f.Blocks {
73		for _, v := range b.Values {
74			i := pt.Pos(v.Pos).Base().InliningIndex()
75			if i < 0 {
76				continue
77			}
78			if liveInlIdx == nil {
79				liveInlIdx = map[int]bool{}
80			}
81			liveInlIdx[i] = true
82		}
83		i := pt.Pos(b.Pos).Base().InliningIndex()
84		if i < 0 {
85			continue
86		}
87		if liveInlIdx == nil {
88			liveInlIdx = map[int]bool{}
89		}
90		liveInlIdx[i] = true
91	}
92
93	// Find all live values
94	q := f.Cache.allocValueSlice(f.NumValues())[:0]
95	defer f.Cache.freeValueSlice(q)
96
97	// Starting set: all control values of reachable blocks are live.
98	// Calls are live (because callee can observe the memory state).
99	for _, b := range f.Blocks {
100		if !reachable[b.ID] {
101			continue
102		}
103		for _, v := range b.ControlValues() {
104			if !live[v.ID] {
105				live[v.ID] = true
106				q = append(q, v)
107				if v.Pos.IsStmt() != src.PosNotStmt {
108					liveOrderStmts = append(liveOrderStmts, v)
109				}
110			}
111		}
112		for _, v := range b.Values {
113			if (opcodeTable[v.Op].call || opcodeTable[v.Op].hasSideEffects || opcodeTable[v.Op].nilCheck) && !live[v.ID] {
114				live[v.ID] = true
115				q = append(q, v)
116				if v.Pos.IsStmt() != src.PosNotStmt {
117					liveOrderStmts = append(liveOrderStmts, v)
118				}
119			}
120			if v.Op == OpInlMark {
121				if !liveInlIdx[int(v.AuxInt)] {
122					// We don't need marks for bodies that
123					// have been completely optimized away.
124					// TODO: save marks only for bodies which
125					// have a faulting instruction or a call?
126					continue
127				}
128				live[v.ID] = true
129				q = append(q, v)
130				if v.Pos.IsStmt() != src.PosNotStmt {
131					liveOrderStmts = append(liveOrderStmts, v)
132				}
133			}
134		}
135	}
136
137	// Compute transitive closure of live values.
138	for len(q) > 0 {
139		// pop a reachable value
140		v := q[len(q)-1]
141		q[len(q)-1] = nil
142		q = q[:len(q)-1]
143		for i, x := range v.Args {
144			if v.Op == OpPhi && !reachable[v.Block.Preds[i].b.ID] {
145				continue
146			}
147			if !live[x.ID] {
148				live[x.ID] = true
149				q = append(q, x) // push
150				if x.Pos.IsStmt() != src.PosNotStmt {
151					liveOrderStmts = append(liveOrderStmts, x)
152				}
153			}
154		}
155	}
156
157	return
158}
159
160// deadcode removes dead code from f.
161func deadcode(f *Func) {
162	// deadcode after regalloc is forbidden for now. Regalloc
163	// doesn't quite generate legal SSA which will lead to some
164	// required moves being eliminated. See the comment at the
165	// top of regalloc.go for details.
166	if f.RegAlloc != nil {
167		f.Fatalf("deadcode after regalloc")
168	}
169
170	// Find reachable blocks.
171	reachable := ReachableBlocks(f)
172
173	// Get rid of edges from dead to live code.
174	for _, b := range f.Blocks {
175		if reachable[b.ID] {
176			continue
177		}
178		for i := 0; i < len(b.Succs); {
179			e := b.Succs[i]
180			if reachable[e.b.ID] {
181				b.removeEdge(i)
182			} else {
183				i++
184			}
185		}
186	}
187
188	// Get rid of dead edges from live code.
189	for _, b := range f.Blocks {
190		if !reachable[b.ID] {
191			continue
192		}
193		if b.Kind != BlockFirst {
194			continue
195		}
196		b.removeEdge(1)
197		b.Kind = BlockPlain
198		b.Likely = BranchUnknown
199	}
200
201	// Splice out any copies introduced during dead block removal.
202	copyelim(f)
203
204	// Find live values.
205	live, order := liveValues(f, reachable)
206	defer func() { f.Cache.freeBoolSlice(live) }()
207	defer func() { f.Cache.freeValueSlice(order) }()
208
209	// Remove dead & duplicate entries from namedValues map.
210	s := f.newSparseSet(f.NumValues())
211	defer f.retSparseSet(s)
212	i := 0
213	for _, name := range f.Names {
214		j := 0
215		s.clear()
216		values := f.NamedValues[*name]
217		for _, v := range values {
218			if live[v.ID] && !s.contains(v.ID) {
219				values[j] = v
220				j++
221				s.add(v.ID)
222			}
223		}
224		if j == 0 {
225			delete(f.NamedValues, *name)
226		} else {
227			f.Names[i] = name
228			i++
229			for k := len(values) - 1; k >= j; k-- {
230				values[k] = nil
231			}
232			f.NamedValues[*name] = values[:j]
233		}
234	}
235	clearNames := f.Names[i:]
236	for j := range clearNames {
237		clearNames[j] = nil
238	}
239	f.Names = f.Names[:i]
240
241	pendingLines := f.cachedLineStarts // Holds statement boundaries that need to be moved to a new value/block
242	pendingLines.clear()
243
244	// Unlink values and conserve statement boundaries
245	for i, b := range f.Blocks {
246		if !reachable[b.ID] {
247			// TODO what if control is statement boundary? Too late here.
248			b.ResetControls()
249		}
250		for _, v := range b.Values {
251			if !live[v.ID] {
252				v.resetArgs()
253				if v.Pos.IsStmt() == src.PosIsStmt && reachable[b.ID] {
254					pendingLines.set(v.Pos, int32(i)) // TODO could be more than one pos for a line
255				}
256			}
257		}
258	}
259
260	// Find new homes for lost lines -- require earliest in data flow with same line that is also in same block
261	for i := len(order) - 1; i >= 0; i-- {
262		w := order[i]
263		if j := pendingLines.get(w.Pos); j > -1 && f.Blocks[j] == w.Block {
264			w.Pos = w.Pos.WithIsStmt()
265			pendingLines.remove(w.Pos)
266		}
267	}
268
269	// Any boundary that failed to match a live value can move to a block end
270	pendingLines.foreachEntry(func(j int32, l uint, bi int32) {
271		b := f.Blocks[bi]
272		if b.Pos.Line() == l && b.Pos.FileIndex() == j {
273			b.Pos = b.Pos.WithIsStmt()
274		}
275	})
276
277	// Remove dead values from blocks' value list. Return dead
278	// values to the allocator.
279	for _, b := range f.Blocks {
280		i := 0
281		for _, v := range b.Values {
282			if live[v.ID] {
283				b.Values[i] = v
284				i++
285			} else {
286				f.freeValue(v)
287			}
288		}
289		b.truncateValues(i)
290	}
291
292	// Remove unreachable blocks. Return dead blocks to allocator.
293	i = 0
294	for _, b := range f.Blocks {
295		if reachable[b.ID] {
296			f.Blocks[i] = b
297			i++
298		} else {
299			if len(b.Values) > 0 {
300				b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
301			}
302			f.freeBlock(b)
303		}
304	}
305	// zero remainder to help GC
306	tail := f.Blocks[i:]
307	for j := range tail {
308		tail[j] = nil
309	}
310	f.Blocks = f.Blocks[:i]
311}
312
313// removeEdge removes the i'th outgoing edge from b (and
314// the corresponding incoming edge from b.Succs[i].b).
315// Note that this potentially reorders successors of b, so it
316// must be used very carefully.
317func (b *Block) removeEdge(i int) {
318	e := b.Succs[i]
319	c := e.b
320	j := e.i
321
322	// Adjust b.Succs
323	b.removeSucc(i)
324
325	// Adjust c.Preds
326	c.removePred(j)
327
328	// Remove phi args from c's phis.
329	for _, v := range c.Values {
330		if v.Op != OpPhi {
331			continue
332		}
333		c.removePhiArg(v, j)
334		// Note: this is trickier than it looks. Replacing
335		// a Phi with a Copy can in general cause problems because
336		// Phi and Copy don't have exactly the same semantics.
337		// Phi arguments always come from a predecessor block,
338		// whereas copies don't. This matters in loops like:
339		// 1: x = (Phi y)
340		//    y = (Add x 1)
341		//    goto 1
342		// If we replace Phi->Copy, we get
343		// 1: x = (Copy y)
344		//    y = (Add x 1)
345		//    goto 1
346		// (Phi y) refers to the *previous* value of y, whereas
347		// (Copy y) refers to the *current* value of y.
348		// The modified code has a cycle and the scheduler
349		// will barf on it.
350		//
351		// Fortunately, this situation can only happen for dead
352		// code loops. We know the code we're working with is
353		// not dead, so we're ok.
354		// Proof: If we have a potential bad cycle, we have a
355		// situation like this:
356		//   x = (Phi z)
357		//   y = (op1 x ...)
358		//   z = (op2 y ...)
359		// Where opX are not Phi ops. But such a situation
360		// implies a cycle in the dominator graph. In the
361		// example, x.Block dominates y.Block, y.Block dominates
362		// z.Block, and z.Block dominates x.Block (treating
363		// "dominates" as reflexive).  Cycles in the dominator
364		// graph can only happen in an unreachable cycle.
365	}
366}
367