]> 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 d2814306934b5bb844771323da98bfb9242b9893..e59ee265312b1f2112caa655b98d057ce4a94af2 100644 (file)
@@ -21,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)
@@ -44,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
 }
 
@@ -120,13 +125,14 @@ func (csa *callSiteAnalyzer) determinePanicPathBits(call ir.Node, r CSPropBits)
 }
 
 func (csa *callSiteAnalyzer) addCallSite(callee *ir.Func, call *ir.CallExpr) {
+       flags := csa.flagsForNode(call)
        // FIXME: maybe bulk-allocate these?
        cs := &CallSite{
                Call:   call,
                Callee: callee,
                Assign: csa.containingAssignment(call),
-               Flags:  csa.flagsForNode(call),
-               Id:     uint(len(csa.cstab)),
+               Flags:  flags,
+               ID:     uint(len(csa.cstab)),
        }
        if _, ok := csa.cstab[call]; ok {
                fmt.Fprintf(os.Stderr, "*** cstab duplicate entry at: %s\n",
@@ -134,12 +140,20 @@ func (csa *callSiteAnalyzer) addCallSite(callee *ir.Func, call *ir.CallExpr) {
                fmt.Fprintf(os.Stderr, "*** call: %+v\n", call)
                panic("bad")
        }
-       if debugTrace&debugTraceCalls != 0 {
-               fmt.Fprintf(os.Stderr, "=-= added callsite: callee=%s call=%v\n",
-                       callee.Sym().Name, callee)
+       if callee.Inl != nil {
+               // Set initial score for callsite to the cost computed
+               // by CanInline; this score will be refined later based
+               // on heuristics.
+               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 at %s: callee=%s call[%p]=%v\n", fmtFullPos(call.Pos()), callee.Sym().Name, call, call)
+       }
 }
 
 func (csa *callSiteAnalyzer) nodeVisitPre(n ir.Node) {
@@ -150,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)
                }
@@ -212,12 +226,12 @@ func hasTopLevelLoopBodyReturnOrBreak(loopBody ir.Nodes) bool {
 //
 // Here the top-level assignment statement for the foo() call is the
 // statement assigning to "x"; the top-level assignment for "bar()"
-// call is the assignment to x,y.   For the baz() and blah() calls,
+// call is the assignment to x,y. For the baz() and blah() calls,
 // there is no top level assignment statement.
 //
-// The unstated goal here is that we want to use the containing assignment
-// to establish a connection between a given call and the variables
-// to which its results/returns are being assigned.
+// The unstated goal here is that we want to use the containing
+// assignment to establish a connection between a given call and the
+// variables to which its results/returns are being assigned.
 //
 // Note that for the "bar" command above, the front end sometimes
 // decomposes this into two assignments, the first one assigning the