From 3dcfce8d19e6fc98131106a6b1b7ce5445efc959 Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Wed, 8 Mar 2017 12:50:00 -0800 Subject: [PATCH] cmd/compile: add OpOffPtr [c] SP to constant cache MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit They accounted for almost 30% of all CSE'd values. By never creating the duplicates in the first place, we reduce the high water mark of Value IDs, which in turn makes all SSA phases cheaper, particularly regalloc. name old time/op new time/op delta Template 200ms ± 3% 198ms ± 4% -0.87% (p=0.016 n=50+49) Unicode 86.9ms ± 2% 85.5ms ± 3% -1.56% (p=0.000 n=49+50) GoTypes 553ms ± 4% 551ms ± 4% ~ (p=0.183 n=50+49) SSA 3.97s ± 3% 3.93s ± 2% -1.06% (p=0.000 n=48+48) Flate 124ms ± 4% 124ms ± 3% ~ (p=0.545 n=48+50) GoParser 146ms ± 4% 146ms ± 4% ~ (p=0.810 n=49+49) Reflect 357ms ± 3% 355ms ± 3% -0.59% (p=0.049 n=50+48) Tar 106ms ± 4% 107ms ± 5% ~ (p=0.454 n=49+50) XML 203ms ± 4% 203ms ± 4% ~ (p=0.726 n=48+50) name old user-ns/op new user-ns/op delta Template 237M ± 3% 235M ± 4% ~ (p=0.208 n=47+48) Unicode 111M ± 4% 108M ± 9% -2.50% (p=0.000 n=47+50) GoTypes 736M ± 5% 729M ± 4% -0.95% (p=0.017 n=50+46) SSA 5.73G ± 4% 5.74G ± 4% ~ (p=0.765 n=50+50) Flate 150M ± 5% 148M ± 6% -0.89% (p=0.045 n=48+47) GoParser 180M ± 5% 178M ± 7% -1.34% (p=0.012 n=50+50) Reflect 450M ± 4% 444M ± 4% -1.40% (p=0.000 n=50+49) Tar 124M ± 7% 123M ± 7% ~ (p=0.092 n=50+50) XML 248M ± 6% 245M ± 5% ~ (p=0.057 n=50+50) name old alloc/op new alloc/op delta Template 39.4MB ± 0% 39.3MB ± 0% -0.37% (p=0.000 n=50+50) Unicode 30.9MB ± 0% 30.9MB ± 0% -0.27% (p=0.000 n=48+50) GoTypes 114MB ± 0% 113MB ± 0% -1.03% (p=0.000 n=50+49) SSA 882MB ± 0% 865MB ± 0% -1.95% (p=0.000 n=49+49) Flate 25.8MB ± 0% 25.7MB ± 0% -0.21% (p=0.000 n=50+50) GoParser 31.7MB ± 0% 31.6MB ± 0% -0.33% (p=0.000 n=50+50) Reflect 79.7MB ± 0% 79.3MB ± 0% -0.49% (p=0.000 n=44+49) Tar 27.2MB ± 0% 27.1MB ± 0% -0.31% (p=0.000 n=50+50) XML 42.7MB ± 0% 42.3MB ± 0% -1.05% (p=0.000 n=48+49) name old allocs/op new allocs/op delta Template 379k ± 1% 380k ± 1% +0.26% (p=0.000 n=50+50) Unicode 324k ± 1% 324k ± 1% ~ (p=0.964 n=49+50) GoTypes 1.14M ± 0% 1.15M ± 0% +0.14% (p=0.000 n=50+49) SSA 7.89M ± 0% 7.89M ± 0% -0.05% (p=0.000 n=49+49) Flate 240k ± 1% 241k ± 1% +0.27% (p=0.001 n=50+50) GoParser 310k ± 1% 311k ± 1% +0.48% (p=0.000 n=50+49) Reflect 1.00M ± 0% 1.00M ± 0% +0.17% (p=0.000 n=48+50) Tar 254k ± 1% 255k ± 1% +0.23% (p=0.005 n=50+50) XML 395k ± 1% 395k ± 1% +0.19% (p=0.002 n=49+47) Change-Id: Iaa8f5f37e23bd81983409f7359f9dcd4dfe2961f Reviewed-on: https://go-review.googlesource.com/38003 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/gc/ssa.go | 19 +++++++++++-------- src/cmd/compile/internal/ssa/func.go | 12 ++++++++++-- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/src/cmd/compile/internal/gc/ssa.go b/src/cmd/compile/internal/gc/ssa.go index c9a5ec42bd..d1fba5514d 100644 --- a/src/cmd/compile/internal/gc/ssa.go +++ b/src/cmd/compile/internal/gc/ssa.go @@ -477,6 +477,9 @@ func (s *state) constInt(t ssa.Type, c int64) *ssa.Value { } return s.constInt32(t, int32(c)) } +func (s *state) constOffPtrSP(t ssa.Type, c int64) *ssa.Value { + return s.f.ConstOffPtrSP(s.peekPos(), t, c, s.sp) +} // stmtList converts the statement list n to SSA and adds it to s. func (s *state) stmtList(l Nodes) { @@ -1953,7 +1956,7 @@ func (s *state) expr(n *Node) *ssa.Value { return s.addr(n.Left, n.Bounded()) case OINDREGSP: - addr := s.entryNewValue1I(ssa.OpOffPtr, ptrto(n.Type), n.Xoffset, s.sp) + addr := s.constOffPtrSP(ptrto(n.Type), n.Xoffset) return s.newValue2(ssa.OpLoad, n.Type, addr, s.mem()) case OIND: @@ -2991,7 +2994,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { if k != callNormal { argStart += int64(2 * Widthptr) } - addr := s.entryNewValue1I(ssa.OpOffPtr, ptrto(Types[TUINTPTR]), argStart, s.sp) + addr := s.constOffPtrSP(ptrto(Types[TUINTPTR]), argStart) s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, rcvr, s.mem()) } @@ -3000,9 +3003,9 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { // Write argsize and closure (args to Newproc/Deferproc). argStart := Ctxt.FixedFrameSize() argsize := s.constInt32(Types[TUINT32], int32(stksize)) - addr := s.entryNewValue1I(ssa.OpOffPtr, ptrto(Types[TUINT32]), argStart, s.sp) + addr := s.constOffPtrSP(ptrto(Types[TUINT32]), argStart) s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, 4, addr, argsize, s.mem()) - addr = s.entryNewValue1I(ssa.OpOffPtr, ptrto(Types[TUINTPTR]), argStart+int64(Widthptr), s.sp) + addr = s.constOffPtrSP(ptrto(Types[TUINTPTR]), argStart+int64(Widthptr)) s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, int64(Widthptr), addr, closure, s.mem()) stksize += 2 * int64(Widthptr) } @@ -3049,7 +3052,7 @@ func (s *state) call(n *Node, k callKind) *ssa.Value { return nil } fp := res.Field(0) - return s.entryNewValue1I(ssa.OpOffPtr, ptrto(fp.Type), fp.Offset+Ctxt.FixedFrameSize(), s.sp) + return s.constOffPtrSP(ptrto(fp.Type), fp.Offset+Ctxt.FixedFrameSize()) } // etypesign returns the signed-ness of e, for integer/pointer etypes. @@ -3129,7 +3132,7 @@ func (s *state) addr(n *Node, bounded bool) *ssa.Value { case OINDREGSP: // indirect off REGSP // used for storing/loading arguments/returns to/from callees - return s.entryNewValue1I(ssa.OpOffPtr, t, n.Xoffset, s.sp) + return s.constOffPtrSP(t, n.Xoffset) case OINDEX: if n.Left.Type.IsSlice() { a := s.expr(n.Left) @@ -3364,7 +3367,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*Type, args ...*ssa for _, arg := range args { t := arg.Type off = Rnd(off, t.Alignment()) - ptr := s.newValue1I(ssa.OpOffPtr, t.PtrTo(), off, s.sp) + ptr := s.constOffPtrSP(t.PtrTo(), off) size := t.Size() s.vars[&memVar] = s.newValue3I(ssa.OpStore, ssa.TypeMem, size, ptr, arg, s.mem()) off += size @@ -3395,7 +3398,7 @@ func (s *state) rtcall(fn *obj.LSym, returns bool, results []*Type, args ...*ssa res := make([]*ssa.Value, len(results)) for i, t := range results { off = Rnd(off, t.Alignment()) - ptr := s.newValue1I(ssa.OpOffPtr, ptrto(t), off, s.sp) + ptr := s.constOffPtrSP(ptrto(t), off) res[i] = s.newValue2(ssa.OpLoad, t, ptr, s.mem()) off += t.Size() } diff --git a/src/cmd/compile/internal/ssa/func.go b/src/cmd/compile/internal/ssa/func.go index 069a5996a4..b005876096 100644 --- a/src/cmd/compile/internal/ssa/func.go +++ b/src/cmd/compile/internal/ssa/func.go @@ -133,9 +133,9 @@ func (f *Func) freeValue(v *Value) { // Clear everything but ID (which we reuse). id := v.ID - // Zero argument values might be cached, so remove them there. + // Values with zero arguments and OpOffPtr values might be cached, so remove them there. nArgs := opcodeTable[v.Op].argLen - if nArgs == 0 { + if nArgs == 0 || v.Op == OpOffPtr { vv := f.constants[v.AuxInt] for i, cv := range vv { if v == cv { @@ -411,6 +411,14 @@ func (f *Func) ConstEmptyString(pos src.XPos, t Type) *Value { v.Aux = "" return v } +func (f *Func) ConstOffPtrSP(pos src.XPos, t Type, c int64, sp *Value) *Value { + v := f.constVal(pos, OpOffPtr, t, c, true) + if len(v.Args) == 0 { + v.AddArg(sp) + } + return v + +} func (f *Func) Logf(msg string, args ...interface{}) { f.Config.Logf(msg, args...) } func (f *Func) Log() bool { return f.Config.Log() }