Source file src/pkg/cmd/compile/internal/ssa/decompose.go
1
2
3
4
5 package ssa
6
7 import (
8 "cmd/compile/internal/types"
9 )
10
11
12
13
14 func decomposeBuiltIn(f *Func) {
15
16 for _, b := range f.Blocks {
17 for _, v := range b.Values {
18 if v.Op != OpPhi {
19 continue
20 }
21 decomposeBuiltInPhi(v)
22 }
23 }
24
25
26 applyRewrite(f, rewriteBlockdec, rewriteValuedec)
27 if f.Config.RegSize == 4 {
28 applyRewrite(f, rewriteBlockdec64, rewriteValuedec64)
29 }
30
31
32 var newNames []LocalSlot
33 for _, name := range f.Names {
34 t := name.Type
35 switch {
36 case t.IsInteger() && t.Size() > f.Config.RegSize:
37 hiName, loName := f.fe.SplitInt64(name)
38 newNames = append(newNames, hiName, loName)
39 for _, v := range f.NamedValues[name] {
40 if v.Op != OpInt64Make {
41 continue
42 }
43 f.NamedValues[hiName] = append(f.NamedValues[hiName], v.Args[0])
44 f.NamedValues[loName] = append(f.NamedValues[loName], v.Args[1])
45 }
46 delete(f.NamedValues, name)
47 case t.IsComplex():
48 rName, iName := f.fe.SplitComplex(name)
49 newNames = append(newNames, rName, iName)
50 for _, v := range f.NamedValues[name] {
51 if v.Op != OpComplexMake {
52 continue
53 }
54 f.NamedValues[rName] = append(f.NamedValues[rName], v.Args[0])
55 f.NamedValues[iName] = append(f.NamedValues[iName], v.Args[1])
56
57 }
58 delete(f.NamedValues, name)
59 case t.IsString():
60 ptrName, lenName := f.fe.SplitString(name)
61 newNames = append(newNames, ptrName, lenName)
62 for _, v := range f.NamedValues[name] {
63 if v.Op != OpStringMake {
64 continue
65 }
66 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
67 f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
68 }
69 delete(f.NamedValues, name)
70 case t.IsSlice():
71 ptrName, lenName, capName := f.fe.SplitSlice(name)
72 newNames = append(newNames, ptrName, lenName, capName)
73 for _, v := range f.NamedValues[name] {
74 if v.Op != OpSliceMake {
75 continue
76 }
77 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], v.Args[0])
78 f.NamedValues[lenName] = append(f.NamedValues[lenName], v.Args[1])
79 f.NamedValues[capName] = append(f.NamedValues[capName], v.Args[2])
80 }
81 delete(f.NamedValues, name)
82 case t.IsInterface():
83 typeName, dataName := f.fe.SplitInterface(name)
84 newNames = append(newNames, typeName, dataName)
85 for _, v := range f.NamedValues[name] {
86 if v.Op != OpIMake {
87 continue
88 }
89 f.NamedValues[typeName] = append(f.NamedValues[typeName], v.Args[0])
90 f.NamedValues[dataName] = append(f.NamedValues[dataName], v.Args[1])
91 }
92 delete(f.NamedValues, name)
93 case t.IsFloat():
94
95 newNames = append(newNames, name)
96 case t.Size() > f.Config.RegSize:
97 f.Fatalf("undecomposed named type %s %v", name, t)
98 default:
99 newNames = append(newNames, name)
100 }
101 }
102 f.Names = newNames
103 }
104
105 func decomposeBuiltInPhi(v *Value) {
106 switch {
107 case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize:
108 decomposeInt64Phi(v)
109 case v.Type.IsComplex():
110 decomposeComplexPhi(v)
111 case v.Type.IsString():
112 decomposeStringPhi(v)
113 case v.Type.IsSlice():
114 decomposeSlicePhi(v)
115 case v.Type.IsInterface():
116 decomposeInterfacePhi(v)
117 case v.Type.IsFloat():
118
119 case v.Type.Size() > v.Block.Func.Config.RegSize:
120 v.Fatalf("undecomposed type %s", v.Type)
121 }
122 }
123
124 func decomposeStringPhi(v *Value) {
125 types := &v.Block.Func.Config.Types
126 ptrType := types.BytePtr
127 lenType := types.Int
128
129 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
130 len := v.Block.NewValue0(v.Pos, OpPhi, lenType)
131 for _, a := range v.Args {
132 ptr.AddArg(a.Block.NewValue1(v.Pos, OpStringPtr, ptrType, a))
133 len.AddArg(a.Block.NewValue1(v.Pos, OpStringLen, lenType, a))
134 }
135 v.reset(OpStringMake)
136 v.AddArg(ptr)
137 v.AddArg(len)
138 }
139
140 func decomposeSlicePhi(v *Value) {
141 types := &v.Block.Func.Config.Types
142 ptrType := types.BytePtr
143 lenType := types.Int
144
145 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
146 len := v.Block.NewValue0(v.Pos, OpPhi, lenType)
147 cap := v.Block.NewValue0(v.Pos, OpPhi, lenType)
148 for _, a := range v.Args {
149 ptr.AddArg(a.Block.NewValue1(v.Pos, OpSlicePtr, ptrType, a))
150 len.AddArg(a.Block.NewValue1(v.Pos, OpSliceLen, lenType, a))
151 cap.AddArg(a.Block.NewValue1(v.Pos, OpSliceCap, lenType, a))
152 }
153 v.reset(OpSliceMake)
154 v.AddArg(ptr)
155 v.AddArg(len)
156 v.AddArg(cap)
157 }
158
159 func decomposeInt64Phi(v *Value) {
160 cfgtypes := &v.Block.Func.Config.Types
161 var partType *types.Type
162 if v.Type.IsSigned() {
163 partType = cfgtypes.Int32
164 } else {
165 partType = cfgtypes.UInt32
166 }
167
168 hi := v.Block.NewValue0(v.Pos, OpPhi, partType)
169 lo := v.Block.NewValue0(v.Pos, OpPhi, cfgtypes.UInt32)
170 for _, a := range v.Args {
171 hi.AddArg(a.Block.NewValue1(v.Pos, OpInt64Hi, partType, a))
172 lo.AddArg(a.Block.NewValue1(v.Pos, OpInt64Lo, cfgtypes.UInt32, a))
173 }
174 v.reset(OpInt64Make)
175 v.AddArg(hi)
176 v.AddArg(lo)
177 }
178
179 func decomposeComplexPhi(v *Value) {
180 cfgtypes := &v.Block.Func.Config.Types
181 var partType *types.Type
182 switch z := v.Type.Size(); z {
183 case 8:
184 partType = cfgtypes.Float32
185 case 16:
186 partType = cfgtypes.Float64
187 default:
188 v.Fatalf("decomposeComplexPhi: bad complex size %d", z)
189 }
190
191 real := v.Block.NewValue0(v.Pos, OpPhi, partType)
192 imag := v.Block.NewValue0(v.Pos, OpPhi, partType)
193 for _, a := range v.Args {
194 real.AddArg(a.Block.NewValue1(v.Pos, OpComplexReal, partType, a))
195 imag.AddArg(a.Block.NewValue1(v.Pos, OpComplexImag, partType, a))
196 }
197 v.reset(OpComplexMake)
198 v.AddArg(real)
199 v.AddArg(imag)
200 }
201
202 func decomposeInterfacePhi(v *Value) {
203 uintptrType := v.Block.Func.Config.Types.Uintptr
204 ptrType := v.Block.Func.Config.Types.BytePtr
205
206 itab := v.Block.NewValue0(v.Pos, OpPhi, uintptrType)
207 data := v.Block.NewValue0(v.Pos, OpPhi, ptrType)
208 for _, a := range v.Args {
209 itab.AddArg(a.Block.NewValue1(v.Pos, OpITab, uintptrType, a))
210 data.AddArg(a.Block.NewValue1(v.Pos, OpIData, ptrType, a))
211 }
212 v.reset(OpIMake)
213 v.AddArg(itab)
214 v.AddArg(data)
215 }
216
217 func decomposeArgs(f *Func) {
218 applyRewrite(f, rewriteBlockdecArgs, rewriteValuedecArgs)
219 }
220
221 func decomposeUser(f *Func) {
222 for _, b := range f.Blocks {
223 for _, v := range b.Values {
224 if v.Op != OpPhi {
225 continue
226 }
227 decomposeUserPhi(v)
228 }
229 }
230
231 i := 0
232 var newNames []LocalSlot
233 for _, name := range f.Names {
234 t := name.Type
235 switch {
236 case t.IsStruct():
237 newNames = decomposeUserStructInto(f, name, newNames)
238 case t.IsArray():
239 newNames = decomposeUserArrayInto(f, name, newNames)
240 default:
241 f.Names[i] = name
242 i++
243 }
244 }
245 f.Names = f.Names[:i]
246 f.Names = append(f.Names, newNames...)
247 }
248
249
250
251
252 func decomposeUserArrayInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
253 t := name.Type
254 if t.NumElem() == 0 {
255
256
257 return slots
258 }
259 if t.NumElem() != 1 {
260
261 f.Fatalf("array not of size 1")
262 }
263 elemName := f.fe.SplitArray(name)
264 for _, v := range f.NamedValues[name] {
265 if v.Op != OpArrayMake1 {
266 continue
267 }
268 f.NamedValues[elemName] = append(f.NamedValues[elemName], v.Args[0])
269 }
270
271 delete(f.NamedValues, name)
272
273 if t.Elem().IsArray() {
274 return decomposeUserArrayInto(f, elemName, slots)
275 } else if t.Elem().IsStruct() {
276 return decomposeUserStructInto(f, elemName, slots)
277 }
278
279 return append(slots, elemName)
280 }
281
282
283
284
285 func decomposeUserStructInto(f *Func, name LocalSlot, slots []LocalSlot) []LocalSlot {
286 fnames := []LocalSlot{}
287 t := name.Type
288 n := t.NumFields()
289
290 for i := 0; i < n; i++ {
291 fs := f.fe.SplitStruct(name, i)
292 fnames = append(fnames, fs)
293
294
295 if !fs.Type.IsArray() && !fs.Type.IsStruct() {
296 slots = append(slots, fs)
297 }
298 }
299
300 makeOp := StructMakeOp(n)
301
302 for _, v := range f.NamedValues[name] {
303 if v.Op != makeOp {
304 continue
305 }
306 for i := 0; i < len(fnames); i++ {
307 f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], v.Args[i])
308 }
309 }
310
311 delete(f.NamedValues, name)
312
313
314
315 for i := 0; i < n; i++ {
316 if name.Type.FieldType(i).IsStruct() {
317 slots = decomposeUserStructInto(f, fnames[i], slots)
318 delete(f.NamedValues, fnames[i])
319 } else if name.Type.FieldType(i).IsArray() {
320 slots = decomposeUserArrayInto(f, fnames[i], slots)
321 delete(f.NamedValues, fnames[i])
322 }
323 }
324 return slots
325 }
326 func decomposeUserPhi(v *Value) {
327 switch {
328 case v.Type.IsStruct():
329 decomposeStructPhi(v)
330 case v.Type.IsArray():
331 decomposeArrayPhi(v)
332 }
333 }
334
335
336
337 func decomposeStructPhi(v *Value) {
338 t := v.Type
339 n := t.NumFields()
340 var fields [MaxStruct]*Value
341 for i := 0; i < n; i++ {
342 fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i))
343 }
344 for _, a := range v.Args {
345 for i := 0; i < n; i++ {
346 fields[i].AddArg(a.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), a))
347 }
348 }
349 v.reset(StructMakeOp(n))
350 v.AddArgs(fields[:n]...)
351
352
353 for _, f := range fields[:n] {
354 decomposeUserPhi(f)
355 }
356 }
357
358
359
360 func decomposeArrayPhi(v *Value) {
361 t := v.Type
362 if t.NumElem() == 0 {
363 v.reset(OpArrayMake0)
364 return
365 }
366 if t.NumElem() != 1 {
367 v.Fatalf("SSAable array must have no more than 1 element")
368 }
369 elem := v.Block.NewValue0(v.Pos, OpPhi, t.Elem())
370 for _, a := range v.Args {
371 elem.AddArg(a.Block.NewValue1I(v.Pos, OpArraySelect, t.Elem(), 0, a))
372 }
373 v.reset(OpArrayMake1)
374 v.AddArg(elem)
375
376
377 decomposeUserPhi(elem)
378 }
379
380
381
382 const MaxStruct = 4
383
384
385
386 func StructMakeOp(nf int) Op {
387 switch nf {
388 case 0:
389 return OpStructMake0
390 case 1:
391 return OpStructMake1
392 case 2:
393 return OpStructMake2
394 case 3:
395 return OpStructMake3
396 case 4:
397 return OpStructMake4
398 }
399 panic("too many fields in an SSAable struct")
400 }
401
View as plain text