github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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 case t.Size() > f.Config.RegSize: 102 f.Fatalf("undecomposed named type %v %v", name, t) 103 default: 104 newNames = append(newNames, name) 105 } 106 } 107 f.Names = newNames 108 } 109 110 func decomposeBuiltInPhi(v *Value) { 111 switch { 112 case v.Type.IsInteger() && v.Type.Size() > v.Block.Func.Config.RegSize: 113 decomposeInt64Phi(v) 114 case v.Type.IsComplex(): 115 decomposeComplexPhi(v) 116 case v.Type.IsString(): 117 decomposeStringPhi(v) 118 case v.Type.IsSlice(): 119 decomposeSlicePhi(v) 120 case v.Type.IsInterface(): 121 decomposeInterfacePhi(v) 122 case v.Type.IsFloat(): 123 // floats are never decomposed, even ones bigger than RegSize 124 case v.Type.Size() > v.Block.Func.Config.RegSize: 125 v.Fatalf("undecomposed type %s", v.Type) 126 } 127 } 128 129 func decomposeStringPhi(v *Value) { 130 types := &v.Block.Func.Config.Types 131 ptrType := types.BytePtr 132 lenType := types.Int 133 134 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 135 len := v.Block.NewValue0(v.Pos, OpPhi, lenType) 136 for _, a := range v.Args { 137 ptr.AddArg(a.Block.NewValue1(v.Pos, OpStringPtr, ptrType, a)) 138 len.AddArg(a.Block.NewValue1(v.Pos, OpStringLen, lenType, a)) 139 } 140 v.reset(OpStringMake) 141 v.AddArg(ptr) 142 v.AddArg(len) 143 } 144 145 func decomposeSlicePhi(v *Value) { 146 types := &v.Block.Func.Config.Types 147 ptrType := types.BytePtr 148 lenType := types.Int 149 150 ptr := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 151 len := v.Block.NewValue0(v.Pos, OpPhi, lenType) 152 cap := v.Block.NewValue0(v.Pos, OpPhi, lenType) 153 for _, a := range v.Args { 154 ptr.AddArg(a.Block.NewValue1(v.Pos, OpSlicePtr, ptrType, a)) 155 len.AddArg(a.Block.NewValue1(v.Pos, OpSliceLen, lenType, a)) 156 cap.AddArg(a.Block.NewValue1(v.Pos, OpSliceCap, lenType, a)) 157 } 158 v.reset(OpSliceMake) 159 v.AddArg(ptr) 160 v.AddArg(len) 161 v.AddArg(cap) 162 } 163 164 func decomposeInt64Phi(v *Value) { 165 cfgtypes := &v.Block.Func.Config.Types 166 var partType *types.Type 167 if v.Type.IsSigned() { 168 partType = cfgtypes.Int32 169 } else { 170 partType = cfgtypes.UInt32 171 } 172 173 hi := v.Block.NewValue0(v.Pos, OpPhi, partType) 174 lo := v.Block.NewValue0(v.Pos, OpPhi, cfgtypes.UInt32) 175 for _, a := range v.Args { 176 hi.AddArg(a.Block.NewValue1(v.Pos, OpInt64Hi, partType, a)) 177 lo.AddArg(a.Block.NewValue1(v.Pos, OpInt64Lo, cfgtypes.UInt32, a)) 178 } 179 v.reset(OpInt64Make) 180 v.AddArg(hi) 181 v.AddArg(lo) 182 } 183 184 func decomposeComplexPhi(v *Value) { 185 cfgtypes := &v.Block.Func.Config.Types 186 var partType *types.Type 187 switch z := v.Type.Size(); z { 188 case 8: 189 partType = cfgtypes.Float32 190 case 16: 191 partType = cfgtypes.Float64 192 default: 193 v.Fatalf("decomposeComplexPhi: bad complex size %d", z) 194 } 195 196 real := v.Block.NewValue0(v.Pos, OpPhi, partType) 197 imag := v.Block.NewValue0(v.Pos, OpPhi, partType) 198 for _, a := range v.Args { 199 real.AddArg(a.Block.NewValue1(v.Pos, OpComplexReal, partType, a)) 200 imag.AddArg(a.Block.NewValue1(v.Pos, OpComplexImag, partType, a)) 201 } 202 v.reset(OpComplexMake) 203 v.AddArg(real) 204 v.AddArg(imag) 205 } 206 207 func decomposeInterfacePhi(v *Value) { 208 ptrType := v.Block.Func.Config.Types.BytePtr 209 210 itab := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 211 data := v.Block.NewValue0(v.Pos, OpPhi, ptrType) 212 for _, a := range v.Args { 213 itab.AddArg(a.Block.NewValue1(v.Pos, OpITab, ptrType, a)) 214 data.AddArg(a.Block.NewValue1(v.Pos, OpIData, ptrType, a)) 215 } 216 v.reset(OpIMake) 217 v.AddArg(itab) 218 v.AddArg(data) 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 // Split up named values into their components. 231 // NOTE: the component values we are making are dead at this point. 232 // We must do the opt pass before any deadcode elimination or we will 233 // lose the name->value correspondence. 234 i := 0 235 var fnames []LocalSlot 236 var newNames []LocalSlot 237 for _, name := range f.Names { 238 t := name.Type 239 switch { 240 case t.IsStruct(): 241 n := t.NumFields() 242 fnames = fnames[:0] 243 for i := 0; i < n; i++ { 244 fnames = append(fnames, f.fe.SplitStruct(name, i)) 245 } 246 for _, v := range f.NamedValues[name] { 247 for i := 0; i < n; i++ { 248 x := v.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), v) 249 f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], x) 250 } 251 } 252 delete(f.NamedValues, name) 253 newNames = append(newNames, fnames...) 254 case t.IsArray(): 255 if t.NumElem() == 0 { 256 // TODO(khr): Not sure what to do here. Probably nothing. 257 // Names for empty arrays aren't important. 258 break 259 } 260 if t.NumElem() != 1 { 261 f.Fatalf("array not of size 1") 262 } 263 elemName := f.fe.SplitArray(name) 264 for _, v := range f.NamedValues[name] { 265 e := v.Block.NewValue1I(v.Pos, OpArraySelect, t.ElemType(), 0, v) 266 f.NamedValues[elemName] = append(f.NamedValues[elemName], e) 267 } 268 269 default: 270 f.Names[i] = name 271 i++ 272 } 273 } 274 f.Names = f.Names[:i] 275 f.Names = append(f.Names, newNames...) 276 } 277 278 func decomposeUserPhi(v *Value) { 279 switch { 280 case v.Type.IsStruct(): 281 decomposeStructPhi(v) 282 case v.Type.IsArray(): 283 decomposeArrayPhi(v) 284 } 285 } 286 287 // decomposeStructPhi replaces phi-of-struct with structmake(phi-for-each-field), 288 // and then recursively decomposes the phis for each field. 289 func decomposeStructPhi(v *Value) { 290 t := v.Type 291 n := t.NumFields() 292 var fields [MaxStruct]*Value 293 for i := 0; i < n; i++ { 294 fields[i] = v.Block.NewValue0(v.Pos, OpPhi, t.FieldType(i)) 295 } 296 for _, a := range v.Args { 297 for i := 0; i < n; i++ { 298 fields[i].AddArg(a.Block.NewValue1I(v.Pos, OpStructSelect, t.FieldType(i), int64(i), a)) 299 } 300 } 301 v.reset(StructMakeOp(n)) 302 v.AddArgs(fields[:n]...) 303 304 // Recursively decompose phis for each field. 305 for _, f := range fields[:n] { 306 decomposeUserPhi(f) 307 } 308 } 309 310 // decomposeArrayPhi replaces phi-of-array with arraymake(phi-of-array-element), 311 // and then recursively decomposes the element phi. 312 func decomposeArrayPhi(v *Value) { 313 t := v.Type 314 if t.NumElem() == 0 { 315 v.reset(OpArrayMake0) 316 return 317 } 318 if t.NumElem() != 1 { 319 v.Fatalf("SSAable array must have no more than 1 element") 320 } 321 elem := v.Block.NewValue0(v.Pos, OpPhi, t.ElemType()) 322 for _, a := range v.Args { 323 elem.AddArg(a.Block.NewValue1I(v.Pos, OpArraySelect, t.ElemType(), 0, a)) 324 } 325 v.reset(OpArrayMake1) 326 v.AddArg(elem) 327 328 // Recursively decompose elem phi. 329 decomposeUserPhi(elem) 330 } 331 332 // MaxStruct is the maximum number of fields a struct 333 // can have and still be SSAable. 334 const MaxStruct = 4 335 336 // StructMakeOp returns the opcode to construct a struct with the 337 // given number of fields. 338 func StructMakeOp(nf int) Op { 339 switch nf { 340 case 0: 341 return OpStructMake0 342 case 1: 343 return OpStructMake1 344 case 2: 345 return OpStructMake2 346 case 3: 347 return OpStructMake3 348 case 4: 349 return OpStructMake4 350 } 351 panic("too many fields in an SSAable struct") 352 }