Commit 194c79c1 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

[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/20026Reviewed-by: default avatarKeith Randall <khr@golang.org>
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
Reviewed-by: default avatarAlexandru Moșoi <alexandru@mosoi.ro>
TryBot-Result: Gobot Gobot <gobot@golang.org>
parent f1f366c1
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment