@@ -44,8 +44,8 @@ import (
44
44
45
45
// Inlining budget parameters, gathered in one place
46
46
const (
47
- inlineMaxBudget = 80
48
- inlineExtraAppendCost = 0
47
+ inlineMaxBudget = 80
48
+ inlineExtraAppendCost = 0
49
49
// default is to inline if there's at most one call. -l=4 overrides this by using 1 instead.
50
50
inlineExtraCallCost = 57 // 57 was benchmarked to provided most benefit with no bad surprises; see https://github.com/golang/go/issues/19348#issuecomment-439370742
51
51
inlineExtraPanicCost = 1 // do not penalize inlining panics.
73
73
inlineHotCalleeMaxBudget int32 = 160
74
74
)
75
75
76
- // weightInPercentage converts profile weights to a percentage.
77
- func weightInPercentage (value int64 , total int64 ) float64 {
78
- var ratio float64
79
- // percentage is computed at the (weight/totalweights) * 100
80
- // e.g. if edge weight is 30 and the sum of all the edges weight is 126
81
- // the percentage will be 23.8%
82
- if total != 0 {
83
- ratio = (float64 (value ) / float64 (total )) * 100
84
- }
85
- return ratio
86
- }
87
-
88
76
// InlinePrologue records the hot callsites from ir-graph.
89
77
func InlinePrologue () {
90
78
if s , err := strconv .ParseFloat (base .Flag .InlineHotThreshold , 64 ); err == nil {
@@ -102,32 +90,37 @@ func InlinePrologue() {
102
90
for _ , f := range list {
103
91
name := ir .PkgFuncName (f )
104
92
if n , ok := pgo .WeightedCG .IRNodes [name ]; ok {
105
- nodeweight := weightInPercentage (n .Flat , pgo .GlobalTotalNodeWeight )
106
-
93
+ nodeweight := pgo .WeightInPercentage (n .Flat , pgo .GlobalTotalNodeWeight )
94
+ if nodeweight > inlineHotThresholdPercent {
95
+ n .HotNode = true
96
+ if base .Flag .LowerM > 1 {
97
+ fmt .Printf ("hot-node=%v\n " , name )
98
+ }
99
+ }
107
100
for _ , e := range pgo .WeightedCG .OutEdges [n ] {
108
101
if e .Weight != 0 {
109
- weightpercent := weightInPercentage (e .Weight , pgo .GlobalTotalEdgeWeight )
102
+ weightpercent := pgo . WeightInPercentage (e .Weight , pgo .GlobalTotalEdgeWeight )
110
103
if weightpercent > inlineHotThresholdPercent {
111
104
splits := strings .Split (e .CallSite , ":" )
112
105
line2 , _ := strconv .ParseInt (splits [len (splits )- 2 ], 0 , 64 )
113
106
lineno := fmt .Sprintf ("%v" , line2 )
114
107
canonicalName := ir .PkgFuncName (n .AST ) + "-" + lineno + "-" + ir .PkgFuncName (e .Dst .AST )
115
- candHotEdgeMap [canonicalName ] = struct {}{}
116
- if base .Flag .LowerM != 0 {
117
- fmt .Printf ("hot-inline cand=%v\n " , canonicalName )
108
+ if _ , ok := candHotEdgeMap [canonicalName ]; ! ok {
109
+ candHotEdgeMap [canonicalName ] = struct {}{}
110
+ if base .Flag .LowerM > 1 {
111
+ fmt .Printf ("hot-inline cand=%v\n " , canonicalName )
112
+ }
118
113
}
119
114
}
120
115
}
121
116
}
122
- if nodeweight > inlineHotThresholdPercent {
123
- n .HotNode = true
124
- if base .Flag .LowerM != 0 {
125
- fmt .Printf ("hot-node=%v\n " , name )
126
- }
127
- }
128
117
}
129
118
}
130
119
})
120
+ if base .Flag .LowerM > 1 {
121
+ fmt .Printf ("hot-cg before inline in dot:" )
122
+ pgo .PrintWeightedCallGraphDOT (inlineHotThresholdPercent )
123
+ }
131
124
}
132
125
133
126
// InlineEpilogue updates IRGraph after inlining.
@@ -140,6 +133,10 @@ func InlineEpilogue() {
140
133
}
141
134
}
142
135
})
136
+ if base .Flag .LowerM > 1 {
137
+ fmt .Printf ("hot-cg after inline in dot:" )
138
+ pgo .PrintWeightedCallGraphDOT (inlineHotThresholdPercent )
139
+ }
143
140
}
144
141
145
142
// InlinePackage finds functions that can be inlined and clones them before walk expands them.
@@ -349,19 +346,15 @@ func (v *hairyVisitor) tooHairy(fn *ir.Func) bool {
349
346
}
350
347
if v .budget < 0 {
351
348
if pgo .WeightedCG != nil {
352
- // If the cost of hot function is greater than inlineHotCalleeMaxBudget,
353
- // the inliner won't inline this function.
354
- if inlineMaxBudget - v .budget < inlineHotCalleeMaxBudget {
355
- // In some cases, there is no hot calling edges in the function.
356
- // However, if the function is hot function, it is still inline
357
- // candidate.
358
- if n , ok := pgo .WeightedCG .IRNodes [ir .PkgFuncName (fn )]; ok {
359
- if n .HotNode == true {
360
- if base .Flag .LowerM != 0 {
361
- fmt .Printf ("hot-node enabled increased budget for func=%v\n " , ir .PkgFuncName (fn ))
362
- }
363
- return false
349
+ // Find the existing node in IRGraph.
350
+ if n , ok := pgo .WeightedCG .IRNodes [ir .PkgFuncName (fn )]; ok {
351
+ // If the cost of hot function is greater than inlineHotCalleeMaxBudget,
352
+ // the inliner won't inline this function.
353
+ if inlineMaxBudget - v .budget < inlineHotCalleeMaxBudget && n .HotNode == true {
354
+ if base .Flag .LowerM > 1 {
355
+ fmt .Printf ("hot-node enabled increased budget for func=%v\n " , ir .PkgFuncName (fn ))
364
356
}
357
+ return false
365
358
}
366
359
}
367
360
}
@@ -437,6 +430,9 @@ func (v *hairyVisitor) doNode(n ir.Node) bool {
437
430
linenum := fmt .Sprintf ("%v" , l )
438
431
canonicalName := ir .PkgFuncName (ir .CurFunc ) + "-" + linenum + "-" + ir .PkgFuncName (fn )
439
432
if _ , o := candHotEdgeMap [canonicalName ]; o {
433
+ if base .Flag .LowerM > 1 {
434
+ fmt .Printf ("hot-callsite identified at line=%v for func=%v\n " , ir .Line (n ), ir .PkgFuncName (ir .CurFunc ))
435
+ }
440
436
listOfHotCallSites [pgo.CallSiteInfo {ir .Line (n ), ir .CurFunc }] = struct {}{}
441
437
}
442
438
}
@@ -848,9 +844,13 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlCalls *[]*ir.Inlin
848
844
849
845
// If the callsite is hot and it is under the inlineHotCalleeMaxBudget budget, then inline it, or else bail.
850
846
if _ , ok := listOfHotCallSites [pgo.CallSiteInfo {ir .Line (n ), ir .CurFunc }]; ok {
847
+
851
848
if fn .Inl .Cost > inlineHotCalleeMaxBudget {
852
849
return n
853
850
}
851
+ if base .Flag .LowerM > 1 {
852
+ fmt .Printf ("hot-budget check allows inlining at %v\n " , ir .Line (n ))
853
+ }
854
854
} else {
855
855
return n
856
856
}
0 commit comments