[dev.typeparams] cmd/compile: set Func.ClosureCalled in escape analysis

The Func.ClosureCalled flag is an optimization used by escape analysis
to detect closures that were directly called, so we know we have
visibility of the result flows. It's not needed by any other phases of
the compiler, so we might as well calculate it within escape analysis
too.

This saves some trouble during IR construction and trying to maintain
the ClosureCalled flag through inlining and copying.

Passes toolstash -cmp.

Change-Id: Ic53cecb7ac439745c0dfba2cd202b9cc40f1e47c
Reviewed-on: https://go-review.googlesource.com/c/go/+/332691
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cuong Manh Le <cuong.manhle.vn@gmail.com>
This commit is contained in:
Matthew Dempsky 2021-07-03 11:22:26 -07:00
parent ea5369bac0
commit 899b158ee9
7 changed files with 9 additions and 18 deletions

View file

@ -57,6 +57,13 @@ func (e *escape) callCommon(ks []hole, call ir.Node, init *ir.Nodes, wrapper *ir
var fn *ir.Name
switch call.Op() {
case ir.OCALLFUNC:
// If we have a direct call to a closure (not just one we were
// able to statically resolve with ir.StaticValue), mark it as
// such so batch.outlives can optimize the flow results.
if call.X.Op() == ir.OCLOSURE {
call.X.(*ir.ClosureExpr).Func.SetClosureCalled(true)
}
switch v := ir.StaticValue(call.X); v.Op() {
case ir.ONAME:
if v := v.(*ir.Name); v.Class == ir.PFUNC {

View file

@ -470,9 +470,6 @@ func inlcopy(n ir.Node) ir.Node {
// x.Func.Body for iexport and local inlining.
oldfn := x.Func
newfn := ir.NewFunc(oldfn.Pos())
if oldfn.ClosureCalled() {
newfn.SetClosureCalled(true)
}
m.(*ir.ClosureExpr).Func = newfn
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), oldfn.Nname.Sym())
// XXX OK to share fn.Type() ??
@ -1154,11 +1151,7 @@ func (subst *inlsubst) closure(n *ir.ClosureExpr) ir.Node {
// the closure is inlined in a specific function.
newclo := newfn.OClosure
newclo.SetInit(subst.list(n.Init()))
if oldfn.ClosureCalled() {
return typecheck.Callee(newclo)
} else {
return typecheck.Expr(newclo)
}
return typecheck.Expr(newclo)
}
// node recursively copies a node from the saved pristine body of the

View file

@ -202,7 +202,7 @@ const (
funcExportInline // include inline body in export data
funcInstrumentBody // add race/msan instrumentation during SSA construction
funcOpenCodedDeferDisallowed // can't do open-coded defers
funcClosureCalled // closure is only immediately called
funcClosureCalled // closure is only immediately called; used by escape analysis
)
type SymAndPos struct {

View file

@ -160,8 +160,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
// Add information, now that we know that fun is actually being called.
switch fun := fun.(type) {
case *ir.ClosureExpr:
fun.Func.SetClosureCalled(true)
case *ir.SelectorExpr:
if fun.Op() == ir.OMETHVALUE {
op := ir.ODOTMETH

View file

@ -1523,9 +1523,6 @@ func (r *reader) expr() ir.Node {
case exprCall:
fun := r.expr()
if clo, ok := fun.(*ir.ClosureExpr); ok {
clo.Func.SetClosureCalled(true)
}
pos := r.pos()
args := r.exprs()
dots := r.bool()

View file

@ -1193,8 +1193,6 @@ func (subst *subster) node(n ir.Node) ir.Node {
newfn := ir.NewClosureFunc(oldfn.Pos(), subst.newf != nil)
ir.NameClosure(newfn.OClosure, subst.newf)
newfn.SetClosureCalled(oldfn.ClosureCalled())
saveNewf := subst.newf
ir.CurFunc = newfn
subst.newf = newfn

View file

@ -242,8 +242,6 @@ func tcClosure(clo *ir.ClosureExpr, top int) ir.Node {
fn.Iota = x
}
fn.SetClosureCalled(top&ctxCallee != 0)
ir.NameClosure(clo, ir.CurFunc)
Func(fn)