Functions
ProfileGuided
function
#
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)
StaticCall
function
#
StaticCall devirtualizes the given call if possible when the concrete callee
is available statically.
func StaticCall(call *ir.CallExpr)
condCall
function
#
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 *ir.CallExpr, elseCall *ir.CallExpr, init ir.Nodes) *ir.InlinedCallExpr
constructCallStat
function
#
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
function
#
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)
findHotConcreteCallee
function
#
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)
findHotConcreteFunctionCallee
function
#
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)
findHotConcreteInterfaceCallee
function
#
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)
interfaceCallRecvTypeAndMethod
function
#
interfaceCallRecvTypeAndMethod returns the type and the method of the interface
used in an interface call.
func interfaceCallRecvTypeAndMethod(call *ir.CallExpr) (*types.Type, *types.Sym)
maybeDevirtualizeFunctionCall
function
#
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)
maybeDevirtualizeInterfaceCall
function
#
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)
methodRecvType
function
#
methodRecvType returns the type containing method fn. Returns nil if fn
is not a method.
func methodRecvType(fn *ir.Func) *types.Type
retTemps
function
#
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
rewriteFunctionCall
function
#
rewriteFunctionCall devirtualizes the given OCALLFUNC using a direct
function call to callee.
func rewriteFunctionCall(call *ir.CallExpr, curfn *ir.Func, callee *ir.Func) ir.Node
rewriteInterfaceCall
function
#
rewriteInterfaceCall devirtualizes the given interface call using a direct
method call to concretetyp.
func rewriteInterfaceCall(call *ir.CallExpr, curfn *ir.Func, callee *ir.Func, concretetyp *types.Type) ir.Node
shouldPGODevirt
function
#
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