mirror of
https://github.com/golang/go
synced 2024-11-05 15:26:15 -07:00
cmd/compile: allow OpVarXXX calls to be duplicated in writebarrier blocks
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 <josharian@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Cherry Zhang <cherryyz@google.com>
This commit is contained in:
parent
5331e7e9df
commit
94a017f3f5
@ -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
|
||||
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,8 +217,12 @@ 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 fn != nil {
|
||||
// Note that we set up a writebarrier function call.
|
||||
if !f.WBPos.IsKnown() {
|
||||
f.WBPos = pos
|
||||
}
|
||||
@ -215,6 +230,7 @@ func writebarrier(f *Func) {
|
||||
f.Warnl(pos, "write barrier")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// merge memory
|
||||
// Splice memory Phi into the last memory of the original sequence,
|
||||
|
Loading…
Reference in New Issue
Block a user