type CallStat … // ProfileGuided performs call devirtualization of indirect calls based on // profile information. // // Specifically, it performs conditional devirtualization of interface calls or // function value calls for the hottest callee. // // That is, for interface calls it performs a transformation like: // // type Iface interface { // Foo() // } // // type Concrete struct{} // // func (Concrete) Foo() {} // // func foo(i Iface) { // i.Foo() // } // // to: // // func foo(i Iface) { // if c, ok := i.(Concrete); ok { // c.Foo() // } else { // i.Foo() // } // } // // For function value calls it performs a transformation like: // // func Concrete() {} // // func foo(fn func()) { // fn() // } // // to: // // func foo(fn func()) { // if internal/abi.FuncPCABIInternal(fn) == internal/abi.FuncPCABIInternal(Concrete) { // Concrete() // } else { // fn() // } // } // // The primary benefit of this transformation is enabling inlining of the // direct call. func ProfileGuided(fn *ir.Func, p *pgoir.Profile) { … } // Devirtualize interface call if possible and eligible. Returns the new // ir.Node if call was devirtualized, and if so also the callee and weight of // the devirtualized edge. func maybeDevirtualizeInterfaceCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallExpr) (ir.Node, *ir.Func, int64) { … } // Devirtualize an indirect function call if possible and eligible. Returns the new // ir.Node if call was devirtualized, and if so also the callee and weight of // the devirtualized edge. func maybeDevirtualizeFunctionCall(p *pgoir.Profile, fn *ir.Func, call *ir.CallExpr) (ir.Node, *ir.Func, int64) { … } // shouldPGODevirt checks if we should perform PGO devirtualization to the // target function. // // PGO devirtualization is most valuable when the callee is inlined, so if it // won't inline we can skip devirtualizing. func shouldPGODevirt(fn *ir.Func) bool { … } // constructCallStat builds an initial CallStat describing this call, for // logging. If the call is devirtualized, the devirtualization fields should be // updated. func constructCallStat(p *pgoir.Profile, fn *ir.Func, name string, call *ir.CallExpr) *CallStat { … } // copyInputs copies the inputs to a call: the receiver (for interface calls) // or function value (for function value calls) and the arguments. These // expressions are evaluated once and assigned to temporaries. // // The assignment statement is added to init and the copied receiver/fn // expression and copied arguments expressions are returned. func copyInputs(curfn *ir.Func, pos src.XPos, recvOrFn ir.Node, args []ir.Node, init *ir.Nodes) (ir.Node, []ir.Node) { … } // retTemps returns a slice of temporaries to be used for storing result values from call. func retTemps(curfn *ir.Func, pos src.XPos, call *ir.CallExpr) []ir.Node { … } // condCall returns an ir.InlinedCallExpr that performs a call to thenCall if // cond is true and elseCall if cond is false. The return variables of the // InlinedCallExpr evaluate to the return values from the call. func condCall(curfn *ir.Func, pos src.XPos, cond ir.Node, thenCall, elseCall *ir.CallExpr, init ir.Nodes) *ir.InlinedCallExpr { … } // rewriteInterfaceCall devirtualizes the given interface call using a direct // method call to concretetyp. func rewriteInterfaceCall(call *ir.CallExpr, curfn, callee *ir.Func, concretetyp *types.Type) ir.Node { … } // rewriteFunctionCall devirtualizes the given OCALLFUNC using a direct // function call to callee. func rewriteFunctionCall(call *ir.CallExpr, curfn, callee *ir.Func) ir.Node { … } // methodRecvType returns the type containing method fn. Returns nil if fn // is not a method. func methodRecvType(fn *ir.Func) *types.Type { … } // interfaceCallRecvTypeAndMethod returns the type and the method of the interface // used in an interface call. func interfaceCallRecvTypeAndMethod(call *ir.CallExpr) (*types.Type, *types.Sym) { … } // findHotConcreteCallee returns the *ir.Func of the hottest callee of a call, // if available, and its edge weight. extraFn can perform additional // applicability checks on each candidate edge. If extraFn returns false, // candidate will not be considered a valid callee candidate. func findHotConcreteCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr, extraFn func(callerName string, callOffset int, candidate *pgoir.IREdge) bool) (*ir.Func, int64) { … } // findHotConcreteInterfaceCallee returns the *ir.Func of the hottest callee of an // interface call, if available, and its edge weight. func findHotConcreteInterfaceCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr) (*ir.Func, int64) { … } // findHotConcreteFunctionCallee returns the *ir.Func of the hottest callee of an // indirect function call, if available, and its edge weight. func findHotConcreteFunctionCallee(p *pgoir.Profile, caller *ir.Func, call *ir.CallExpr) (*ir.Func, int64) { … }