1
2
3
4
5 package ssacompile
6
7 import (
8 "cmd/compile/internal/ssa"
9 "cmd/compile/internal/ssa/block"
10 )
11
12
13
14
15 func layout(f *ssa.Func) {
16 f.Blocks = layoutOrder(f)
17 }
18
19
20
21 func layoutRegallocOrder(f *ssa.Func) []*ssa.Block {
22
23 return f.Blocks
24 }
25
26 func layoutOrder(f *ssa.Func) []*ssa.Block {
27 order := make([]*ssa.Block, 0, f.NumBlocks())
28 scheduled := f.Cache.AllocBoolSlice(f.NumBlocks())
29 defer f.Cache.FreeBoolSlice(scheduled)
30 idToBlock := f.Cache.AllocBlockSlice(f.NumBlocks())
31 defer f.Cache.FreeBlockSlice(idToBlock)
32 indegree := f.Cache.AllocIntSlice(f.NumBlocks())
33 defer f.Cache.FreeIntSlice(indegree)
34 posdegree := f.NewSparseSet(f.NumBlocks())
35 defer f.RetSparseSet(posdegree)
36
37
38 var zerodegree []ssa.ID
39
40
41
42 var succs []ssa.ID
43 exit := f.NewSparseSet(f.NumBlocks())
44 defer f.RetSparseSet(exit)
45
46
47 for _, b := range f.Blocks {
48 idToBlock[b.ID] = b
49 if b.Kind == block.BlockExit {
50 exit.Add(b.ID)
51 }
52 }
53
54
55 for {
56 changed := false
57 for _, id := range exit.Contents() {
58 b := idToBlock[id]
59 NextPred:
60 for _, pe := range b.Preds {
61 p := pe.B
62 if exit.Contains(p.ID) {
63 continue
64 }
65 for _, s := range p.Succs {
66 if !exit.Contains(s.B.ID) {
67 continue NextPred
68 }
69 }
70
71 exit.Add(p.ID)
72 changed = true
73 }
74 }
75 if !changed {
76 break
77 }
78 }
79
80
81 for _, b := range f.Blocks {
82 if exit.Contains(b.ID) {
83
84 continue
85 }
86 indegree[b.ID] = len(b.Preds)
87 if len(b.Preds) == 0 {
88
89 zerodegree = append(zerodegree, b.ID)
90 } else {
91 posdegree.Add(b.ID)
92 }
93 }
94
95 bid := f.Entry.ID
96 blockloop:
97 for {
98
99 b := idToBlock[bid]
100 order = append(order, b)
101 scheduled[bid] = true
102 if len(order) == len(f.Blocks) {
103 break
104 }
105
106
107
108
109
110
111
112
113
114
115
116 for i := len(b.Succs) - 1; i >= 0; i-- {
117 c := b.Succs[i].B
118 indegree[c.ID]--
119 if indegree[c.ID] == 0 {
120 posdegree.Remove(c.ID)
121 zerodegree = append(zerodegree, c.ID)
122 } else {
123 succs = append(succs, c.ID)
124 }
125 }
126
127
128
129
130
131 var likely *ssa.Block
132 switch b.Likely {
133 case ssa.BranchLikely:
134 likely = b.Succs[0].B
135 case ssa.BranchUnlikely:
136 likely = b.Succs[1].B
137 }
138 if likely != nil && !scheduled[likely.ID] {
139 bid = likely.ID
140 continue
141 }
142
143
144 bid = 0
145
146
147
148 for len(zerodegree) > 0 {
149
150 cid := zerodegree[len(zerodegree)-1]
151 zerodegree = zerodegree[:len(zerodegree)-1]
152 if !scheduled[cid] {
153 bid = cid
154 continue blockloop
155 }
156 }
157
158
159 for len(succs) > 0 {
160
161 cid := succs[len(succs)-1]
162 succs = succs[:len(succs)-1]
163 if !scheduled[cid] {
164 bid = cid
165 continue blockloop
166 }
167 }
168
169
170 for posdegree.Size() > 0 {
171 cid := posdegree.Pop()
172 if !scheduled[cid] {
173 bid = cid
174 continue blockloop
175 }
176 }
177
178
179 for {
180 cid := exit.Pop()
181 if !scheduled[cid] {
182 bid = cid
183 continue blockloop
184 }
185 }
186 }
187 f.Laidout = true
188 return order
189
190 }
191
View as plain text