1
2
3
4
5 package ssacompile
6
7 import (
8 "cmd/compile/internal/ssa"
9 "cmd/compile/internal/ssa/block"
10 "cmd/internal/src"
11 )
12
13
14 func deadcode(f *ssa.Func) {
15
16
17
18
19 if f.RegAlloc != nil {
20 f.Fatalf("deadcode after regalloc")
21 }
22
23
24 reachable := ssa.ReachableBlocks(f)
25
26
27 for _, b := range f.Blocks {
28 if reachable[b.ID] {
29 continue
30 }
31 for i := 0; i < len(b.Succs); {
32 e := b.Succs[i]
33 if reachable[e.B.ID] {
34 b.RemoveEdge(i)
35 } else {
36 i++
37 }
38 }
39 }
40
41
42 for _, b := range f.Blocks {
43 if !reachable[b.ID] {
44 continue
45 }
46 if b.Kind != block.BlockFirst {
47 continue
48 }
49 b.RemoveEdge(1)
50 b.Kind = block.BlockPlain
51 b.Likely = ssa.BranchUnknown
52 }
53
54
55 copyelim(f)
56
57
58 live, order := ssa.LiveValues(f, reachable)
59 defer func() { f.Cache.FreeBoolSlice(live) }()
60 defer func() { f.Cache.FreeValueSlice(order) }()
61
62
63 s := f.NewSparseSet(f.NumValues())
64 defer f.RetSparseSet(s)
65 i := 0
66 for _, name := range f.Names {
67 j := 0
68 s.Clear()
69 values := f.NamedValues[name]
70 for _, v := range values {
71 if live[v.ID] && !s.Contains(v.ID) {
72 values[j] = v
73 j++
74 s.Add(v.ID)
75 }
76 }
77 if j == 0 {
78 delete(f.NamedValues, name)
79 } else {
80 f.Names[i] = name
81 i++
82 for k := len(values) - 1; k >= j; k-- {
83 values[k] = nil
84 }
85 f.NamedValues[name] = values[:j]
86 }
87 }
88 clear(f.Names[i:])
89 f.Names = f.Names[:i]
90
91 pendingLines := f.CachedLineStarts
92 pendingLines.Clear()
93
94
95 for i, b := range f.Blocks {
96 if !reachable[b.ID] {
97
98 b.ResetControls()
99 }
100 for _, v := range b.Values {
101 if !live[v.ID] {
102 v.ResetArgs()
103 if v.Pos.IsStmt() == src.PosIsStmt && reachable[b.ID] {
104 pendingLines.Set(v.Pos, int32(i))
105 }
106 }
107 }
108 }
109
110
111 for i := len(order) - 1; i >= 0; i-- {
112 w := order[i]
113 if j, ok := pendingLines.Get(w.Pos); ok && f.Blocks[j] == w.Block {
114 w.Pos = w.Pos.WithIsStmt()
115 pendingLines.Remove(w.Pos)
116 }
117 }
118
119
120 pendingLines.ForeachEntry(func(j int32, l uint, bi int32) {
121 b := f.Blocks[bi]
122 if b.Pos.Line() == l && b.Pos.FileIndex() == j {
123 b.Pos = b.Pos.WithIsStmt()
124 }
125 })
126
127
128
129 for _, b := range f.Blocks {
130 i := 0
131 for _, v := range b.Values {
132 if live[v.ID] {
133 b.Values[i] = v
134 i++
135 } else {
136 f.FreeValue(v)
137 }
138 }
139 b.TruncateValues(i)
140 }
141
142
143 i = 0
144 for _, b := range f.Blocks {
145 if reachable[b.ID] {
146 f.Blocks[i] = b
147 i++
148 } else {
149 if len(b.Values) > 0 {
150 b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
151 }
152 f.FreeBlock(b)
153 }
154 }
155
156 clear(f.Blocks[i:])
157 f.Blocks = f.Blocks[:i]
158 }
159
View as plain text