github.com/riscv/riscv-go@v0.0.0-20200123204226-124ebd6fcc8e/src/cmd/compile/internal/ssa/func.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 (
     8  	"cmd/internal/src"
     9  	"fmt"
    10  	"math"
    11  	"strings"
    12  )
    13  
    14  // A Func represents a Go func declaration (or function literal) and
    15  // its body. This package compiles each Func independently.
    16  type Func struct {
    17  	Config *Config  // architecture information
    18  	pass   *pass    // current pass information (name, options, etc.)
    19  	Name   string   // e.g. bytes·Compare
    20  	Type   Type     // type signature of the function.
    21  	Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
    22  	Entry  *Block   // the entry basic block
    23  	bid    idAlloc  // block ID allocator
    24  	vid    idAlloc  // value ID allocator
    25  
    26  	scheduled bool // Values in Blocks are in final order
    27  	NoSplit   bool // true if function is marked as nosplit.  Used by schedule check pass.
    28  
    29  	// when register allocation is done, maps value ids to locations
    30  	RegAlloc []Location
    31  
    32  	// map from LocalSlot to set of Values that we want to store in that slot.
    33  	NamedValues map[LocalSlot][]*Value
    34  	// Names is a copy of NamedValues.Keys. We keep a separate list
    35  	// of keys to make iteration order deterministic.
    36  	Names []LocalSlot
    37  
    38  	freeValues *Value // free Values linked by argstorage[0].  All other fields except ID are 0/nil.
    39  	freeBlocks *Block // free Blocks linked by succstorage[0].b.  All other fields except ID are 0/nil.
    40  
    41  	cachedPostorder []*Block   // cached postorder traversal
    42  	cachedIdom      []*Block   // cached immediate dominators
    43  	cachedSdom      SparseTree // cached dominator tree
    44  	cachedLoopnest  *loopnest  // cached loop nest information
    45  
    46  	constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
    47  }
    48  
    49  // NumBlocks returns an integer larger than the id of any Block in the Func.
    50  func (f *Func) NumBlocks() int {
    51  	return f.bid.num()
    52  }
    53  
    54  // NumValues returns an integer larger than the id of any Value in the Func.
    55  func (f *Func) NumValues() int {
    56  	return f.vid.num()
    57  }
    58  
    59  // newSparseSet returns a sparse set that can store at least up to n integers.
    60  func (f *Func) newSparseSet(n int) *sparseSet {
    61  	for i, scr := range f.Config.scrSparse {
    62  		if scr != nil && scr.cap() >= n {
    63  			f.Config.scrSparse[i] = nil
    64  			scr.clear()
    65  			return scr
    66  		}
    67  	}
    68  	return newSparseSet(n)
    69  }
    70  
    71  // retSparseSet returns a sparse set to the config's cache of sparse sets to be reused by f.newSparseSet.
    72  func (f *Func) retSparseSet(ss *sparseSet) {
    73  	for i, scr := range f.Config.scrSparse {
    74  		if scr == nil {
    75  			f.Config.scrSparse[i] = ss
    76  			return
    77  		}
    78  	}
    79  	f.Config.scrSparse = append(f.Config.scrSparse, ss)
    80  }
    81  
    82  // newValue allocates a new Value with the given fields and places it at the end of b.Values.
    83  func (f *Func) newValue(op Op, t Type, b *Block, pos src.XPos) *Value {
    84  	var v *Value
    85  	if f.freeValues != nil {
    86  		v = f.freeValues
    87  		f.freeValues = v.argstorage[0]
    88  		v.argstorage[0] = nil
    89  	} else {
    90  		ID := f.vid.get()
    91  		if int(ID) < len(f.Config.values) {
    92  			v = &f.Config.values[ID]
    93  		} else {
    94  			v = &Value{ID: ID}
    95  		}
    96  	}
    97  	v.Op = op
    98  	v.Type = t
    99  	v.Block = b
   100  	v.Pos = pos
   101  	b.Values = append(b.Values, v)
   102  	return v
   103  }
   104  
   105  // logPassStat writes a string key and int value as a warning in a
   106  // tab-separated format easily handled by spreadsheets or awk.
   107  // file names, lines, and function names are included to provide enough (?)
   108  // context to allow item-by-item comparisons across runs.
   109  // For example:
   110  // awk 'BEGIN {FS="\t"} $3~/TIME/{sum+=$4} END{print "t(ns)=",sum}' t.log
   111  func (f *Func) LogStat(key string, args ...interface{}) {
   112  	value := ""
   113  	for _, a := range args {
   114  		value += fmt.Sprintf("\t%v", a)
   115  	}
   116  	n := "missing_pass"
   117  	if f.pass != nil {
   118  		n = strings.Replace(f.pass.name, " ", "_", -1)
   119  	}
   120  	f.Config.Warnl(f.Entry.Pos, "\t%s\t%s%s\t%s", n, key, value, f.Name)
   121  }
   122  
   123  // freeValue frees a value. It must no longer be referenced.
   124  func (f *Func) freeValue(v *Value) {
   125  	if v.Block == nil {
   126  		f.Fatalf("trying to free an already freed value")
   127  	}
   128  	if v.Uses != 0 {
   129  		f.Fatalf("value %s still has %d uses", v, v.Uses)
   130  	}
   131  	// Clear everything but ID (which we reuse).
   132  	id := v.ID
   133  
   134  	// Zero argument values might be cached, so remove them there.
   135  	nArgs := opcodeTable[v.Op].argLen
   136  	if nArgs == 0 {
   137  		vv := f.constants[v.AuxInt]
   138  		for i, cv := range vv {
   139  			if v == cv {
   140  				vv[i] = vv[len(vv)-1]
   141  				f.constants[v.AuxInt] = vv[0 : len(vv)-1]
   142  				break
   143  			}
   144  		}
   145  	}
   146  	*v = Value{}
   147  	v.ID = id
   148  	v.argstorage[0] = f.freeValues
   149  	f.freeValues = v
   150  }
   151  
   152  // newBlock allocates a new Block of the given kind and places it at the end of f.Blocks.
   153  func (f *Func) NewBlock(kind BlockKind) *Block {
   154  	var b *Block
   155  	if f.freeBlocks != nil {
   156  		b = f.freeBlocks
   157  		f.freeBlocks = b.succstorage[0].b
   158  		b.succstorage[0].b = nil
   159  	} else {
   160  		ID := f.bid.get()
   161  		if int(ID) < len(f.Config.blocks) {
   162  			b = &f.Config.blocks[ID]
   163  		} else {
   164  			b = &Block{ID: ID}
   165  		}
   166  	}
   167  	b.Kind = kind
   168  	b.Func = f
   169  	b.Preds = b.predstorage[:0]
   170  	b.Succs = b.succstorage[:0]
   171  	b.Values = b.valstorage[:0]
   172  	f.Blocks = append(f.Blocks, b)
   173  	f.invalidateCFG()
   174  	return b
   175  }
   176  
   177  func (f *Func) freeBlock(b *Block) {
   178  	if b.Func == nil {
   179  		f.Fatalf("trying to free an already freed block")
   180  	}
   181  	// Clear everything but ID (which we reuse).
   182  	id := b.ID
   183  	*b = Block{}
   184  	b.ID = id
   185  	b.succstorage[0].b = f.freeBlocks
   186  	f.freeBlocks = b
   187  }
   188  
   189  // NewValue0 returns a new value in the block with no arguments and zero aux values.
   190  func (b *Block) NewValue0(pos src.XPos, op Op, t Type) *Value {
   191  	v := b.Func.newValue(op, t, b, pos)
   192  	v.AuxInt = 0
   193  	v.Args = v.argstorage[:0]
   194  	return v
   195  }
   196  
   197  // NewValue returns a new value in the block with no arguments and an auxint value.
   198  func (b *Block) NewValue0I(pos src.XPos, op Op, t Type, auxint int64) *Value {
   199  	v := b.Func.newValue(op, t, b, pos)
   200  	v.AuxInt = auxint
   201  	v.Args = v.argstorage[:0]
   202  	return v
   203  }
   204  
   205  // NewValue returns a new value in the block with no arguments and an aux value.
   206  func (b *Block) NewValue0A(pos src.XPos, op Op, t Type, aux interface{}) *Value {
   207  	if _, ok := aux.(int64); ok {
   208  		// Disallow int64 aux values. They should be in the auxint field instead.
   209  		// Maybe we want to allow this at some point, but for now we disallow it
   210  		// to prevent errors like using NewValue1A instead of NewValue1I.
   211  		b.Fatalf("aux field has int64 type op=%s type=%s aux=%v", op, t, aux)
   212  	}
   213  	v := b.Func.newValue(op, t, b, pos)
   214  	v.AuxInt = 0
   215  	v.Aux = aux
   216  	v.Args = v.argstorage[:0]
   217  	return v
   218  }
   219  
   220  // NewValue returns a new value in the block with no arguments and both an auxint and aux values.
   221  func (b *Block) NewValue0IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}) *Value {
   222  	v := b.Func.newValue(op, t, b, pos)
   223  	v.AuxInt = auxint
   224  	v.Aux = aux
   225  	v.Args = v.argstorage[:0]
   226  	return v
   227  }
   228  
   229  // NewValue1 returns a new value in the block with one argument and zero aux values.
   230  func (b *Block) NewValue1(pos src.XPos, op Op, t Type, arg *Value) *Value {
   231  	v := b.Func.newValue(op, t, b, pos)
   232  	v.AuxInt = 0
   233  	v.Args = v.argstorage[:1]
   234  	v.argstorage[0] = arg
   235  	arg.Uses++
   236  	return v
   237  }
   238  
   239  // NewValue1I returns a new value in the block with one argument and an auxint value.
   240  func (b *Block) NewValue1I(pos src.XPos, op Op, t Type, auxint int64, arg *Value) *Value {
   241  	v := b.Func.newValue(op, t, b, pos)
   242  	v.AuxInt = auxint
   243  	v.Args = v.argstorage[:1]
   244  	v.argstorage[0] = arg
   245  	arg.Uses++
   246  	return v
   247  }
   248  
   249  // NewValue1A returns a new value in the block with one argument and an aux value.
   250  func (b *Block) NewValue1A(pos src.XPos, op Op, t Type, aux interface{}, arg *Value) *Value {
   251  	v := b.Func.newValue(op, t, b, pos)
   252  	v.AuxInt = 0
   253  	v.Aux = aux
   254  	v.Args = v.argstorage[:1]
   255  	v.argstorage[0] = arg
   256  	arg.Uses++
   257  	return v
   258  }
   259  
   260  // NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
   261  func (b *Block) NewValue1IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}, arg *Value) *Value {
   262  	v := b.Func.newValue(op, t, b, pos)
   263  	v.AuxInt = auxint
   264  	v.Aux = aux
   265  	v.Args = v.argstorage[:1]
   266  	v.argstorage[0] = arg
   267  	arg.Uses++
   268  	return v
   269  }
   270  
   271  // NewValue2 returns a new value in the block with two arguments and zero aux values.
   272  func (b *Block) NewValue2(pos src.XPos, op Op, t Type, arg0, arg1 *Value) *Value {
   273  	v := b.Func.newValue(op, t, b, pos)
   274  	v.AuxInt = 0
   275  	v.Args = v.argstorage[:2]
   276  	v.argstorage[0] = arg0
   277  	v.argstorage[1] = arg1
   278  	arg0.Uses++
   279  	arg1.Uses++
   280  	return v
   281  }
   282  
   283  // NewValue2I returns a new value in the block with two arguments and an auxint value.
   284  func (b *Block) NewValue2I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1 *Value) *Value {
   285  	v := b.Func.newValue(op, t, b, pos)
   286  	v.AuxInt = auxint
   287  	v.Args = v.argstorage[:2]
   288  	v.argstorage[0] = arg0
   289  	v.argstorage[1] = arg1
   290  	arg0.Uses++
   291  	arg1.Uses++
   292  	return v
   293  }
   294  
   295  // NewValue3 returns a new value in the block with three arguments and zero aux values.
   296  func (b *Block) NewValue3(pos src.XPos, op Op, t Type, arg0, arg1, arg2 *Value) *Value {
   297  	v := b.Func.newValue(op, t, b, pos)
   298  	v.AuxInt = 0
   299  	v.Args = v.argstorage[:3]
   300  	v.argstorage[0] = arg0
   301  	v.argstorage[1] = arg1
   302  	v.argstorage[2] = arg2
   303  	arg0.Uses++
   304  	arg1.Uses++
   305  	arg2.Uses++
   306  	return v
   307  }
   308  
   309  // NewValue3I returns a new value in the block with three arguments and an auxint value.
   310  func (b *Block) NewValue3I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
   311  	v := b.Func.newValue(op, t, b, pos)
   312  	v.AuxInt = auxint
   313  	v.Args = v.argstorage[:3]
   314  	v.argstorage[0] = arg0
   315  	v.argstorage[1] = arg1
   316  	v.argstorage[2] = arg2
   317  	arg0.Uses++
   318  	arg1.Uses++
   319  	arg2.Uses++
   320  	return v
   321  }
   322  
   323  // NewValue4 returns a new value in the block with four arguments and zero aux values.
   324  func (b *Block) NewValue4(pos src.XPos, op Op, t Type, arg0, arg1, arg2, arg3 *Value) *Value {
   325  	v := b.Func.newValue(op, t, b, pos)
   326  	v.AuxInt = 0
   327  	v.Args = []*Value{arg0, arg1, arg2, arg3}
   328  	arg0.Uses++
   329  	arg1.Uses++
   330  	arg2.Uses++
   331  	arg3.Uses++
   332  	return v
   333  }
   334  
   335  // constVal returns a constant value for c.
   336  func (f *Func) constVal(pos src.XPos, op Op, t Type, c int64, setAux bool) *Value {
   337  	if f.constants == nil {
   338  		f.constants = make(map[int64][]*Value)
   339  	}
   340  	vv := f.constants[c]
   341  	for _, v := range vv {
   342  		if v.Op == op && v.Type.Compare(t) == CMPeq {
   343  			if setAux && v.AuxInt != c {
   344  				panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
   345  			}
   346  			return v
   347  		}
   348  	}
   349  	var v *Value
   350  	if setAux {
   351  		v = f.Entry.NewValue0I(pos, op, t, c)
   352  	} else {
   353  		v = f.Entry.NewValue0(pos, op, t)
   354  	}
   355  	f.constants[c] = append(vv, v)
   356  	return v
   357  }
   358  
   359  // These magic auxint values let us easily cache non-numeric constants
   360  // using the same constants map while making collisions unlikely.
   361  // These values are unlikely to occur in regular code and
   362  // are easy to grep for in case of bugs.
   363  const (
   364  	constSliceMagic       = 1122334455
   365  	constInterfaceMagic   = 2233445566
   366  	constNilMagic         = 3344556677
   367  	constEmptyStringMagic = 4455667788
   368  )
   369  
   370  // ConstInt returns an int constant representing its argument.
   371  func (f *Func) ConstBool(pos src.XPos, t Type, c bool) *Value {
   372  	i := int64(0)
   373  	if c {
   374  		i = 1
   375  	}
   376  	return f.constVal(pos, OpConstBool, t, i, true)
   377  }
   378  func (f *Func) ConstInt8(pos src.XPos, t Type, c int8) *Value {
   379  	return f.constVal(pos, OpConst8, t, int64(c), true)
   380  }
   381  func (f *Func) ConstInt16(pos src.XPos, t Type, c int16) *Value {
   382  	return f.constVal(pos, OpConst16, t, int64(c), true)
   383  }
   384  func (f *Func) ConstInt32(pos src.XPos, t Type, c int32) *Value {
   385  	return f.constVal(pos, OpConst32, t, int64(c), true)
   386  }
   387  func (f *Func) ConstInt64(pos src.XPos, t Type, c int64) *Value {
   388  	return f.constVal(pos, OpConst64, t, c, true)
   389  }
   390  func (f *Func) ConstFloat32(pos src.XPos, t Type, c float64) *Value {
   391  	return f.constVal(pos, OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
   392  }
   393  func (f *Func) ConstFloat64(pos src.XPos, t Type, c float64) *Value {
   394  	return f.constVal(pos, OpConst64F, t, int64(math.Float64bits(c)), true)
   395  }
   396  
   397  func (f *Func) ConstSlice(pos src.XPos, t Type) *Value {
   398  	return f.constVal(pos, OpConstSlice, t, constSliceMagic, false)
   399  }
   400  func (f *Func) ConstInterface(pos src.XPos, t Type) *Value {
   401  	return f.constVal(pos, OpConstInterface, t, constInterfaceMagic, false)
   402  }
   403  func (f *Func) ConstNil(pos src.XPos, t Type) *Value {
   404  	return f.constVal(pos, OpConstNil, t, constNilMagic, false)
   405  }
   406  func (f *Func) ConstEmptyString(pos src.XPos, t Type) *Value {
   407  	v := f.constVal(pos, OpConstString, t, constEmptyStringMagic, false)
   408  	v.Aux = ""
   409  	return v
   410  }
   411  
   412  func (f *Func) Logf(msg string, args ...interface{})   { f.Config.Logf(msg, args...) }
   413  func (f *Func) Log() bool                              { return f.Config.Log() }
   414  func (f *Func) Fatalf(msg string, args ...interface{}) { f.Config.Fatalf(f.Entry.Pos, msg, args...) }
   415  
   416  func (f *Func) Free() {
   417  	// Clear cached CFG info.
   418  	f.invalidateCFG()
   419  
   420  	// Clear values.
   421  	n := f.vid.num()
   422  	if n > len(f.Config.values) {
   423  		n = len(f.Config.values)
   424  	}
   425  	for i := 1; i < n; i++ {
   426  		f.Config.values[i] = Value{}
   427  		f.Config.values[i].ID = ID(i)
   428  	}
   429  
   430  	// Clear blocks.
   431  	n = f.bid.num()
   432  	if n > len(f.Config.blocks) {
   433  		n = len(f.Config.blocks)
   434  	}
   435  	for i := 1; i < n; i++ {
   436  		f.Config.blocks[i] = Block{}
   437  		f.Config.blocks[i].ID = ID(i)
   438  	}
   439  
   440  	// Clear locs.
   441  	n = len(f.RegAlloc)
   442  	if n > len(f.Config.locs) {
   443  		n = len(f.Config.locs)
   444  	}
   445  	head := f.Config.locs[:n]
   446  	for i := range head {
   447  		head[i] = nil
   448  	}
   449  
   450  	// Unregister from config.
   451  	if f.Config.curFunc != f {
   452  		f.Fatalf("free of function which isn't the last one allocated")
   453  	}
   454  	f.Config.curFunc = nil
   455  	*f = Func{} // just in case
   456  }
   457  
   458  // postorder returns the reachable blocks in f in a postorder traversal.
   459  func (f *Func) postorder() []*Block {
   460  	if f.cachedPostorder == nil {
   461  		f.cachedPostorder = postorder(f)
   462  	}
   463  	return f.cachedPostorder
   464  }
   465  
   466  // Idom returns a map from block ID to the immediate dominator of that block.
   467  // f.Entry.ID maps to nil. Unreachable blocks map to nil as well.
   468  func (f *Func) Idom() []*Block {
   469  	if f.cachedIdom == nil {
   470  		f.cachedIdom = dominators(f)
   471  	}
   472  	return f.cachedIdom
   473  }
   474  
   475  // sdom returns a sparse tree representing the dominator relationships
   476  // among the blocks of f.
   477  func (f *Func) sdom() SparseTree {
   478  	if f.cachedSdom == nil {
   479  		f.cachedSdom = newSparseTree(f, f.Idom())
   480  	}
   481  	return f.cachedSdom
   482  }
   483  
   484  // loopnest returns the loop nest information for f.
   485  func (f *Func) loopnest() *loopnest {
   486  	if f.cachedLoopnest == nil {
   487  		f.cachedLoopnest = loopnestfor(f)
   488  	}
   489  	return f.cachedLoopnest
   490  }
   491  
   492  // invalidateCFG tells f that its CFG has changed.
   493  func (f *Func) invalidateCFG() {
   494  	f.cachedPostorder = nil
   495  	f.cachedIdom = nil
   496  	f.cachedSdom = nil
   497  	f.cachedLoopnest = nil
   498  }