mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: change Node.Nbody, Func.Inl from *NodeList to Nodes
Passes toolstash -cmp. Casual timings show about a 3% improvement in compile times. Update #14473. Change-Id: I584add2e8f1a52486ba418b25ba6122b7347b643 Reviewed-on: https://go-review.googlesource.com/19989 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
75cc05fa55
commit
1d5001afef
24 changed files with 525 additions and 327 deletions
|
|
@ -41,8 +41,8 @@ import (
|
|||
|
||||
// Order holds state during the ordering process.
|
||||
type Order struct {
|
||||
out *NodeList // list of generated statements
|
||||
temp []*Node // stack of temporary variables
|
||||
out []*Node // list of generated statements
|
||||
temp []*Node // stack of temporary variables
|
||||
}
|
||||
|
||||
// Order rewrites fn->nbody to apply the ordering constraints
|
||||
|
|
@ -50,10 +50,10 @@ type Order struct {
|
|||
func order(fn *Node) {
|
||||
if Debug['W'] > 1 {
|
||||
s := fmt.Sprintf("\nbefore order %v", fn.Func.Nname.Sym)
|
||||
dumplist(s, fn.Nbody)
|
||||
dumpslice(s, fn.Nbody.Slice())
|
||||
}
|
||||
|
||||
orderblock(&fn.Nbody)
|
||||
orderblockNodes(&fn.Nbody)
|
||||
}
|
||||
|
||||
// Ordertemp allocates a new temporary with the given type,
|
||||
|
|
@ -64,7 +64,7 @@ func ordertemp(t *Type, order *Order, clear bool) *Node {
|
|||
if clear {
|
||||
a := Nod(OAS, var_, nil)
|
||||
typecheck(&a, Etop)
|
||||
order.out = list(order.out, a)
|
||||
order.out = append(order.out, a)
|
||||
}
|
||||
|
||||
order.temp = append(order.temp, var_)
|
||||
|
|
@ -87,7 +87,7 @@ func ordercopyexpr(n *Node, t *Type, order *Order, clear int) *Node {
|
|||
var_ := ordertemp(t, order, clear != 0)
|
||||
a := Nod(OAS, var_, n)
|
||||
typecheck(&a, Etop)
|
||||
order.out = list(order.out, a)
|
||||
order.out = append(order.out, a)
|
||||
return var_
|
||||
}
|
||||
|
||||
|
|
@ -223,7 +223,7 @@ func poptemp(mark ordermarker, order *Order) {
|
|||
// Cleantempnopop emits to *out VARKILL instructions for each temporary
|
||||
// above the mark on the temporary stack, but it does not pop them
|
||||
// from the stack.
|
||||
func cleantempnopop(mark ordermarker, order *Order, out **NodeList) {
|
||||
func cleantempnopop(mark ordermarker, order *Order, out *[]*Node) {
|
||||
var kill *Node
|
||||
|
||||
for i := len(order.temp) - 1; i >= int(mark); i-- {
|
||||
|
|
@ -232,11 +232,11 @@ func cleantempnopop(mark ordermarker, order *Order, out **NodeList) {
|
|||
n.Name.Keepalive = false
|
||||
kill = Nod(OVARLIVE, n, nil)
|
||||
typecheck(&kill, Etop)
|
||||
*out = list(*out, kill)
|
||||
*out = append(*out, kill)
|
||||
}
|
||||
kill = Nod(OVARKILL, n, nil)
|
||||
typecheck(&kill, Etop)
|
||||
*out = list(*out, kill)
|
||||
*out = append(*out, kill)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -254,6 +254,13 @@ func orderstmtlist(l *NodeList, order *Order) {
|
|||
}
|
||||
}
|
||||
|
||||
// Orderstmtslice orders each of the statements in the slice.
|
||||
func orderstmtslice(l []*Node, order *Order) {
|
||||
for _, n := range l {
|
||||
orderstmt(n, order)
|
||||
}
|
||||
}
|
||||
|
||||
// Orderblock orders the block of statements *l onto a new list,
|
||||
// and then replaces *l with that list.
|
||||
func orderblock(l **NodeList) {
|
||||
|
|
@ -261,7 +268,21 @@ func orderblock(l **NodeList) {
|
|||
mark := marktemp(&order)
|
||||
orderstmtlist(*l, &order)
|
||||
cleantemp(mark, &order)
|
||||
*l = order.out
|
||||
var ll *NodeList
|
||||
for _, n := range order.out {
|
||||
ll = list(ll, n)
|
||||
}
|
||||
*l = ll
|
||||
}
|
||||
|
||||
// OrderblockNodes orders the block of statements in n into a new slice,
|
||||
// and then replaces the old slice in n with the new slice.
|
||||
func orderblockNodes(n *Nodes) {
|
||||
var order Order
|
||||
mark := marktemp(&order)
|
||||
orderstmtslice(n.Slice(), &order)
|
||||
cleantemp(mark, &order)
|
||||
n.Set(order.out)
|
||||
}
|
||||
|
||||
// Orderexprinplace orders the side effects in *np and
|
||||
|
|
@ -270,7 +291,7 @@ func orderexprinplace(np **Node, outer *Order) {
|
|||
n := *np
|
||||
var order Order
|
||||
orderexpr(&n, &order, nil)
|
||||
addinit(&n, order.out)
|
||||
addinitslice(&n, order.out)
|
||||
|
||||
// insert new temporaries from order
|
||||
// at head of outer list.
|
||||
|
|
@ -287,7 +308,7 @@ func orderstmtinplace(np **Node) {
|
|||
mark := marktemp(&order)
|
||||
orderstmt(n, &order)
|
||||
cleantemp(mark, &order)
|
||||
*np = liststmt(order.out)
|
||||
*np = liststmtslice(order.out)
|
||||
}
|
||||
|
||||
// Orderinit moves n's init list to order->out.
|
||||
|
|
@ -413,7 +434,7 @@ func ordermapassign(n *Node, order *Order) {
|
|||
Fatalf("ordermapassign %v", Oconv(int(n.Op), 0))
|
||||
|
||||
case OAS:
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
|
||||
// We call writebarrierfat only for values > 4 pointers long. See walk.go.
|
||||
if (n.Left.Op == OINDEXMAP || (needwritebarrier(n.Left, n.Right) && n.Left.Type.Width > int64(4*Widthptr))) && !isaddrokay(n.Right) {
|
||||
|
|
@ -421,11 +442,11 @@ func ordermapassign(n *Node, order *Order) {
|
|||
n.Left = ordertemp(m.Type, order, false)
|
||||
a := Nod(OAS, m, n.Left)
|
||||
typecheck(&a, Etop)
|
||||
order.out = list(order.out, a)
|
||||
order.out = append(order.out, a)
|
||||
}
|
||||
|
||||
case OAS2, OAS2DOTTYPE, OAS2MAPR, OAS2FUNC:
|
||||
var post *NodeList
|
||||
var post []*Node
|
||||
var m *Node
|
||||
var a *Node
|
||||
for l := n.List; l != nil; l = l.Next {
|
||||
|
|
@ -440,18 +461,18 @@ func ordermapassign(n *Node, order *Order) {
|
|||
l.N = ordertemp(m.Type, order, false)
|
||||
a = Nod(OAS, m, l.N)
|
||||
typecheck(&a, Etop)
|
||||
post = list(post, a)
|
||||
post = append(post, a)
|
||||
} else if instrumenting && n.Op == OAS2FUNC && !isblank(l.N) {
|
||||
m = l.N
|
||||
l.N = ordertemp(m.Type, order, false)
|
||||
a = Nod(OAS, m, l.N)
|
||||
typecheck(&a, Etop)
|
||||
post = list(post, a)
|
||||
post = append(post, a)
|
||||
}
|
||||
}
|
||||
|
||||
order.out = list(order.out, n)
|
||||
order.out = concat(order.out, post)
|
||||
order.out = append(order.out, n)
|
||||
order.out = append(order.out, post...)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -472,7 +493,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
Fatalf("orderstmt %v", Oconv(int(n.Op), 0))
|
||||
|
||||
case OVARKILL, OVARLIVE:
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
|
||||
case OAS:
|
||||
t := marktemp(order)
|
||||
|
|
@ -497,7 +518,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
case OAS2, OAS2DOTTYPE:
|
||||
ordermapassign(n, order)
|
||||
default:
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
}
|
||||
cleantemp(t, order)
|
||||
|
||||
|
|
@ -561,11 +582,11 @@ func orderstmt(n *Node, order *Order) {
|
|||
orderexprlist(n.List, order)
|
||||
orderexpr(&n.Rlist.N.Left, order, nil) // i in i.(T)
|
||||
if isblank(n.List.N) {
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
} else {
|
||||
typ := n.Rlist.N.Type
|
||||
tmp1 := ordertemp(typ, order, haspointers(typ))
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
r := Nod(OAS, n.List.N, tmp1)
|
||||
typecheck(&r, Etop)
|
||||
ordermapassign(r, order)
|
||||
|
|
@ -589,7 +610,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
} else {
|
||||
tmp2 = ordertemp(Types[TBOOL], order, false)
|
||||
}
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
r := Nod(OAS, n.List.N, tmp1)
|
||||
typecheck(&r, Etop)
|
||||
ordermapassign(r, order)
|
||||
|
|
@ -614,14 +635,14 @@ func orderstmt(n *Node, order *Order) {
|
|||
OGOTO,
|
||||
OLABEL,
|
||||
ORETJMP:
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
|
||||
// Special: handle call arguments.
|
||||
case OCALLFUNC, OCALLINTER, OCALLMETH:
|
||||
t := marktemp(order)
|
||||
|
||||
ordercall(n, order)
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
// Special: order arguments to inner call but not call itself.
|
||||
|
|
@ -644,7 +665,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
ordercall(n.Left, order)
|
||||
}
|
||||
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
case ODELETE:
|
||||
|
|
@ -652,7 +673,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
orderexpr(&n.List.N, order, nil)
|
||||
orderexpr(&n.List.Next.N, order, nil)
|
||||
orderaddrtemp(&n.List.Next.N, order) // map key
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
// Clean temporaries from condition evaluation at
|
||||
|
|
@ -661,12 +682,12 @@ func orderstmt(n *Node, order *Order) {
|
|||
t := marktemp(order)
|
||||
|
||||
orderexprinplace(&n.Left, order)
|
||||
var l *NodeList
|
||||
var l []*Node
|
||||
cleantempnopop(t, order, &l)
|
||||
n.Nbody = concat(l, n.Nbody)
|
||||
orderblock(&n.Nbody)
|
||||
n.Nbody.Set(append(l, n.Nbody.Slice()...))
|
||||
orderblockNodes(&n.Nbody)
|
||||
orderstmtinplace(&n.Right)
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
// Clean temporaries from condition at
|
||||
|
|
@ -675,16 +696,20 @@ func orderstmt(n *Node, order *Order) {
|
|||
t := marktemp(order)
|
||||
|
||||
orderexprinplace(&n.Left, order)
|
||||
var l *NodeList
|
||||
var l []*Node
|
||||
cleantempnopop(t, order, &l)
|
||||
n.Nbody = concat(l, n.Nbody)
|
||||
n.Nbody.Set(append(l, n.Nbody.Slice()...))
|
||||
l = nil
|
||||
cleantempnopop(t, order, &l)
|
||||
n.Rlist = concat(l, n.Rlist)
|
||||
var ll *NodeList
|
||||
for _, n := range l {
|
||||
ll = list(ll, n)
|
||||
}
|
||||
n.Rlist = concat(ll, n.Rlist)
|
||||
poptemp(t, order)
|
||||
orderblock(&n.Nbody)
|
||||
orderblockNodes(&n.Nbody)
|
||||
orderblock(&n.Rlist)
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
|
||||
// Special: argument will be converted to interface using convT2E
|
||||
// so make sure it is an addressable temporary.
|
||||
|
|
@ -695,7 +720,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
if !Isinter(n.Left.Type) {
|
||||
orderaddrtemp(&n.Left, order)
|
||||
}
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
// n->right is the expression being ranged over.
|
||||
|
|
@ -756,13 +781,13 @@ func orderstmt(n *Node, order *Order) {
|
|||
for l := n.List; l != nil; l = l.Next {
|
||||
orderexprinplace(&l.N, order)
|
||||
}
|
||||
orderblock(&n.Nbody)
|
||||
order.out = list(order.out, n)
|
||||
orderblockNodes(&n.Nbody)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
case ORETURN:
|
||||
ordercallargs(&n.List, order)
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
|
||||
// Special: clean case temporaries in each block entry.
|
||||
// Select must enter one of its blocks, so there is no
|
||||
|
|
@ -897,19 +922,23 @@ func orderstmt(n *Node, order *Order) {
|
|||
}
|
||||
}
|
||||
|
||||
orderblock(&l.N.Nbody)
|
||||
orderblockNodes(&l.N.Nbody)
|
||||
}
|
||||
|
||||
// Now that we have accumulated all the temporaries, clean them.
|
||||
// Also insert any ninit queued during the previous loop.
|
||||
// (The temporary cleaning must follow that ninit work.)
|
||||
for l := n.List; l != nil; l = l.Next {
|
||||
cleantempnopop(t, order, &l.N.Ninit)
|
||||
l.N.Nbody = concat(l.N.Ninit, l.N.Nbody)
|
||||
s := make([]*Node, 0, count(l.N.Ninit))
|
||||
for ll := l.N.Ninit; ll != nil; ll = ll.Next {
|
||||
s = append(s, ll.N)
|
||||
}
|
||||
cleantempnopop(t, order, &s)
|
||||
l.N.Nbody.Set(append(s, l.N.Nbody.Slice()...))
|
||||
l.N.Ninit = nil
|
||||
}
|
||||
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
poptemp(t, order)
|
||||
|
||||
// Special: value being sent is passed as a pointer; make it addressable.
|
||||
|
|
@ -919,7 +948,7 @@ func orderstmt(n *Node, order *Order) {
|
|||
orderexpr(&n.Left, order, nil)
|
||||
orderexpr(&n.Right, order, nil)
|
||||
orderaddrtemp(&n.Right, order)
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
|
||||
// TODO(rsc): Clean temporaries more aggressively.
|
||||
|
|
@ -938,10 +967,10 @@ func orderstmt(n *Node, order *Order) {
|
|||
Fatalf("order switch case %v", Oconv(int(l.N.Op), 0))
|
||||
}
|
||||
orderexprlistinplace(l.N.List, order)
|
||||
orderblock(&l.N.Nbody)
|
||||
orderblockNodes(&l.N.Nbody)
|
||||
}
|
||||
|
||||
order.out = list(order.out, n)
|
||||
order.out = append(order.out, n)
|
||||
cleantemp(t, order)
|
||||
}
|
||||
|
||||
|
|
@ -1080,9 +1109,13 @@ func orderexpr(np **Node, order *Order, lhs *Node) {
|
|||
// Clean temporaries from first branch at beginning of second.
|
||||
// Leave them on the stack so that they can be killed in the outer
|
||||
// context in case the short circuit is taken.
|
||||
var l *NodeList
|
||||
var s []*Node
|
||||
|
||||
cleantempnopop(mark, order, &l)
|
||||
cleantempnopop(mark, order, &s)
|
||||
var l *NodeList
|
||||
for _, n := range s {
|
||||
l = list(l, n)
|
||||
}
|
||||
n.Right.Ninit = concat(l, n.Right.Ninit)
|
||||
orderexprinplace(&n.Right, order)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue