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