1
0
mirror of https://github.com/golang/go synced 2024-11-24 10:00:12 -07:00

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: Keith Randall <khr@golang.org>
This commit is contained in:
Josh Bleecher Snyder 2016-03-06 18:06:09 -08:00
parent 7529701d11
commit 39214275d6
3 changed files with 57 additions and 20 deletions

View File

@ -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. // 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 { func (s *state) constBool(c bool) *ssa.Value {
return s.f.ConstBool(s.peekLine(), Types[TBOOL], c) return s.f.ConstBool(s.peekLine(), Types[TBOOL], c)
} }
@ -1383,6 +1387,9 @@ func (s *state) expr(n *Node) *ssa.Value {
return nil return nil
} }
case CTSTR: case CTSTR:
if n.Val().U == "" {
return s.constEmptyString(n.Type)
}
return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U) return s.entryNewValue0A(ssa.OpConstString, n.Type, n.Val().U)
case CTBOOL: case CTBOOL:
v := s.constBool(n.Val().U.(bool)) v := s.constBool(n.Val().U.(bool))
@ -1397,11 +1404,11 @@ func (s *state) expr(n *Node) *ssa.Value {
t := n.Type t := n.Type
switch { switch {
case t.IsSlice(): case t.IsSlice():
return s.entryNewValue0(ssa.OpConstSlice, t) return s.constSlice(t)
case t.IsInterface(): case t.IsInterface():
return s.entryNewValue0(ssa.OpConstInterface, t) return s.constInterface(t)
default: default:
return s.entryNewValue0(ssa.OpConstNil, t) return s.constNil(t)
} }
case CTFLT: case CTFLT:
f := n.Val().U.(*Mpflt) f := n.Val().U.(*Mpflt)
@ -2266,15 +2273,15 @@ func (s *state) zeroVal(t *Type) *ssa.Value {
} }
case t.IsString(): case t.IsString():
return s.entryNewValue0A(ssa.OpConstString, t, "") return s.constEmptyString(t)
case t.IsPtr(): case t.IsPtr():
return s.entryNewValue0(ssa.OpConstNil, t) return s.constNil(t)
case t.IsBoolean(): case t.IsBoolean():
return s.constBool(false) return s.constBool(false)
case t.IsInterface(): case t.IsInterface():
return s.entryNewValue0(ssa.OpConstInterface, t) return s.constInterface(t)
case t.IsSlice(): case t.IsSlice():
return s.entryNewValue0(ssa.OpConstSlice, t) return s.constSlice(t)
case t.IsStruct(): case t.IsStruct():
n := t.NumFields() n := t.NumFields()
v := s.entryNewValue0(ssa.StructMakeOp(t.NumFields()), t) 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) // return *(((*int)n)+1)
// } // }
lenType := n.Type lenType := n.Type
nilValue := s.newValue0(ssa.OpConstNil, Types[TUINTPTR]) nilValue := s.constNil(Types[TUINTPTR])
cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue) cmp := s.newValue2(ssa.OpEqPtr, Types[TBOOL], x, nilValue)
b := s.endBlock() b := s.endBlock()
b.Kind = ssa.BlockIf 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) tab := s.newValue1(ssa.OpITab, byteptr, v)
s.vars[&typVar] = tab 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 := s.endBlock()
b.Kind = ssa.BlockIf b.Kind = ssa.BlockIf
b.Control = isnonnil b.Control = isnonnil
@ -3391,7 +3398,7 @@ func (s *state) dottype(n *Node, commaok bool) (res, resok *ssa.Value) {
// type assertion failed // type assertion failed
s.startBlock(bFail) s.startBlock(bFail)
s.vars[&idataVar] = s.entryNewValue0(ssa.OpConstNil, byteptr) s.vars[&idataVar] = s.constNil(byteptr)
s.vars[&okVar] = s.constBool(false) s.vars[&okVar] = s.constBool(false)
s.endBlock() s.endBlock()
bFail.AddEdgeTo(bEnd) bFail.AddEdgeTo(bEnd)

View File

@ -30,7 +30,6 @@ Optimizations (better compiled code)
Optimizations (better compiler) Optimizations (better compiler)
------------------------------- -------------------------------
- OpStore uses 3 args. Increase the size of Value.argstorage to 3? - 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 - Handle signed division overflow and sign extension earlier
Regalloc Regalloc

View File

@ -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. // 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 { if f.constants == nil {
f.constants = make(map[int64][]*Value) 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 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) f.constants[c] = append(vv, v)
return 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. // ConstInt returns an int constant representing its argument.
func (f *Func) ConstBool(line int32, t Type, c bool) *Value { func (f *Func) ConstBool(line int32, t Type, c bool) *Value {
i := int64(0) i := int64(0)
if c { if c {
i = 1 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 { 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 { 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 { 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 { 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 { 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 { 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...) } func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) }