aboutsummaryrefslogtreecommitdiff
path: root/src/cmd
diff options
context:
space:
mode:
authorAustin Clements <austin@google.com>2023-03-23 15:50:21 -0400
committerGopher Robot <gobot@golang.org>2023-03-31 20:00:40 +0000
commit2ff684a5419a72771fd750cebf06370f560dd96a (patch)
tree853b6ac803e0b30194418c73737aa305ccfe1f55 /src/cmd
parentbfe3c678ab70d9a033b219276636c3f4669c1dc9 (diff)
downloadgo-2ff684a5419a72771fd750cebf06370f560dd96a.tar.xz
cmd/compile: allow more inlining of functions that construct closures
Currently, when the inliner is determining if a function is inlineable, it descends into the bodies of closures constructed by that function. This has several unfortunate consequences: - If the closure contains a disallowed operation (e.g., a defer), then the outer function can't be inlined. It makes sense that the *closure* can't be inlined in this case, but it doesn't make sense to punish the function that constructs the closure. - The hairiness of the closure counts against the inlining budget of the outer function. Since we currently copy the closure body when inlining the outer function, this makes sense from the perspective of export data size and binary size, but ultimately doesn't make much sense from the perspective of what should be inlineable. - Since the inliner walks into every closure created by an outer function in addition to starting a walk at every closure, this adds an n^2 factor to inlinability analysis. This CL simply drops this behavior. In std, this makes 57 more functions inlinable, and disallows inlining for 10 (due to the basic instability of our bottom-up inlining approach), for an net increase of 47 inlinable functions (+0.6%). This will help significantly with the performance of the functions to be added for #56102, which have a somewhat complicated nesting of closures with a performance-critical fast path. The downside of this seems to be a potential increase in export data and text size, but the practical impact of this seems to be negligible: │ before │ after │ │ bytes │ bytes vs base │ Go/binary 15.12Mi ± 0% 15.14Mi ± 0% +0.16% (n=1) Go/text 5.220Mi ± 0% 5.237Mi ± 0% +0.32% (n=1) Compile/binary 22.92Mi ± 0% 22.94Mi ± 0% +0.07% (n=1) Compile/text 8.428Mi ± 0% 8.435Mi ± 0% +0.08% (n=1) Change-Id: Ie9e38104fed5689a94c368288653fd7cb4b7a35e Reviewed-on: https://go-review.googlesource.com/c/go/+/479095 Reviewed-by: Than McIntosh <thanm@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Austin Clements <austin@google.com> Run-TryBot: Austin Clements <austin@google.com>
Diffstat (limited to 'src/cmd')
-rw-r--r--src/cmd/compile/internal/inline/inl.go11
1 files changed, 5 insertions, 6 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go
index 80be841efa..b8f3f9baee 100644
--- a/src/cmd/compile/internal/inline/inl.go
+++ b/src/cmd/compile/internal/inline/inl.go
@@ -446,6 +446,8 @@ func (v *hairyVisitor) tooHairy(fn *ir.Func) bool {
return false
}
+// doNode visits n and its children, updates the state in v, and returns true if
+// n makes the current function too hairy for inlining.
func (v *hairyVisitor) doNode(n ir.Node) bool {
if n == nil {
return false
@@ -577,13 +579,10 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
// TODO(danscales): Maybe make budget proportional to number of closure
// variables, e.g.:
//v.budget -= int32(len(n.(*ir.ClosureExpr).Func.ClosureVars) * 3)
+ // TODO(austin): However, if we're able to inline this closure into
+ // v.curFunc, then we actually pay nothing for the closure captures. We
+ // should try to account for that if we're going to account for captures.
v.budget -= 15
- // Scan body of closure (which DoChildren doesn't automatically
- // do) to check for disallowed ops in the body and include the
- // body in the budget.
- if doList(n.(*ir.ClosureExpr).Func.Body, v.do) {
- return true
- }
case ir.OGO,
ir.ODEFER,