github.com/shogo82148/std@v1.22.1-0.20240327122250-4e474527810c/cmd/compile/internal/inline/inlheur/scoring.go (about)

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package inlheur
     6  
     7  import (
     8  	"github.com/shogo82148/std/cmd/compile/internal/ir"
     9  	"github.com/shogo82148/std/cmd/compile/internal/pgo"
    10  )
    11  
    12  // SetupScoreAdjustments interprets the value of the -d=inlscoreadj
    13  // debugging option, if set. The value of this flag is expected to be
    14  // a series of "/"-separated clauses of the form adj1:value1. Example:
    15  // -d=inlscoreadj=inLoopAdj=0/passConstToIfAdj=-99
    16  func SetupScoreAdjustments()
    17  
    18  // LargestNegativeScoreAdjustment tries to estimate the largest possible
    19  // negative score adjustment that could be applied to a call of the
    20  // function with the specified props. Example:
    21  //
    22  //	func foo() {                  func bar(x int, p *int) int {
    23  //	   ...                          if x < 0 { *p = x }
    24  //	}                               return 99
    25  //	                              }
    26  //
    27  // Function 'foo' above on the left has no interesting properties,
    28  // thus as a result the most we'll adjust any call to is the value for
    29  // "call in loop". If the calculated cost of the function is 150, and
    30  // the in-loop adjustment is 5 (for example), then there is not much
    31  // point treating it as inlinable. On the other hand "bar" has a param
    32  // property (parameter "x" feeds unmodified to an "if" statement") and
    33  // a return property (always returns same constant) meaning that a
    34  // given call _could_ be rescored down as much as -35 points-- thus if
    35  // the size of "bar" is 100 (for example) then there is at least a
    36  // chance that scoring will enable inlining.
    37  func LargestNegativeScoreAdjustment(fn *ir.Func, props *FuncProps) int
    38  
    39  // LargestPositiveScoreAdjustment tries to estimate the largest possible
    40  // positive score adjustment that could be applied to a given callsite.
    41  // At the moment we don't have very many positive score adjustments, so
    42  // this is just hard-coded, not table-driven.
    43  func LargestPositiveScoreAdjustment(fn *ir.Func) int
    44  
    45  // ScoreCalls assigns numeric scores to each of the callsites in
    46  // function 'fn'; the lower the score, the more helpful we think it
    47  // will be to inline.
    48  //
    49  // Unlike a lot of the other inline heuristics machinery, callsite
    50  // scoring can't be done as part of the CanInline call for a function,
    51  // due to fact that we may be working on a non-trivial SCC. So for
    52  // example with this SCC:
    53  //
    54  //	func foo(x int) {           func bar(x int, f func()) {
    55  //	  if x != 0 {                  f()
    56  //	    bar(x, func(){})           foo(x-1)
    57  //	  }                         }
    58  //	}
    59  //
    60  // We don't want to perform scoring for the 'foo' call in "bar" until
    61  // after foo has been analyzed, but it's conceivable that CanInline
    62  // might visit bar before foo for this SCC.
    63  func ScoreCalls(fn *ir.Func)
    64  
    65  // ScoreCallsCleanup resets the state of the callsite cache
    66  // once ScoreCalls is done with a function.
    67  func ScoreCallsCleanup()
    68  
    69  // GetCallSiteScore returns the previously calculated score for call
    70  // within fn.
    71  func GetCallSiteScore(fn *ir.Func, call *ir.CallExpr) (int, bool)
    72  
    73  // BudgetExpansion returns the amount to relax/expand the base
    74  // inlining budget when the new inliner is turned on; the inliner
    75  // will add the returned value to the hairiness budget.
    76  //
    77  // Background: with the new inliner, the score for a given callsite
    78  // can be adjusted down by some amount due to heuristics, however we
    79  // won't know whether this is going to happen until much later after
    80  // the CanInline call. This function returns the amount to relax the
    81  // budget initially (to allow for a large score adjustment); later on
    82  // in RevisitInlinability we'll look at each individual function to
    83  // demote it if needed.
    84  func BudgetExpansion(maxBudget int32) int32
    85  
    86  // DumpInlCallSiteScores is invoked by the inliner if the debug flag
    87  // "-d=dumpinlcallsitescores" is set; it dumps out a human-readable
    88  // summary of all (potentially) inlinable callsites in the package,
    89  // along with info on call site scoring and the adjustments made to a
    90  // given score. Here profile is the PGO profile in use (may be
    91  // nil), budgetCallback is a callback that can be invoked to find out
    92  // the original pre-adjustment hairiness limit for the function, and
    93  // inlineHotMaxBudget is the constant of the same name used in the
    94  // inliner. Sample output lines:
    95  //
    96  // Score  Adjustment  Status  Callee  CallerPos ScoreFlags
    97  // 115    40          DEMOTED cmd/compile/internal/abi.(*ABIParamAssignment).Offset     expand_calls.go:1679:14|6       panicPathAdj
    98  // 76     -5n         PROMOTED runtime.persistentalloc   mcheckmark.go:48:45|3   inLoopAdj
    99  // 201    0           --- PGO  unicode.DecodeRuneInString        utf8.go:312:30|1
   100  // 7      -5          --- PGO  internal/abi.Name.DataChecked     type.go:625:22|0        inLoopAdj
   101  //
   102  // In the dump above, "Score" is the final score calculated for the
   103  // callsite, "Adjustment" is the amount added to or subtracted from
   104  // the original hairiness estimate to form the score. "Status" shows
   105  // whether anything changed with the site -- did the adjustment bump
   106  // it down just below the threshold ("PROMOTED") or instead bump it
   107  // above the threshold ("DEMOTED"); this will be blank ("---") if no
   108  // threshold was crossed as a result of the heuristics. Note that
   109  // "Status" also shows whether PGO was involved. "Callee" is the name
   110  // of the function called, "CallerPos" is the position of the
   111  // callsite, and "ScoreFlags" is a digest of the specific properties
   112  // we used to make adjustments to callsite score via heuristics.
   113  func DumpInlCallSiteScores(profile *pgo.Profile, budgetCallback func(fn *ir.Func, profile *pgo.Profile) (int32, bool))