From 94a017f3f53509ea84d3f51236a49de0b716ee7f Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 27 Apr 2017 11:56:46 -0700 Subject: [PATCH] cmd/compile: allow OpVarXXX calls to be duplicated in writebarrier blocks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OpVarXXX Values don't generate instructions, so there's no reason not to duplicate them, and duplicating them generates better code (fewer branches). This requires changing the start/end accounting to correctly handle the case in which we have run of Values beginning with an OpVarXXX, e.g. OpVarDef, OpZeroWB, OpMoveWB. In that case, the sequence of values should begin at the OpZeroWB, not the OpVarDef. This also lays the groundwork for experimenting with allowing duplication of some scalar stores. Shrinks function text sizes a tiny amount: name old object-bytes new object-bytes delta Template 381k ± 0% 381k ± 0% -0.01% (p=0.008 n=5+5) Unicode 203k ± 0% 203k ± 0% -0.04% (p=0.008 n=5+5) GoTypes 1.17M ± 0% 1.17M ± 0% -0.01% (p=0.008 n=5+5) SSA 8.24M ± 0% 8.24M ± 0% -0.00% (p=0.008 n=5+5) Flate 230k ± 0% 230k ± 0% ~ (all equal) GoParser 286k ± 0% 286k ± 0% ~ (all equal) Reflect 1.00M ± 0% 1.00M ± 0% ~ (all equal) Tar 189k ± 0% 189k ± 0% ~ (all equal) XML 415k ± 0% 415k ± 0% -0.01% (p=0.008 n=5+5) Updates #19838 Change-Id: Ic5ef30855919f1468066eba08ae5c4bd9a01db27 Reviewed-on: https://go-review.googlesource.com/42011 Run-TryBot: Josh Bleecher Snyder TryBot-Result: Gobot Gobot Reviewed-by: Cherry Zhang --- src/cmd/compile/internal/ssa/writebarrier.go | 40 ++++++++++++++------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/src/cmd/compile/internal/ssa/writebarrier.go b/src/cmd/compile/internal/ssa/writebarrier.go index 7aec598f6f..3443c6464f 100644 --- a/src/cmd/compile/internal/ssa/writebarrier.go +++ b/src/cmd/compile/internal/ssa/writebarrier.go @@ -117,18 +117,23 @@ func writebarrier(f *Func) { var last *Value var start, end int values := b.Values + FindSeq: for i := len(values) - 1; i >= 0; i-- { w := values[i] - if w.Op == OpStoreWB || w.Op == OpMoveWB || w.Op == OpZeroWB { + switch w.Op { + case OpStoreWB, OpMoveWB, OpZeroWB: + start = i if last == nil { last = w end = i + 1 } - } else { - if last != nil { - start = i + 1 - break + case OpVarDef, OpVarLive, OpVarKill: + continue + default: + if last == nil { + continue } + break FindSeq } } stores = append(stores[:0], b.Values[start:end]...) // copy to avoid aliasing @@ -190,11 +195,17 @@ func writebarrier(f *Func) { case OpZeroWB: fn = typedmemclr typ = &ExternSymbol{Sym: w.Aux.(*types.Type).Symbol()} + case OpVarDef, OpVarLive, OpVarKill: } // then block: emit write barrier call - volatile := w.Op == OpMoveWB && isVolatile(val) - memThen = wbcall(pos, bThen, fn, typ, ptr, val, memThen, sp, sb, volatile) + switch w.Op { + case OpStoreWB, OpMoveWB, OpZeroWB: + volatile := w.Op == OpMoveWB && isVolatile(val) + memThen = wbcall(pos, bThen, fn, typ, ptr, val, memThen, sp, sb, volatile) + case OpVarDef, OpVarLive, OpVarKill: + memThen = bThen.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, memThen) + } // else block: normal store switch w.Op { @@ -206,13 +217,18 @@ func writebarrier(f *Func) { case OpZeroWB: memElse = bElse.NewValue2I(pos, OpZero, types.TypeMem, w.AuxInt, ptr, memElse) memElse.Aux = w.Aux + case OpVarDef, OpVarLive, OpVarKill: + memElse = bElse.NewValue1A(pos, w.Op, types.TypeMem, w.Aux, memElse) } - if !f.WBPos.IsKnown() { - f.WBPos = pos - } - if f.fe.Debug_wb() { - f.Warnl(pos, "write barrier") + if fn != nil { + // Note that we set up a writebarrier function call. + if !f.WBPos.IsKnown() { + f.WBPos = pos + } + if f.fe.Debug_wb() { + f.Warnl(pos, "write barrier") + } } }