From 295307ae78f8dd463a2ab8d85a1592ca76619d36 Mon Sep 17 00:00:00 2001 From: philhofer Date: Mon, 13 Mar 2017 15:03:17 -0700 Subject: cmd/compile: de-virtualize interface calls MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With this change, code like h := sha1.New() h.Write(buf) sum := h.Sum() gets compiled into static calls rather than interface calls, because the compiler is able to prove that 'h' is really a *sha1.digest. The InterCall re-write rule hits a few dozen times during make.bash, and hundreds of times during all.bash. The most common pattern identified by the compiler is a constructor like func New() Interface { return &impl{...} } where the constructor gets inlined into the caller, and the result is used immediately. Examples include {sha1,md5,crc32,crc64,...}.New, base64.NewEncoder, base64.NewDecoder, errors.New, net.Pipe, and so on. Some existing benchmarks that change on darwin/amd64: Crc64/ISO4KB-8 2.67µs ± 1% 2.66µs ± 0% -0.36% (p=0.015 n=10+10) Crc64/ISO1KB-8 694ns ± 0% 690ns ± 1% -0.59% (p=0.001 n=10+10) Adler32KB-8 473ns ± 1% 471ns ± 0% -0.39% (p=0.010 n=10+9) On architectures like amd64, the reduction in code size appears to contribute more to benchmark improvements than just removing the indirect call, since that branch gets predicted accurately when called in a loop. Updates #19361 Change-Id: I57d4dc21ef40a05ec0fbd55a9bb0eb74cdc67a3d Reviewed-on: https://go-review.googlesource.com/38139 Run-TryBot: Philip Hofer TryBot-Result: Gobot Gobot Reviewed-by: David Chase --- src/cmd/compile/internal/ssa/export_test.go | 31 +++++++++++++++-------------- 1 file changed, 16 insertions(+), 15 deletions(-) (limited to 'src/cmd/compile/internal/ssa/export_test.go') diff --git a/src/cmd/compile/internal/ssa/export_test.go b/src/cmd/compile/internal/ssa/export_test.go index 74bb08d5c2..b687076a28 100644 --- a/src/cmd/compile/internal/ssa/export_test.go +++ b/src/cmd/compile/internal/ssa/export_test.go @@ -97,21 +97,22 @@ func (d DummyFrontend) Warnl(_ src.XPos, msg string, args ...interface{}) { d.t func (d DummyFrontend) Debug_checknil() bool { return false } func (d DummyFrontend) Debug_wb() bool { return false } -func (d DummyFrontend) TypeBool() Type { return TypeBool } -func (d DummyFrontend) TypeInt8() Type { return TypeInt8 } -func (d DummyFrontend) TypeInt16() Type { return TypeInt16 } -func (d DummyFrontend) TypeInt32() Type { return TypeInt32 } -func (d DummyFrontend) TypeInt64() Type { return TypeInt64 } -func (d DummyFrontend) TypeUInt8() Type { return TypeUInt8 } -func (d DummyFrontend) TypeUInt16() Type { return TypeUInt16 } -func (d DummyFrontend) TypeUInt32() Type { return TypeUInt32 } -func (d DummyFrontend) TypeUInt64() Type { return TypeUInt64 } -func (d DummyFrontend) TypeFloat32() Type { return TypeFloat32 } -func (d DummyFrontend) TypeFloat64() Type { return TypeFloat64 } -func (d DummyFrontend) TypeInt() Type { return TypeInt64 } -func (d DummyFrontend) TypeUintptr() Type { return TypeUInt64 } -func (d DummyFrontend) TypeString() Type { panic("unimplemented") } -func (d DummyFrontend) TypeBytePtr() Type { return TypeBytePtr } +func (d DummyFrontend) TypeBool() Type { return TypeBool } +func (d DummyFrontend) TypeInt8() Type { return TypeInt8 } +func (d DummyFrontend) TypeInt16() Type { return TypeInt16 } +func (d DummyFrontend) TypeInt32() Type { return TypeInt32 } +func (d DummyFrontend) TypeInt64() Type { return TypeInt64 } +func (d DummyFrontend) TypeUInt8() Type { return TypeUInt8 } +func (d DummyFrontend) TypeUInt16() Type { return TypeUInt16 } +func (d DummyFrontend) TypeUInt32() Type { return TypeUInt32 } +func (d DummyFrontend) TypeUInt64() Type { return TypeUInt64 } +func (d DummyFrontend) TypeFloat32() Type { return TypeFloat32 } +func (d DummyFrontend) TypeFloat64() Type { return TypeFloat64 } +func (d DummyFrontend) TypeInt() Type { return TypeInt64 } +func (d DummyFrontend) TypeUintptr() Type { return TypeUInt64 } +func (d DummyFrontend) TypeString() Type { panic("unimplemented") } +func (d DummyFrontend) TypeBytePtr() Type { return TypeBytePtr } +func (d DummyFrontend) DerefItab(sym *obj.LSym, off int64) *obj.LSym { return nil } func (d DummyFrontend) CanSSA(t Type) bool { // There are no un-SSAable types in dummy land. -- cgit v1.2.3-54-g00ecf