github.com/slayercat/go@v0.0.0-20170428012452-c51559813f61/src/cmd/compile/internal/ssa/decompose.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package ssa 6 7 // decompose converts phi ops on compound builtin types into phi 8 // ops on simple types. 9 // (The remaining compound ops are decomposed with rewrite rules.) 10 func decomposeBuiltIn(f *Func) { 11 for _, b := range f.Blocks { 12 for _, v := range b.Values { 13 if v.Op != OpPhi { 14 continue 15 } 16 decomposeBuiltInPhi(v) 17 } 18 } 19 20 // Split up named values into their components. 21 // NOTE: the component values we are making are dead at this point. 22 // We must do the opt pass before any deadcode elimination or we will 23 // lose the name->value correspondence. 24 var newNames []LocalSlot 25 for _, name := range f.Names { 26 t := name.Type 27 switch { 28 case t.IsInteger() && t.Size() > f.Config.RegSize: 29 var elemType Type 30 if t.IsSigned() { 31 elemType = f.Config.Types.Int32 32 } else { 33 elemType = f.Config.Types.UInt32 34 } 35 hiName, loName := f.fe.SplitInt64(name) 36 newNames = append(newNames, hiName, loName) 37 for _, v := range f.NamedValues[name] { 38 hi := v.Block.NewValue1(v.Pos, OpInt64Hi, elemType, v) 39 lo := v.Block.NewValue1(v.Pos, OpInt64Lo, f.Config.Types.UInt32, v) 40 f.NamedValues[hiName] = append(f.NamedValues[hiName], hi) 41 f.NamedValues[loName] = append(f.NamedValues[loName], lo) 42 } 43 delete(f.NamedValues, name) 44 case t.IsComplex(): 45 var elemType Type 46 if t.Size() == 16 { 47 elemType = f.Config.Types.Float64 48 } else { 49 elemType = f.Config.Types.Float32 50 } 51 rName, iName := f.fe.SplitComplex(name) 52 newNames = append(newNames, rName, iName) 53 for _, v := range f.NamedValues[name] { 54 r := v.Block.NewValue1(v.Pos, OpComplexReal, elemType, v) 55 i := v.Block.NewValue1(v.Pos, OpComplexImag, elemType, v) 56 f.NamedValues[rName] = append(f.NamedValues[rName], r) 57 f.NamedValues[iName] = append(f.NamedValues[iName], i) 58 } 59 delete(f.NamedValues, name) 60 case t.IsString(): 61 ptrType := f.Config.Types.BytePtr 62 lenType := f.Config.Types.Int 63 ptrName, lenName := f.fe.SplitString(name) 64 newNames = append(newNames, ptrName, lenName) 65 for _, v := range f.NamedValues[name] { 66 ptr := v.Block.NewValue1(v.Pos, OpStringPtr, ptrType, v) 67 len := v.Block.NewValue1(v.Pos, OpStringLen, lenType, v) 68 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 69 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 70 } 71 delete(f.NamedValues, name) 72 case t.IsSlice(): 73 ptrType := f.Config.Types.BytePtr 74 lenType := f.Config.Types.Int 75 ptrName, lenName, capName := f.fe.SplitSlice(name) 76 newNames = append(newNames, ptrName, lenName, capName) 77 for _, v := range f.NamedValues[name] { 78 ptr := v.Block.NewValue1(v.Pos, OpSlicePtr, ptrType, v) 79 len := v.Block.NewValue1(v.Pos, OpSliceLen, lenType, v) 80 cap := v.Block.NewValue1(v.Pos, OpSliceCap, lenType, v) 81 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 82 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 83 f.NamedValues[capName] = append(f.NamedValues[capName], cap) 84 } 85 delete(f.NamedValues, name) 86 case t.IsInterface(): 87 ptrType := f.Config.Types.BytePtr 88 typeName, dataName := f.fe.SplitInterface(name) 89 newNames = append(newNames, typeName, dataName) 90 for _, v := range f.NamedValues[name] { 91 typ := v.Block.NewValue1(v.Pos, OpITab, ptrType, v) 92 data := v.Block.NewValue1(v.Pos, OpIData, ptrType, v) 93 f.NamedValues[typeName] = append(f.NamedValues[typeName], typ) 94 f.NamedValues[dataName] = append(f.NamedValues[dataName], data) 95 } 96 delete(f.NamedValues, name) 97 case t.IsFloat(): 98 // floats are never decomposed, even ones bigger than RegSize 99 case t.Size() > f.Config.RegSize: 100 f.Fatalf("undecomposed named type %v %v", name, t) 101 default: 102 newNames = append(newNames, name) 103 } 104 } 105 f.Names = newNames 106 } 107 108 func decomposeBuiltInPhi(v *Value) { 109 switch { 110 case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize: 111 decomposeInt64Phi(v) 112 case v.Type.IsComplex(): 113 decomposeComplexPhi(v) 114 case v.Type.IsString(): 115 decomposeStringPhi(v) 116 case v.Type.IsSlice(): 117 decomposeSlicePhi(v) 118 case v.Type.IsInterface(): 119 decomposeInterfacePhi(v) 120 case v.Type.IsFloat(): 121 // floats are never decomposed, even ones bigger than RegSize 122 case v.Type.Size() > v.Block.Func.Config.RegSize: 123 v.Fatalf("undecomposed type %s", v.Type) 124 } 125 } 126 127 func decomposeStringPhi(v *Value) { 128 types := &v.Block.Func.Config.Types 129 ptrType := types.BytePtr 130 lenType := types.Int 131 132 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 133 len := v.Block.NewValue0(v.Pos, OpPhi, lenType) 134 for _, a := range v.Args { 135 ptr.AddArg(a.Block.NewValue1(v.Pos, OpStringPtr, ptrType, a)) 136 len.AddArg(a.Block.NewValue1(v.Pos, OpStringLen, lenType, a)) 137 } 138 v.reset(OpStringMake) 139 v.AddArg(ptr) 140 v.AddArg(len) 141 } 142 143 func decomposeSlicePhi(v *Value) { 144 types := &v.Block.Func.Config.Types 145 ptrType := types.BytePtr 146 lenType := types.Int 147 148 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 149 len := v.Block.NewValue0(v.Pos, OpPhi, lenType) 150 cap := v.Block.NewValue0(v.Pos, OpPhi, lenType) 151 for _, a := range v.Args { 152 ptr.AddArg(a.Block.NewValue1(v.Pos, OpSlicePtr, ptrType, a)) 153 len.AddArg(a.Block.NewValue1(v.Pos, OpSliceLen, lenType, a)) 154 cap.AddArg(a.Block.NewValue1(v.Pos, OpSliceCap, lenType, a)) 155 } 156 v.reset(OpSliceMake) 157 v.AddArg(ptr) 158 v.AddArg(len) 159 v.AddArg(cap) 160 } 161 162 func decomposeInt64Phi(v *Value) { 163 types := &v.Block.Func.Config.Types 164 var partType Type 165 if v.Type.IsSigned() { 166 partType = types.Int32 167 } else { 168 partType = types.UInt32 169 } 170 171 hi := v.Block.NewValue0(v.Pos, OpPhi, partType) 172 lo := v.Block.NewValue0(v.Pos, OpPhi, types.UInt32) 173 for _, a := range v.Args { 174 hi.AddArg(a.Block.NewValue1(v.Pos, OpInt64Hi, partType, a)) 175 lo.AddArg(a.Block.NewValue1(v.Pos, OpInt64Lo, types.UInt32, a)) 176 } 177 v.reset(OpInt64Make) 178 v.AddArg(hi) 179 v.AddArg(lo) 180 } 181 182 func decomposeComplexPhi(v *Value) { 183 types := &v.Block.Func.Config.Types 184 var partType Type 185 switch z := v.Type.Size(); z { 186 case 8: 187 partType = types.Float32 188 case 16: 189 partType = types.Float64 190 default: 191 v.Fatalf("decomposeComplexPhi: bad complex size %d", z) 192 } 193 194 real := v.Block.NewValue0(v.Pos, OpPhi, partType) 195 imag := v.Block.NewValue0(v.Pos, OpPhi, partType) 196 for _, a := range v.Args { 197 real.AddArg(a.Block.NewValue1(v.Pos, OpComplexReal, partType, a)) 198 imag.AddArg(a.Block.NewValue1(v.Pos, OpComplexImag, partType, a)) 199 } 200 v.reset(OpComplexMake) 201 v.AddArg(real) 202 v.AddArg(imag) 203 } 204 205 func decomposeInterfacePhi(v *Value) { 206 ptrType := v.Block.Func.Config.Types.BytePtr 207 208 itab := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 209 data := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 210 for _, a := range v.Args { 211 itab.AddArg(a.Block.NewValue1(v.Pos, OpITab, ptrType, a)) 212 data.AddArg(a.Block.NewValue1(v.Pos, OpIData, ptrType, a)) 213 } 214 v.reset(OpIMake) 215 v.AddArg(itab) 216 v.AddArg(data) 217 } 218 219 func decomposeUser(f *Func) { 220 for _, b := range f.Blocks { 221 for _, v := range b.Values { 222 if v.Op != OpPhi { 223 continue 224 } 225 decomposeUserPhi(v) 226 } 227 } 228 // Split up named values into their components. 229 // NOTE: the component values we are making are dead at this point. 230 // We must do the opt pass before any deadcode elimination or we will 231 // lose the name->value correspondence. 232 i := 0 233 var fnames []LocalSlot 234 var newNames []LocalSlot 235 for _, name := range f.Names { 236 t := name.Type 237 switch { 238 case t.IsStruct(): 239 n := t.NumFields() 240 fnames = fnames[:0] 241 for i := 0; i < n; i++ { 242 fnames = append(fnames, f.fe.SplitStruct(name, i)) 243 } 244 for _, v := range f.NamedValues[name] { 245 for i := 0; i < n; i++ { 246 x := v.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), v) 247 f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], x) 248 } 249 } 250 delete(f.NamedValues, name) 251 newNames = append(newNames, fnames...) 252 case t.IsArray(): 253 if t.NumElem() == 0 { 254 // TODO(khr): Not sure what to do here. Probably nothing. 255 // Names for empty arrays aren't important. 256 break 257 } 258 if t.NumElem() != 1 { 259 f.Fatalf("array not of size 1") 260 } 261 elemName := f.fe.SplitArray(name) 262 for _, v := range f.NamedValues[name] { 263 e := v.Block.NewValue1I(v.Pos, OpArraySelect, t.ElemType(), 0, v) 264 f.NamedValues[elemName] = append(f.NamedValues[elemName], e) 265 } 266 267 default: 268 f.Names[i] = name 269 i++ 270 } 271 } 272 f.Names = f.Names[:i] 273 f.Names = append(f.Names, newNames...) 274 } 275 276 func decomposeUserPhi(v *Value) { 277 switch { 278 case v.Type.IsStruct(): 279 decomposeStructPhi(v) 280 case v.Type.IsArray(): 281 decomposeArrayPhi(v) 282 } 283 } 284 285 // decomposeStructPhi replaces phi-of-struct with structmake(phi-for-each-field), 286 // and then recursively decomposes the phis for each field. 287 func decomposeStructPhi(v *Value) { 288 t := v.Type 289 n := t.NumFields() 290 var fields [MaxStruct]*Value 291 for i := 0; i < n; i++ { 292 fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i)) 293 } 294 for _, a := range v.Args { 295 for i := 0; i < n; i++ { 296 fields[i].AddArg(a.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), a)) 297 } 298 } 299 v.reset(StructMakeOp(n)) 300 v.AddArgs(fields[:n]...) 301 302 // Recursively decompose phis for each field. 303 for _, f := range fields[:n] { 304 decomposeUserPhi(f) 305 } 306 } 307 308 // decomposeArrayPhi replaces phi-of-array with arraymake(phi-of-array-element), 309 // and then recursively decomposes the element phi. 310 func decomposeArrayPhi(v *Value) { 311 t := v.Type 312 if t.NumElem() == 0 { 313 v.reset(OpArrayMake0) 314 return 315 } 316 if t.NumElem() != 1 { 317 v.Fatalf("SSAable array must have no more than 1 element") 318 } 319 elem := v.Block.NewValue0(v.Pos, OpPhi, t.ElemType()) 320 for _, a := range v.Args { 321 elem.AddArg(a.Block.NewValue1I(v.Pos, OpArraySelect, t.ElemType(), 0, a)) 322 } 323 v.reset(OpArrayMake1) 324 v.AddArg(elem) 325 326 // Recursively decompose elem phi. 327 decomposeUserPhi(elem) 328 } 329 330 // MaxStruct is the maximum number of fields a struct 331 // can have and still be SSAable. 332 const MaxStruct = 4 333 334 // StructMakeOp returns the opcode to construct a struct with the 335 // given number of fields. 336 func StructMakeOp(nf int) Op { 337 switch nf { 338 case 0: 339 return OpStructMake0 340 case 1: 341 return OpStructMake1 342 case 2: 343 return OpStructMake2 344 case 3: 345 return OpStructMake3 346 case 4: 347 return OpStructMake4 348 } 349 panic("too many fields in an SSAable struct") 350 }