Commit 4201c207 authored by Ilya Tocar's avatar Ilya Tocar

cmd/compile: omit racefuncentry/exit when they are not needed

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: default avatarKeith Randall <khr@golang.org>
parent f76eaeb2
......@@ -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)
......
......@@ -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
......
......@@ -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 //
}
......
......@@ -1791,3 +1791,5 @@
(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
......@@ -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
}
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment