1
2
3
4
5 package ssa
6
7 import (
8 "fmt"
9
10 "cmd/compile/internal/ssa/block"
11 "cmd/internal/src"
12 )
13
14
15 type Block struct {
16
17
18 ID ID
19
20
21 Pos src.XPos
22
23
24 CPUfeatures CPUfeatures
25
26
27 Kind block.BlockKind
28
29
30
31
32
33
34 Likely BranchPrediction
35
36
37 FlagsLiveAtEnd bool
38
39
40 Hotness Hotness
41
42
43 Succs []Edge
44
45
46
47
48
49 Preds []Edge
50
51
52
53
54
55
56
57
58
59
60 Controls [2]*Value
61
62
63 Aux Aux
64 AuxInt int64
65
66
67
68 Values []*Value
69
70
71 Func *Func
72
73
74 Succstorage [2]Edge
75 Predstorage [4]Edge
76 Valstorage [9]*Value
77 }
78
79 const (
80 BranchUnlikely = BranchPrediction(-1)
81 BranchUnknown = BranchPrediction(0)
82 BranchLikely = BranchPrediction(+1)
83 )
84
85 type BranchPrediction int8
86
87 const (
88 CPUNone CPUfeatures = 0
89 CPUAll CPUfeatures = ^CPUfeatures(0)
90 CPUavx CPUfeatures = 1 << iota
91 CPUavx2
92 CPUavxvnni
93 CPUavx512
94 CPUbitalg
95 CPUgfni
96 CPUvbmi
97 CPUvbmi2
98 CPUvpopcntdq
99 CPUavx512vnni
100
101 CPUneon
102 CPUsve2
103 )
104
105 type CPUfeatures uint32
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130 type Edge struct {
131
132 B *Block
133
134
135
136
137 I int
138 }
139
140 const (
141
142
143 HotNotFlowIn Hotness = 1 << iota
144 HotInitial
145 HotPgo
146
147 HotNot = 0
148 HotInitialNotFlowIn = HotInitial | HotNotFlowIn
149 HotPgoInitial = HotPgo | HotInitial
150 HotPgoInitialNotFLowIn = HotPgo | HotInitial | HotNotFlowIn
151 )
152
153 type Hotness int8
154
155 func (e Edge) Block() *Block {
156 return e.B
157 }
158
159 func (e Edge) Index() int {
160 return e.I
161 }
162
163 func (e Edge) String() string {
164 return fmt.Sprintf("{%v,%d}", e.B, e.I)
165 }
166
167
168 func (b *Block) String() string {
169 return fmt.Sprintf("b%d", b.ID)
170 }
171
172
173 func (b *Block) LongString() string {
174 s := b.Kind.String()
175 if b.Aux != nil {
176 s += fmt.Sprintf(" {%s}", b.Aux)
177 }
178 if t := b.AuxIntString(); t != "" {
179 s += fmt.Sprintf(" [%s]", t)
180 }
181 for _, c := range b.ControlValues() {
182 s += fmt.Sprintf(" %s", c)
183 }
184 if len(b.Succs) > 0 {
185 s += " ->"
186 for _, c := range b.Succs {
187 s += " " + c.B.String()
188 }
189 }
190 switch b.Likely {
191 case BranchUnlikely:
192 s += " (unlikely)"
193 case BranchLikely:
194 s += " (likely)"
195 }
196 return s
197 }
198
199
200
201 func (b *Block) NumControls() int {
202 if b.Controls[0] == nil {
203 return 0
204 }
205 if b.Controls[1] == nil {
206 return 1
207 }
208 return 2
209 }
210
211
212
213
214
215 func (b *Block) ControlValues() []*Value {
216 if b.Controls[0] == nil {
217 return b.Controls[:0]
218 }
219 if b.Controls[1] == nil {
220 return b.Controls[:1]
221 }
222 return b.Controls[:2]
223 }
224
225
226
227
228 func (b *Block) SetControl(v *Value) {
229 b.ResetControls()
230 b.Controls[0] = v
231 v.Uses++
232 }
233
234
235 func (b *Block) ResetControls() {
236 if b.Controls[0] != nil {
237 b.Controls[0].Uses--
238 }
239 if b.Controls[1] != nil {
240 b.Controls[1].Uses--
241 }
242 b.Controls = [2]*Value{}
243 }
244
245
246 func (b *Block) AddControl(v *Value) {
247 i := b.NumControls()
248 b.Controls[i] = v
249 v.Uses++
250 }
251
252
253
254 func (b *Block) ReplaceControl(i int, v *Value) {
255 b.Controls[i].Uses--
256 b.Controls[i] = v
257 v.Uses++
258 }
259
260
261
262 func (b *Block) CopyControls(from *Block) {
263 if b == from {
264 return
265 }
266 b.ResetControls()
267 for _, c := range from.ControlValues() {
268 b.AddControl(c)
269 }
270 }
271
272
273
274
275 func (b *Block) Reset(kind block.BlockKind) {
276 b.Kind = kind
277 b.ResetControls()
278 b.Aux = nil
279 b.AuxInt = 0
280 }
281
282
283
284
285
286 func (b *Block) ResetWithControl(kind block.BlockKind, v *Value) {
287 b.Kind = kind
288 b.ResetControls()
289 b.Aux = nil
290 b.AuxInt = 0
291 b.Controls[0] = v
292 v.Uses++
293 }
294
295
296
297
298
299 func (b *Block) ResetWithControl2(kind block.BlockKind, v, w *Value) {
300 b.Kind = kind
301 b.ResetControls()
302 b.Aux = nil
303 b.AuxInt = 0
304 b.Controls[0] = v
305 b.Controls[1] = w
306 v.Uses++
307 w.Uses++
308 }
309
310
311
312
313 func (b *Block) TruncateValues(i int) {
314 clear(b.Values[i:])
315 b.Values = b.Values[:i]
316 }
317
318
319 func (b *Block) AddEdgeTo(c *Block) {
320 i := len(b.Succs)
321 j := len(c.Preds)
322 b.Succs = append(b.Succs, Edge{c, j})
323 c.Preds = append(c.Preds, Edge{b, i})
324 b.Func.InvalidateCFG()
325 }
326
327
328
329
330
331 func (b *Block) RemovePred(i int) {
332 n := len(b.Preds) - 1
333 if i != n {
334 e := b.Preds[n]
335 b.Preds[i] = e
336
337 e.B.Succs[e.I].I = i
338 }
339 b.Preds[n] = Edge{}
340 b.Preds = b.Preds[:n]
341 b.Func.InvalidateCFG()
342 }
343
344
345
346
347
348
349 func (b *Block) RemoveSucc(i int) {
350 n := len(b.Succs) - 1
351 if i != n {
352 e := b.Succs[n]
353 b.Succs[i] = e
354
355 e.B.Preds[e.I].I = i
356 }
357 b.Succs[n] = Edge{}
358 b.Succs = b.Succs[:n]
359 b.Func.InvalidateCFG()
360 }
361
362 func (b *Block) SwapSuccessors() {
363 if len(b.Succs) != 2 {
364 b.Fatalf("swapSuccessors with len(Succs)=%d", len(b.Succs))
365 }
366 e0 := b.Succs[0]
367 e1 := b.Succs[1]
368 b.Succs[0] = e1
369 b.Succs[1] = e0
370 e0.B.Preds[e0.I].I = 1
371 e1.B.Preds[e1.I].I = 0
372 b.Likely *= -1
373 }
374
375
376 func (b *Block) SwapSuccessorsByIdx(x, y int) {
377 if x == y {
378 return
379 }
380 ex := b.Succs[x]
381 ey := b.Succs[y]
382 b.Succs[x] = ey
383 b.Succs[y] = ex
384 ex.B.Preds[ex.I].I = y
385 ey.B.Preds[ey.I].I = x
386 }
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401 func (b *Block) RemovePhiArg(phi *Value, i int) {
402 n := len(b.Preds)
403 if numPhiArgs := len(phi.Args); numPhiArgs-1 != n {
404 b.Fatalf("inconsistent state for %v, num predecessors: %d, num phi args: %d", phi, n, numPhiArgs)
405 }
406 phi.Args[i].Uses--
407 phi.Args[i] = phi.Args[n]
408 phi.Args[n] = nil
409 phi.Args = phi.Args[:n]
410 PhiElimValue(phi)
411 }
412
413
414
415 func (b *Block) UniquePred() *Block {
416 if len(b.Preds) != 1 {
417 return nil
418 }
419 return b.Preds[0].B
420 }
421
422
423
424
425
426 func (b *Block) LackingPos() bool {
427
428
429
430 if b.Kind != block.BlockPlain {
431 return false
432 }
433 if b.Pos != src.NoXPos {
434 return false
435 }
436 for _, v := range b.Values {
437 if v.LackingPos() {
438 continue
439 }
440 return false
441 }
442 return true
443 }
444
445 func (b *Block) AuxIntString() string {
446 switch b.Kind.AuxIntType() {
447 case "int8":
448 return fmt.Sprintf("%v", int8(b.AuxInt))
449 case "uint8":
450 return fmt.Sprintf("%v", uint8(b.AuxInt))
451 case "":
452 return ""
453 default:
454 return fmt.Sprintf("%v", b.AuxInt)
455 }
456 }
457
458
459 func (b *Block) LikelyBranch() bool {
460 if len(b.Preds) == 0 {
461 return false
462 }
463 for _, e := range b.Preds {
464 p := e.B
465 if len(p.Succs) == 1 || len(p.Succs) == 2 && (p.Likely == BranchLikely && p.Succs[0].B == b ||
466 p.Likely == BranchUnlikely && p.Succs[1].B == b) {
467 continue
468 }
469 return false
470 }
471 return true
472 }
473
474 func (b *Block) Logf(msg string, args ...any) { b.Func.Logf(msg, args...) }
475
476 func (b *Block) Log() bool { return b.Func.Log() }
477
478 func (b *Block) Fatalf(msg string, args ...any) { b.Func.FatalfWithPos(b.Pos, msg, args...) }
479
480 func (f CPUfeatures) HasFeature(x CPUfeatures) bool {
481 return f&x == x
482 }
483
484 func (f CPUfeatures) String() string {
485 if f == CPUNone {
486 return "none"
487 }
488 if f == CPUAll {
489 return "all"
490 }
491 s := ""
492 foo := func(what string, feat CPUfeatures) {
493 if feat&f != 0 {
494 if s != "" {
495 s += "+"
496 }
497 s += what
498 }
499 }
500 foo("avx", CPUavx)
501 foo("avx2", CPUavx2)
502 foo("avx512", CPUavx512)
503 foo("avxvnni", CPUavxvnni)
504 foo("bitalg", CPUbitalg)
505 foo("gfni", CPUgfni)
506 foo("vbmi", CPUvbmi)
507 foo("vbmi2", CPUvbmi2)
508 foo("popcntdq", CPUvpopcntdq)
509 foo("avx512vnni", CPUavx512vnni)
510
511 return s
512 }
513
View as plain text