package inlheur
import (
- "cmd/compile/internal/base"
"cmd/compile/internal/ir"
"cmd/compile/internal/pgo"
"fmt"
"os"
- "sort"
"strings"
)
isInit bool
}
-func makeCallSiteAnalyzer(fn *ir.Func, ptab map[ir.Node]pstate, loopNestingLevel int) *callSiteAnalyzer {
+func makeCallSiteAnalyzer(fn *ir.Func, cstab CallSiteTab, ptab map[ir.Node]pstate, loopNestingLevel int) *callSiteAnalyzer {
isInit := fn.IsPackageInit() || strings.HasPrefix(fn.Sym().Name, "init.")
return &callSiteAnalyzer{
fn: fn,
- cstab: make(CallSiteTab),
+ cstab: cstab,
ptab: ptab,
isInit: isInit,
loopNest: loopNestingLevel,
// specific subtree within the AST for a function. The main intended
// use cases are for 'region' to be either A) an entire function body,
// or B) an inlined call expression.
-func computeCallSiteTable(fn *ir.Func, region ir.Nodes, ptab map[ir.Node]pstate, loopNestingLevel int) CallSiteTab {
- csa := makeCallSiteAnalyzer(fn, ptab, loopNestingLevel)
+func computeCallSiteTable(fn *ir.Func, region ir.Nodes, cstab CallSiteTab, ptab map[ir.Node]pstate, loopNestingLevel int) CallSiteTab {
+ csa := makeCallSiteAnalyzer(fn, cstab, ptab, loopNestingLevel)
var doNode func(ir.Node) bool
doNode = func(n ir.Node) bool {
csa.nodeVisitPre(n)
cs.Score = int(callee.Inl.Cost)
}
+ if csa.cstab == nil {
+ csa.cstab = make(CallSiteTab)
+ }
csa.cstab[call] = cs
if debugTrace&debugTraceCalls != 0 {
- fmt.Fprintf(os.Stderr, "=-= added callsite: callee=%s call=%v\n",
- callee.Sym().Name, callee)
- }
-}
-
-// ScoreCalls assigns numeric scores to each of the callsites in
-// function fn; the lower the score, the more helpful we think it will
-// be to inline.
-//
-// Unlike a lot of the other inline heuristics machinery, callsite
-// scoring can't be done as part of the CanInline call for a function,
-// due to fact that we may be working on a non-trivial SCC. So for
-// example with this SCC:
-//
-// func foo(x int) { func bar(x int, f func()) {
-// if x != 0 { f()
-// bar(x, func(){}) foo(x-1)
-// } }
-// }
-//
-// We don't want to perform scoring for the 'foo' call in "bar" until
-// after foo has been analyzed, but it's conceivable that CanInline
-// might visit bar before foo for this SCC.
-func ScoreCalls(fn *ir.Func) {
- enableDebugTraceIfEnv()
- defer disableDebugTrace()
- if debugTrace&debugTraceScoring != 0 {
- fmt.Fprintf(os.Stderr, "=-= ScoreCalls(%v)\n", ir.FuncName(fn))
- }
-
- funcInlHeur, ok := fpmap[fn]
- if !ok {
- // TODO: add an assert/panic here.
- return
- }
- scoreCallsRegion(fn, fn.Body, funcInlHeur.cstab)
-}
-
-// scoreCallsRegion assigns numeric scores to each of the callsites in
-// region 'region' within function 'fn'. This can be called on
-// an entire function, or with 'region' set to a chunk of
-// code corresponding to an inlined call.
-func scoreCallsRegion(fn *ir.Func, region ir.Nodes, cstab CallSiteTab) {
- if debugTrace&debugTraceScoring != 0 {
- fmt.Fprintf(os.Stderr, "=-= scoreCallsRegion(%v, %s)\n",
- ir.FuncName(fn), region[0].Op().String())
- }
-
- resultNameTab := make(map[*ir.Name]resultPropAndCS)
-
- // Sort callsites to avoid any surprises with non deterministic
- // map iteration order (this is probably not needed, but here just
- // in case).
- csl := make([]*CallSite, 0, len(cstab))
- for _, cs := range cstab {
- csl = append(csl, cs)
- }
- sort.Slice(csl, func(i, j int) bool {
- return csl[i].ID < csl[j].ID
- })
-
- // Score each call site.
- for _, cs := range csl {
- var cprops *FuncProps
- fihcprops := false
- desercprops := false
- if funcInlHeur, ok := fpmap[cs.Callee]; ok {
- cprops = funcInlHeur.props
- fihcprops = true
- } else if cs.Callee.Inl != nil {
- cprops = DeserializeFromString(cs.Callee.Inl.Properties)
- desercprops = true
- } else {
- if base.Debug.DumpInlFuncProps != "" {
- fmt.Fprintf(os.Stderr, "=-= *** unable to score call to %s from %s\n", cs.Callee.Sym().Name, fmtFullPos(cs.Call.Pos()))
- panic("should never happen")
- } else {
- continue
- }
- }
- cs.Score, cs.ScoreMask = computeCallSiteScore(cs.Callee, cprops, cs.Call, cs.Flags)
-
- examineCallResults(cs, resultNameTab)
-
- if debugTrace&debugTraceScoring != 0 {
- fmt.Fprintf(os.Stderr, "=-= examineCallResults at %s: flags=%d score=%d funcInlHeur=%v deser=%v\n", fmtFullPos(cs.Call.Pos()), cs.Flags, cs.Score, fihcprops, desercprops)
- }
+ fmt.Fprintf(os.Stderr, "=-= added callsite at %s: callee=%s call[%p]=%v\n", fmtFullPos(call.Pos()), callee.Sym().Name, call, call)
}
-
- rescoreBasedOnCallResultUses(fn, resultNameTab, cstab)
}
func (csa *callSiteAnalyzer) nodeVisitPre(n ir.Node) {