Skip to content

Commit 0fd6ae5

Browse files
prattmicgopherbot
authored andcommitted
cmd/compile: escape package path for PGO symbol matching
Symbol names in the final executable apply escaping to the final component of a package path (main in example.com becomes example%2ecom.main). ir.PkgFuncName does not perform this escaping, meaning we'd fail to match functions that are escaped in the profile. Add ir.LinkFuncName which does perform escaping and use it for PGO. Fixes #59887. Change-Id: I10634d63d99d0a6fd2f72b929ab35ea227e1336f Reviewed-on: https://go-review.googlesource.com/c/go/+/490555 Reviewed-by: Cherry Mui <[email protected]> Auto-Submit: Michael Pratt <[email protected]> Run-TryBot: Michael Pratt <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 8b67cf0 commit 0fd6ae5

File tree

3 files changed

+35
-20
lines changed

3 files changed

+35
-20
lines changed

src/cmd/compile/internal/inline/inl.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ func pgoInlineEpilogue(p *pgo.Profile, decls []ir.Node) {
163163
if base.Debug.PGOInline >= 2 {
164164
ir.VisitFuncsBottomUp(decls, func(list []*ir.Func, recursive bool) {
165165
for _, f := range list {
166-
name := ir.PkgFuncName(f)
166+
name := ir.LinkFuncName(f)
167167
if n, ok := p.WeightedCG.IRNodes[name]; ok {
168168
p.RedirectEdges(n, inlinedCallSites)
169169
}
@@ -352,7 +352,7 @@ func CanInline(fn *ir.Func, profile *pgo.Profile) {
352352
// Update the budget for profile-guided inlining.
353353
budget := int32(inlineMaxBudget)
354354
if profile != nil {
355-
if n, ok := profile.WeightedCG.IRNodes[ir.PkgFuncName(fn)]; ok {
355+
if n, ok := profile.WeightedCG.IRNodes[ir.LinkFuncName(fn)]; ok {
356356
if _, ok := candHotCalleeMap[n]; ok {
357357
budget = int32(inlineHotMaxBudget)
358358
if base.Debug.PGOInline > 0 {

src/cmd/compile/internal/ir/func.go

+20-5
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"cmd/compile/internal/base"
99
"cmd/compile/internal/types"
1010
"cmd/internal/obj"
11+
"cmd/internal/objabi"
1112
"cmd/internal/src"
1213
"fmt"
1314
)
@@ -263,18 +264,20 @@ func (f *Func) SetWBPos(pos src.XPos) {
263264
}
264265
}
265266

266-
// FuncName returns the name (without the package) of the function n.
267+
// FuncName returns the name (without the package) of the function f.
267268
func FuncName(f *Func) string {
268269
if f == nil || f.Nname == nil {
269270
return "<nil>"
270271
}
271272
return f.Sym().Name
272273
}
273274

274-
// PkgFuncName returns the name of the function referenced by n, with package prepended.
275-
// This differs from the compiler's internal convention where local functions lack a package
276-
// because the ultimate consumer of this is a human looking at an IDE; package is only empty
277-
// if the compilation package is actually the empty string.
275+
// PkgFuncName returns the name of the function referenced by f, with package
276+
// prepended.
277+
//
278+
// This differs from the compiler's internal convention where local functions
279+
// lack a package. This is primarily useful when the ultimate consumer of this
280+
// is a human looking at message.
278281
func PkgFuncName(f *Func) string {
279282
if f == nil || f.Nname == nil {
280283
return "<nil>"
@@ -285,6 +288,18 @@ func PkgFuncName(f *Func) string {
285288
return pkg.Path + "." + s.Name
286289
}
287290

291+
// LinkFuncName returns the name of the function f, as it will appear in the
292+
// symbol table of the final linked binary.
293+
func LinkFuncName(f *Func) string {
294+
if f == nil || f.Nname == nil {
295+
return "<nil>"
296+
}
297+
s := f.Sym()
298+
pkg := s.Pkg
299+
300+
return objabi.PathToPrefix(pkg.Path) + "." + s.Name
301+
}
302+
288303
// IsEqOrHashFunc reports whether f is type eq/hash function.
289304
func IsEqOrHashFunc(f *Func) bool {
290305
if f == nil || f.Nname == nil {

src/cmd/compile/internal/pgo/irgraph.go

+13-13
Original file line numberDiff line numberDiff line change
@@ -270,7 +270,7 @@ func (p *Profile) VisitIR(fn *ir.Func) {
270270
if g.InEdges == nil {
271271
g.InEdges = make(map[*IRNode][]*IREdge)
272272
}
273-
name := ir.PkgFuncName(fn)
273+
name := ir.LinkFuncName(fn)
274274
node := new(IRNode)
275275
node.AST = fn
276276
if g.IRNodes[name] == nil {
@@ -308,7 +308,7 @@ func (p *Profile) addIREdge(caller *IRNode, callername string, call ir.Node, cal
308308
// Create an IRNode for the callee.
309309
calleenode := new(IRNode)
310310
calleenode.AST = callee
311-
calleename := ir.PkgFuncName(callee)
311+
calleename := ir.LinkFuncName(callee)
312312

313313
// Create key for NodeMapKey.
314314
nodeinfo := NodeMapKey{
@@ -395,7 +395,7 @@ func (p *Profile) PrintWeightedCallGraphDOT(edgeThreshold float64) {
395395
funcs := make(map[string]struct{})
396396
ir.VisitFuncsBottomUp(typecheck.Target.Decls, func(list []*ir.Func, recursive bool) {
397397
for _, f := range list {
398-
name := ir.PkgFuncName(f)
398+
name := ir.LinkFuncName(f)
399399
funcs[name] = struct{}{}
400400
}
401401
})
@@ -405,15 +405,15 @@ func (p *Profile) PrintWeightedCallGraphDOT(edgeThreshold float64) {
405405
for name := range funcs {
406406
if n, ok := p.WeightedCG.IRNodes[name]; ok {
407407
for _, e := range p.WeightedCG.OutEdges[n] {
408-
if _, ok := nodes[ir.PkgFuncName(e.Src.AST)]; !ok {
409-
nodes[ir.PkgFuncName(e.Src.AST)] = e.Src.AST
408+
if _, ok := nodes[ir.LinkFuncName(e.Src.AST)]; !ok {
409+
nodes[ir.LinkFuncName(e.Src.AST)] = e.Src.AST
410410
}
411-
if _, ok := nodes[ir.PkgFuncName(e.Dst.AST)]; !ok {
412-
nodes[ir.PkgFuncName(e.Dst.AST)] = e.Dst.AST
411+
if _, ok := nodes[ir.LinkFuncName(e.Dst.AST)]; !ok {
412+
nodes[ir.LinkFuncName(e.Dst.AST)] = e.Dst.AST
413413
}
414414
}
415-
if _, ok := nodes[ir.PkgFuncName(n.AST)]; !ok {
416-
nodes[ir.PkgFuncName(n.AST)] = n.AST
415+
if _, ok := nodes[ir.LinkFuncName(n.AST)]; !ok {
416+
nodes[ir.LinkFuncName(n.AST)] = n.AST
417417
}
418418
}
419419
}
@@ -424,16 +424,16 @@ func (p *Profile) PrintWeightedCallGraphDOT(edgeThreshold float64) {
424424
nodeweight := WeightInPercentage(n.Flat, p.TotalNodeWeight)
425425
color := "black"
426426
if ast.Inl != nil {
427-
fmt.Printf("\"%v\" [color=%v,label=\"%v,freq=%.2f,inl_cost=%d\"];\n", ir.PkgFuncName(ast), color, ir.PkgFuncName(ast), nodeweight, ast.Inl.Cost)
427+
fmt.Printf("\"%v\" [color=%v,label=\"%v,freq=%.2f,inl_cost=%d\"];\n", ir.LinkFuncName(ast), color, ir.LinkFuncName(ast), nodeweight, ast.Inl.Cost)
428428
} else {
429-
fmt.Printf("\"%v\" [color=%v, label=\"%v,freq=%.2f\"];\n", ir.PkgFuncName(ast), color, ir.PkgFuncName(ast), nodeweight)
429+
fmt.Printf("\"%v\" [color=%v, label=\"%v,freq=%.2f\"];\n", ir.LinkFuncName(ast), color, ir.LinkFuncName(ast), nodeweight)
430430
}
431431
}
432432
}
433433
// Print edges.
434434
ir.VisitFuncsBottomUp(typecheck.Target.Decls, func(list []*ir.Func, recursive bool) {
435435
for _, f := range list {
436-
name := ir.PkgFuncName(f)
436+
name := ir.LinkFuncName(f)
437437
if n, ok := p.WeightedCG.IRNodes[name]; ok {
438438
for _, e := range p.WeightedCG.OutEdges[n] {
439439
edgepercent := WeightInPercentage(e.Weight, p.TotalEdgeWeight)
@@ -443,7 +443,7 @@ func (p *Profile) PrintWeightedCallGraphDOT(edgeThreshold float64) {
443443
fmt.Printf("edge [color=black, style=solid];\n")
444444
}
445445

446-
fmt.Printf("\"%v\" -> \"%v\" [label=\"%.2f\"];\n", ir.PkgFuncName(n.AST), ir.PkgFuncName(e.Dst.AST), edgepercent)
446+
fmt.Printf("\"%v\" -> \"%v\" [label=\"%.2f\"];\n", ir.LinkFuncName(n.AST), ir.LinkFuncName(e.Dst.AST), edgepercent)
447447
}
448448
}
449449
}

0 commit comments

Comments
 (0)