aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/inline
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2021-01-01 02:39:00 -0800
committerMatthew Dempsky <mdempsky@google.com>2021-01-01 11:30:21 +0000
commitfad9a8b52864da738037163565e8eacc958baaa8 (patch)
treef6c90c6a4257ef17bd47eaf27a2442e434be24ec /src/cmd/compile/internal/inline
parent7d55669847389b8d2e490400226f272023da8605 (diff)
downloadgo-fad9a8b52864da738037163565e8eacc958baaa8.tar.gz
go-fad9a8b52864da738037163565e8eacc958baaa8.zip
[dev.regabi] cmd/compile: simplify inlining of closures
Closures have their own ONAMEs for captured variables, which their function bodies refer to. So during inlining, we need to account for this and ensure the references still work. The previous inlining handled this by actually declaring the variables and then either copying the original value or creating a pointer to them, as appropriate for variables captured by value or by reference. But this is needlessly complicated. When inlining the function body, we need to rewrite all variable references anyway. We can just detect closure variables and change them to directly point to the enclosing function's version of this variable. No need for copying or further indirection. Does not pass toolstash -cmp. Presumably because we're able to generate better code in some circumstances. Change-Id: I8f0ccf7b098f39b8cd33f3bcefb875c8132d2c62 Reviewed-on: https://go-review.googlesource.com/c/go/+/280996 Trust: Matthew Dempsky <mdempsky@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com> TryBot-Result: Go Bot <gobot@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/inline')
-rw-r--r--src/cmd/compile/internal/inline/inl.go55
1 files changed, 19 insertions, 36 deletions
diff --git a/src/cmd/compile/internal/inline/inl.go b/src/cmd/compile/internal/inline/inl.go
index df797da2d1..9e9d0bba7c 100644
--- a/src/cmd/compile/internal/inline/inl.go
+++ b/src/cmd/compile/internal/inline/inl.go
@@ -753,42 +753,6 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlMap map[*ir.Func]b
// record formals/locals for later post-processing
var inlfvars []ir.Node
- // Handle captured variables when inlining closures.
- if c := fn.OClosure; c != nil {
- for _, v := range fn.ClosureVars {
- if v.Op() == ir.OXXX {
- continue
- }
-
- o := v.Outer
- // make sure the outer param matches the inlining location
- // NB: if we enabled inlining of functions containing OCLOSURE or refined
- // the reassigned check via some sort of copy propagation this would most
- // likely need to be changed to a loop to walk up to the correct Param
- if o == nil || o.Curfn != ir.CurFunc {
- base.Fatalf("%v: unresolvable capture %v %v\n", ir.Line(n), fn, v)
- }
-
- if v.Byval() {
- iv := typecheck.Expr(inlvar(v))
- ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, iv.(*ir.Name)))
- ninit.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, iv, o)))
- inlvars[v] = iv
- } else {
- addr := typecheck.NewName(typecheck.Lookup("&" + v.Sym().Name))
- addr.SetType(types.NewPtr(v.Type()))
- ia := typecheck.Expr(inlvar(addr))
- ninit.Append(ir.NewDecl(base.Pos, ir.ODCL, ia.(*ir.Name)))
- ninit.Append(typecheck.Stmt(ir.NewAssignStmt(base.Pos, ia, typecheck.NodAddr(o))))
- inlvars[addr] = ia
-
- // When capturing by reference, all occurrence of the captured var
- // must be substituted with dereference of the temporary address
- inlvars[v] = typecheck.Expr(ir.NewStarExpr(base.Pos, ia))
- }
- }
- }
-
for _, ln := range fn.Inl.Dcl {
if ln.Op() != ir.ONAME {
continue
@@ -1088,6 +1052,25 @@ func (subst *inlsubst) node(n ir.Node) ir.Node {
switch n.Op() {
case ir.ONAME:
n := n.(*ir.Name)
+
+ // Handle captured variables when inlining closures.
+ if n.IsClosureVar() {
+ o := n.Outer
+
+ // make sure the outer param matches the inlining location
+ // NB: if we enabled inlining of functions containing OCLOSURE or refined
+ // the reassigned check via some sort of copy propagation this would most
+ // likely need to be changed to a loop to walk up to the correct Param
+ if o == nil || o.Curfn != ir.CurFunc {
+ base.Fatalf("%v: unresolvable capture %v\n", ir.Line(n), n)
+ }
+
+ if base.Flag.LowerM > 2 {
+ fmt.Printf("substituting captured name %+v -> %+v\n", n, o)
+ }
+ return o
+ }
+
if inlvar := subst.inlvars[n]; inlvar != nil { // These will be set during inlnode
if base.Flag.LowerM > 2 {
fmt.Printf("substituting name %+v -> %+v\n", n, inlvar)