Commit 4d0ed149 authored by David Chase's avatar David Chase

cmd/compile: enable optimizer logging for inline-related events

Change-Id: I72de8cb5e1df7a73e46a4b7e5b4e7290fcca4bc1
Reviewed-on: https://go-review.googlesource.com/c/go/+/204162
Run-TryBot: David Chase <drchase@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarCherry Zhang <cherryyz@google.com>
parent 405a2f21
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
package gc package gc
import ( import (
"cmd/compile/internal/logopt"
"cmd/compile/internal/types" "cmd/compile/internal/types"
"cmd/internal/obj" "cmd/internal/obj"
"cmd/internal/src" "cmd/internal/src"
...@@ -115,10 +116,15 @@ func caninl(fn *Node) { ...@@ -115,10 +116,15 @@ func caninl(fn *Node) {
} }
var reason string // reason, if any, that the function was not inlined var reason string // reason, if any, that the function was not inlined
if Debug['m'] > 1 { if Debug['m'] > 1 || logopt.Enabled() {
defer func() { defer func() {
if reason != "" { if reason != "" {
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason) if Debug['m'] > 1 {
fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason)
}
if logopt.Enabled() {
logopt.LogOpt(fn.Pos, "cannotInlineFunction", "inline", fn.funcname(), reason)
}
} }
}() }()
} }
...@@ -223,6 +229,9 @@ func caninl(fn *Node) { ...@@ -223,6 +229,9 @@ func caninl(fn *Node) {
} else if Debug['m'] != 0 { } else if Debug['m'] != 0 {
fmt.Printf("%v: can inline %v\n", fn.Line(), n) fmt.Printf("%v: can inline %v\n", fn.Line(), n)
} }
if logopt.Enabled() {
logopt.LogOpt(fn.Pos, "canInlineFunction", "inline", fn.funcname(), fmt.Sprintf("cost: %d", inlineMaxBudget-visitor.budget))
}
} }
// inlFlood marks n's inline body for export and recursively ensures // inlFlood marks n's inline body for export and recursively ensures
...@@ -412,7 +421,7 @@ func (v *hairyVisitor) visit(n *Node) bool { ...@@ -412,7 +421,7 @@ func (v *hairyVisitor) visit(n *Node) bool {
v.budget-- v.budget--
// When debugging, don't stop early, to get full cost of inlining this function // When debugging, don't stop early, to get full cost of inlining this function
if v.budget < 0 && Debug['m'] < 2 { if v.budget < 0 && Debug['m'] < 2 && !logopt.Enabled() {
return true return true
} }
...@@ -826,11 +835,18 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node { ...@@ -826,11 +835,18 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
if fn.Func.Inl.Cost > maxCost { if fn.Func.Inl.Cost > maxCost {
// The inlined function body is too big. Typically we use this check to restrict // The inlined function body is too big. Typically we use this check to restrict
// inlining into very big functions. See issue 26546 and 17566. // inlining into very big functions. See issue 26546 and 17566.
if logopt.Enabled() {
logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", Curfn.funcname(),
fmt.Sprintf("cost %d of %s exceeds max large caller cost %d", fn.Func.Inl.Cost, fn.pkgFuncName(), maxCost))
}
return n return n
} }
if fn == Curfn || fn.Name.Defn == Curfn { if fn == Curfn || fn.Name.Defn == Curfn {
// Can't recursively inline a function into itself. // Can't recursively inline a function into itself.
if logopt.Enabled() {
logopt.LogOpt(n.Pos, "cannotInlineCall", "inline", fmt.Sprintf("recursive call to %s", Curfn.funcname()))
}
return n return n
} }
...@@ -857,6 +873,9 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node { ...@@ -857,6 +873,9 @@ func mkinlcall(n, fn *Node, maxCost int32) *Node {
if Debug['m'] > 2 { if Debug['m'] > 2 {
fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n) fmt.Printf("%v: Before inlining: %+v\n", n.Line(), n)
} }
if logopt.Enabled() {
logopt.LogOpt(n.Pos, "inlineCall", "inline", Curfn.funcname(), fn.pkgFuncName())
}
if ssaDump != "" && ssaDump == Curfn.funcname() { if ssaDump != "" && ssaDump == Curfn.funcname() {
ssaDumpInlined = append(ssaDumpInlined, fn) ssaDumpInlined = append(ssaDumpInlined, fn)
......
...@@ -269,6 +269,35 @@ func (n *Node) funcname() string { ...@@ -269,6 +269,35 @@ func (n *Node) funcname() string {
return n.Func.Nname.Sym.Name return n.Func.Nname.Sym.Name
} }
// pkgFuncName returns the name of the function referenced by n, with package prepended.
// This differs from the compiler's internal convention where local functions lack a package
// because the ultimate consumer of this is a human looking at an IDE; package is only empty
// if the compilation package is actually the empty string.
func (n *Node) pkgFuncName() string {
var s *types.Sym
if n == nil {
return "<nil>"
}
if n.Op == ONAME {
s = n.Sym
} else {
if n.Func == nil || n.Func.Nname == nil {
return "<nil>"
}
s = n.Func.Nname.Sym
}
pkg := s.Pkg
p := myimportpath
if pkg != nil && pkg.Path != "" {
p = pkg.Path
}
if p == "" {
return s.Name
}
return p + "." + s.Name
}
// Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL). // Name holds Node fields used only by named nodes (ONAME, OTYPE, OPACK, OLABEL, some OLITERAL).
type Name struct { type Name struct {
Pack *Node // real package for import . names Pack *Node // real package for import . names
......
...@@ -106,6 +106,9 @@ func TestLogOpt(t *testing.T) { ...@@ -106,6 +106,9 @@ func TestLogOpt(t *testing.T) {
// below shows proper inlining and nilcheck // below shows proper inlining and nilcheck
want(t, slogged, `{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}},"severity":3,"code":"nilcheck","source":"go compiler","message":"","relatedInformation":[{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"}]}`) want(t, slogged, `{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}},"severity":3,"code":"nilcheck","source":"go compiler","message":"","relatedInformation":[{"location":{"uri":"file://tmpdir/file.go","range":{"start":{"line":4,"character":11},"end":{"line":4,"character":11}}},"message":"inlineLoc"}]}`)
want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`) want(t, slogged, `{"range":{"start":{"line":11,"character":6},"end":{"line":11,"character":6}},"severity":3,"code":"isInBounds","source":"go compiler","message":""}`)
want(t, slogged, `{"range":{"start":{"line":7,"character":6},"end":{"line":7,"character":6}},"severity":3,"code":"canInlineFunction","source":"go compiler","message":"cost: 35"}`)
want(t, slogged, `{"range":{"start":{"line":9,"character":13},"end":{"line":9,"character":13}},"severity":3,"code":"inlineCall","source":"go compiler","message":"x.bar"}`)
want(t, slogged, `{"range":{"start":{"line":8,"character":9},"end":{"line":8,"character":9}},"severity":3,"code":"inlineCall","source":"go compiler","message":"x.bar"}`)
}) })
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment