1
0
mirror of https://github.com/golang/go synced 2024-11-24 21:20:05 -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:
Keith Randall 2016-01-28 15:54:45 -08:00
parent 4c5459da2b
commit 056c09bb88
5 changed files with 24 additions and 15 deletions

View File

@ -53,6 +53,11 @@ type Block struct {
// After flagalloc, records whether flags are live at the end of the block.
FlagsLiveAtEnd bool
// Storage for Succs, Preds, and Values
succstorage [2]*Block
predstorage [4]*Block
valstorage [8]*Value
}
// kind control successors

View File

@ -219,7 +219,7 @@ func checkFunc(f *Func) {
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] {
f.Fatalf("used block b%d in free list", b.ID)
}

View File

@ -183,7 +183,7 @@ func deadcode(f *Func) {
b.Values = b.Values[:i]
}
// Remove unreachable blocks. Return dead block ids to allocator.
// Remove unreachable blocks. Return dead blocks to allocator.
i = 0
for _, b := range f.Blocks {
if reachable[b.ID] {
@ -193,10 +193,6 @@ func deadcode(f *Func) {
if len(b.Values) > 0 {
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)
}
}
@ -206,9 +202,6 @@ func deadcode(f *Func) {
tail[j] = nil
}
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.

View File

@ -30,7 +30,7 @@ type Func struct {
Names []LocalSlot
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.
@ -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.
func (f *Func) freeValue(v *Value) {
if v.Type == nil {
if v.Block == nil {
f.Fatalf("trying to free an already freed value")
}
// Clear everything but ID (which we reuse).
@ -84,8 +84,8 @@ func (f *Func) NewBlock(kind BlockKind) *Block {
var b *Block
if f.freeBlocks != nil {
b = f.freeBlocks
f.freeBlocks = b.Aux.(*Block)
b.Aux = nil
f.freeBlocks = b.succstorage[0]
b.succstorage[0] = nil
} else {
ID := f.bid.get()
if int(ID) < len(f.Config.blocks) {
@ -96,16 +96,22 @@ func (f *Func) NewBlock(kind BlockKind) *Block {
}
b.Kind = kind
b.Func = f
b.Preds = b.predstorage[:0]
b.Succs = b.succstorage[:0]
b.Values = b.valstorage[:0]
f.Blocks = append(f.Blocks, b)
return b
}
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).
id := b.ID
*b = Block{}
b.ID = id
b.Aux = f.freeBlocks
b.succstorage[0] = f.freeBlocks
f.freeBlocks = b
}

View File

@ -22,7 +22,12 @@ func fuse(f *Func) {
}
// 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 i, q := range p.Succs {
if q == b {