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