cmd/compile: change Func.{Dcl,Inldcl} from NodeList to slice

A slice uses less memory than a NodeList, and has better memory locality
when walking the list.

This uncovered a tricky case involving closures: the escape analysis
pass when run on a closure was appending to the Dcl list of the OCLOSURE
rather than the ODCLFUNC.  This happened to work because they shared the
same NodeList.  Fixed with a change to addrescapes, and a check to
Tempname to catch any recurrences.

This removes the last use of the listsort function outside of tests.
I'll send a separate CL to remove it.

Unfortunately, while this passes all tests, it does not pass toolstash
-cmp.  The problem is that cmpstackvarlt does not fully determine the
sort order, and the change from listsort to sort.Sort, while generally
desirable, produces a different ordering.  I could stage this by first
making cmpstackvarlt fully determined, but no matter what toolstash -cmp
is going to break at some point.

In my casual testing the compiler is 2.2% faster.

Update #14473.

Change-Id: I367d66daa4ec73ed95c14c66ccda3a2133ad95d5
Reviewed-on: https://go-review.googlesource.com/19919
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
Ian Lance Taylor 2016-02-25 10:35:19 -08:00
parent 67dbde0d71
commit b66a892358
21 changed files with 161 additions and 163 deletions

View file

@ -8,6 +8,7 @@ import (
"cmd/internal/obj"
"crypto/md5"
"fmt"
"sort"
"strings"
)
@ -217,6 +218,13 @@ func cmpstackvarlt(a, b *Node) bool {
return a.Sym.Name < b.Sym.Name
}
// byStackvar implements sort.Interface for []*Node using cmpstackvarlt.
type byStackVar []*Node
func (s byStackVar) Len() int { return len(s) }
func (s byStackVar) Less(i, j int) bool { return cmpstackvarlt(s[i], s[j]) }
func (s byStackVar) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
// stkdelta records the stack offset delta for a node
// during the compaction of the stack frame to remove
// unused stack slots.
@ -227,25 +235,23 @@ func allocauto(ptxt *obj.Prog) {
Stksize = 0
stkptrsize = 0
if Curfn.Func.Dcl == nil {
if len(Curfn.Func.Dcl) == 0 {
return
}
// Mark the PAUTO's unused.
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
if ll.N.Class == PAUTO {
ll.N.Used = false
for _, ln := range Curfn.Func.Dcl {
if ln.Class == PAUTO {
ln.Used = false
}
}
markautoused(ptxt)
listsort(&Curfn.Func.Dcl, cmpstackvarlt)
sort.Sort(byStackVar(Curfn.Func.Dcl))
// Unused autos are at the end, chop 'em off.
ll := Curfn.Func.Dcl
n := ll.N
n := Curfn.Func.Dcl[0]
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
// No locals used at all
Curfn.Func.Dcl = nil
@ -254,19 +260,17 @@ func allocauto(ptxt *obj.Prog) {
return
}
for ll := Curfn.Func.Dcl; ll.Next != nil; ll = ll.Next {
n = ll.Next.N
for i := 1; i < len(Curfn.Func.Dcl); i++ {
n = Curfn.Func.Dcl[i]
if n.Class == PAUTO && n.Op == ONAME && !n.Used {
ll.Next = nil
Curfn.Func.Dcl.End = ll
Curfn.Func.Dcl = Curfn.Func.Dcl[:i]
break
}
}
// Reassign stack offsets of the locals that are still there.
var w int64
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
n = ll.N
for _, n := range Curfn.Func.Dcl {
if n.Class != PAUTO || n.Op != ONAME {
continue
}
@ -298,12 +302,12 @@ func allocauto(ptxt *obj.Prog) {
fixautoused(ptxt)
// The debug information needs accurate offsets on the symbols.
for ll := Curfn.Func.Dcl; ll != nil; ll = ll.Next {
if ll.N.Class != PAUTO || ll.N.Op != ONAME {
for _, ln := range Curfn.Func.Dcl {
if ln.Class != PAUTO || ln.Op != ONAME {
continue
}
ll.N.Xoffset += stkdelta[ll.N]
delete(stkdelta, ll.N)
ln.Xoffset += stkdelta[ln]
delete(stkdelta, ln)
}
}
@ -455,16 +459,15 @@ func compile(fn *Node) {
gtrack(tracksym(t))
}
for l := fn.Func.Dcl; l != nil; l = l.Next {
n = l.N
for _, n := range fn.Func.Dcl {
if n.Op != ONAME { // might be OTYPE or OLITERAL
continue
}
switch n.Class {
case PAUTO, PPARAM, PPARAMOUT:
Nodconst(&nod1, Types[TUINTPTR], l.N.Type.Width)
p = Thearch.Gins(obj.ATYPE, l.N, &nod1)
p.From.Gotype = Linksym(ngotype(l.N))
Nodconst(&nod1, Types[TUINTPTR], n.Type.Width)
p = Thearch.Gins(obj.ATYPE, n, &nod1)
p.From.Gotype = Linksym(ngotype(n))
}
}