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))