]> Cypherpunks.ru repositories - gostls13.git/blobdiff - src/cmd/compile/internal/inline/inlheur/analyze_func_callsites.go
cmd/compile/internal/inline: rework call scoring for non-inlinable funcs
[gostls13.git] / src / cmd / compile / internal / inline / inlheur / analyze_func_callsites.go
index c785dd0a407a9501103a64215816b23670de23e0..e59ee265312b1f2112caa655b98d057ce4a94af2 100644 (file)
@@ -5,12 +5,10 @@
 package inlheur
 
 import (
-       "cmd/compile/internal/base"
        "cmd/compile/internal/ir"
        "cmd/compile/internal/pgo"
        "fmt"
        "os"
-       "sort"
        "strings"
 )
 
@@ -23,22 +21,25 @@ type callSiteAnalyzer struct {
        isInit   bool
 }
 
-func makeCallSiteAnalyzer(fn *ir.Func, ptab map[ir.Node]pstate) *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),
-               ptab:   ptab,
-               isInit: isInit,
+               fn:       fn,
+               cstab:    cstab,
+               ptab:     ptab,
+               isInit:   isInit,
+               loopNest: loopNestingLevel,
+               nstack:   []ir.Node{fn},
        }
 }
 
-func computeCallSiteTable(fn *ir.Func, ptab map[ir.Node]pstate) CallSiteTab {
-       if debugTrace != 0 {
-               fmt.Fprintf(os.Stderr, "=-= making callsite table for func %v:\n",
-                       fn.Sym().Name)
-       }
-       csa := makeCallSiteAnalyzer(fn, ptab)
+// computeCallSiteTable builds and returns a table of call sites for
+// the specified region in function fn. A region here corresponds to a
+// 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, 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)
@@ -46,7 +47,9 @@ func computeCallSiteTable(fn *ir.Func, ptab map[ir.Node]pstate) CallSiteTab {
                csa.nodeVisitPost(n)
                return false
        }
-       doNode(fn)
+       for _, n := range region {
+               doNode(n)
+       }
        return csa.cstab
 }
 
@@ -144,86 +147,13 @@ func (csa *callSiteAnalyzer) addCallSite(callee *ir.Func, call *ir.CallExpr) {
                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))
-       }
-
-       fih, ok := fpmap[fn]
-       if !ok {
-               // TODO: add an assert/panic here.
-               return
+               fmt.Fprintf(os.Stderr, "=-= added callsite at %s: callee=%s call[%p]=%v\n", fmtFullPos(call.Pos()), callee.Sym().Name, call, call)
        }
-
-       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(fih.cstab))
-       for _, cs := range fih.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 fih, ok := fpmap[cs.Callee]; ok {
-                       cprops = fih.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, "=-= scoring call at %s: flags=%d score=%d fih=%v deser=%v\n", fmtFullPos(cs.Call.Pos()), cs.Flags, cs.Score, fihcprops, desercprops)
-               }
-       }
-
-       rescoreBasedOnCallResultUses(fn, resultNameTab, fih.cstab)
 }
 
 func (csa *callSiteAnalyzer) nodeVisitPre(n ir.Node) {
@@ -234,7 +164,7 @@ func (csa *callSiteAnalyzer) nodeVisitPre(n ir.Node) {
                }
        case ir.OCALLFUNC:
                ce := n.(*ir.CallExpr)
-               callee := pgo.DirectCallee(ce.X)
+               callee := pgo.DirectCallee(ce.Fun)
                if callee != nil && callee.Inl != nil {
                        csa.addCallSite(callee, ce)
                }