mirror of
https://github.com/golang/go
synced 2024-11-24 15:30:13 -07:00
[dev.ssa] cmd/compile: add constant cache
The cache gets a 62% hit rate while compiling the standard library. name old time/op new time/op delta Template 449ms ± 2% 443ms ± 4% -1.40% (p=0.006 n=23+25) GoTypes 1.54s ± 1% 1.50s ± 2% -2.53% (p=0.000 n=22+22) Compiler 5.51s ± 1% 5.39s ± 1% -2.29% (p=0.000 n=23+25) name old alloc/op new alloc/op delta Template 90.4MB ± 0% 90.0MB ± 0% -0.45% (p=0.000 n=25+25) GoTypes 334MB ± 0% 331MB ± 0% -1.05% (p=0.000 n=25+25) Compiler 1.12GB ± 0% 1.10GB ± 0% -1.57% (p=0.000 n=25+24) name old allocs/op new allocs/op delta Template 681k ± 0% 682k ± 0% +0.26% (p=0.000 n=25+25) GoTypes 2.23M ± 0% 2.23M ± 0% +0.05% (p=0.000 n=23+24) Compiler 6.46M ± 0% 6.46M ± 0% +0.02% (p=0.000 n=24+25) Change-Id: I2629c291892827493d7b55ec4d83f6973a2ab133 Reviewed-on: https://go-review.googlesource.com/20026 Reviewed-by: Keith Randall <khr@golang.org> Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com> Reviewed-by: Alexandru Moșoi <alexandru@mosoi.ro> TryBot-Result: Gobot Gobot <gobot@golang.org>
This commit is contained in:
parent
f1f366c1e7
commit
194c79c163
@ -47,7 +47,7 @@ Optimizations (better compiler)
|
||||
-------------------------------
|
||||
- Smaller Value.Type (int32 or ptr)? Get rid of types altogether?
|
||||
- OpStore uses 3 args. Increase the size of Value.argstorage to 3?
|
||||
- Constant cache
|
||||
- Use a constant cache for OpConstNil, OpConstInterface, OpConstSlice, maybe OpConstString
|
||||
- Handle signed division overflow and sign extension earlier
|
||||
- Implement 64 bit const division with high multiply, maybe in the frontend?
|
||||
- Add bit widths to complex ops
|
||||
|
@ -35,6 +35,8 @@ type Func struct {
|
||||
|
||||
freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil.
|
||||
freeBlocks *Block // free Blocks linked by succstorage[0]. All other fields except ID are 0/nil.
|
||||
|
||||
constants map[int64][]*Value // constants cache, keyed by constant value; users must check value's Op and Type
|
||||
}
|
||||
|
||||
// NumBlocks returns an integer larger than the id of any Block in the Func.
|
||||
@ -270,38 +272,47 @@ func (b *Block) NewValue3I(line int32, op Op, t Type, auxint int64, arg0, arg1,
|
||||
return v
|
||||
}
|
||||
|
||||
// constVal returns a constant value for c.
|
||||
func (f *Func) constVal(line int32, op Op, t Type, c int64) *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.Equal(t) {
|
||||
return v
|
||||
}
|
||||
}
|
||||
v := f.Entry.NewValue0I(line, op, t, c)
|
||||
f.constants[c] = append(vv, v)
|
||||
return v
|
||||
}
|
||||
|
||||
// ConstInt returns an int constant representing its argument.
|
||||
func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
|
||||
// TODO: cache?
|
||||
i := int64(0)
|
||||
if c {
|
||||
i = 1
|
||||
}
|
||||
return f.Entry.NewValue0I(line, OpConstBool, t, i)
|
||||
return f.constVal(line, OpConstBool, t, i)
|
||||
}
|
||||
func (f *Func) ConstInt8(line int32, t Type, c int8) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst8, t, int64(c))
|
||||
return f.constVal(line, OpConst8, t, int64(c))
|
||||
}
|
||||
func (f *Func) ConstInt16(line int32, t Type, c int16) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst16, t, int64(c))
|
||||
return f.constVal(line, OpConst16, t, int64(c))
|
||||
}
|
||||
func (f *Func) ConstInt32(line int32, t Type, c int32) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst32, t, int64(c))
|
||||
return f.constVal(line, OpConst32, t, int64(c))
|
||||
}
|
||||
func (f *Func) ConstInt64(line int32, t Type, c int64) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst64, t, c)
|
||||
return f.constVal(line, OpConst64, t, c)
|
||||
}
|
||||
func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst32F, t, int64(math.Float64bits(c)))
|
||||
return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)))
|
||||
}
|
||||
func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value {
|
||||
// TODO: cache?
|
||||
return f.Entry.NewValue0I(line, OpConst64F, t, int64(math.Float64bits(c)))
|
||||
return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)))
|
||||
}
|
||||
|
||||
func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) }
|
||||
|
@ -426,6 +426,8 @@ func genResult(w io.Writer, arch arch, result string) {
|
||||
genResult0(w, arch, result, new(int), true, move)
|
||||
}
|
||||
func genResult0(w io.Writer, arch arch, result string, alloc *int, top, move bool) string {
|
||||
// TODO: when generating a constant result, use f.constVal to avoid
|
||||
// introducing copies just to clean them up again.
|
||||
if result[0] != '(' {
|
||||
// variable
|
||||
if top {
|
||||
|
Loading…
Reference in New Issue
Block a user