]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: allow OpVarXXX calls to be duplicated in writebarrier blocks
authorJosh Bleecher Snyder <josharian@gmail.com>
Thu, 27 Apr 2017 18:56:46 +0000 (11:56 -0700)
committerJosh Bleecher Snyder <josharian@gmail.com>
Tue, 9 May 2017 23:54:14 +0000 (23:54 +0000)
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>
src/cmd/compile/internal/ssa/writebarrier.go

index 7aec598f6f1e520aa6fa6f3b268a8ee81c715f88..3443c6464f2ceefe40a254c98017d34e98458678 100644 (file)
@@ -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")
+                               }
                        }
                }