Commit 577c05ca authored by Austin Clements's avatar Austin Clements

cmd/compile: single pass over Blocks in Liveness.epilogue

Currently Liveness.epilogue makes three passes over the Blocks, but
there's no need to do this. Combine them into a single pass. This
eliminates the need for blockEffects.lastbitmapindex, but, more
importantly, will let us incrementally compact the liveness bitmaps
and significantly reduce allocatons in Liveness.epilogue.

Passes toolstash -cmp.

Updates #24543.

Change-Id: I27802bcd00d23aa122a7ec16cdfd739ae12dd7aa
Reviewed-on: https://go-review.googlesource.com/110175
Run-TryBot: Austin Clements <austin@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: default avatarKeith Randall <khr@golang.org>
Reviewed-by: default avatarDavid Chase <drchase@google.com>
parent 51be90a2
...@@ -80,8 +80,6 @@ import ( ...@@ -80,8 +80,6 @@ import (
// BlockEffects summarizes the liveness effects on an SSA block. // BlockEffects summarizes the liveness effects on an SSA block.
type BlockEffects struct { type BlockEffects struct {
lastbitmapindex int // for Liveness.epilogue
// Computed during Liveness.prologue using only the content of // Computed during Liveness.prologue using only the content of
// individual blocks: // individual blocks:
// //
...@@ -988,6 +986,7 @@ func (lv *Liveness) epilogue() { ...@@ -988,6 +986,7 @@ func (lv *Liveness) epilogue() {
for _, b := range lv.f.Blocks { for _, b := range lv.f.Blocks {
be := lv.blockEffects(b) be := lv.blockEffects(b)
firstBitmapIndex := len(lv.livevars)
// Compute avarinitany and avarinitall for entry to block. // Compute avarinitany and avarinitall for entry to block.
// This duplicates information known during Liveness.solve // This duplicates information known during Liveness.solve
...@@ -1039,14 +1038,8 @@ func (lv *Liveness) epilogue() { ...@@ -1039,14 +1038,8 @@ func (lv *Liveness) epilogue() {
lv.livevars = append(lv.livevars, varRegVec{vars: live}) lv.livevars = append(lv.livevars, varRegVec{vars: live})
} }
be.lastbitmapindex = len(lv.livevars) - 1
}
for _, b := range lv.f.Blocks {
be := lv.blockEffects(b)
// walk backward, construct maps at each safe point // walk backward, construct maps at each safe point
index := int32(be.lastbitmapindex) index := int32(len(lv.livevars) - 1)
if index < 0 { if index < 0 {
// the first block we encounter should have the ATEXT so // the first block we encounter should have the ATEXT so
// at no point should pos ever be less than zero. // at no point should pos ever be less than zero.
...@@ -1089,6 +1082,21 @@ func (lv *Liveness) epilogue() { ...@@ -1089,6 +1082,21 @@ func (lv *Liveness) epilogue() {
live := &lv.livevars[index] live := &lv.livevars[index]
live.Or(*live, liveout) live.Or(*live, liveout)
} }
// Check that no registers are live across calls.
// For closure calls, the CALLclosure is the last use
// of the context register, so it's dead after the call.
index = int32(firstBitmapIndex)
for _, v := range b.Values {
if lv.issafepoint(v) {
live := lv.livevars[index]
if v.Op.IsCall() && live.regs != 0 {
lv.printDebug()
v.Fatalf("internal error: %v register %s recorded as live at call", lv.fn.Func.Nname, live.regs.niceString(lv.f.Config))
}
index++
}
}
} }
// Useful sanity check: on entry to the function, // Useful sanity check: on entry to the function,
...@@ -1107,23 +1115,6 @@ func (lv *Liveness) epilogue() { ...@@ -1107,23 +1115,6 @@ func (lv *Liveness) epilogue() {
lv.printDebug() lv.printDebug()
lv.f.Fatalf("internal error: %v register %s recorded as live on entry", lv.fn.Func.Nname, regs.niceString(lv.f.Config)) lv.f.Fatalf("internal error: %v register %s recorded as live on entry", lv.fn.Func.Nname, regs.niceString(lv.f.Config))
} }
// Check that no registers are live across calls.
// For closure calls, the CALLclosure is the last use
// of the context register, so it's dead after the call.
for _, b := range lv.f.Blocks {
index := int32(lv.blockEffects(b).lastbitmapindex)
for i := len(b.Values) - 1; i >= 0; i-- {
v := b.Values[i]
if lv.issafepoint(v) {
live := lv.livevars[index]
if v.Op.IsCall() && live.regs != 0 {
lv.printDebug()
v.Fatalf("internal error: %v register %s recorded as live at call", lv.fn.Func.Nname, live.regs.niceString(lv.f.Config))
}
index--
}
}
}
} }
func (lv *Liveness) clobber() { func (lv *Liveness) clobber() {
......
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