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:
parent
7529701d11
commit
39214275d6
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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...) }
|
||||||
|
Loading…
Reference in New Issue
Block a user