cmd/compile: record InlCost in export data

Previously, we were treating cross-package function calls as free for
inlining budgeting.

In theory, we should be able to recompute InlCost from the
exported/reimported function bodies. However, that process mutates the
structure of the Node AST enough that it doesn't preserve InlCost. To
avoid unexpected issues, just record and restore InlCost in the export
data.

Fixes #19261.

Change-Id: Iac2bc0d32d4f948b64524aca657051f9fc96d92d
Reviewed-on: https://go-review.googlesource.com/70151
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Matthew Dempsky 2017-10-11 15:25:13 -07:00
parent 1fbeccb15a
commit a509cae90d
5 changed files with 51 additions and 0 deletions

View file

@ -377,6 +377,7 @@ func export(out *bufio.Writer, trace bool) int {
p.tracef("\n----\nfunc { %#v }\n", f.Inl)
}
p.int(i)
p.int(int(f.InlCost))
p.stmtList(f.Inl)
if p.trace {
p.tracef("\n")

View file

@ -187,6 +187,7 @@ func Import(imp *types.Pkg, in *bufio.Reader) {
// them only for functions with inlineable bodies. funchdr does
// parameter renaming which doesn't matter if we don't have a body.
inlCost := p.int()
if f := p.funcList[i]; f != nil {
// function not yet imported - read body and set it
funchdr(f)
@ -200,6 +201,7 @@ func Import(imp *types.Pkg, in *bufio.Reader) {
body = []*Node{nod(OEMPTY, nil, nil)}
}
f.Func.Inl.Set(body)
f.Func.InlCost = int32(inlCost)
funcbody()
} else {
// function already imported - read body but discard declarations

View file

@ -0,0 +1,24 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package p
func F() { // ERROR "can inline F"
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
}
func G() {
F() // ERROR "inlining call to F"
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
}

View file

@ -0,0 +1,17 @@
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package q
import "./p"
func H() {
p.F() // ERROR "inlining call to p.F"
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
print(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
}

View file

@ -0,0 +1,7 @@
// errorcheckdir -0 -m
// Copyright 2017 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored