Commit 0153137a authored by Russ Cox's avatar Russ Cox

cmd/internal/gc: clean up liveness code

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