github.com/gocuntian/go@v0.0.0-20160610041250-fee02d270bf8/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.IsComplex(): 29 var elemType Type 30 if t.Size() == 16 { 31 elemType = f.Config.fe.TypeFloat64() 32 } else { 33 elemType = f.Config.fe.TypeFloat32() 34 } 35 rName, iName := f.Config.fe.SplitComplex(name) 36 newNames = append(newNames, rName, iName) 37 for _, v := range f.NamedValues[name] { 38 r := v.Block.NewValue1(v.Line, OpComplexReal, elemType, v) 39 i := v.Block.NewValue1(v.Line, OpComplexImag, elemType, v) 40 f.NamedValues[rName] = append(f.NamedValues[rName], r) 41 f.NamedValues[iName] = append(f.NamedValues[iName], i) 42 } 43 delete(f.NamedValues, name) 44 case t.IsString(): 45 ptrType := f.Config.fe.TypeBytePtr() 46 lenType := f.Config.fe.TypeInt() 47 ptrName, lenName := f.Config.fe.SplitString(name) 48 newNames = append(newNames, ptrName, lenName) 49 for _, v := range f.NamedValues[name] { 50 ptr := v.Block.NewValue1(v.Line, OpStringPtr, ptrType, v) 51 len := v.Block.NewValue1(v.Line, OpStringLen, lenType, v) 52 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 53 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 54 } 55 delete(f.NamedValues, name) 56 case t.IsSlice(): 57 ptrType := f.Config.fe.TypeBytePtr() 58 lenType := f.Config.fe.TypeInt() 59 ptrName, lenName, capName := f.Config.fe.SplitSlice(name) 60 newNames = append(newNames, ptrName, lenName, capName) 61 for _, v := range f.NamedValues[name] { 62 ptr := v.Block.NewValue1(v.Line, OpSlicePtr, ptrType, v) 63 len := v.Block.NewValue1(v.Line, OpSliceLen, lenType, v) 64 cap := v.Block.NewValue1(v.Line, OpSliceCap, lenType, v) 65 f.NamedValues[ptrName] = append(f.NamedValues[ptrName], ptr) 66 f.NamedValues[lenName] = append(f.NamedValues[lenName], len) 67 f.NamedValues[capName] = append(f.NamedValues[capName], cap) 68 } 69 delete(f.NamedValues, name) 70 case t.IsInterface(): 71 ptrType := f.Config.fe.TypeBytePtr() 72 typeName, dataName := f.Config.fe.SplitInterface(name) 73 newNames = append(newNames, typeName, dataName) 74 for _, v := range f.NamedValues[name] { 75 typ := v.Block.NewValue1(v.Line, OpITab, ptrType, v) 76 data := v.Block.NewValue1(v.Line, OpIData, ptrType, v) 77 f.NamedValues[typeName] = append(f.NamedValues[typeName], typ) 78 f.NamedValues[dataName] = append(f.NamedValues[dataName], data) 79 } 80 delete(f.NamedValues, name) 81 case t.Size() > f.Config.IntSize: 82 f.Unimplementedf("undecomposed named type %s %s", name, t) 83 default: 84 newNames = append(newNames, name) 85 } 86 } 87 f.Names = newNames 88 } 89 90 func decomposeBuiltInPhi(v *Value) { 91 // TODO: decompose 64-bit ops on 32-bit archs? 92 switch { 93 case v.Type.IsComplex(): 94 decomposeComplexPhi(v) 95 case v.Type.IsString(): 96 decomposeStringPhi(v) 97 case v.Type.IsSlice(): 98 decomposeSlicePhi(v) 99 case v.Type.IsInterface(): 100 decomposeInterfacePhi(v) 101 case v.Type.Size() > v.Block.Func.Config.IntSize: 102 v.Unimplementedf("undecomposed type %s", v.Type) 103 } 104 } 105 106 func decomposeStringPhi(v *Value) { 107 fe := v.Block.Func.Config.fe 108 ptrType := fe.TypeBytePtr() 109 lenType := fe.TypeInt() 110 111 ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) 112 len := v.Block.NewValue0(v.Line, OpPhi, lenType) 113 for _, a := range v.Args { 114 ptr.AddArg(a.Block.NewValue1(v.Line, OpStringPtr, ptrType, a)) 115 len.AddArg(a.Block.NewValue1(v.Line, OpStringLen, lenType, a)) 116 } 117 v.reset(OpStringMake) 118 v.AddArg(ptr) 119 v.AddArg(len) 120 } 121 122 func decomposeSlicePhi(v *Value) { 123 fe := v.Block.Func.Config.fe 124 ptrType := fe.TypeBytePtr() 125 lenType := fe.TypeInt() 126 127 ptr := v.Block.NewValue0(v.Line, OpPhi, ptrType) 128 len := v.Block.NewValue0(v.Line, OpPhi, lenType) 129 cap := v.Block.NewValue0(v.Line, OpPhi, lenType) 130 for _, a := range v.Args { 131 ptr.AddArg(a.Block.NewValue1(v.Line, OpSlicePtr, ptrType, a)) 132 len.AddArg(a.Block.NewValue1(v.Line, OpSliceLen, lenType, a)) 133 cap.AddArg(a.Block.NewValue1(v.Line, OpSliceCap, lenType, a)) 134 } 135 v.reset(OpSliceMake) 136 v.AddArg(ptr) 137 v.AddArg(len) 138 v.AddArg(cap) 139 } 140 141 func decomposeComplexPhi(v *Value) { 142 fe := v.Block.Func.Config.fe 143 var partType Type 144 switch z := v.Type.Size(); z { 145 case 8: 146 partType = fe.TypeFloat32() 147 case 16: 148 partType = fe.TypeFloat64() 149 default: 150 v.Fatalf("decomposeComplexPhi: bad complex size %d", z) 151 } 152 153 real := v.Block.NewValue0(v.Line, OpPhi, partType) 154 imag := v.Block.NewValue0(v.Line, OpPhi, partType) 155 for _, a := range v.Args { 156 real.AddArg(a.Block.NewValue1(v.Line, OpComplexReal, partType, a)) 157 imag.AddArg(a.Block.NewValue1(v.Line, OpComplexImag, partType, a)) 158 } 159 v.reset(OpComplexMake) 160 v.AddArg(real) 161 v.AddArg(imag) 162 } 163 164 func decomposeInterfacePhi(v *Value) { 165 ptrType := v.Block.Func.Config.fe.TypeBytePtr() 166 167 itab := v.Block.NewValue0(v.Line, OpPhi, ptrType) 168 data := v.Block.NewValue0(v.Line, OpPhi, ptrType) 169 for _, a := range v.Args { 170 itab.AddArg(a.Block.NewValue1(v.Line, OpITab, ptrType, a)) 171 data.AddArg(a.Block.NewValue1(v.Line, OpIData, ptrType, a)) 172 } 173 v.reset(OpIMake) 174 v.AddArg(itab) 175 v.AddArg(data) 176 } 177 178 func decomposeUser(f *Func) { 179 for _, b := range f.Blocks { 180 for _, v := range b.Values { 181 if v.Op != OpPhi { 182 continue 183 } 184 decomposeUserPhi(v) 185 } 186 } 187 // Split up named values into their components. 188 // NOTE: the component values we are making are dead at this point. 189 // We must do the opt pass before any deadcode elimination or we will 190 // lose the name->value correspondence. 191 i := 0 192 var fnames []LocalSlot 193 var newNames []LocalSlot 194 for _, name := range f.Names { 195 t := name.Type 196 switch { 197 case t.IsStruct(): 198 n := t.NumFields() 199 fnames = fnames[:0] 200 for i := 0; i < n; i++ { 201 fnames = append(fnames, f.Config.fe.SplitStruct(name, i)) 202 } 203 for _, v := range f.NamedValues[name] { 204 for i := 0; i < n; i++ { 205 x := v.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), v) 206 f.NamedValues[fnames[i]] = append(f.NamedValues[fnames[i]], x) 207 } 208 } 209 delete(f.NamedValues, name) 210 newNames = append(newNames, fnames...) 211 default: 212 f.Names[i] = name 213 i++ 214 } 215 } 216 f.Names = f.Names[:i] 217 f.Names = append(f.Names, newNames...) 218 } 219 220 func decomposeUserPhi(v *Value) { 221 switch { 222 case v.Type.IsStruct(): 223 decomposeStructPhi(v) 224 } 225 // TODO: Arrays of length 1? 226 } 227 228 func decomposeStructPhi(v *Value) { 229 t := v.Type 230 n := t.NumFields() 231 var fields [MaxStruct]*Value 232 for i := 0; i < n; i++ { 233 fields[i] = v.Block.NewValue0(v.Line, OpPhi, t.FieldType(i)) 234 } 235 for _, a := range v.Args { 236 for i := 0; i < n; i++ { 237 fields[i].AddArg(a.Block.NewValue1I(v.Line, OpStructSelect, t.FieldType(i), int64(i), a)) 238 } 239 } 240 v.reset(StructMakeOp(n)) 241 v.AddArgs(fields[:n]...) 242 243 // Recursively decompose phis for each field. 244 for _, f := range fields[:n] { 245 if f.Type.IsStruct() { 246 decomposeStructPhi(f) 247 } 248 } 249 } 250 251 // MaxStruct is the maximum number of fields a struct 252 // can have and still be SSAable. 253 const MaxStruct = 4 254 255 // StructMakeOp returns the opcode to construct a struct with the 256 // given number of fields. 257 func StructMakeOp(nf int) Op { 258 switch nf { 259 case 0: 260 return OpStructMake0 261 case 1: 262 return OpStructMake1 263 case 2: 264 return OpStructMake2 265 case 3: 266 return OpStructMake3 267 case 4: 268 return OpStructMake4 269 } 270 panic("too many fields in an SSAable struct") 271 }