...
1
2
3
4
5 package ssa
6
7 import (
8 "cmd/internal/src"
9 "fmt"
10 )
11
12
13 type Block struct {
14
15
16 ID ID
17
18
19 Pos src.XPos
20
21
22 Kind BlockKind
23
24
25
26
27
28
29 Likely BranchPrediction
30
31
32 FlagsLiveAtEnd bool
33
34
35 Succs []Edge
36
37
38
39
40
41 Preds []Edge
42
43
44
45
46
47
48
49
50
51
52 Controls [2]*Value
53
54
55 Aux Aux
56 AuxInt int64
57
58
59
60 Values []*Value
61
62
63 Func *Func
64
65
66 succstorage [2]Edge
67 predstorage [4]Edge
68 valstorage [9]*Value
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94 type Edge struct {
95
96 b *Block
97
98
99
100
101 i int
102 }
103
104 func (e Edge) Block() *Block {
105 return e.b
106 }
107 func (e Edge) Index() int {
108 return e.i
109 }
110 func (e Edge) String() string {
111 return fmt.Sprintf("{%v,%d}", e.b, e.i)
112 }
113
114
115 type BlockKind int16
116
117
118 func (b *Block) String() string {
119 return fmt.Sprintf("b%d", b.ID)
120 }
121
122
123 func (b *Block) LongString() string {
124 s := b.Kind.String()
125 if b.Aux != nil {
126 s += fmt.Sprintf(" {%s}", b.Aux)
127 }
128 if t := b.AuxIntString(); t != "" {
129 s += fmt.Sprintf(" [%s]", t)
130 }
131 for _, c := range b.ControlValues() {
132 s += fmt.Sprintf(" %s", c)
133 }
134 if len(b.Succs) > 0 {
135 s += " ->"
136 for _, c := range b.Succs {
137 s += " " + c.b.String()
138 }
139 }
140 switch b.Likely {
141 case BranchUnlikely:
142 s += " (unlikely)"
143 case BranchLikely:
144 s += " (likely)"
145 }
146 return s
147 }
148
149
150
151 func (b *Block) NumControls() int {
152 if b.Controls[0] == nil {
153 return 0
154 }
155 if b.Controls[1] == nil {
156 return 1
157 }
158 return 2
159 }
160
161
162
163
164
165 func (b *Block) ControlValues() []*Value {
166 if b.Controls[0] == nil {
167 return b.Controls[:0]
168 }
169 if b.Controls[1] == nil {
170 return b.Controls[:1]
171 }
172 return b.Controls[:2]
173 }
174
175
176
177
178 func (b *Block) SetControl(v *Value) {
179 b.ResetControls()
180 b.Controls[0] = v
181 v.Uses++
182 }
183
184
185 func (b *Block) ResetControls() {
186 if b.Controls[0] != nil {
187 b.Controls[0].Uses--
188 }
189 if b.Controls[1] != nil {
190 b.Controls[1].Uses--
191 }
192 b.Controls = [2]*Value{}
193 }
194
195
196 func (b *Block) AddControl(v *Value) {
197 i := b.NumControls()
198 b.Controls[i] = v
199 v.Uses++
200 }
201
202
203
204 func (b *Block) ReplaceControl(i int, v *Value) {
205 b.Controls[i].Uses--
206 b.Controls[i] = v
207 v.Uses++
208 }
209
210
211
212 func (b *Block) CopyControls(from *Block) {
213 if b == from {
214 return
215 }
216 b.ResetControls()
217 for _, c := range from.ControlValues() {
218 b.AddControl(c)
219 }
220 }
221
222
223
224
225 func (b *Block) Reset(kind BlockKind) {
226 b.Kind = kind
227 b.ResetControls()
228 b.Aux = nil
229 b.AuxInt = 0
230 }
231
232
233
234
235
236 func (b *Block) resetWithControl(kind BlockKind, v *Value) {
237 b.Kind = kind
238 b.ResetControls()
239 b.Aux = nil
240 b.AuxInt = 0
241 b.Controls[0] = v
242 v.Uses++
243 }
244
245
246
247
248
249 func (b *Block) resetWithControl2(kind BlockKind, v, w *Value) {
250 b.Kind = kind
251 b.ResetControls()
252 b.Aux = nil
253 b.AuxInt = 0
254 b.Controls[0] = v
255 b.Controls[1] = w
256 v.Uses++
257 w.Uses++
258 }
259
260
261
262
263 func (b *Block) truncateValues(i int) {
264 tail := b.Values[i:]
265 for j := range tail {
266 tail[j] = nil
267 }
268 b.Values = b.Values[:i]
269 }
270
271
272 func (b *Block) AddEdgeTo(c *Block) {
273 i := len(b.Succs)
274 j := len(c.Preds)
275 b.Succs = append(b.Succs, Edge{c, j})
276 c.Preds = append(c.Preds, Edge{b, i})
277 b.Func.invalidateCFG()
278 }
279
280
281
282
283
284 func (b *Block) removePred(i int) {
285 n := len(b.Preds) - 1
286 if i != n {
287 e := b.Preds[n]
288 b.Preds[i] = e
289
290 e.b.Succs[e.i].i = i
291 }
292 b.Preds[n] = Edge{}
293 b.Preds = b.Preds[:n]
294 b.Func.invalidateCFG()
295 }
296
297
298
299
300
301
302 func (b *Block) removeSucc(i int) {
303 n := len(b.Succs) - 1
304 if i != n {
305 e := b.Succs[n]
306 b.Succs[i] = e
307
308 e.b.Preds[e.i].i = i
309 }
310 b.Succs[n] = Edge{}
311 b.Succs = b.Succs[:n]
312 b.Func.invalidateCFG()
313 }
314
315 func (b *Block) swapSuccessors() {
316 if len(b.Succs) != 2 {
317 b.Fatalf("swapSuccessors with len(Succs)=%d", len(b.Succs))
318 }
319 e0 := b.Succs[0]
320 e1 := b.Succs[1]
321 b.Succs[0] = e1
322 b.Succs[1] = e0
323 e0.b.Preds[e0.i].i = 1
324 e1.b.Preds[e1.i].i = 0
325 b.Likely *= -1
326 }
327
328
329 func (b *Block) swapSuccessorsByIdx(x, y int) {
330 if x == y {
331 return
332 }
333 ex := b.Succs[x]
334 ey := b.Succs[y]
335 b.Succs[x] = ey
336 b.Succs[y] = ex
337 ex.b.Preds[ex.i].i = y
338 ey.b.Preds[ey.i].i = x
339 }
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354 func (b *Block) removePhiArg(phi *Value, i int) {
355 n := len(b.Preds)
356 if numPhiArgs := len(phi.Args); numPhiArgs-1 != n {
357 b.Fatalf("inconsistent state for %v, num predecessors: %d, num phi args: %d", phi, n, numPhiArgs)
358 }
359 phi.Args[i].Uses--
360 phi.Args[i] = phi.Args[n]
361 phi.Args[n] = nil
362 phi.Args = phi.Args[:n]
363 phielimValue(phi)
364 }
365
366
367
368
369
370 func (b *Block) LackingPos() bool {
371
372
373
374 if b.Kind != BlockPlain {
375 return false
376 }
377 if b.Pos != src.NoXPos {
378 return false
379 }
380 for _, v := range b.Values {
381 if v.LackingPos() {
382 continue
383 }
384 return false
385 }
386 return true
387 }
388
389 func (b *Block) AuxIntString() string {
390 switch b.Kind.AuxIntType() {
391 case "int8":
392 return fmt.Sprintf("%v", int8(b.AuxInt))
393 case "uint8":
394 return fmt.Sprintf("%v", uint8(b.AuxInt))
395 case "":
396 return ""
397 default:
398 return fmt.Sprintf("%v", b.AuxInt)
399 }
400 }
401
402
403 func (b *Block) likelyBranch() bool {
404 if len(b.Preds) == 0 {
405 return false
406 }
407 for _, e := range b.Preds {
408 p := e.b
409 if len(p.Succs) == 1 || len(p.Succs) == 2 && (p.Likely == BranchLikely && p.Succs[0].b == b ||
410 p.Likely == BranchUnlikely && p.Succs[1].b == b) {
411 continue
412 }
413 return false
414 }
415 return true
416 }
417
418 func (b *Block) Logf(msg string, args ...interface{}) { b.Func.Logf(msg, args...) }
419 func (b *Block) Log() bool { return b.Func.Log() }
420 func (b *Block) Fatalf(msg string, args ...interface{}) { b.Func.Fatalf(msg, args...) }
421
422 type BranchPrediction int8
423
424 const (
425 BranchUnlikely = BranchPrediction(-1)
426 BranchUnknown = BranchPrediction(0)
427 BranchLikely = BranchPrediction(+1)
428 )
429
View as plain text