[go] cmd/compile: treat singly-assigned func vars as static in escape analysis

0 views
Skip to first unread message

Keith Randall (Gerrit)

unread,
May 15, 2026, 12:50:00 PM (16 hours ago) May 15
to Keith Randall, Jake Bailey, goph...@pubsubhelper.golang.org, golang-...@googlegroups.com, Dmitri Shuralyov, Dmitri Shuralyov, Keith Randall, golang...@luci-project-accounts.iam.gserviceaccount.com, Mateusz Poliwczak, Alan Donovan, David Chase, t hepudds, golang-co...@googlegroups.com

Keith Randall submitted the change

Change information

Commit message:
cmd/compile: treat singly-assigned func vars as static in escape analysis

When a function variable is declared without an initializer and then
assigned exactly once, escape analysis cannot identify the callee:

var f func(*int)
f = func(p *int) {} // callee not visible to StaticValue
f(new(int)) // new(int) conservatively escapes

This pattern is common for recursive closures:

var visit func(*Node)
visit = func(n *Node) {
for _, child := range n.Children {
visit(child)
}
}
visit(root)

There is a trick we can use here: a nil func cannot be called, because
it panics, and a panic cannot cause anything to escape. So for
variables declared without an initializer and assigned exactly once, we
can treat that single assignment as the static value for escape
analysis purposes, since the only other possible value (nil) is a dead
end.

Add ir.FuncSingleAssignment to find such singly-assigned func variables,
and use it as a fallback in escape analysis when StaticCalleeName fails.
This is restricted to func-typed variables only: tracking all local
variables is too expensive, and only func-typed variables benefit from
callee resolution. A future CL will instead do this in the "oracle",
but I am splitting that up as I think it is wasteful to do that and
then not use it to replace StaticValue, but apparently that has its
own issues.

This optimization resolves callees 7 times in std, 100 times in cmd,
51 times in github.com/microsoft/typescript-go, 276 times in x/tools,
and 547 times in x/tools/gopls. Most resolutions improve parameter
escape precision; of those, 5 heap allocations are eliminated in
std/cmd, 6 in x/tools, 5 in x/tools/gopls, and 16 in typescript-go.

compilebench results (this CL vs parent):

│ sec/op │ sec/op vs base │
Template 157.8m ± 6% 157.9m ± 10% ~ (p=0.699 n=6)
Unicode 121.7m ± 12% 122.1m ± 4% ~ (p=0.589 n=6)
GoTypes 897.4m ± 5% 902.5m ± 3% ~ (p=0.937 n=6)
Compiler 163.1m ± 5% 162.4m ± 2% ~ (p=0.818 n=6)
SSA 7.269 ± 2% 7.177 ± 1% ~ (p=0.699 n=6)
Flate 167.6m ± 5% 167.7m ± 14% ~ (p=1.000 n=6)
GoParser 180.5m ± 5% 179.1m ± 5% ~ (p=1.000 n=6)
Reflect 399.5m ± 2% 411.2m ± 7% ~ (p=0.310 n=6)
Tar 172.2m ± 7% 180.0m ± 9% ~ (p=0.699 n=6)
XML 201.1m ± 6% 197.4m ± 4% ~ (p=0.699 n=6)
LinkCompiler 675.7m ± 2% 672.7m ± 2% ~ (p=0.485 n=6)
ExternalLinkCompiler 2.313 ± 2% 2.330 ± 1% ~ (p=0.394 n=6)
LinkWithoutDebugCompiler 430.5m ± 3% 430.9m ± 6% ~ (p=0.818 n=6)
StdCmd 30.43 ± 5% 30.31 ± 2% ~ (p=0.699 n=6)
geomean 539.1m 540.6m +0.28%

Updates #59708
Fixes #70171
Change-Id: I6b701748f05f62376a46bc811181698d8ef76d47
Reviewed-by: Keith Randall <k...@golang.org>
Reviewed-by: Keith Randall <k...@google.com>
Reviewed-by: Mateusz Poliwczak <mpoliw...@gmail.com>
Reviewed-by: Dmitri Shuralyov <dmit...@google.com>
Files:
  • M src/cmd/compile/internal/escape/call.go
  • M src/cmd/compile/internal/ir/expr.go
  • M test/escape_closure.go
Change size: M
Delta: 3 files changed, 204 insertions(+), 0 deletions(-)
Branch: refs/heads/master
Submit Requirements:
Open in Gerrit
Inspect html for hidden footers to help with email filtering. To unsubscribe visit settings. DiffyGerrit
Gerrit-MessageType: merged
Gerrit-Project: go
Gerrit-Branch: master
Gerrit-Change-Id: I6b701748f05f62376a46bc811181698d8ef76d47
Gerrit-Change-Number: 771160
Gerrit-PatchSet: 14
Gerrit-Owner: Jake Bailey <jacob.b...@gmail.com>
Gerrit-Reviewer: David Chase <drc...@google.com>
Gerrit-Reviewer: Dmitri Shuralyov <dmit...@google.com>
Gerrit-Reviewer: Jake Bailey <jacob.b...@gmail.com>
Gerrit-Reviewer: Keith Randall <k...@golang.org>
Gerrit-Reviewer: Keith Randall <k...@google.com>
Gerrit-Reviewer: Mateusz Poliwczak <mpoliw...@gmail.com>
Gerrit-Reviewer: t hepudds <thepud...@gmail.com>
Gerrit-CC: Alan Donovan <adon...@google.com>
Gerrit-CC: Dmitri Shuralyov <dmit...@golang.org>
open
diffy
satisfied_requirement
Reply all
Reply to author
Forward
0 new messages