mirror of https://github.com/golang/go.git
[dev.regabi] cmd/compile: split out package inline [generated]
[git-generate] cd src/cmd/compile/internal/gc rf ' mv numNonClosures inl.go mv inlFlood Inline_Flood mv inlcalls InlineCalls mv devirtualize Devirtualize mv caninl CanInline mv inl.go cmd/compile/internal/inline ' Change-Id: Iee1f5b1e82d5cea6be4ecd91e6920500810f21de Reviewed-on: https://go-review.googlesource.com/c/go/+/279309 Trust: Russ Cox <rsc@golang.org> Run-TryBot: Russ Cox <rsc@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
parent
0256ba99a8
commit
575fd6ff0a
|
|
@ -6,6 +6,7 @@ package gc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
|
"cmd/compile/internal/inline"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/typecheck"
|
"cmd/compile/internal/typecheck"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
|
|
@ -83,7 +84,7 @@ func (p *exporter) markObject(n ir.Node) {
|
||||||
if n.Op() == ir.ONAME {
|
if n.Op() == ir.ONAME {
|
||||||
n := n.(*ir.Name)
|
n := n.(*ir.Name)
|
||||||
if n.Class_ == ir.PFUNC {
|
if n.Class_ == ir.PFUNC {
|
||||||
inlFlood(n, typecheck.Export)
|
inline.Inline_Flood(n, typecheck.Export)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
|
"cmd/compile/internal/inline"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/logopt"
|
"cmd/compile/internal/logopt"
|
||||||
"cmd/compile/internal/ssa"
|
"cmd/compile/internal/ssa"
|
||||||
|
|
@ -184,7 +185,7 @@ func Main(archInit func(*Arch)) {
|
||||||
|
|
||||||
ir.EscFmt = escFmt
|
ir.EscFmt = escFmt
|
||||||
ir.IsIntrinsicCall = isIntrinsicCall
|
ir.IsIntrinsicCall = isIntrinsicCall
|
||||||
SSADumpInline = ssaDumpInline
|
inline.SSADumpInline = ssaDumpInline
|
||||||
initSSAEnv()
|
initSSAEnv()
|
||||||
initSSATables()
|
initSSATables()
|
||||||
|
|
||||||
|
|
@ -231,13 +232,13 @@ func Main(archInit func(*Arch)) {
|
||||||
// Inlining
|
// Inlining
|
||||||
base.Timer.Start("fe", "inlining")
|
base.Timer.Start("fe", "inlining")
|
||||||
if base.Flag.LowerL != 0 {
|
if base.Flag.LowerL != 0 {
|
||||||
InlinePackage()
|
inline.InlinePackage()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Devirtualize.
|
// Devirtualize.
|
||||||
for _, n := range typecheck.Target.Decls {
|
for _, n := range typecheck.Target.Decls {
|
||||||
if n.Op() == ir.ODCLFUNC {
|
if n.Op() == ir.ODCLFUNC {
|
||||||
devirtualize(n.(*ir.Func))
|
inline.Devirtualize(n.(*ir.Func))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ir.CurFunc = nil
|
ir.CurFunc = nil
|
||||||
|
|
@ -372,17 +373,6 @@ func cgoSymABIs() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// numNonClosures returns the number of functions in list which are not closures.
|
|
||||||
func numNonClosures(list []*ir.Func) int {
|
|
||||||
count := 0
|
|
||||||
for _, fn := range list {
|
|
||||||
if fn.OClosure == nil {
|
|
||||||
count++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return count
|
|
||||||
}
|
|
||||||
|
|
||||||
func writebench(filename string) error {
|
func writebench(filename string) error {
|
||||||
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
f, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ package gc
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
|
"cmd/compile/internal/inline"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/typecheck"
|
"cmd/compile/internal/typecheck"
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
|
|
@ -481,7 +482,7 @@ func genwrapper(rcvr *types.Type, method *types.Field, newnam *types.Sym) {
|
||||||
// generate those wrappers within the same compilation unit as (T).M.
|
// generate those wrappers within the same compilation unit as (T).M.
|
||||||
// TODO(mdempsky): Investigate why we can't enable this more generally.
|
// TODO(mdempsky): Investigate why we can't enable this more generally.
|
||||||
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil {
|
if rcvr.IsPtr() && rcvr.Elem() == method.Type.Recv().Type && rcvr.Elem().Sym() != nil {
|
||||||
inlcalls(fn)
|
inline.InlineCalls(fn)
|
||||||
}
|
}
|
||||||
escapeFuncs([]*ir.Func{fn}, false)
|
escapeFuncs([]*ir.Func{fn}, false)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -24,9 +24,14 @@
|
||||||
// The Debug.m flag enables diagnostic output. a single -m is useful for verifying
|
// The Debug.m flag enables diagnostic output. a single -m is useful for verifying
|
||||||
// which calls get inlined or not, more is for debugging, and may go away at any point.
|
// which calls get inlined or not, more is for debugging, and may go away at any point.
|
||||||
|
|
||||||
package gc
|
package inline
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"go/constant"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"cmd/compile/internal/base"
|
"cmd/compile/internal/base"
|
||||||
"cmd/compile/internal/ir"
|
"cmd/compile/internal/ir"
|
||||||
"cmd/compile/internal/logopt"
|
"cmd/compile/internal/logopt"
|
||||||
|
|
@ -34,10 +39,6 @@ import (
|
||||||
"cmd/compile/internal/types"
|
"cmd/compile/internal/types"
|
||||||
"cmd/internal/obj"
|
"cmd/internal/obj"
|
||||||
"cmd/internal/src"
|
"cmd/internal/src"
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"go/constant"
|
|
||||||
"strings"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Inlining budget parameters, gathered in one place
|
// Inlining budget parameters, gathered in one place
|
||||||
|
|
@ -62,21 +63,21 @@ func InlinePackage() {
|
||||||
// We allow inlining if there is no
|
// We allow inlining if there is no
|
||||||
// recursion, or the recursion cycle is
|
// recursion, or the recursion cycle is
|
||||||
// across more than one function.
|
// across more than one function.
|
||||||
caninl(n)
|
CanInline(n)
|
||||||
} else {
|
} else {
|
||||||
if base.Flag.LowerM > 1 {
|
if base.Flag.LowerM > 1 {
|
||||||
fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Nname)
|
fmt.Printf("%v: cannot inline %v: recursive\n", ir.Line(n), n.Nname)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
inlcalls(n)
|
InlineCalls(n)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Caninl determines whether fn is inlineable.
|
// Caninl determines whether fn is inlineable.
|
||||||
// If so, caninl saves fn->nbody in fn->inl and substitutes it with a copy.
|
// If so, CanInline saves fn->nbody in fn->inl and substitutes it with a copy.
|
||||||
// fn and ->nbody will already have been typechecked.
|
// fn and ->nbody will already have been typechecked.
|
||||||
func caninl(fn *ir.Func) {
|
func CanInline(fn *ir.Func) {
|
||||||
if fn.Nname == nil {
|
if fn.Nname == nil {
|
||||||
base.Fatalf("caninl no nname %+v", fn)
|
base.Fatalf("caninl no nname %+v", fn)
|
||||||
}
|
}
|
||||||
|
|
@ -192,9 +193,9 @@ func caninl(fn *ir.Func) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// inlFlood marks n's inline body for export and recursively ensures
|
// Inline_Flood marks n's inline body for export and recursively ensures
|
||||||
// all called functions are marked too.
|
// all called functions are marked too.
|
||||||
func inlFlood(n *ir.Name, exportsym func(*ir.Name)) {
|
func Inline_Flood(n *ir.Name, exportsym func(*ir.Name)) {
|
||||||
if n == nil {
|
if n == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -222,13 +223,13 @@ func inlFlood(n *ir.Name, exportsym func(*ir.Name)) {
|
||||||
ir.VisitList(ir.Nodes(fn.Inl.Body), func(n ir.Node) {
|
ir.VisitList(ir.Nodes(fn.Inl.Body), func(n ir.Node) {
|
||||||
switch n.Op() {
|
switch n.Op() {
|
||||||
case ir.OMETHEXPR, ir.ODOTMETH:
|
case ir.OMETHEXPR, ir.ODOTMETH:
|
||||||
inlFlood(ir.MethodExprName(n), exportsym)
|
Inline_Flood(ir.MethodExprName(n), exportsym)
|
||||||
|
|
||||||
case ir.ONAME:
|
case ir.ONAME:
|
||||||
n := n.(*ir.Name)
|
n := n.(*ir.Name)
|
||||||
switch n.Class_ {
|
switch n.Class_ {
|
||||||
case ir.PFUNC:
|
case ir.PFUNC:
|
||||||
inlFlood(n, exportsym)
|
Inline_Flood(n, exportsym)
|
||||||
exportsym(n)
|
exportsym(n)
|
||||||
case ir.PEXTERN:
|
case ir.PEXTERN:
|
||||||
exportsym(n)
|
exportsym(n)
|
||||||
|
|
@ -442,7 +443,7 @@ func isBigFunc(fn *ir.Func) bool {
|
||||||
|
|
||||||
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
|
// Inlcalls/nodelist/node walks fn's statements and expressions and substitutes any
|
||||||
// calls made to inlineable functions. This is the external entry point.
|
// calls made to inlineable functions. This is the external entry point.
|
||||||
func inlcalls(fn *ir.Func) {
|
func InlineCalls(fn *ir.Func) {
|
||||||
savefn := ir.CurFunc
|
savefn := ir.CurFunc
|
||||||
ir.CurFunc = fn
|
ir.CurFunc = fn
|
||||||
maxCost := int32(inlineMaxBudget)
|
maxCost := int32(inlineMaxBudget)
|
||||||
|
|
@ -631,7 +632,7 @@ func inlCallee(fn ir.Node) *ir.Func {
|
||||||
case ir.OCLOSURE:
|
case ir.OCLOSURE:
|
||||||
fn := fn.(*ir.ClosureExpr)
|
fn := fn.(*ir.ClosureExpr)
|
||||||
c := fn.Func
|
c := fn.Func
|
||||||
caninl(c)
|
CanInline(c)
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -1202,9 +1203,9 @@ func pruneUnusedAutos(ll []*ir.Name, vis *hairyVisitor) []*ir.Name {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// devirtualize replaces interface method calls within fn with direct
|
// Devirtualize replaces interface method calls within fn with direct
|
||||||
// concrete-type method calls where applicable.
|
// concrete-type method calls where applicable.
|
||||||
func devirtualize(fn *ir.Func) {
|
func Devirtualize(fn *ir.Func) {
|
||||||
ir.CurFunc = fn
|
ir.CurFunc = fn
|
||||||
ir.VisitList(fn.Body, func(n ir.Node) {
|
ir.VisitList(fn.Body, func(n ir.Node) {
|
||||||
if n.Op() == ir.OCALLINTER {
|
if n.Op() == ir.OCALLINTER {
|
||||||
|
|
@ -1268,3 +1269,14 @@ func devirtualizeCall(call *ir.CallExpr) {
|
||||||
call.SetType(ft.Results())
|
call.SetType(ft.Results())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// numNonClosures returns the number of functions in list which are not closures.
|
||||||
|
func numNonClosures(list []*ir.Func) int {
|
||||||
|
count := 0
|
||||||
|
for _, fn := range list {
|
||||||
|
if fn.OClosure == nil {
|
||||||
|
count++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return count
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue