cmd/internal/gc, runtime: speed up some cases of _, ok := i.(T)
Some type assertions of the form _, ok := i.(T) allow efficient inlining.
Such type assertions commonly show up in type switches.
For example, with this optimization, using 6g, the length of
encoding/binary's intDataSize function shrinks from 2224 to 1728 bytes (-22%).
benchmark old ns/op new ns/op delta
BenchmarkAssertI2E2Blank 4.67 0.82 -82.44%
BenchmarkAssertE2T2Blank 4.38 0.83 -81.05%
BenchmarkAssertE2E2Blank 3.88 0.83 -78.61%
BenchmarkAssertE2E2 14.2 14.4 +1.41%
BenchmarkAssertE2T2 10.3 10.4 +0.97%
BenchmarkAssertI2E2 13.4 13.3 -0.75%
Change-Id: Ie9798c3e85432bb8e0f2c723afc376e233639df7
Reviewed-on: https://go-review.googlesource.com/7697
Reviewed-by: Keith Randall <khr@golang.org>
diff --git a/src/runtime/iface.go b/src/runtime/iface.go
index 811a31b..d94c391 100644
--- a/src/runtime/iface.go
+++ b/src/runtime/iface.go
@@ -219,20 +219,17 @@
}
}
+// The compiler ensures that r is non-nil.
func assertE2T2(t *_type, e interface{}, r unsafe.Pointer) bool {
ep := (*eface)(unsafe.Pointer(&e))
if ep._type != t {
- if r != nil {
- memclr(r, uintptr(t.size))
- }
+ memclr(r, uintptr(t.size))
return false
}
- if r != nil {
- if isDirectIface(t) {
- writebarrierptr((*uintptr)(r), uintptr(ep.data))
- } else {
- typedmemmove(t, r, ep.data)
- }
+ if isDirectIface(t) {
+ writebarrierptr((*uintptr)(r), uintptr(ep.data))
+ } else {
+ typedmemmove(t, r, ep.data)
}
return true
}
@@ -262,17 +259,16 @@
return
}
+// The compiler ensures that r is non-nil.
func assertI2E2(inter *interfacetype, i fInterface, r *interface{}) bool {
ip := (*iface)(unsafe.Pointer(&i))
tab := ip.tab
if tab == nil {
return false
}
- if r != nil {
- rp := (*eface)(unsafe.Pointer(r))
- rp._type = tab._type
- rp.data = ip.data
- }
+ rp := (*eface)(unsafe.Pointer(r))
+ rp._type = tab._type
+ rp.data = ip.data
return true
}
@@ -386,17 +382,14 @@
*r = e
}
+// The compiler ensures that r is non-nil.
func assertE2E2(inter *interfacetype, e interface{}, r *interface{}) bool {
ep := (*eface)(unsafe.Pointer(&e))
if ep._type == nil {
- if r != nil {
- *r = nil
- }
+ *r = nil
return false
}
- if r != nil {
- *r = e
- }
+ *r = e
return true
}