]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: omit racefuncentry/exit when they are not needed
authorIlya Tocar <ilya.tocar@intel.com>
Wed, 27 Jun 2018 16:40:24 +0000 (11:40 -0500)
committerIlya Tocar <ilya.tocar@intel.com>
Mon, 20 Aug 2018 22:07:22 +0000 (22:07 +0000)
When compiling with -race, we insert calls to racefuncentry,
into every function. Add a rule that removes them in leaf functions,
without instrumented loads/stores.
Shaves ~30kb from "-race" version of go tool:

file difference:
go_old 15626192
go_new 15597520 [-28672 bytes]

section differences:
global text (code) = -24513 bytes (-0.358598%)
read-only data = -5849 bytes (-0.167064%)
Total difference -30362 bytes (-0.097928%)

Fixes #24662

Change-Id: Ia63bf1827f4cf2c25e3e28dcd097c150994ade0a
Reviewed-on: https://go-review.googlesource.com/121235
Run-TryBot: Ilya Tocar <ilya.tocar@intel.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/gc/racewalk.go
src/cmd/compile/internal/gc/ssa.go
src/cmd/compile/internal/ssa/config.go
src/cmd/compile/internal/ssa/gen/generic.rules
src/cmd/compile/internal/ssa/rewrite.go
src/cmd/compile/internal/ssa/rewritegeneric.go

index df0e5f4059035f4c9f18c3c09d58cbbeeac00586..e8c7fb5b149060b5597ac24fbbfa40657bb81f56 100644 (file)
@@ -10,7 +10,7 @@ import (
        "cmd/internal/sys"
 )
 
-// The racewalk pass is currently handled in two parts.
+// The racewalk pass is currently handled in three parts.
 //
 // First, for flag_race, it inserts calls to racefuncenter and
 // racefuncexit at the start and end (respectively) of each
@@ -22,6 +22,10 @@ import (
 // the Func.InstrumentBody flag as needed. For background on why this
 // is done during SSA construction rather than a separate SSA pass,
 // see issue #19054.
+//
+// Third we remove calls to racefuncenter and racefuncexit, for leaf
+// functions without instrumented operations. This is done as part of
+// ssa opt pass via special rule.
 
 // TODO(dvyukov): do not instrument initialization as writes:
 // a := make([]int, 10)
index af43da627546189294abce9bfea4db4b3447b0aa..86b457b75821e8f6e0d0f8bc2bffbd12e7c67bbd 100644 (file)
@@ -131,6 +131,7 @@ func buildssa(fn *Node, worker int) *ssa.Func {
        s.f.Cache = &ssaCaches[worker]
        s.f.Cache.Reset()
        s.f.DebugTest = s.f.DebugHashMatch("GOSSAHASH", name)
+       s.f.Config.Race = flag_race
        s.f.Name = name
        if fn.Func.Pragma&Nosplit != 0 {
                s.f.NoSplit = true
index af8cccff90bb1c5f239fb8ae2f0021465e15b69c..40008bcf8792edfc601f0122793daf86da4b5488 100644 (file)
@@ -38,6 +38,7 @@ type Config struct {
        nacl           bool          // GOOS=nacl
        use387         bool          // GO386=387
        SoftFloat      bool          //
+       Race           bool          // race detector enabled
        NeedsFpScratch bool          // No direct move between GP and FP register sets
        BigEndian      bool          //
 }
index 0b68db7f0465df7ff30f3702a49f8711dd0bcd01..b1a0775e4a8f8912b2c1238c7b0694df32f25b1b 100644 (file)
                        (Store {t4} (OffPtr <tt4> [o4] dst) d3
                                (Store {t5} (OffPtr <tt5> [o5] dst) d4
                                        (Zero {t1} [n] dst mem)))))
+
+(StaticCall {sym} x) && needRaceCleanup(sym,v) -> x
index 2a72b0006f1617a94b31b783fe03efdf5bda81c8..31195638ab5f8038b29daab6589a81fcc5629a8e 100644 (file)
@@ -1026,3 +1026,31 @@ func registerizable(b *Block, t interface{}) bool {
        }
        return false
 }
+
+// needRaceCleanup reports whether this call to racefuncenter/exit isn't needed.
+func needRaceCleanup(sym interface{}, v *Value) bool {
+       f := v.Block.Func
+       if !f.Config.Race {
+               return false
+       }
+       if !isSameSym(sym, "runtime.racefuncenter") && !isSameSym(sym, "runtime.racefuncexit") {
+               return false
+       }
+       for _, b := range f.Blocks {
+               for _, v := range b.Values {
+                       if v.Op == OpStaticCall {
+                               switch v.Aux.(fmt.Stringer).String() {
+                               case "runtime.racefuncenter", "runtime.racefuncexit", "runtime.panicindex",
+                                       "runtime.panicslice", "runtime.panicdivide", "runtime.panicwrap":
+                               // Check for racefuncenter will encounter racefuncexit and vice versa.
+                               // Allow calls to panic*
+                               default:
+                                       // If we encounterd any call, we need to keep racefunc*,
+                                       // for accurate stacktraces.
+                                       return false
+                               }
+                       }
+               }
+       }
+       return true
+}
index a1c83ea37834ef7aa6fee21d3549e5019093144b..5ad53dd0b6d388706a811a31ed3b4a4fdd9a2817 100644 (file)
@@ -27595,6 +27595,20 @@ func rewriteValuegeneric_OpStaticCall_0(v *Value) bool {
                v.AddArg(mem)
                return true
        }
+       // match: (StaticCall {sym} x)
+       // cond: needRaceCleanup(sym,v)
+       // result: x
+       for {
+               sym := v.Aux
+               x := v.Args[0]
+               if !(needRaceCleanup(sym, v)) {
+                       break
+               }
+               v.reset(OpCopy)
+               v.Type = x.Type
+               v.AddArg(x)
+               return true
+       }
        return false
 }
 func rewriteValuegeneric_OpStore_0(v *Value) bool {