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  }