1
2
3
4
5 package ssa
6
7
8
9
10 func flagalloc(f *Func) {
11
12
13
14 end := f.Cache.allocValueSlice(f.NumBlocks())
15 defer f.Cache.freeValueSlice(end)
16 po := f.postorder()
17 for n := 0; n < 2; n++ {
18 for _, b := range po {
19
20
21
22 var flag *Value
23 for _, c := range b.ControlValues() {
24 if c.Type.IsFlags() {
25 if flag != nil {
26 panic("cannot have multiple controls using flags")
27 }
28 flag = c
29 }
30 }
31 if flag == nil {
32 flag = end[b.ID]
33 }
34 for j := len(b.Values) - 1; j >= 0; j-- {
35 v := b.Values[j]
36 if v == flag {
37 flag = nil
38 }
39 if v.clobbersFlags() {
40 flag = nil
41 }
42 for _, a := range v.Args {
43 if a.Type.IsFlags() {
44 flag = a
45 }
46 }
47 }
48 if flag != nil {
49 for _, e := range b.Preds {
50 p := e.b
51 end[p.ID] = flag
52 }
53 }
54 }
55 }
56
57
58
59
60 for _, b := range f.Blocks {
61 if b.Kind == BlockDefer {
62
63 end[b.ID] = nil
64 continue
65 }
66 for _, v := range b.ControlValues() {
67 if v.Type.IsFlags() && end[b.ID] != v {
68 end[b.ID] = nil
69 }
70 }
71 }
72
73
74 spill := map[ID]bool{}
75 for _, b := range f.Blocks {
76 var flag *Value
77 if len(b.Preds) > 0 {
78 flag = end[b.Preds[0].b.ID]
79 }
80 for _, v := range b.Values {
81 for _, a := range v.Args {
82 if !a.Type.IsFlags() {
83 continue
84 }
85 if a == flag {
86 continue
87 }
88
89 spill[a.ID] = true
90 flag = a
91 }
92 if v.clobbersFlags() {
93 flag = nil
94 }
95 if v.Type.IsFlags() {
96 flag = v
97 }
98 }
99 for _, v := range b.ControlValues() {
100 if v != flag && v.Type.IsFlags() {
101 spill[v.ID] = true
102 }
103 }
104 if v := end[b.ID]; v != nil && v != flag {
105 spill[v.ID] = true
106 }
107 }
108
109
110 var remove []*Value
111 var oldSched []*Value
112 for _, b := range f.Blocks {
113 oldSched = append(oldSched[:0], b.Values...)
114 b.Values = b.Values[:0]
115
116 var flag *Value
117 if len(b.Preds) > 0 {
118 flag = end[b.Preds[0].b.ID]
119
120 for _, e := range b.Preds[1:] {
121 p := e.b
122 if end[p.ID] != flag {
123 f.Fatalf("live flag in %s's predecessors not consistent", b)
124 }
125 }
126 }
127 for _, v := range oldSched {
128 if v.Op == OpPhi && v.Type.IsFlags() {
129 f.Fatalf("phi of flags not supported: %s", v.LongString())
130 }
131
132
133
134 if spill[v.ID] && v.MemoryArg() != nil {
135 remove = append(remove, v)
136 if !f.Config.splitLoad(v) {
137 f.Fatalf("can't split flag generator: %s", v.LongString())
138 }
139 }
140
141
142
143 for i, a := range v.Args {
144 if !a.Type.IsFlags() {
145 continue
146 }
147 if a == flag {
148 continue
149 }
150
151 c := copyFlags(a, b)
152
153 v.SetArg(i, c)
154
155 flag = a
156 }
157
158 b.Values = append(b.Values, v)
159 if v.clobbersFlags() {
160 flag = nil
161 }
162 if v.Type.IsFlags() {
163 flag = v
164 }
165 }
166 for i, v := range b.ControlValues() {
167 if v != flag && v.Type.IsFlags() {
168
169 remove = append(remove, v)
170 c := copyFlags(v, b)
171 b.ReplaceControl(i, c)
172 flag = v
173 }
174 }
175 if v := end[b.ID]; v != nil && v != flag {
176
177
178 remove = append(remove, v)
179 copyFlags(v, b)
180
181
182
183
184
185
186
187 }
188 }
189
190
191 for _, b := range f.Blocks {
192 b.FlagsLiveAtEnd = end[b.ID] != nil
193 }
194
195
196
197
198
199
200
201 for i := 0; i < len(remove); i++ {
202 v := remove[i]
203 if v.Uses == 0 {
204 v.reset(OpInvalid)
205 continue
206 }
207
208 last := len(remove) - 1
209 remove[i] = remove[last]
210 remove[last] = nil
211 remove = remove[:last]
212 i--
213 }
214
215 if len(remove) == 0 {
216 return
217 }
218
219 removeBlocks := f.newSparseSet(f.NumBlocks())
220 defer f.retSparseSet(removeBlocks)
221 for _, v := range remove {
222 removeBlocks.add(v.Block.ID)
223 }
224
225
226 for _, b := range f.Blocks {
227 if !removeBlocks.contains(b.ID) {
228 continue
229 }
230 i := 0
231 for j := 0; j < len(b.Values); j++ {
232 v := b.Values[j]
233 if v.Op == OpInvalid {
234 continue
235 }
236 b.Values[i] = v
237 i++
238 }
239 b.truncateValues(i)
240 }
241 }
242
243 func (v *Value) clobbersFlags() bool {
244 if opcodeTable[v.Op].clobberFlags {
245 return true
246 }
247 if v.Type.IsTuple() && (v.Type.FieldType(0).IsFlags() || v.Type.FieldType(1).IsFlags()) {
248
249
250
251 return true
252 }
253 return false
254 }
255
256
257
258 func copyFlags(v *Value, b *Block) *Value {
259 flagsArgs := make(map[int]*Value)
260 for i, a := range v.Args {
261 if a.Type.IsFlags() || a.Type.IsTuple() {
262 flagsArgs[i] = copyFlags(a, b)
263 }
264 }
265 c := v.copyInto(b)
266 for i, a := range flagsArgs {
267 c.SetArg(i, a)
268 }
269 return c
270 }
271
View as plain text