mirror of
https://github.com/golang/go
synced 2024-10-04 15:09:59 +00:00
cmd/compile: use HaveInlineBody for unified IR
In go.dev/cl/419674 I added a mechanism to the inliner to allow inlining to fail gracefully when a function body is missing, but I missed we already have a mechanism for that: typecheck.HaveInlineBody. This CL makes it overridable so that unified IR can plug in its appropriate logic, like it does with the logic for building the ir.InlinedCallExpr node. While here, rename inline.NewInline to inline.InlineCall, because the name "NewInline" is now a misnomer since we initialize it to oldInline (now named oldInlineCall). Change-Id: I4e65618d3725919f69e6f43cf409699d20fb797c Reviewed-on: https://go-review.googlesource.com/c/go/+/427234 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com> Run-TryBot: Matthew Dempsky <mdempsky@google.com> Auto-Submit: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
33a7e5a4b4
commit
e4b624eae5
|
@ -689,9 +689,9 @@ var inlgen int
|
||||||
// when producing output for debugging the compiler itself.
|
// when producing output for debugging the compiler itself.
|
||||||
var SSADumpInline = func(*ir.Func) {}
|
var SSADumpInline = func(*ir.Func) {}
|
||||||
|
|
||||||
// NewInline allows the inliner implementation to be overridden.
|
// InlineCall allows the inliner implementation to be overridden.
|
||||||
// If it returns nil, the function will not be inlined.
|
// If it returns nil, the function will not be inlined.
|
||||||
var NewInline = oldInline
|
var InlineCall = oldInlineCall
|
||||||
|
|
||||||
// If n is a OCALLFUNC node, and fn is an ONAME node for a
|
// If n is a OCALLFUNC node, and fn is an ONAME node for a
|
||||||
// function with an inlinable body, return an OINLCALL node that can replace n.
|
// function with an inlinable body, return an OINLCALL node that can replace n.
|
||||||
|
@ -817,9 +817,9 @@ func mkinlcall(n *ir.CallExpr, fn *ir.Func, maxCost int32, inlCalls *[]*ir.Inlin
|
||||||
fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n)
|
fmt.Printf("%v: Before inlining: %+v\n", ir.Line(n), n)
|
||||||
}
|
}
|
||||||
|
|
||||||
res := NewInline(n, fn, inlIndex)
|
res := InlineCall(n, fn, inlIndex)
|
||||||
if res == nil {
|
if res == nil {
|
||||||
return n
|
base.FatalfAt(n.Pos(), "inlining call to %v failed", fn)
|
||||||
}
|
}
|
||||||
|
|
||||||
if base.Flag.LowerM > 2 {
|
if base.Flag.LowerM > 2 {
|
||||||
|
@ -855,11 +855,11 @@ func CalleeEffects(init *ir.Nodes, callee ir.Node) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// oldInline creates an InlinedCallExpr to replace the given call
|
// oldInlineCall creates an InlinedCallExpr to replace the given call
|
||||||
// expression. fn is the callee function to be inlined. inlIndex is
|
// expression. fn is the callee function to be inlined. inlIndex is
|
||||||
// the inlining tree position index, for use with src.NewInliningBase
|
// the inlining tree position index, for use with src.NewInliningBase
|
||||||
// when rewriting positions.
|
// when rewriting positions.
|
||||||
func oldInline(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
|
func oldInlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
|
||||||
if base.Debug.TypecheckInl == 0 {
|
if base.Debug.TypecheckInl == 0 {
|
||||||
typecheck.ImportedBody(fn)
|
typecheck.ImportedBody(fn)
|
||||||
}
|
}
|
||||||
|
|
|
@ -3374,22 +3374,28 @@ func (r *reader) pkgObjs(target *ir.Package) []*ir.Name {
|
||||||
|
|
||||||
// @@@ Inlining
|
// @@@ Inlining
|
||||||
|
|
||||||
|
// unifiedHaveInlineBody reports whether we have the function body for
|
||||||
|
// fn, so we can inline it.
|
||||||
|
func unifiedHaveInlineBody(fn *ir.Func) bool {
|
||||||
|
if fn.Inl == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
_, ok := bodyReaderFor(fn)
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
var inlgen = 0
|
var inlgen = 0
|
||||||
|
|
||||||
// InlineCall implements inline.NewInline by re-reading the function
|
// unifiedInlineCall implements inline.NewInline by re-reading the function
|
||||||
// body from its Unified IR export data.
|
// body from its Unified IR export data.
|
||||||
func InlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
|
func unifiedInlineCall(call *ir.CallExpr, fn *ir.Func, inlIndex int) *ir.InlinedCallExpr {
|
||||||
// TODO(mdempsky): Turn callerfn into an explicit parameter.
|
// TODO(mdempsky): Turn callerfn into an explicit parameter.
|
||||||
callerfn := ir.CurFunc
|
callerfn := ir.CurFunc
|
||||||
|
|
||||||
pri, ok := bodyReaderFor(fn)
|
pri, ok := bodyReaderFor(fn)
|
||||||
if !ok {
|
if !ok {
|
||||||
// TODO(mdempsky): Reconsider this diagnostic's wording, if it's
|
base.FatalfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
|
||||||
// to be included in Go 1.20.
|
|
||||||
if base.Flag.LowerM != 0 {
|
|
||||||
base.WarnfAt(call.Pos(), "cannot inline call to %v: missing inline body", fn)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if fn.Inl.Body == nil {
|
if fn.Inl.Body == nil {
|
||||||
|
|
|
@ -69,7 +69,8 @@ var localPkgReader *pkgReader
|
||||||
// In other words, we have all the necessary information to build the generic IR form
|
// In other words, we have all the necessary information to build the generic IR form
|
||||||
// (see writer.captureVars for an example).
|
// (see writer.captureVars for an example).
|
||||||
func unified(noders []*noder) {
|
func unified(noders []*noder) {
|
||||||
inline.NewInline = InlineCall
|
inline.InlineCall = unifiedInlineCall
|
||||||
|
typecheck.HaveInlineBody = unifiedHaveInlineBody
|
||||||
|
|
||||||
data := writePkgStub(noders)
|
data := writePkgStub(noders)
|
||||||
|
|
||||||
|
|
|
@ -83,17 +83,14 @@ func ImportBody(fn *ir.Func) {
|
||||||
|
|
||||||
// HaveInlineBody reports whether we have fn's inline body available
|
// HaveInlineBody reports whether we have fn's inline body available
|
||||||
// for inlining.
|
// for inlining.
|
||||||
func HaveInlineBody(fn *ir.Func) bool {
|
//
|
||||||
|
// It's a function literal so that it can be overriden for
|
||||||
|
// GOEXPERIMENT=unified.
|
||||||
|
var HaveInlineBody = func(fn *ir.Func) bool {
|
||||||
if fn.Inl == nil {
|
if fn.Inl == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unified IR is much more conservative about pruning unreachable
|
|
||||||
// methods (at the cost of increased build artifact size).
|
|
||||||
if base.Debug.Unified != 0 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
if fn.Inl.Body != nil {
|
if fn.Inl.Body != nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue