...
Source file src/pkg/cmd/compile/internal/ssa/critical.go
1
2
3
4
5 package ssa
6
7
8
9
10 func critical(f *Func) {
11
12 blocks := make([]*Block, f.NumValues())
13
14
15 for j := 0; j < len(f.Blocks); j++ {
16 b := f.Blocks[j]
17 if len(b.Preds) <= 1 {
18 continue
19 }
20
21 var phi *Value
22
23
24
25 for _, v := range b.Values {
26 if v.Op == OpPhi {
27 if phi != nil {
28 phi = nil
29 break
30 }
31 phi = v
32 }
33 }
34
35
36 if phi != nil {
37 for _, v := range phi.Args {
38 blocks[v.ID] = nil
39 }
40 }
41
42
43 for i := 0; i < len(b.Preds); {
44 e := b.Preds[i]
45 p := e.b
46 pi := e.i
47 if p.Kind == BlockPlain {
48 i++
49 continue
50 }
51
52 var d *Block
53 reusedBlock := false
54 if phi != nil {
55 argID := phi.Args[i].ID
56
57
58 if d = blocks[argID]; d == nil {
59
60
61
62 d = f.NewBlock(BlockPlain)
63 d.Pos = p.Pos
64 blocks[argID] = d
65 if f.pass.debug > 0 {
66 f.Warnl(p.Pos, "split critical edge")
67 }
68 } else {
69 reusedBlock = true
70 }
71 } else {
72
73
74 d = f.NewBlock(BlockPlain)
75 d.Pos = p.Pos
76 if f.pass.debug > 0 {
77 f.Warnl(p.Pos, "split critical edge")
78 }
79 }
80
81
82
83
84
85 if reusedBlock {
86
87 p.Succs[pi] = Edge{d, len(d.Preds)}
88 d.Preds = append(d.Preds, Edge{p, pi})
89
90
91 b.removePred(i)
92
93
94 n := len(b.Preds)
95 phi.Args[i].Uses--
96 phi.Args[i] = phi.Args[n]
97 phi.Args[n] = nil
98 phi.Args = phi.Args[:n]
99
100
101 if n == 1 {
102 phi.Op = OpCopy
103 }
104
105
106 } else {
107
108 p.Succs[pi] = Edge{d, 0}
109 b.Preds[i] = Edge{d, 0}
110 d.Preds = append(d.Preds, Edge{p, pi})
111 d.Succs = append(d.Succs, Edge{b, i})
112 i++
113 }
114 }
115 }
116 }
117
View as plain text