From e4cae432d6185b75d45fcf0c3f9c6d49591c128a Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Tue, 3 May 2016 17:21:32 -0700 Subject: [PATCH] cmd/compile: add inline explainer When compiling with -m -m, this adds output for every non-inlined function explaining why it was not inlined. Change-Id: Icb59ae912a835c996e6b3475b163ee5125113001 Reviewed-on: https://go-review.googlesource.com/22782 Run-TryBot: Josh Bleecher Snyder Reviewed-by: Brad Fitzpatrick TryBot-Result: Gobot Gobot --- src/cmd/compile/internal/gc/inl.go | 33 ++++++++++++++++++++++++----- src/cmd/compile/internal/gc/main.go | 4 ++++ 2 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/cmd/compile/internal/gc/inl.go b/src/cmd/compile/internal/gc/inl.go index 9c346fbedf..d45186aa51 100644 --- a/src/cmd/compile/internal/gc/inl.go +++ b/src/cmd/compile/internal/gc/inl.go @@ -92,13 +92,24 @@ func caninl(fn *Node) { Fatalf("caninl no nname %v", Nconv(fn, FmtSign)) } + var reason string // reason, if any, that the function was not inlined + if Debug['m'] > 1 { + defer func() { + if reason != "" { + fmt.Printf("%v: cannot inline %v: %s\n", fn.Line(), fn.Func.Nname, reason) + } + }() + } + // If marked "go:noinline", don't inline if fn.Func.Pragma&Noinline != 0 { + reason = "marked go:noinline" return } // If fn has no body (is defined outside of Go), cannot inline it. if fn.Nbody.Len() == 0 { + reason = "no function body" return } @@ -111,6 +122,7 @@ func caninl(fn *Node) { f := fn.Type.Params().Fields() if len := f.Len(); len > 0 { if t := f.Index(len - 1); t.Isddd { + reason = "has ... args" return } } @@ -123,12 +135,17 @@ func caninl(fn *Node) { // The example that we observed is inlining of LockOSThread, // which lead to false race reports on m contents. if instrumenting && myimportpath == "runtime" { + reason = "instrumenting and is runtime function" return } const maxBudget = 80 budget := int32(maxBudget) // allowed hairyness - if ishairylist(fn.Nbody, &budget) || budget < 0 { + if ishairylist(fn.Nbody, &budget, &reason) { + return + } + if budget < 0 { + reason = "function too complex" return } @@ -157,16 +174,16 @@ func caninl(fn *Node) { } // Look for anything we want to punt on. -func ishairylist(ll Nodes, budget *int32) bool { +func ishairylist(ll Nodes, budget *int32, reason *string) bool { for _, n := range ll.Slice() { - if ishairy(n, budget) { + if ishairy(n, budget, reason) { return true } } return false } -func ishairy(n *Node, budget *int32) bool { +func ishairy(n *Node, budget *int32, reason *string) bool { if n == nil { return false } @@ -186,6 +203,7 @@ func ishairy(n *Node, budget *int32) bool { } } if Debug['l'] < 4 { + *reason = "non-leaf function" return true } @@ -203,12 +221,14 @@ func ishairy(n *Node, budget *int32) bool { break } if Debug['l'] < 4 { + *reason = "non-leaf method" return true } // Things that are too hairy, irrespective of the budget case OCALL, OCALLINTER, OPANIC, ORECOVER: if Debug['l'] < 4 { + *reason = "non-leaf op " + n.Op.String() return true } @@ -223,12 +243,15 @@ func ishairy(n *Node, budget *int32) bool { ODCLTYPE, // can't print yet OBREAK, ORETJMP: + *reason = "unhandled op " + n.Op.String() return true } (*budget)-- - return *budget < 0 || ishairy(n.Left, budget) || ishairy(n.Right, budget) || ishairylist(n.List, budget) || ishairylist(n.Rlist, budget) || ishairylist(n.Ninit, budget) || ishairylist(n.Nbody, budget) + return *budget < 0 || ishairy(n.Left, budget, reason) || ishairy(n.Right, budget, reason) || + ishairylist(n.List, budget, reason) || ishairylist(n.Rlist, budget, reason) || + ishairylist(n.Ninit, budget, reason) || ishairylist(n.Nbody, budget, reason) } // Inlcopy and inlcopylist recursively copy the body of a function. diff --git a/src/cmd/compile/internal/gc/main.go b/src/cmd/compile/internal/gc/main.go index eeadc7e73e..76bfdff4aa 100644 --- a/src/cmd/compile/internal/gc/main.go +++ b/src/cmd/compile/internal/gc/main.go @@ -440,6 +440,10 @@ func Main() { for _, n := range list { if !recursive { caninl(n) + } else { + if Debug['m'] > 1 { + fmt.Printf("%v: cannot inline %v: recursive\n", n.Line(), n.Func.Nname) + } } inlcalls(n) } -- 2.48.1