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