mirror of
https://github.com/golang/go
synced 2024-11-24 23:27:57 -07:00
[dev.ssa] cmd/compile: add backing store buffers for block.{Preds,Succs,Values}
Speeds up compilation by 6%. Change-Id: Ibaad95710323ddbe13c1b0351843fe43a48d776e Reviewed-on: https://go-review.googlesource.com/19080 Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
This commit is contained in:
parent
4c5459da2b
commit
056c09bb88
@ -53,6 +53,11 @@ type Block struct {
|
|||||||
|
|
||||||
// After flagalloc, records whether flags are live at the end of the block.
|
// After flagalloc, records whether flags are live at the end of the block.
|
||||||
FlagsLiveAtEnd bool
|
FlagsLiveAtEnd bool
|
||||||
|
|
||||||
|
// Storage for Succs, Preds, and Values
|
||||||
|
succstorage [2]*Block
|
||||||
|
predstorage [4]*Block
|
||||||
|
valstorage [8]*Value
|
||||||
}
|
}
|
||||||
|
|
||||||
// kind control successors
|
// kind control successors
|
||||||
|
@ -219,7 +219,7 @@ func checkFunc(f *Func) {
|
|||||||
f.Fatalf("control value for %s is missing: %v", b, b.Control)
|
f.Fatalf("control value for %s is missing: %v", b, b.Control)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for b := f.freeBlocks; b != nil; b = b.Aux.(*Block) {
|
for b := f.freeBlocks; b != nil; b = b.succstorage[0] {
|
||||||
if blockMark[b.ID] {
|
if blockMark[b.ID] {
|
||||||
f.Fatalf("used block b%d in free list", b.ID)
|
f.Fatalf("used block b%d in free list", b.ID)
|
||||||
}
|
}
|
||||||
|
@ -183,7 +183,7 @@ func deadcode(f *Func) {
|
|||||||
b.Values = b.Values[:i]
|
b.Values = b.Values[:i]
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove unreachable blocks. Return dead block ids to allocator.
|
// Remove unreachable blocks. Return dead blocks to allocator.
|
||||||
i = 0
|
i = 0
|
||||||
for _, b := range f.Blocks {
|
for _, b := range f.Blocks {
|
||||||
if reachable[b.ID] {
|
if reachable[b.ID] {
|
||||||
@ -193,10 +193,6 @@ func deadcode(f *Func) {
|
|||||||
if len(b.Values) > 0 {
|
if len(b.Values) > 0 {
|
||||||
b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
|
b.Fatalf("live values in unreachable block %v: %v", b, b.Values)
|
||||||
}
|
}
|
||||||
b.Preds = nil
|
|
||||||
b.Succs = nil
|
|
||||||
b.Control = nil
|
|
||||||
b.Kind = BlockDead
|
|
||||||
f.freeBlock(b)
|
f.freeBlock(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,9 +202,6 @@ func deadcode(f *Func) {
|
|||||||
tail[j] = nil
|
tail[j] = nil
|
||||||
}
|
}
|
||||||
f.Blocks = f.Blocks[:i]
|
f.Blocks = f.Blocks[:i]
|
||||||
|
|
||||||
// TODO: renumber Blocks and Values densely?
|
|
||||||
// TODO: save dead Values and Blocks for reuse? Or should we just let GC handle it?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// removePred removes the predecessor p from b's predecessor list.
|
// removePred removes the predecessor p from b's predecessor list.
|
||||||
|
@ -30,7 +30,7 @@ type Func struct {
|
|||||||
Names []LocalSlot
|
Names []LocalSlot
|
||||||
|
|
||||||
freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil.
|
freeValues *Value // free Values linked by argstorage[0]. All other fields except ID are 0/nil.
|
||||||
freeBlocks *Block // free Blocks linked by Aux.(*Block). All other fields except ID are 0/nil.
|
freeBlocks *Block // free Blocks linked by succstorage[0]. All other fields except ID are 0/nil.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NumBlocks returns an integer larger than the id of any Block in the Func.
|
// NumBlocks returns an integer larger than the id of any Block in the Func.
|
||||||
@ -68,7 +68,7 @@ func (f *Func) newValue(op Op, t Type, b *Block, line int32) *Value {
|
|||||||
|
|
||||||
// freeValue frees a value. It must no longer be referenced.
|
// freeValue frees a value. It must no longer be referenced.
|
||||||
func (f *Func) freeValue(v *Value) {
|
func (f *Func) freeValue(v *Value) {
|
||||||
if v.Type == nil {
|
if v.Block == nil {
|
||||||
f.Fatalf("trying to free an already freed value")
|
f.Fatalf("trying to free an already freed value")
|
||||||
}
|
}
|
||||||
// Clear everything but ID (which we reuse).
|
// Clear everything but ID (which we reuse).
|
||||||
@ -84,8 +84,8 @@ func (f *Func) NewBlock(kind BlockKind) *Block {
|
|||||||
var b *Block
|
var b *Block
|
||||||
if f.freeBlocks != nil {
|
if f.freeBlocks != nil {
|
||||||
b = f.freeBlocks
|
b = f.freeBlocks
|
||||||
f.freeBlocks = b.Aux.(*Block)
|
f.freeBlocks = b.succstorage[0]
|
||||||
b.Aux = nil
|
b.succstorage[0] = nil
|
||||||
} else {
|
} else {
|
||||||
ID := f.bid.get()
|
ID := f.bid.get()
|
||||||
if int(ID) < len(f.Config.blocks) {
|
if int(ID) < len(f.Config.blocks) {
|
||||||
@ -96,16 +96,22 @@ func (f *Func) NewBlock(kind BlockKind) *Block {
|
|||||||
}
|
}
|
||||||
b.Kind = kind
|
b.Kind = kind
|
||||||
b.Func = f
|
b.Func = f
|
||||||
|
b.Preds = b.predstorage[:0]
|
||||||
|
b.Succs = b.succstorage[:0]
|
||||||
|
b.Values = b.valstorage[:0]
|
||||||
f.Blocks = append(f.Blocks, b)
|
f.Blocks = append(f.Blocks, b)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Func) freeBlock(b *Block) {
|
func (f *Func) freeBlock(b *Block) {
|
||||||
|
if b.Func == nil {
|
||||||
|
f.Fatalf("trying to free an already freed block")
|
||||||
|
}
|
||||||
// Clear everything but ID (which we reuse).
|
// Clear everything but ID (which we reuse).
|
||||||
id := b.ID
|
id := b.ID
|
||||||
*b = Block{}
|
*b = Block{}
|
||||||
b.ID = id
|
b.ID = id
|
||||||
b.Aux = f.freeBlocks
|
b.succstorage[0] = f.freeBlocks
|
||||||
f.freeBlocks = b
|
f.freeBlocks = b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,7 +22,12 @@ func fuse(f *Func) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// replace b->c edge with preds(b) -> c
|
// replace b->c edge with preds(b) -> c
|
||||||
c.Preds = b.Preds
|
c.predstorage[0] = nil
|
||||||
|
if len(b.Preds) > len(b.predstorage) {
|
||||||
|
c.Preds = b.Preds
|
||||||
|
} else {
|
||||||
|
c.Preds = append(c.predstorage[:0], b.Preds...)
|
||||||
|
}
|
||||||
for _, p := range c.Preds {
|
for _, p := range c.Preds {
|
||||||
for i, q := range p.Succs {
|
for i, q := range p.Succs {
|
||||||
if q == b {
|
if q == b {
|
||||||
|
Loading…
Reference in New Issue
Block a user