]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/internal/gc: clean up liveness code
authorRuss Cox <rsc@golang.org>
Tue, 3 Mar 2015 02:25:33 +0000 (21:25 -0500)
committerRuss Cox <rsc@golang.org>
Tue, 3 Mar 2015 20:34:07 +0000 (20:34 +0000)
- use Bvec, not *Bvec, and bulk allocate backing store
- use range loops
- put Bvecs in BasicBlock struct instead of indexing into parallel slices

Change-Id: I5cb30f50dccb4d38cc18fae422f7f132c52876be
Reviewed-on: https://go-review.googlesource.com/6602
Reviewed-by: Rob Pike <r@golang.org>
src/cmd/internal/gc/bv.go
src/cmd/internal/gc/go.go
src/cmd/internal/gc/plive.go
src/cmd/internal/gc/walk.go

index e7fdd70b71487cefc48f233a221abcb38282ba84..07b17bb93705240cb42fc0089f52eead8ad31639 100644 (file)
@@ -13,24 +13,51 @@ const (
        WORDSHIFT = 5
 )
 
+// A Bvec is a bit vector.
+type Bvec struct {
+       n int32    // number of bits in vector
+       b []uint32 // words holding bits
+}
+
 func bvsize(n uint32) uint32 {
        return ((n + WORDBITS - 1) / WORDBITS) * WORDSIZE
 }
 
-func bvbits(bv *Bvec) int32 {
+func bvbits(bv Bvec) int32 {
        return bv.n
 }
 
-func bvwords(bv *Bvec) int32 {
+func bvwords(bv Bvec) int32 {
        return (bv.n + WORDBITS - 1) / WORDBITS
 }
 
-func bvalloc(n int32) *Bvec {
-       return &Bvec{n, make([]uint32, bvsize(uint32(n))/4)}
+func bvalloc(n int32) Bvec {
+       return Bvec{n, make([]uint32, bvsize(uint32(n))/4)}
+}
+
+type bulkBvec struct {
+       words []uint32
+       nbit  int32
+       nword int32
+}
+
+func bvbulkalloc(nbit int32, count int32) bulkBvec {
+       nword := (nbit + WORDBITS - 1) / WORDBITS
+       return bulkBvec{
+               words: make([]uint32, nword*count),
+               nbit:  nbit,
+               nword: nword,
+       }
+}
+
+func (b *bulkBvec) next() Bvec {
+       out := Bvec{b.nbit, b.words[:b.nword]}
+       b.words = b.words[b.nword:]
+       return out
 }
 
 /* difference */
-func bvandnot(dst *Bvec, src1 *Bvec, src2 *Bvec) {
+func bvandnot(dst Bvec, src1 Bvec, src2 Bvec) {
        var i int32
        var w int32
 
@@ -44,7 +71,7 @@ func bvandnot(dst *Bvec, src1 *Bvec, src2 *Bvec) {
        }
 }
 
-func bvcmp(bv1 *Bvec, bv2 *Bvec) int {
+func bvcmp(bv1 Bvec, bv2 Bvec) int {
        if bv1.n != bv2.n {
                Fatal("bvequal: lengths %d and %d are not equal", bv1.n, bv2.n)
        }
@@ -56,13 +83,13 @@ func bvcmp(bv1 *Bvec, bv2 *Bvec) int {
        return 0
 }
 
-func bvcopy(dst *Bvec, src *Bvec) {
+func bvcopy(dst Bvec, src Bvec) {
        for i, x := range src.b {
                dst.b[i] = x
        }
 }
 
-func bvconcat(src1 *Bvec, src2 *Bvec) *Bvec {
+func bvconcat(src1 Bvec, src2 Bvec) Bvec {
        dst := bvalloc(src1.n + src2.n)
        for i := int32(0); i < src1.n; i++ {
                if bvget(src1, i) != 0 {
@@ -77,7 +104,7 @@ func bvconcat(src1 *Bvec, src2 *Bvec) *Bvec {
        return dst
 }
 
-func bvget(bv *Bvec, i int32) int {
+func bvget(bv Bvec, i int32) int {
        if i < 0 || i >= bv.n {
                Fatal("bvget: index %d is out of bounds with length %d\n", i, bv.n)
        }
@@ -86,7 +113,7 @@ func bvget(bv *Bvec, i int32) int {
 
 // bvnext returns the smallest index >= i for which bvget(bv, i) == 1.
 // If there is no such index, bvnext returns -1.
-func bvnext(bv *Bvec, i int32) int {
+func bvnext(bv Bvec, i int32) int {
        if i >= bv.n {
                return -1
        }
@@ -115,7 +142,7 @@ func bvnext(bv *Bvec, i int32) int {
        return int(i)
 }
 
-func bvisempty(bv *Bvec) bool {
+func bvisempty(bv Bvec) bool {
        for i := int32(0); i < bv.n; i += WORDBITS {
                if bv.b[i>>WORDSHIFT] != 0 {
                        return false
@@ -124,7 +151,7 @@ func bvisempty(bv *Bvec) bool {
        return true
 }
 
-func bvnot(bv *Bvec) {
+func bvnot(bv Bvec) {
        var i int32
        var w int32
 
@@ -136,7 +163,7 @@ func bvnot(bv *Bvec) {
 }
 
 /* union */
-func bvor(dst *Bvec, src1 *Bvec, src2 *Bvec) {
+func bvor(dst Bvec, src1 Bvec, src2 Bvec) {
        var i int32
        var w int32
 
@@ -151,7 +178,7 @@ func bvor(dst *Bvec, src1 *Bvec, src2 *Bvec) {
 }
 
 /* intersection */
-func bvand(dst *Bvec, src1 *Bvec, src2 *Bvec) {
+func bvand(dst Bvec, src1 Bvec, src2 Bvec) {
        var i int32
        var w int32
 
@@ -165,14 +192,14 @@ func bvand(dst *Bvec, src1 *Bvec, src2 *Bvec) {
        }
 }
 
-func bvprint(bv *Bvec) {
+func bvprint(bv Bvec) {
        fmt.Printf("#*")
        for i := int32(0); i < bv.n; i++ {
                fmt.Printf("%d", bvget(bv, i))
        }
 }
 
-func bvreset(bv *Bvec, i int32) {
+func bvreset(bv Bvec, i int32) {
        if i < 0 || i >= bv.n {
                Fatal("bvreset: index %d is out of bounds with length %d\n", i, bv.n)
        }
@@ -180,13 +207,13 @@ func bvreset(bv *Bvec, i int32) {
        bv.b[i/WORDBITS] &= mask
 }
 
-func bvresetall(bv *Bvec) {
+func bvresetall(bv Bvec) {
        for i := range bv.b {
                bv.b[i] = 0
        }
 }
 
-func bvset(bv *Bvec, i int32) {
+func bvset(bv Bvec, i int32) {
        if i < 0 || i >= bv.n {
                Fatal("bvset: index %d is out of bounds with length %d\n", i, bv.n)
        }
index d23cdd49595b7ee67f94583186c7a8f26d982e27..2d460f75c055e9482f15fba8bf61d8068b9c786d 100644 (file)
@@ -100,11 +100,6 @@ type Array struct {
        data     string
 }
 
-type Bvec struct {
-       n int32
-       b []uint32
-}
-
 type Pkg struct {
        Name     string
        Path     string
index ba13cdb1c3df62bcd5fa7124afb081712f0efe7e..229489f0254dbce884a5415b7bf58708e812999a 100644 (file)
@@ -41,6 +41,13 @@ type BasicBlock struct {
        rpo             int
        mark            int
        lastbitmapindex int
+       uevar           Bvec
+       varkill         Bvec
+       livein          Bvec
+       liveout         Bvec
+       avarinit        Bvec
+       avarinitany     Bvec
+       avarinitall     Bvec
 }
 
 // A collection of global state used by liveness analysis.
@@ -49,15 +56,8 @@ type Liveness struct {
        ptxt             *obj.Prog
        vars             []*Node
        cfg              []*BasicBlock
-       uevar            []*Bvec
-       varkill          []*Bvec
-       livein           []*Bvec
-       liveout          []*Bvec
-       avarinit         []*Bvec
-       avarinitany      []*Bvec
-       avarinitall      []*Bvec
-       argslivepointers []*Bvec
-       livepointers     []*Bvec
+       argslivepointers []Bvec
+       livepointers     []Bvec
 }
 
 func xmalloc(size uint32) interface{} {
@@ -143,23 +143,16 @@ func splicebefore(lv *Liveness, bb *BasicBlock, prev *obj.Prog, curr *obj.Prog)
 
 // A pretty printer for basic blocks.
 func printblock(bb *BasicBlock) {
-       var pred *BasicBlock
-
        fmt.Printf("basic block %d\n", bb.rpo)
        fmt.Printf("\tpred:")
-       for i := 0; i < len(bb.pred); i++ {
-               pred = bb.pred[i]
+       for _, pred := range bb.pred {
                fmt.Printf(" %d", pred.rpo)
        }
-
        fmt.Printf("\n")
        fmt.Printf("\tsucc:")
-       var succ *BasicBlock
-       for i := 0; i < len(bb.succ); i++ {
-               succ = bb.succ[i]
+       for _, succ := range bb.succ {
                fmt.Printf(" %d", succ.rpo)
        }
-
        fmt.Printf("\n")
        fmt.Printf("\tprog:\n")
        for prog := bb.first; ; prog = prog.Link {
@@ -231,10 +224,7 @@ func getvariables(fn *Node) []*Node {
 
 // A pretty printer for control flow graphs.  Takes an array of BasicBlock*s.
 func printcfg(cfg []*BasicBlock) {
-       var bb *BasicBlock
-
-       for i := int32(0); i < int32(len(cfg)); i++ {
-               bb = cfg[i]
+       for _, bb := range cfg {
                printblock(bb)
        }
 }
@@ -242,16 +232,12 @@ func printcfg(cfg []*BasicBlock) {
 // Assigns a reverse post order number to each connected basic block using the
 // standard algorithm.  Unconnected blocks will not be affected.
 func reversepostorder(root *BasicBlock, rpo *int32) {
-       var bb *BasicBlock
-
        root.mark = VISITED
-       for i := 0; i < len(root.succ); i++ {
-               bb = root.succ[i]
+       for _, bb := range root.succ {
                if bb.mark == UNVISITED {
                        reversepostorder(bb, rpo)
                }
        }
-
        *rpo -= 1
        root.rpo = int(*rpo)
 }
@@ -282,18 +268,18 @@ func iscall(prog *obj.Prog, name *obj.LSym) bool {
 // Returns true for instructions that call a runtime function implementing a
 // select communication clause.
 
-var isselectcommcasecall_names [5]*obj.LSym
+var selectNames [4]*obj.LSym
 
 func isselectcommcasecall(prog *obj.Prog) bool {
-       if isselectcommcasecall_names[0] == nil {
-               isselectcommcasecall_names[0] = Linksym(Pkglookup("selectsend", Runtimepkg))
-               isselectcommcasecall_names[1] = Linksym(Pkglookup("selectrecv", Runtimepkg))
-               isselectcommcasecall_names[2] = Linksym(Pkglookup("selectrecv2", Runtimepkg))
-               isselectcommcasecall_names[3] = Linksym(Pkglookup("selectdefault", Runtimepkg))
+       if selectNames[0] == nil {
+               selectNames[0] = Linksym(Pkglookup("selectsend", Runtimepkg))
+               selectNames[1] = Linksym(Pkglookup("selectrecv", Runtimepkg))
+               selectNames[2] = Linksym(Pkglookup("selectrecv2", Runtimepkg))
+               selectNames[3] = Linksym(Pkglookup("selectdefault", Runtimepkg))
        }
 
-       for i := int32(0); isselectcommcasecall_names[i] != nil; i++ {
-               if iscall(prog, isselectcommcasecall_names[i]) {
+       for _, name := range selectNames {
+               if iscall(prog, name) {
                        return true
                }
        }
@@ -374,10 +360,7 @@ func addselectgosucc(selectgo *BasicBlock) {
 // The entry point for the missing selectgo control flow algorithm.  Takes an
 // array of BasicBlock*s containing selectgo calls.
 func fixselectgo(selectgo []*BasicBlock) {
-       var bb *BasicBlock
-
-       for i := int32(0); i < int32(len(selectgo)); i++ {
-               bb = selectgo[i]
+       for _, bb := range selectgo {
                addselectgosucc(bb)
        }
 }
@@ -432,10 +415,8 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
        // Loop through all basic blocks maximally growing the list of
        // contained instructions until a label is reached.  Add edges
        // for branches and fall-through instructions.
-       var p *obj.Prog
-       for i := int32(0); i < int32(len(cfg)); i++ {
-               bb = cfg[i]
-               for p = bb.last; p != nil; p = p.Link {
+       for _, bb := range cfg {
+               for p := bb.last; p != nil; p = p.Link {
                        if p.Opt != nil && p != bb.last {
                                break
                        }
@@ -467,11 +448,9 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
 
        // Add back links so the instructions in a basic block can be traversed
        // backward.  This is the final state of the instruction opt field.
-       var prev *obj.Prog
-       for i := int32(0); i < int32(len(cfg)); i++ {
-               bb = cfg[i]
-               p = bb.first
-               prev = nil
+       for _, bb := range cfg {
+               p := bb.first
+               var prev *obj.Prog
                for {
                        p.Opt = prev
                        if p == bb.last {
@@ -489,11 +468,9 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
 
        // Find a depth-first order and assign a depth-first number to
        // all basic blocks.
-       for i := int32(0); i < int32(len(cfg)); i++ {
-               bb = cfg[i]
+       for _, bb := range cfg {
                bb.mark = UNVISITED
        }
-
        bb = cfg[0]
        rpo := int32(len(cfg))
        reversepostorder(bb, &rpo)
@@ -503,11 +480,10 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
        // node being the root.
        sort.Sort(blockrpocmp(cfg))
 
-       bb = cfg[0]
-
        // Unreachable control flow nodes are indicated by a -1 in the rpo
        // field.  If we see these nodes something must have gone wrong in an
        // upstream compilation phase.
+       bb = cfg[0]
        if bb.rpo == -1 {
                fmt.Printf("newcfg: unreachable basic block for %v\n", bb.last)
                printcfg(cfg)
@@ -520,18 +496,11 @@ func newcfg(firstp *obj.Prog) []*BasicBlock {
 // Frees a control flow graph (an array of BasicBlock*s) and all of its leaf
 // data structures.
 func freecfg(cfg []*BasicBlock) {
-       n := int32(len(cfg))
-       if n > 0 {
+       if len(cfg) > 0 {
                bb0 := cfg[0]
                for p := bb0.first; p != nil; p = p.Link {
                        p.Opt = nil
                }
-
-               var bb *BasicBlock
-               for i := int32(0); i < n; i++ {
-                       bb = cfg[i]
-                       freeblock(bb)
-               }
        }
 }
 
@@ -555,7 +524,7 @@ func isfunny(n *Node) bool {
 // The avarinit output serves as a signal that the data has been
 // initialized, because any use of a variable must come after its
 // initialization.
-func progeffects(prog *obj.Prog, vars []*Node, uevar *Bvec, varkill *Bvec, avarinit *Bvec) {
+func progeffects(prog *obj.Prog, vars []*Node, uevar Bvec, varkill Bvec, avarinit Bvec) {
        bvresetall(uevar)
        bvresetall(varkill)
        bvresetall(avarinit)
@@ -572,12 +541,10 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar *Bvec, varkill *Bvec, avari
                // all the parameters for correctness, and similarly it must not
                // read the out arguments - they won't be set until the new
                // function runs.
-               var node *Node
-               for i := int32(0); i < int32(len(vars)); i++ {
-                       node = vars[i]
+               for i, node := range vars {
                        switch node.Class &^ PHEAP {
                        case PPARAM:
-                               bvset(uevar, i)
+                               bvset(uevar, int32(i))
 
                                // If the result had its address taken, it is being tracked
                        // by the avarinit code, which does not use uevar.
@@ -589,7 +556,7 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar *Bvec, varkill *Bvec, avari
                        // the for loop for details.
                        case PPARAMOUT:
                                if node.Addrtaken == 0 && prog.To.Type == obj.TYPE_NONE {
-                                       bvset(uevar, i)
+                                       bvset(uevar, int32(i))
                                }
                        }
                }
@@ -600,15 +567,13 @@ func progeffects(prog *obj.Prog, vars []*Node, uevar *Bvec, varkill *Bvec, avari
        if prog.As == obj.ATEXT {
                // A text instruction marks the entry point to a function and
                // the definition point of all in arguments.
-               var node *Node
-               for i := int32(0); i < int32(len(vars)); i++ {
-                       node = vars[i]
+               for i, node := range vars {
                        switch node.Class &^ PHEAP {
                        case PPARAM:
                                if node.Addrtaken != 0 {
-                                       bvset(avarinit, i)
+                                       bvset(avarinit, int32(i))
                                }
-                               bvset(varkill, i)
+                               bvset(varkill, int32(i))
                        }
                }
 
@@ -701,27 +666,20 @@ func newliveness(fn *Node, ptxt *obj.Prog, cfg []*BasicBlock, vars []*Node) *Liv
        result.vars = vars
 
        nblocks := int32(len(cfg))
-       result.uevar = make([]*Bvec, nblocks)
-       result.varkill = make([]*Bvec, nblocks)
-       result.livein = make([]*Bvec, nblocks)
-       result.liveout = make([]*Bvec, nblocks)
-       result.avarinit = make([]*Bvec, nblocks)
-       result.avarinitany = make([]*Bvec, nblocks)
-       result.avarinitall = make([]*Bvec, nblocks)
-
        nvars := int32(len(vars))
-       for i := int32(0); i < nblocks; i++ {
-               result.uevar[i] = bvalloc(nvars)
-               result.varkill[i] = bvalloc(nvars)
-               result.livein[i] = bvalloc(nvars)
-               result.liveout[i] = bvalloc(nvars)
-               result.avarinit[i] = bvalloc(nvars)
-               result.avarinitany[i] = bvalloc(nvars)
-               result.avarinitall[i] = bvalloc(nvars)
-       }
-
-       result.livepointers = make([]*Bvec, 0, 0)
-       result.argslivepointers = make([]*Bvec, 0, 0)
+       bulk := bvbulkalloc(nvars, nblocks*7)
+       for _, bb := range cfg {
+               bb.uevar = bulk.next()
+               bb.varkill = bulk.next()
+               bb.livein = bulk.next()
+               bb.liveout = bulk.next()
+               bb.avarinit = bulk.next()
+               bb.avarinitany = bulk.next()
+               bb.avarinitall = bulk.next()
+       }
+
+       result.livepointers = make([]Bvec, 0, 0)
+       result.argslivepointers = make([]Bvec, 0, 0)
        return result
 }
 
@@ -730,18 +688,9 @@ func freeliveness(lv *Liveness) {
        if lv == nil {
                Fatal("freeliveness: cannot free nil")
        }
-
-       for i := int32(0); i < int32(len(lv.livepointers)); i++ {
-       }
-
-       for i := int32(0); i < int32(len(lv.argslivepointers)); i++ {
-       }
-
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-       }
 }
 
-func printeffects(p *obj.Prog, uevar *Bvec, varkill *Bvec, avarinit *Bvec) {
+func printeffects(p *obj.Prog, uevar Bvec, varkill Bvec, avarinit Bvec) {
        fmt.Printf("effects of %v", p)
        fmt.Printf("\nuevar: ")
        bvprint(uevar)
@@ -768,11 +717,11 @@ func printnode(node *Node) {
 }
 
 // Pretty print a list of variables.  The vars argument is an array of Node*s.
-func printvars(name string, bv *Bvec, vars []*Node) {
+func printvars(name string, bv Bvec, vars []*Node) {
        fmt.Printf("%s:", name)
-       for i := int32(0); i < int32(len(vars)); i++ {
-               if bvget(bv, i) != 0 {
-                       printnode(vars[i])
+       for i, node := range vars {
+               if bvget(bv, int32(i)) != 0 {
+                       printnode(node)
                }
        }
        fmt.Printf("\n")
@@ -781,43 +730,34 @@ func printvars(name string, bv *Bvec, vars []*Node) {
 // Prints a basic block annotated with the information computed by liveness
 // analysis.
 func livenessprintblock(lv *Liveness, bb *BasicBlock) {
-       var pred *BasicBlock
-
        fmt.Printf("basic block %d\n", bb.rpo)
 
        fmt.Printf("\tpred:")
-       for i := 0; i < len(bb.pred); i++ {
-               pred = bb.pred[i]
+       for _, pred := range bb.pred {
                fmt.Printf(" %d", pred.rpo)
        }
-
        fmt.Printf("\n")
 
        fmt.Printf("\tsucc:")
-       var succ *BasicBlock
-       for i := 0; i < len(bb.succ); i++ {
-               succ = bb.succ[i]
+       for _, succ := range bb.succ {
                fmt.Printf(" %d", succ.rpo)
        }
-
        fmt.Printf("\n")
 
-       printvars("\tuevar", lv.uevar[bb.rpo], []*Node(lv.vars))
-       printvars("\tvarkill", lv.varkill[bb.rpo], []*Node(lv.vars))
-       printvars("\tlivein", lv.livein[bb.rpo], []*Node(lv.vars))
-       printvars("\tliveout", lv.liveout[bb.rpo], []*Node(lv.vars))
-       printvars("\tavarinit", lv.avarinit[bb.rpo], []*Node(lv.vars))
-       printvars("\tavarinitany", lv.avarinitany[bb.rpo], []*Node(lv.vars))
-       printvars("\tavarinitall", lv.avarinitall[bb.rpo], []*Node(lv.vars))
+       printvars("\tuevar", bb.uevar, []*Node(lv.vars))
+       printvars("\tvarkill", bb.varkill, []*Node(lv.vars))
+       printvars("\tlivein", bb.livein, []*Node(lv.vars))
+       printvars("\tliveout", bb.liveout, []*Node(lv.vars))
+       printvars("\tavarinit", bb.avarinit, []*Node(lv.vars))
+       printvars("\tavarinitany", bb.avarinitany, []*Node(lv.vars))
+       printvars("\tavarinitall", bb.avarinitall, []*Node(lv.vars))
 
        fmt.Printf("\tprog:\n")
-       var live *Bvec
-       var pos int32
        for prog := bb.first; ; prog = prog.Link {
                fmt.Printf("\t\t%v", prog)
                if prog.As == obj.APCDATA && prog.From.Offset == obj.PCDATA_StackMapIndex {
-                       pos = int32(prog.To.Offset)
-                       live = lv.livepointers[pos]
+                       pos := int32(prog.To.Offset)
+                       live := lv.livepointers[pos]
                        fmt.Printf(" ")
                        bvprint(live)
                }
@@ -832,10 +772,7 @@ func livenessprintblock(lv *Liveness, bb *BasicBlock) {
 // Prints a control flow graph annotated with any information computed by
 // liveness analysis.
 func livenessprintcfg(lv *Liveness) {
-       var bb *BasicBlock
-
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-               bb = lv.cfg[i]
+       for _, bb := range lv.cfg {
                livenessprintblock(lv, bb)
        }
 }
@@ -919,7 +856,7 @@ func checkptxt(fn *Node, firstp *obj.Prog) {
 // and then simply copied into bv at the correct offset on future calls with
 // the same type t. On https://rsc.googlecode.com/hg/testdata/slow.go, twobitwalktype1
 // accounts for 40% of the 6g execution time.
-func twobitwalktype1(t *Type, xoffset *int64, bv *Bvec) {
+func twobitwalktype1(t *Type, xoffset *int64, bv Bvec) {
        if t.Align > 0 && *xoffset&int64(t.Align-1) != 0 {
                Fatal("twobitwalktype1: invalid initial alignment, %v", Tconv(t, 0))
        }
@@ -1027,7 +964,7 @@ func argswords() int32 {
 // Generates live pointer value maps for arguments and local variables.  The
 // this argument and the in arguments are always assumed live.  The vars
 // argument is an array of Node*s.
-func twobitlivepointermap(lv *Liveness, liveout *Bvec, vars []*Node, args *Bvec, locals *Bvec) {
+func twobitlivepointermap(lv *Liveness, liveout Bvec, vars []*Node, args Bvec, locals Bvec) {
        var node *Node
        var xoffset int64
 
@@ -1100,39 +1037,34 @@ func issafepoint(prog *obj.Prog) bool {
 // instructions in each basic block to summarizes the information at each basic
 // block
 func livenessprologue(lv *Liveness) {
-       var bb *BasicBlock
-       var p *obj.Prog
-
        nvars := int32(len(lv.vars))
        uevar := bvalloc(nvars)
        varkill := bvalloc(nvars)
        avarinit := bvalloc(nvars)
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-               bb = lv.cfg[i]
-
+       for _, bb := range lv.cfg {
                // Walk the block instructions backward and update the block
                // effects with the each prog effects.
-               for p = bb.last; p != nil; p = p.Opt.(*obj.Prog) {
+               for p := bb.last; p != nil; p = p.Opt.(*obj.Prog) {
                        progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit)
                        if debuglive >= 3 {
                                printeffects(p, uevar, varkill, avarinit)
                        }
-                       bvor(lv.varkill[i], lv.varkill[i], varkill)
-                       bvandnot(lv.uevar[i], lv.uevar[i], varkill)
-                       bvor(lv.uevar[i], lv.uevar[i], uevar)
+                       bvor(bb.varkill, bb.varkill, varkill)
+                       bvandnot(bb.uevar, bb.uevar, varkill)
+                       bvor(bb.uevar, bb.uevar, uevar)
                }
 
                // Walk the block instructions forward to update avarinit bits.
                // avarinit describes the effect at the end of the block, not the beginning.
                bvresetall(varkill)
 
-               for p = bb.first; ; p = p.Link {
+               for p := bb.first; ; p = p.Link {
                        progeffects(p, []*Node(lv.vars), uevar, varkill, avarinit)
                        if debuglive >= 3 {
                                printeffects(p, uevar, varkill, avarinit)
                        }
-                       bvandnot(lv.avarinit[i], lv.avarinit[i], varkill)
-                       bvor(lv.avarinit[i], lv.avarinit[i], avarinit)
+                       bvandnot(bb.avarinit, bb.avarinit, varkill)
+                       bvor(bb.avarinit, bb.avarinit, avarinit)
                        if p == bb.last {
                                break
                        }
@@ -1142,9 +1074,6 @@ func livenessprologue(lv *Liveness) {
 
 // Solve the liveness dataflow equations.
 func livenesssolve(lv *Liveness) {
-       var bb *BasicBlock
-       var rpo int32
-
        // These temporary bitvectors exist to avoid successive allocations and
        // frees within the loop.
        newlivein := bvalloc(int32(len(lv.vars)))
@@ -1156,53 +1085,44 @@ func livenesssolve(lv *Liveness) {
        // Push avarinitall, avarinitany forward.
        // avarinitall says the addressed var is initialized along all paths reaching the block exit.
        // avarinitany says the addressed var is initialized along some path reaching the block exit.
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-               bb = lv.cfg[i]
-               rpo = int32(bb.rpo)
+       for i, bb := range lv.cfg {
                if i == 0 {
-                       bvcopy(lv.avarinitall[rpo], lv.avarinit[rpo])
+                       bvcopy(bb.avarinitall, bb.avarinit)
                } else {
-                       bvresetall(lv.avarinitall[rpo])
-                       bvnot(lv.avarinitall[rpo])
+                       bvresetall(bb.avarinitall)
+                       bvnot(bb.avarinitall)
                }
-
-               bvcopy(lv.avarinitany[rpo], lv.avarinit[rpo])
+               bvcopy(bb.avarinitany, bb.avarinit)
        }
 
        change := int32(1)
-       var j int32
-       var i int32
-       var pred *BasicBlock
        for change != 0 {
                change = 0
-               for i = 0; i < int32(len(lv.cfg)); i++ {
-                       bb = lv.cfg[i]
-                       rpo = int32(bb.rpo)
+               for _, bb := range lv.cfg {
                        bvresetall(any)
                        bvresetall(all)
-                       for j = 0; j < int32(len(bb.pred)); j++ {
-                               pred = bb.pred[j]
+                       for j, pred := range bb.pred {
                                if j == 0 {
-                                       bvcopy(any, lv.avarinitany[pred.rpo])
-                                       bvcopy(all, lv.avarinitall[pred.rpo])
+                                       bvcopy(any, pred.avarinitany)
+                                       bvcopy(all, pred.avarinitall)
                                } else {
-                                       bvor(any, any, lv.avarinitany[pred.rpo])
-                                       bvand(all, all, lv.avarinitall[pred.rpo])
+                                       bvor(any, any, pred.avarinitany)
+                                       bvand(all, all, pred.avarinitall)
                                }
                        }
 
-                       bvandnot(any, any, lv.varkill[rpo])
-                       bvandnot(all, all, lv.varkill[rpo])
-                       bvor(any, any, lv.avarinit[rpo])
-                       bvor(all, all, lv.avarinit[rpo])
-                       if bvcmp(any, lv.avarinitany[rpo]) != 0 {
+                       bvandnot(any, any, bb.varkill)
+                       bvandnot(all, all, bb.varkill)
+                       bvor(any, any, bb.avarinit)
+                       bvor(all, all, bb.avarinit)
+                       if bvcmp(any, bb.avarinitany) != 0 {
                                change = 1
-                               bvcopy(lv.avarinitany[rpo], any)
+                               bvcopy(bb.avarinitany, any)
                        }
 
-                       if bvcmp(all, lv.avarinitall[rpo]) != 0 {
+                       if bvcmp(all, bb.avarinitall) != 0 {
                                change = 1
-                               bvcopy(lv.avarinitall[rpo], all)
+                               bvcopy(bb.avarinitall, all)
                        }
                }
        }
@@ -1212,29 +1132,26 @@ func livenesssolve(lv *Liveness) {
        // so low that it hardly seems to be worth the complexity.
        change = 1
 
-       var succ *BasicBlock
        for change != 0 {
                change = 0
 
                // Walk blocks in the general direction of propagation.  This
                // improves convergence.
-               for i = int32(len(lv.cfg)) - 1; i >= 0; i-- {
+               for i := len(lv.cfg) - 1; i >= 0; i-- {
+                       bb := lv.cfg[i]
+
                        // A variable is live on output from this block
                        // if it is live on input to some successor.
                        //
                        // out[b] = \bigcup_{s \in succ[b]} in[s]
-                       bb = lv.cfg[i]
-
-                       rpo = int32(bb.rpo)
                        bvresetall(newliveout)
-                       for j = 0; j < int32(len(bb.succ)); j++ {
-                               succ = bb.succ[j]
-                               bvor(newliveout, newliveout, lv.livein[succ.rpo])
+                       for _, succ := range bb.succ {
+                               bvor(newliveout, newliveout, succ.livein)
                        }
 
-                       if bvcmp(lv.liveout[rpo], newliveout) != 0 {
+                       if bvcmp(bb.liveout, newliveout) != 0 {
                                change = 1
-                               bvcopy(lv.liveout[rpo], newliveout)
+                               bvcopy(bb.liveout, newliveout)
                        }
 
                        // A variable is live on input to this block
@@ -1242,16 +1159,16 @@ func livenesssolve(lv *Liveness) {
                        // not set by the code in this block.
                        //
                        // in[b] = uevar[b] \cup (out[b] \setminus varkill[b])
-                       bvandnot(newlivein, lv.liveout[rpo], lv.varkill[rpo])
+                       bvandnot(newlivein, bb.liveout, bb.varkill)
 
-                       bvor(lv.livein[rpo], newlivein, lv.uevar[rpo])
+                       bvor(bb.livein, newlivein, bb.uevar)
                }
        }
 }
 
 // This function is slow but it is only used for generating debug prints.
 // Check whether n is marked live in args/locals.
-func islive(n *Node, args *Bvec, locals *Bvec) bool {
+func islive(n *Node, args Bvec, locals Bvec) bool {
        switch n.Class {
        case PPARAM,
                PPARAMOUT:
@@ -1275,10 +1192,9 @@ func islive(n *Node, args *Bvec, locals *Bvec) bool {
 // Visits all instructions in a basic block and computes a bit vector of live
 // variables at each safe point locations.
 func livenessepilogue(lv *Liveness) {
-       var bb *BasicBlock
        var pred *BasicBlock
-       var args *Bvec
-       var locals *Bvec
+       var args Bvec
+       var locals Bvec
        var n *Node
        var p *obj.Prog
        var j int32
@@ -1297,9 +1213,7 @@ func livenessepilogue(lv *Liveness) {
        nmsg := int32(0)
        startmsg := int32(0)
 
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-               bb = lv.cfg[i]
-
+       for _, bb := range lv.cfg {
                // Compute avarinitany and avarinitall for entry to block.
                // This duplicates information known during livenesssolve
                // but avoids storing two more vectors for each block.
@@ -1309,11 +1223,11 @@ func livenessepilogue(lv *Liveness) {
                for j = 0; j < int32(len(bb.pred)); j++ {
                        pred = bb.pred[j]
                        if j == 0 {
-                               bvcopy(any, lv.avarinitany[pred.rpo])
-                               bvcopy(all, lv.avarinitall[pred.rpo])
+                               bvcopy(any, pred.avarinitany)
+                               bvcopy(all, pred.avarinitall)
                        } else {
-                               bvor(any, any, lv.avarinitany[pred.rpo])
-                               bvand(all, all, lv.avarinitall[pred.rpo])
+                               bvor(any, any, pred.avarinitany)
+                               bvand(all, all, pred.avarinitall)
                        }
                }
 
@@ -1390,9 +1304,7 @@ func livenessepilogue(lv *Liveness) {
        var next *obj.Prog
        var numlive int32
        var msg []string
-       for i := int32(0); i < int32(len(lv.cfg)); i++ {
-               bb = lv.cfg[i]
-
+       for _, bb := range lv.cfg {
                if debuglive >= 1 && Curfn.Nname.Sym.Name != "init" && Curfn.Nname.Sym.Name[0] != '.' {
                        nmsg = int32(len(lv.livepointers))
                        startmsg = nmsg
@@ -1411,7 +1323,7 @@ func livenessepilogue(lv *Liveness) {
                        Fatal("livenessepilogue")
                }
 
-               bvcopy(livein, lv.liveout[bb.rpo])
+               bvcopy(livein, bb.liveout)
                for p = bb.last; p != nil; p = next {
                        next = p.Opt.(*obj.Prog) // splicebefore modifies p->opt
 
@@ -1535,7 +1447,7 @@ const (
        Hp = 16777619
 )
 
-func hashbitmap(h uint32, bv *Bvec) uint32 {
+func hashbitmap(h uint32, bv Bvec) uint32 {
        var w uint32
 
        n := int((bv.n + 31) / 32)
@@ -1589,12 +1501,12 @@ func livenesscompact(lv *Liveness) {
        // record in remap, record in lv->livepointers and lv->argslivepointers
        // under the new index, and add entry to hash table.
        // If already seen, record earlier index in remap and free bitmaps.
-       var jarg *Bvec
+       var jarg Bvec
        var j int
        var h uint32
-       var arg *Bvec
-       var jlocal *Bvec
-       var local *Bvec
+       var arg Bvec
+       var jlocal Bvec
+       var local Bvec
        for i := 0; i < n; i++ {
                local = lv.livepointers[i]
                arg = lv.argslivepointers[i]
@@ -1632,8 +1544,8 @@ func livenesscompact(lv *Liveness) {
        // array so that we can tell where the coalesced bitmaps stop
        // and so that we don't double-free when cleaning up.
        for j := uniq; j < n; j++ {
-               lv.livepointers[j] = nil
-               lv.argslivepointers[j] = nil
+               lv.livepointers[j] = Bvec{}
+               lv.argslivepointers[j] = Bvec{}
        }
 
        // Rewrite PCDATA instructions to use new numbering.
@@ -1648,11 +1560,9 @@ func livenesscompact(lv *Liveness) {
        }
 }
 
-func printbitset(printed int, name string, vars []*Node, bits *Bvec) int {
-       var n *Node
-
+func printbitset(printed int, name string, vars []*Node, bits Bvec) int {
        started := 0
-       for i := 0; i < len(vars); i++ {
+       for i, n := range vars {
                if bvget(bits, int32(i)) == 0 {
                        continue
                }
@@ -1669,7 +1579,6 @@ func printbitset(printed int, name string, vars []*Node, bits *Bvec) int {
                        fmt.Printf(",")
                }
 
-               n = vars[i]
                fmt.Printf("%s", n.Sym.Name)
        }
 
@@ -1682,10 +1591,9 @@ func printbitset(printed int, name string, vars []*Node, bits *Bvec) int {
 func livenessprintdebug(lv *Liveness) {
        var j int
        var printed int
-       var bb *BasicBlock
        var p *obj.Prog
-       var args *Bvec
-       var locals *Bvec
+       var args Bvec
+       var locals Bvec
        var n *Node
 
        fmt.Printf("liveness: %s\n", Curfn.Nname.Sym.Name)
@@ -1695,11 +1603,10 @@ func livenessprintdebug(lv *Liveness) {
        avarinit := bvalloc(int32(len(lv.vars)))
 
        pcdata := 0
-       for i := 0; i < len(lv.cfg); i++ {
+       for i, bb := range lv.cfg {
                if i > 0 {
                        fmt.Printf("\n")
                }
-               bb = lv.cfg[i]
 
                // bb#0 pred=1,2 succ=3,4
                fmt.Printf("bb#%d pred=", i)
@@ -1724,8 +1631,8 @@ func livenessprintdebug(lv *Liveness) {
                // initial settings
                printed = 0
 
-               printed = printbitset(printed, "uevar", lv.vars, lv.uevar[bb.rpo])
-               printed = printbitset(printed, "livein", lv.vars, lv.livein[bb.rpo])
+               printed = printbitset(printed, "uevar", lv.vars, bb.uevar)
+               printed = printbitset(printed, "livein", lv.vars, bb.livein)
                if printed != 0 {
                        fmt.Printf("\n")
                }
@@ -1772,11 +1679,11 @@ func livenessprintdebug(lv *Liveness) {
                // bb bitsets
                fmt.Printf("end\n")
 
-               printed = printbitset(printed, "varkill", lv.vars, lv.varkill[bb.rpo])
-               printed = printbitset(printed, "liveout", lv.vars, lv.liveout[bb.rpo])
-               printed = printbitset(printed, "avarinit", lv.vars, lv.avarinit[bb.rpo])
-               printed = printbitset(printed, "avarinitany", lv.vars, lv.avarinitany[bb.rpo])
-               printed = printbitset(printed, "avarinitall", lv.vars, lv.avarinitall[bb.rpo])
+               printed = printbitset(printed, "varkill", lv.vars, bb.varkill)
+               printed = printbitset(printed, "liveout", lv.vars, bb.liveout)
+               printed = printbitset(printed, "avarinit", lv.vars, bb.avarinit)
+               printed = printbitset(printed, "avarinitany", lv.vars, bb.avarinitany)
+               printed = printbitset(printed, "avarinitall", lv.vars, bb.avarinitall)
                if printed != 0 {
                        fmt.Printf("\n")
                }
@@ -1790,7 +1697,7 @@ func livenessprintdebug(lv *Liveness) {
 // length of the bitmaps.  All bitmaps are assumed to be of equal length.  The
 // words that are followed are the raw bitmap words.  The arr argument is an
 // array of Node*s.
-func twobitwritesymbol(arr []*Bvec, sym *Sym) {
+func twobitwritesymbol(arr []Bvec, sym *Sym) {
        var i int
        var j int
        var word uint32
@@ -1804,7 +1711,7 @@ func twobitwritesymbol(arr []*Bvec, sym *Sym) {
                // bitmap words
                bv = arr[i]
 
-               if bv == nil {
+               if bv.b == nil {
                        break
                }
                for j = 0; int32(j) < bv.n; j += 32 {
index 0992c181cd3ab7dc91e4249bf5e3a1bbd43ccdb4..14396440f7e40fd94e9c043224a76f99116a586e 100644 (file)
@@ -2196,7 +2196,7 @@ func needwritebarrier(l *Node, r *Node) bool {
 
 // TODO(rsc): Perhaps componentgen should run before this.
 
-var applywritebarrier_bv *Bvec
+var applywritebarrier_bv Bvec
 
 func applywritebarrier(n *Node, init **NodeList) *Node {
        if n.Left != nil && n.Right != nil && needwritebarrier(n.Left, n.Right) {
@@ -2216,7 +2216,7 @@ func applywritebarrier(n *Node, init **NodeList) *Node {
                        n = mkcall1(writebarrierfn("writebarrieriface", t, n.Right.Type), nil, init, l, n.Right)
                } else if t.Width <= int64(4*Widthptr) {
                        x := int64(0)
-                       if applywritebarrier_bv == nil {
+                       if applywritebarrier_bv.b == nil {
                                applywritebarrier_bv = bvalloc(obj.BitsPerPointer * 4)
                        }
                        bvresetall(applywritebarrier_bv)