Commit 39214275 authored by Josh Bleecher Snyder's avatar Josh Bleecher Snyder

cmd/compile: cache const nil, iface, slice, and ""

name      old time/op    new time/op    delta
Template     441ms ± 4%     446ms ± 4%  +1.23%  (p=0.048 n=22+25)
GoTypes      1.51s ± 2%     1.51s ± 2%    ~     (p=0.224 n=25+25)
Compiler     5.59s ± 1%     5.57s ± 2%  -0.38%  (p=0.019 n=24+24)

name      old alloc/op   new alloc/op   delta
Template    85.6MB ± 0%    85.6MB ± 0%  -0.11%  (p=0.000 n=25+24)
GoTypes      307MB ± 0%     305MB ± 0%  -0.45%  (p=0.000 n=25+25)
Compiler    1.06GB ± 0%    1.06GB ± 0%  -0.34%  (p=0.000 n=25+25)

name      old allocs/op  new allocs/op  delta
Template     1.10M ± 0%     1.10M ± 0%  -0.03%  (p=0.001 n=25+24)
GoTypes      3.36M ± 0%     3.35M ± 0%  -0.13%  (p=0.000 n=25+25)
Compiler     13.0M ± 0%     13.0M ± 0%  -0.12%  (p=0.000 n=25+24)

Change-Id: I7fc18acbc3b1588aececef9692e24a0bd3dba974
Reviewed-on: https://go-review.googlesource.com/20295
Run-TryBot: Josh Bleecher Snyder <josharian@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: 's avatarKeith Randall <khr@golang.org>
parent 7529701d
......@@ -466,6 +466,10 @@ func (s *state) entryNewValue2(op ssa.Op, t ssa.Type, arg0, arg1 *ssa.Value) *ss
}
// const* routines add a new const value to the entry block.
func (s *state) constSlice(t ssa.Type) *ssa.Value { return s.f.ConstSlice(s.peekLine(), t) }
func (s *state) constInterface(t ssa.Type) *ssa.Value { return s.f.ConstInterface(s.peekLine(), t) }
func (s *state) constNil(t ssa.Type) *ssa.Value { return s.f.ConstNil(s.peekLine(), t) }
func (s *state) constEmptyString(t ssa.Type) *ssa.Value { return s.f.ConstEmptyString(s.peekLine(), t) }
func (s *state) constBool(c bool) *ssa.Value {
return s.f.ConstBool(s.peekLine(), Types[TBOOL], c)
}
......@@ -1383,6 +1387,9 @@ func (s *state) expr(n *Node) *ssa.Value {
return nil
}
case CTSTR:
if n.Val().U == "" {
return s.constEmptyString(n.Type)
}
return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U)
case CTBOOL:
v := s.constBool(n.Val().U.(bool))
......@@ -1397,11 +1404,11 @@ func (s *state) expr(n *Node) *ssa.Value {
t := n.Type
switch {
case t.IsSlice():
return s.entryNewValue0(ssa.OpConstSlice, t)
return s.constSlice(t)
case t.IsInterface():
return s.entryNewValue0(ssa.OpConstInterface, t)
return s.constInterface(t)
default:
return s.entryNewValue0(ssa.OpConstNil, t)
return s.constNil(t)
}
case CTFLT:
f := n.Val().U.(*Mpflt)
......@@ -2266,15 +2273,15 @@ func (s *state) zeroVal(t *Type) *ssa.Value {
}
case t.IsString():
return s.entryNewValue0A(ssa.OpConstString, t, "")
return s.constEmptyString(t)
case t.IsPtr():
return s.entryNewValue0(ssa.OpConstNil, t)
return s.constNil(t)
case t.IsBoolean():
return s.constBool(false)
case t.IsInterface():
return s.entryNewValue0(ssa.OpConstInterface, t)
return s.constInterface(t)
case t.IsSlice():
return s.entryNewValue0(ssa.OpConstSlice, t)
return s.constSlice(t)
case t.IsStruct():
n := t.NumFields()
v := s.entryNewValue0(ssa.StructMakeOp(t.NumFields()), t)
......@@ -3191,7 +3198,7 @@ func (s *state) referenceTypeBuiltin(n *Node, x *ssa.Value) *ssa.Value {
// return *(((*int)n)+1)
// }
lenType := n.Type
nilValue := s.newValue0(ssa.OpConstNil, Types[TUINTPTR])
nilValue := s.constNil(Types[TUINTPTR])
cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue)
b := s.endBlock()
b.Kind = ssa.BlockIf
......@@ -3312,7 +3319,7 @@ func (s *state) ifaceType(n *Node, v *ssa.Value) *ssa.Value {
tab := s.newValue1(ssa.OpITab, byteptr, v)
s.vars[&typVar] = tab
isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.entryNewValue0(ssa.OpConstNil, byteptr))
isnonnil := s.newValue2(ssa.OpNeqPtr, Types[TBOOL], tab, s.constNil(byteptr))
b := s.endBlock()
b.Kind = ssa.BlockIf
b.Control = isnonnil
......@@ -3391,7 +3398,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
// type assertion failed
s.startBlock(bFail)
s.vars[&idataVar] = s.entryNewValue0(ssa.OpConstNil, byteptr)
s.vars[&idataVar] = s.constNil(byteptr)
s.vars[&okVar] = s.constBool(false)
s.endBlock()
bFail.AddEdgeTo(bEnd)
......
......@@ -30,7 +30,6 @@ Optimizations (better compiled code)
Optimizations (better compiler)
-------------------------------
- OpStore uses 3 args. Increase the size of Value.argstorage to 3?
- Use a constant cache for OpConstNil, OpConstInterface, OpConstSlice, maybe OpConstString
- Handle signed division overflow and sign extension earlier
Regalloc
......
......@@ -273,7 +273,7 @@ func (b *Block) NewValue3I(line int32, op Op, t Type, auxint int64, arg0, arg1,
}
// constVal returns a constant value for c.
func (f *Func) constVal(line int32, op Op, t Type, c int64) *Value {
func (f *Func) constVal(line int32, op Op, t Type, c int64, setAux bool) *Value {
if f.constants == nil {
f.constants = make(map[int64][]*Value)
}
......@@ -283,36 +283,67 @@ func (f *Func) constVal(line int32, op Op, t Type, c int64) *Value {
return v
}
}
v := f.Entry.NewValue0I(line, op, t, c)
var v *Value
if setAux {
v = f.Entry.NewValue0I(line, op, t, c)
} else {
v = f.Entry.NewValue0(line, op, t)
}
f.constants[c] = append(vv, v)
return v
}
// These magic auxint values let us easily cache non-numeric constants
// using the same constants map while making collisions unlikely.
// These values are unlikely to occur in regular code and
// are easy to grep for in case of bugs.
const (
constSliceMagic = 1122334455
constInterfaceMagic = 2233445566
constNilMagic = 3344556677
constEmptyStringMagic = 4455667788
)
// ConstInt returns an int constant representing its argument.
func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
i := int64(0)
if c {
i = 1
}
return f.constVal(line, OpConstBool, t, i)
return f.constVal(line, OpConstBool, t, i, true)
}
func (f *Func) ConstInt8(line int32, t Type, c int8) *Value {
return f.constVal(line, OpConst8, t, int64(c))
return f.constVal(line, OpConst8, t, int64(c), true)
}
func (f *Func) ConstInt16(line int32, t Type, c int16) *Value {
return f.constVal(line, OpConst16, t, int64(c))
return f.constVal(line, OpConst16, t, int64(c), true)
}
func (f *Func) ConstInt32(line int32, t Type, c int32) *Value {
return f.constVal(line, OpConst32, t, int64(c))
return f.constVal(line, OpConst32, t, int64(c), true)
}
func (f *Func) ConstInt64(line int32, t Type, c int64) *Value {
return f.constVal(line, OpConst64, t, c)
return f.constVal(line, OpConst64, t, c, true)
}
func (f *Func) ConstFloat32(line int32, t Type, c float64) *Value {
return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)))
return f.constVal(line, OpConst32F, t, int64(math.Float64bits(c)), true)
}
func (f *Func) ConstFloat64(line int32, t Type, c float64) *Value {
return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)))
return f.constVal(line, OpConst64F, t, int64(math.Float64bits(c)), true)
}
func (f *Func) ConstSlice(line int32, t Type) *Value {
return f.constVal(line, OpConstSlice, t, constSliceMagic, false)
}
func (f *Func) ConstInterface(line int32, t Type) *Value {
return f.constVal(line, OpConstInterface, t, constInterfaceMagic, false)
}
func (f *Func) ConstNil(line int32, t Type) *Value {
return f.constVal(line, OpConstNil, t, constNilMagic, false)
}
func (f *Func) ConstEmptyString(line int32, t Type) *Value {
v := f.constVal(line, OpConstString, t, constEmptyStringMagic, false)
v.Aux = ""
return v
}
func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) }
......
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