mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: change ssa.Type into *types.Type
When package ssa was created, Type was in package gc. To avoid circular dependencies, we used an interface (ssa.Type) to represent type information in SSA. In the Go 1.9 cycle, gri extricated the Type type from package gc. As a result, we can now use it in package ssa. Now, instead of package types depending on package ssa, it is the other way. This is a more sensible dependency tree, and helps compiler performance a bit. Though this is a big CL, most of the changes are mechanical and uninteresting. Interesting bits: * Add new singleton globals to package types for the special SSA types Memory, Void, Invalid, Flags, and Int128. * Add two new Types, TSSA for the special types, and TTUPLE, for SSA tuple types. ssa.MakeTuple is now types.NewTuple. * Move type comparison result constants CMPlt, CMPeq, and CMPgt to package types. * We had picked the name "types" in our rules for the handy list of types provided by ssa.Config. That conflicted with the types package name, so change it to "typ". * Update the type comparison routine to handle tuples and special types inline. * Teach gc/fmt.go how to print special types. * We can now eliminate ElemTypes in favor of just Elem, and probably also some other duplicated Type methods designed to return ssa.Type instead of *types.Type. * The ssa tests were using their own dummy types, and they were not particularly careful about types in general. Of necessity, this CL switches them to use *types.Type; it does not make them more type-accurate. Unfortunately, using types.Type means initializing a bit of the types universe. This is prime for refactoring and improvement. This shrinks ssa.Value; it now fits in a smaller size class on 64 bit systems. This doesn't have a giant impact, though, since most Values are preallocated in a chunk. name old alloc/op new alloc/op delta Template 37.9MB ± 0% 37.7MB ± 0% -0.57% (p=0.000 n=10+8) Unicode 28.9MB ± 0% 28.7MB ± 0% -0.52% (p=0.000 n=10+10) GoTypes 110MB ± 0% 109MB ± 0% -0.88% (p=0.000 n=10+10) Flate 24.7MB ± 0% 24.6MB ± 0% -0.66% (p=0.000 n=10+10) GoParser 31.1MB ± 0% 30.9MB ± 0% -0.61% (p=0.000 n=10+9) Reflect 73.9MB ± 0% 73.4MB ± 0% -0.62% (p=0.000 n=10+8) Tar 25.8MB ± 0% 25.6MB ± 0% -0.77% (p=0.000 n=9+10) XML 41.2MB ± 0% 40.9MB ± 0% -0.80% (p=0.000 n=10+10) [Geo mean] 40.5MB 40.3MB -0.68% name old allocs/op new allocs/op delta Template 385k ± 0% 386k ± 0% ~ (p=0.356 n=10+9) Unicode 343k ± 1% 344k ± 0% ~ (p=0.481 n=10+10) GoTypes 1.16M ± 0% 1.16M ± 0% -0.16% (p=0.004 n=10+10) Flate 238k ± 1% 238k ± 1% ~ (p=0.853 n=10+10) GoParser 320k ± 0% 320k ± 0% ~ (p=0.720 n=10+9) Reflect 957k ± 0% 957k ± 0% ~ (p=0.460 n=10+8) Tar 252k ± 0% 252k ± 0% ~ (p=0.133 n=9+10) XML 400k ± 0% 400k ± 0% ~ (p=0.796 n=10+10) [Geo mean] 428k 428k -0.01% Removing all the interface calls helps non-trivially with CPU, though. name old time/op new time/op delta Template 178ms ± 4% 173ms ± 3% -2.90% (p=0.000 n=94+96) Unicode 85.0ms ± 4% 83.9ms ± 4% -1.23% (p=0.000 n=96+96) GoTypes 543ms ± 3% 528ms ± 3% -2.73% (p=0.000 n=98+96) Flate 116ms ± 3% 113ms ± 4% -2.34% (p=0.000 n=96+99) GoParser 144ms ± 3% 140ms ± 4% -2.80% (p=0.000 n=99+97) Reflect 344ms ± 3% 334ms ± 4% -3.02% (p=0.000 n=100+99) Tar 106ms ± 5% 103ms ± 4% -3.30% (p=0.000 n=98+94) XML 198ms ± 5% 192ms ± 4% -2.88% (p=0.000 n=92+95) [Geo mean] 178ms 173ms -2.65% name old user-time/op new user-time/op delta Template 229ms ± 5% 224ms ± 5% -2.36% (p=0.000 n=95+99) Unicode 107ms ± 6% 106ms ± 5% -1.13% (p=0.001 n=93+95) GoTypes 696ms ± 4% 679ms ± 4% -2.45% (p=0.000 n=97+99) Flate 137ms ± 4% 134ms ± 5% -2.66% (p=0.000 n=99+96) GoParser 176ms ± 5% 172ms ± 8% -2.27% (p=0.000 n=98+100) Reflect 430ms ± 6% 411ms ± 5% -4.46% (p=0.000 n=100+92) Tar 128ms ±13% 123ms ±13% -4.21% (p=0.000 n=100+100) XML 239ms ± 6% 233ms ± 6% -2.50% (p=0.000 n=95+97) [Geo mean] 220ms 213ms -2.76% Change-Id: I15c7d6268347f8358e75066dfdbd77db24e8d0c1 Reviewed-on: https://go-review.googlesource.com/42145 Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
6a24b2d0c1
commit
46b88c9fbc
71 changed files with 7478 additions and 7561 deletions
|
|
@ -5,6 +5,7 @@
|
|||
package ssa
|
||||
|
||||
import (
|
||||
"cmd/compile/internal/types"
|
||||
"cmd/internal/src"
|
||||
"crypto/sha1"
|
||||
"fmt"
|
||||
|
|
@ -23,16 +24,16 @@ type writeSyncer interface {
|
|||
// This package compiles each Func independently.
|
||||
// Funcs are single-use; a new Func must be created for every compiled function.
|
||||
type Func struct {
|
||||
Config *Config // architecture information
|
||||
Cache *Cache // re-usable cache
|
||||
fe Frontend // frontend state associated with this Func, callbacks into compiler frontend
|
||||
pass *pass // current pass information (name, options, etc.)
|
||||
Name string // e.g. bytes·Compare
|
||||
Type Type // type signature of the function.
|
||||
Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
|
||||
Entry *Block // the entry basic block
|
||||
bid idAlloc // block ID allocator
|
||||
vid idAlloc // value ID allocator
|
||||
Config *Config // architecture information
|
||||
Cache *Cache // re-usable cache
|
||||
fe Frontend // frontend state associated with this Func, callbacks into compiler frontend
|
||||
pass *pass // current pass information (name, options, etc.)
|
||||
Name string // e.g. bytes·Compare
|
||||
Type *types.Type // type signature of the function.
|
||||
Blocks []*Block // unordered set of all basic blocks (note: not indexable by ID)
|
||||
Entry *Block // the entry basic block
|
||||
bid idAlloc // block ID allocator
|
||||
vid idAlloc // value ID allocator
|
||||
|
||||
// Given an environment variable used for debug hash match,
|
||||
// what file (if any) receives the yes/no logging?
|
||||
|
|
@ -107,7 +108,7 @@ func (f *Func) retSparseSet(ss *sparseSet) {
|
|||
}
|
||||
|
||||
// newValue allocates a new Value with the given fields and places it at the end of b.Values.
|
||||
func (f *Func) newValue(op Op, t Type, b *Block, pos src.XPos) *Value {
|
||||
func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value {
|
||||
var v *Value
|
||||
if f.freeValues != nil {
|
||||
v = f.freeValues
|
||||
|
|
@ -134,7 +135,7 @@ func (f *Func) newValue(op Op, t Type, b *Block, pos src.XPos) *Value {
|
|||
// The returned value is not placed in any block. Once the caller
|
||||
// decides on a block b, it must set b.Block and append
|
||||
// the returned value to b.Values.
|
||||
func (f *Func) newValueNoBlock(op Op, t Type, pos src.XPos) *Value {
|
||||
func (f *Func) newValueNoBlock(op Op, t *types.Type, pos src.XPos) *Value {
|
||||
var v *Value
|
||||
if f.freeValues != nil {
|
||||
v = f.freeValues
|
||||
|
|
@ -243,7 +244,7 @@ func (f *Func) freeBlock(b *Block) {
|
|||
}
|
||||
|
||||
// NewValue0 returns a new value in the block with no arguments and zero aux values.
|
||||
func (b *Block) NewValue0(pos src.XPos, op Op, t Type) *Value {
|
||||
func (b *Block) NewValue0(pos src.XPos, op Op, t *types.Type) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Args = v.argstorage[:0]
|
||||
|
|
@ -251,7 +252,7 @@ func (b *Block) NewValue0(pos src.XPos, op Op, t Type) *Value {
|
|||
}
|
||||
|
||||
// NewValue returns a new value in the block with no arguments and an auxint value.
|
||||
func (b *Block) NewValue0I(pos src.XPos, op Op, t Type, auxint int64) *Value {
|
||||
func (b *Block) NewValue0I(pos src.XPos, op Op, t *types.Type, auxint int64) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Args = v.argstorage[:0]
|
||||
|
|
@ -259,7 +260,7 @@ func (b *Block) NewValue0I(pos src.XPos, op Op, t Type, auxint int64) *Value {
|
|||
}
|
||||
|
||||
// NewValue returns a new value in the block with no arguments and an aux value.
|
||||
func (b *Block) NewValue0A(pos src.XPos, op Op, t Type, aux interface{}) *Value {
|
||||
func (b *Block) NewValue0A(pos src.XPos, op Op, t *types.Type, aux interface{}) *Value {
|
||||
if _, ok := aux.(int64); ok {
|
||||
// Disallow int64 aux values. They should be in the auxint field instead.
|
||||
// Maybe we want to allow this at some point, but for now we disallow it
|
||||
|
|
@ -274,7 +275,7 @@ func (b *Block) NewValue0A(pos src.XPos, op Op, t Type, aux interface{}) *Value
|
|||
}
|
||||
|
||||
// NewValue returns a new value in the block with no arguments and both an auxint and aux values.
|
||||
func (b *Block) NewValue0IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}) *Value {
|
||||
func (b *Block) NewValue0IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Aux = aux
|
||||
|
|
@ -283,7 +284,7 @@ func (b *Block) NewValue0IA(pos src.XPos, op Op, t Type, auxint int64, aux inter
|
|||
}
|
||||
|
||||
// NewValue1 returns a new value in the block with one argument and zero aux values.
|
||||
func (b *Block) NewValue1(pos src.XPos, op Op, t Type, arg *Value) *Value {
|
||||
func (b *Block) NewValue1(pos src.XPos, op Op, t *types.Type, arg *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Args = v.argstorage[:1]
|
||||
|
|
@ -293,7 +294,7 @@ func (b *Block) NewValue1(pos src.XPos, op Op, t Type, arg *Value) *Value {
|
|||
}
|
||||
|
||||
// NewValue1I returns a new value in the block with one argument and an auxint value.
|
||||
func (b *Block) NewValue1I(pos src.XPos, op Op, t Type, auxint int64, arg *Value) *Value {
|
||||
func (b *Block) NewValue1I(pos src.XPos, op Op, t *types.Type, auxint int64, arg *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Args = v.argstorage[:1]
|
||||
|
|
@ -303,7 +304,7 @@ func (b *Block) NewValue1I(pos src.XPos, op Op, t Type, auxint int64, arg *Value
|
|||
}
|
||||
|
||||
// NewValue1A returns a new value in the block with one argument and an aux value.
|
||||
func (b *Block) NewValue1A(pos src.XPos, op Op, t Type, aux interface{}, arg *Value) *Value {
|
||||
func (b *Block) NewValue1A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Aux = aux
|
||||
|
|
@ -314,7 +315,7 @@ func (b *Block) NewValue1A(pos src.XPos, op Op, t Type, aux interface{}, arg *Va
|
|||
}
|
||||
|
||||
// NewValue1IA returns a new value in the block with one argument and both an auxint and aux values.
|
||||
func (b *Block) NewValue1IA(pos src.XPos, op Op, t Type, auxint int64, aux interface{}, arg *Value) *Value {
|
||||
func (b *Block) NewValue1IA(pos src.XPos, op Op, t *types.Type, auxint int64, aux interface{}, arg *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Aux = aux
|
||||
|
|
@ -325,7 +326,7 @@ func (b *Block) NewValue1IA(pos src.XPos, op Op, t Type, auxint int64, aux inter
|
|||
}
|
||||
|
||||
// NewValue2 returns a new value in the block with two arguments and zero aux values.
|
||||
func (b *Block) NewValue2(pos src.XPos, op Op, t Type, arg0, arg1 *Value) *Value {
|
||||
func (b *Block) NewValue2(pos src.XPos, op Op, t *types.Type, arg0, arg1 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Args = v.argstorage[:2]
|
||||
|
|
@ -337,7 +338,7 @@ func (b *Block) NewValue2(pos src.XPos, op Op, t Type, arg0, arg1 *Value) *Value
|
|||
}
|
||||
|
||||
// NewValue2I returns a new value in the block with two arguments and an auxint value.
|
||||
func (b *Block) NewValue2I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1 *Value) *Value {
|
||||
func (b *Block) NewValue2I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Args = v.argstorage[:2]
|
||||
|
|
@ -349,7 +350,7 @@ func (b *Block) NewValue2I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1
|
|||
}
|
||||
|
||||
// NewValue3 returns a new value in the block with three arguments and zero aux values.
|
||||
func (b *Block) NewValue3(pos src.XPos, op Op, t Type, arg0, arg1, arg2 *Value) *Value {
|
||||
func (b *Block) NewValue3(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Args = v.argstorage[:3]
|
||||
|
|
@ -363,7 +364,7 @@ func (b *Block) NewValue3(pos src.XPos, op Op, t Type, arg0, arg1, arg2 *Value)
|
|||
}
|
||||
|
||||
// NewValue3I returns a new value in the block with three arguments and an auxint value.
|
||||
func (b *Block) NewValue3I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
|
||||
func (b *Block) NewValue3I(pos src.XPos, op Op, t *types.Type, auxint int64, arg0, arg1, arg2 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = auxint
|
||||
v.Args = v.argstorage[:3]
|
||||
|
|
@ -377,7 +378,7 @@ func (b *Block) NewValue3I(pos src.XPos, op Op, t Type, auxint int64, arg0, arg1
|
|||
}
|
||||
|
||||
// NewValue3A returns a new value in the block with three argument and an aux value.
|
||||
func (b *Block) NewValue3A(pos src.XPos, op Op, t Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
|
||||
func (b *Block) NewValue3A(pos src.XPos, op Op, t *types.Type, aux interface{}, arg0, arg1, arg2 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Aux = aux
|
||||
|
|
@ -392,7 +393,7 @@ func (b *Block) NewValue3A(pos src.XPos, op Op, t Type, aux interface{}, arg0, a
|
|||
}
|
||||
|
||||
// NewValue4 returns a new value in the block with four arguments and zero aux values.
|
||||
func (b *Block) NewValue4(pos src.XPos, op Op, t Type, arg0, arg1, arg2, arg3 *Value) *Value {
|
||||
func (b *Block) NewValue4(pos src.XPos, op Op, t *types.Type, arg0, arg1, arg2, arg3 *Value) *Value {
|
||||
v := b.Func.newValue(op, t, b, pos)
|
||||
v.AuxInt = 0
|
||||
v.Args = []*Value{arg0, arg1, arg2, arg3}
|
||||
|
|
@ -404,13 +405,13 @@ func (b *Block) NewValue4(pos src.XPos, op Op, t Type, arg0, arg1, arg2, arg3 *V
|
|||
}
|
||||
|
||||
// constVal returns a constant value for c.
|
||||
func (f *Func) constVal(pos src.XPos, op Op, t Type, c int64, setAuxInt bool) *Value {
|
||||
func (f *Func) constVal(pos src.XPos, op Op, t *types.Type, c int64, setAuxInt bool) *Value {
|
||||
if f.constants == nil {
|
||||
f.constants = make(map[int64][]*Value)
|
||||
}
|
||||
vv := f.constants[c]
|
||||
for _, v := range vv {
|
||||
if v.Op == op && v.Type.Compare(t) == CMPeq {
|
||||
if v.Op == op && v.Type.Compare(t) == types.CMPeq {
|
||||
if setAuxInt && v.AuxInt != c {
|
||||
panic(fmt.Sprintf("cached const %s should have AuxInt of %d", v.LongString(), c))
|
||||
}
|
||||
|
|
@ -439,47 +440,47 @@ const (
|
|||
)
|
||||
|
||||
// ConstInt returns an int constant representing its argument.
|
||||
func (f *Func) ConstBool(pos src.XPos, t Type, c bool) *Value {
|
||||
func (f *Func) ConstBool(pos src.XPos, t *types.Type, c bool) *Value {
|
||||
i := int64(0)
|
||||
if c {
|
||||
i = 1
|
||||
}
|
||||
return f.constVal(pos, OpConstBool, t, i, true)
|
||||
}
|
||||
func (f *Func) ConstInt8(pos src.XPos, t Type, c int8) *Value {
|
||||
func (f *Func) ConstInt8(pos src.XPos, t *types.Type, c int8) *Value {
|
||||
return f.constVal(pos, OpConst8, t, int64(c), true)
|
||||
}
|
||||
func (f *Func) ConstInt16(pos src.XPos, t Type, c int16) *Value {
|
||||
func (f *Func) ConstInt16(pos src.XPos, t *types.Type, c int16) *Value {
|
||||
return f.constVal(pos, OpConst16, t, int64(c), true)
|
||||
}
|
||||
func (f *Func) ConstInt32(pos src.XPos, t Type, c int32) *Value {
|
||||
func (f *Func) ConstInt32(pos src.XPos, t *types.Type, c int32) *Value {
|
||||
return f.constVal(pos, OpConst32, t, int64(c), true)
|
||||
}
|
||||
func (f *Func) ConstInt64(pos src.XPos, t Type, c int64) *Value {
|
||||
func (f *Func) ConstInt64(pos src.XPos, t *types.Type, c int64) *Value {
|
||||
return f.constVal(pos, OpConst64, t, c, true)
|
||||
}
|
||||
func (f *Func) ConstFloat32(pos src.XPos, t Type, c float64) *Value {
|
||||
func (f *Func) ConstFloat32(pos src.XPos, t *types.Type, c float64) *Value {
|
||||
return f.constVal(pos, OpConst32F, t, int64(math.Float64bits(float64(float32(c)))), true)
|
||||
}
|
||||
func (f *Func) ConstFloat64(pos src.XPos, t Type, c float64) *Value {
|
||||
func (f *Func) ConstFloat64(pos src.XPos, t *types.Type, c float64) *Value {
|
||||
return f.constVal(pos, OpConst64F, t, int64(math.Float64bits(c)), true)
|
||||
}
|
||||
|
||||
func (f *Func) ConstSlice(pos src.XPos, t Type) *Value {
|
||||
func (f *Func) ConstSlice(pos src.XPos, t *types.Type) *Value {
|
||||
return f.constVal(pos, OpConstSlice, t, constSliceMagic, false)
|
||||
}
|
||||
func (f *Func) ConstInterface(pos src.XPos, t Type) *Value {
|
||||
func (f *Func) ConstInterface(pos src.XPos, t *types.Type) *Value {
|
||||
return f.constVal(pos, OpConstInterface, t, constInterfaceMagic, false)
|
||||
}
|
||||
func (f *Func) ConstNil(pos src.XPos, t Type) *Value {
|
||||
func (f *Func) ConstNil(pos src.XPos, t *types.Type) *Value {
|
||||
return f.constVal(pos, OpConstNil, t, constNilMagic, false)
|
||||
}
|
||||
func (f *Func) ConstEmptyString(pos src.XPos, t Type) *Value {
|
||||
func (f *Func) ConstEmptyString(pos src.XPos, t *types.Type) *Value {
|
||||
v := f.constVal(pos, OpConstString, t, constEmptyStringMagic, false)
|
||||
v.Aux = ""
|
||||
return v
|
||||
}
|
||||
func (f *Func) ConstOffPtrSP(pos src.XPos, t Type, c int64, sp *Value) *Value {
|
||||
func (f *Func) ConstOffPtrSP(pos src.XPos, t *types.Type, c int64, sp *Value) *Value {
|
||||
v := f.constVal(pos, OpOffPtr, t, c, true)
|
||||
if len(v.Args) == 0 {
|
||||
v.AddArg(sp)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue