Skip to content

Commit 323cf73

Browse files
committed
cmd/compile: write "properties" to export data for inlinable funcs
Augment the ir.Inline container to include an entry for function properties (currently serialized as a string), and if GOEXPERIMENT=newinliner is set, compute and store function properties for all inline candidates processed by the inliner. The idea here is that if the function properties are going to drive inlining decisions, we'd like to have the same info from non-local / imported functions as for local / in-package functions, hence we need to include the properties in the export data. Hand testing on the compiler itself and with k8s kubelet shows that this increases the size of export data overall by about 2-3 percent, so a pretty modest increase. Updates #61502. Change-Id: I9d1c311aa8418d02ffea3629c3dd9d8076886d15 Reviewed-on: https://go-review.googlesource.com/c/go/+/511562 LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
1 parent 906a073 commit 323cf73

File tree

5 files changed

+54
-13
lines changed

5 files changed

+54
-13
lines changed

src/cmd/compile/internal/inline/inl.go

+12-4
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ package inline
2929
import (
3030
"fmt"
3131
"go/constant"
32+
"internal/goexperiment"
3233
"sort"
3334
"strconv"
3435

@@ -292,11 +293,15 @@ func CanInline(fn *ir.Func, profile *pgo.Profile) {
292293
base.Fatalf("CanInline no nname %+v", fn)
293294
}
294295

296+
canInline := func(fn *ir.Func) { CanInline(fn, profile) }
297+
298+
var funcProps *inlheur.FuncProps
299+
if goexperiment.NewInliner {
300+
funcProps = inlheur.AnalyzeFunc(fn, canInline)
301+
}
302+
295303
if base.Debug.DumpInlFuncProps != "" {
296-
inlheur.DumpFuncProps(fn, base.Debug.DumpInlFuncProps,
297-
func(fn *ir.Func) {
298-
CanInline(fn, profile)
299-
})
304+
inlheur.DumpFuncProps(fn, base.Debug.DumpInlFuncProps, canInline)
300305
}
301306

302307
var reason string // reason, if any, that the function was not inlined
@@ -363,6 +368,9 @@ func CanInline(fn *ir.Func, profile *pgo.Profile) {
363368

364369
CanDelayResults: canDelayResults(fn),
365370
}
371+
if goexperiment.NewInliner {
372+
n.Func.Inl.Properties = funcProps.SerializeToString()
373+
}
366374

367375
if base.Flag.LowerM > 1 {
368376
fmt.Printf("%v: can inline %v with cost %d as: %v { %v }\n", ir.Line(fn), n, budget-visitor.budget, fn.Type(), ir.Nodes(fn.Body))

src/cmd/compile/internal/inline/inlheur/analyze.go

+30-9
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"cmd/compile/internal/ir"
1010
"encoding/json"
1111
"fmt"
12+
"internal/goexperiment"
1213
"io"
1314
"os"
1415
"path/filepath"
@@ -48,6 +49,24 @@ type fnInlHeur struct {
4849
props *FuncProps
4950
}
5051

52+
var fpmap = map[*ir.Func]fnInlHeur{}
53+
54+
func AnalyzeFunc(fn *ir.Func, canInline func(*ir.Func)) *FuncProps {
55+
if fih, ok := fpmap[fn]; ok {
56+
return fih.props
57+
}
58+
fp := computeFuncProps(fn, canInline)
59+
file, line := fnFileLine(fn)
60+
entry := fnInlHeur{
61+
fname: fn.Sym().Name,
62+
file: file,
63+
line: line,
64+
props: fp,
65+
}
66+
fpmap[fn] = entry
67+
return fp
68+
}
69+
5170
// computeFuncProps examines the Go function 'fn' and computes for it
5271
// a function "properties" object, to be used to drive inlining
5372
// heuristics. See comments on the FuncProps type for more info.
@@ -148,6 +167,16 @@ func captureFuncDumpEntry(fn *ir.Func, canInline func(*ir.Func)) {
148167
if strings.HasPrefix(fn.Sym().Name, ".eq.") {
149168
return
150169
}
170+
fih, ok := fpmap[fn]
171+
if goexperiment.NewInliner {
172+
// Props object should already be present.
173+
if !ok {
174+
panic("unexpected missing props")
175+
}
176+
} else {
177+
AnalyzeFunc(fn, canInline)
178+
fih = fpmap[fn]
179+
}
151180
if dumpBuffer == nil {
152181
dumpBuffer = make(map[*ir.Func]fnInlHeur)
153182
}
@@ -156,15 +185,7 @@ func captureFuncDumpEntry(fn *ir.Func, canInline func(*ir.Func)) {
156185
// so don't add them more than once.
157186
return
158187
}
159-
fp := computeFuncProps(fn, canInline)
160-
file, line := fnFileLine(fn)
161-
entry := fnInlHeur{
162-
fname: fn.Sym().Name,
163-
file: file,
164-
line: line,
165-
props: fp,
166-
}
167-
dumpBuffer[fn] = entry
188+
dumpBuffer[fn] = fih
168189
}
169190

170191
// dumpFilePreamble writes out a file-level preamble for a given

src/cmd/compile/internal/ir/func.go

+4
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ type Inline struct {
200200
Dcl []*Name
201201
HaveDcl bool // whether we've loaded Dcl
202202

203+
// Function properties, encoded as a string (these are used for
204+
// making inlining decisions). See cmd/compile/internal/inline/inlheur.
205+
Properties string
206+
203207
// CanDelayResults reports whether it's safe for the inliner to delay
204208
// initializing the result parameters until immediately before the
205209
// "return" statement.

src/cmd/compile/internal/noder/linker.go

+4
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package noder
66

77
import (
88
"internal/buildcfg"
9+
"internal/goexperiment"
910
"internal/pkgbits"
1011
"io"
1112

@@ -296,6 +297,9 @@ func (l *linker) relocFuncExt(w *pkgbits.Encoder, name *ir.Name) {
296297
if inl := name.Func.Inl; w.Bool(inl != nil) {
297298
w.Len(int(inl.Cost))
298299
w.Bool(inl.CanDelayResults)
300+
if goexperiment.NewInliner {
301+
w.String(inl.Properties)
302+
}
299303
}
300304

301305
w.Sync(pkgbits.SyncEOF)

src/cmd/compile/internal/noder/reader.go

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"go/constant"
1010
"internal/buildcfg"
11+
"internal/goexperiment"
1112
"internal/pkgbits"
1213
"path/filepath"
1314
"strings"
@@ -1118,6 +1119,9 @@ func (r *reader) funcExt(name *ir.Name, method *types.Sym) {
11181119
Cost: int32(r.Len()),
11191120
CanDelayResults: r.Bool(),
11201121
}
1122+
if goexperiment.NewInliner {
1123+
fn.Inl.Properties = r.String()
1124+
}
11211125
}
11221126
} else {
11231127
r.addBody(name.Func, method)

0 commit comments

Comments
 (0)