Speeds up compilation by 6%.
Change-Id: Ibaad95710323ddbe13c1b0351843fe43a48d776e
Reviewed-on: https://go-review.googlesource.com/19080
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
// 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
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)
}
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] {
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)
}
}
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.
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.
// 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).
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) {
}
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
}
}
// 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 {