mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: cache sparse maps across ssa passes
This is done for sparse sets already, but it was missing for sparse maps. Only affects deadstore and regalloc, as they're the only ones that use sparse maps. name old time/op new time/op delta DSEPass-4 247µs ± 0% 216µs ± 0% -12.75% (p=0.008 n=5+5) DSEPassBlock-4 3.05ms ± 1% 2.87ms ± 1% -6.02% (p=0.002 n=6+6) CSEPass-4 2.30ms ± 0% 2.32ms ± 0% +0.53% (p=0.026 n=6+6) CSEPassBlock-4 23.8ms ± 0% 23.8ms ± 0% ~ (p=0.931 n=6+5) DeadcodePass-4 51.7µs ± 1% 51.5µs ± 2% ~ (p=0.429 n=5+6) DeadcodePassBlock-4 734µs ± 1% 742µs ± 3% ~ (p=0.394 n=6+6) MultiPass-4 152µs ± 0% 149µs ± 2% ~ (p=0.082 n=5+6) MultiPassBlock-4 2.67ms ± 1% 2.41ms ± 2% -9.77% (p=0.008 n=5+5) name old alloc/op new alloc/op delta DSEPass-4 41.2kB ± 0% 0.1kB ± 0% -99.68% (p=0.002 n=6+6) DSEPassBlock-4 560kB ± 0% 4kB ± 0% -99.34% (p=0.026 n=5+6) CSEPass-4 189kB ± 0% 189kB ± 0% ~ (all equal) CSEPassBlock-4 3.10MB ± 0% 3.10MB ± 0% ~ (p=0.444 n=5+5) DeadcodePass-4 10.5kB ± 0% 10.5kB ± 0% ~ (all equal) DeadcodePassBlock-4 164kB ± 0% 164kB ± 0% ~ (all equal) MultiPass-4 240kB ± 0% 199kB ± 0% -17.06% (p=0.002 n=6+6) MultiPassBlock-4 3.60MB ± 0% 2.99MB ± 0% -17.06% (p=0.002 n=6+6) name old allocs/op new allocs/op delta DSEPass-4 8.00 ± 0% 4.00 ± 0% -50.00% (p=0.002 n=6+6) DSEPassBlock-4 240 ± 0% 120 ± 0% -50.00% (p=0.002 n=6+6) CSEPass-4 9.00 ± 0% 9.00 ± 0% ~ (all equal) CSEPassBlock-4 1.35k ± 0% 1.35k ± 0% ~ (all equal) DeadcodePass-4 3.00 ± 0% 3.00 ± 0% ~ (all equal) DeadcodePassBlock-4 9.00 ± 0% 9.00 ± 0% ~ (all equal) MultiPass-4 11.0 ± 0% 10.0 ± 0% -9.09% (p=0.002 n=6+6) MultiPassBlock-4 165 ± 0% 150 ± 0% -9.09% (p=0.002 n=6+6) Change-Id: I43860687c88f33605eb1415f36473c5cfe8fde4a Reviewed-on: https://go-review.googlesource.com/98449 Run-TryBot: Daniel Martí <mvdan@mvdan.cc> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Josh Bleecher Snyder <josharian@gmail.com>
This commit is contained in:
parent
a35ec9a59e
commit
cd2cb6e3f5
5 changed files with 43 additions and 10 deletions
|
|
@ -22,7 +22,8 @@ type Cache struct {
|
|||
stackAllocState *stackAllocState
|
||||
|
||||
domblockstore []ID // scratch space for computing dominators
|
||||
scrSparse []*sparseSet // scratch sparse sets to be re-used.
|
||||
scrSparseSet []*sparseSet // scratch sparse sets to be re-used.
|
||||
scrSparseMap []*sparseMap // scratch sparse maps to be re-used.
|
||||
|
||||
ValueToProgAfter []*obj.Prog
|
||||
debugState debugState
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@ func dse(f *Func) {
|
|||
defer f.retSparseSet(loadUse)
|
||||
storeUse := f.newSparseSet(f.NumValues())
|
||||
defer f.retSparseSet(storeUse)
|
||||
shadowed := newSparseMap(f.NumValues()) // TODO: cache
|
||||
shadowed := f.newSparseMap(f.NumValues())
|
||||
defer f.retSparseMap(shadowed)
|
||||
for _, b := range f.Blocks {
|
||||
// Find all the stores in this block. Categorize their uses:
|
||||
// loadUse contains stores which are used by a subsequent load.
|
||||
|
|
|
|||
|
|
@ -84,9 +84,9 @@ func (f *Func) NumValues() int {
|
|||
|
||||
// newSparseSet returns a sparse set that can store at least up to n integers.
|
||||
func (f *Func) newSparseSet(n int) *sparseSet {
|
||||
for i, scr := range f.Cache.scrSparse {
|
||||
for i, scr := range f.Cache.scrSparseSet {
|
||||
if scr != nil && scr.cap() >= n {
|
||||
f.Cache.scrSparse[i] = nil
|
||||
f.Cache.scrSparseSet[i] = nil
|
||||
scr.clear()
|
||||
return scr
|
||||
}
|
||||
|
|
@ -94,15 +94,40 @@ func (f *Func) newSparseSet(n int) *sparseSet {
|
|||
return newSparseSet(n)
|
||||
}
|
||||
|
||||
// retSparseSet returns a sparse set to the config's cache of sparse sets to be reused by f.newSparseSet.
|
||||
// retSparseSet returns a sparse set to the config's cache of sparse
|
||||
// sets to be reused by f.newSparseSet.
|
||||
func (f *Func) retSparseSet(ss *sparseSet) {
|
||||
for i, scr := range f.Cache.scrSparse {
|
||||
for i, scr := range f.Cache.scrSparseSet {
|
||||
if scr == nil {
|
||||
f.Cache.scrSparse[i] = ss
|
||||
f.Cache.scrSparseSet[i] = ss
|
||||
return
|
||||
}
|
||||
}
|
||||
f.Cache.scrSparse = append(f.Cache.scrSparse, ss)
|
||||
f.Cache.scrSparseSet = append(f.Cache.scrSparseSet, ss)
|
||||
}
|
||||
|
||||
// newSparseMap returns a sparse map that can store at least up to n integers.
|
||||
func (f *Func) newSparseMap(n int) *sparseMap {
|
||||
for i, scr := range f.Cache.scrSparseMap {
|
||||
if scr != nil && scr.cap() >= n {
|
||||
f.Cache.scrSparseMap[i] = nil
|
||||
scr.clear()
|
||||
return scr
|
||||
}
|
||||
}
|
||||
return newSparseMap(n)
|
||||
}
|
||||
|
||||
// retSparseMap returns a sparse map to the config's cache of sparse
|
||||
// sets to be reused by f.newSparseMap.
|
||||
func (f *Func) retSparseMap(ss *sparseMap) {
|
||||
for i, scr := range f.Cache.scrSparseMap {
|
||||
if scr == nil {
|
||||
f.Cache.scrSparseMap[i] = ss
|
||||
return
|
||||
}
|
||||
}
|
||||
f.Cache.scrSparseMap = append(f.Cache.scrSparseMap, ss)
|
||||
}
|
||||
|
||||
// newValue allocates a new Value with the given fields and places it at the end of b.Values.
|
||||
|
|
|
|||
|
|
@ -2183,8 +2183,10 @@ func (s *regAllocState) computeLive() {
|
|||
s.desired = make([]desiredState, f.NumBlocks())
|
||||
var phis []*Value
|
||||
|
||||
live := newSparseMap(f.NumValues())
|
||||
t := newSparseMap(f.NumValues())
|
||||
live := f.newSparseMap(f.NumValues())
|
||||
defer f.retSparseMap(live)
|
||||
t := f.newSparseMap(f.NumValues())
|
||||
defer f.retSparseMap(t)
|
||||
|
||||
// Keep track of which value we want in each register.
|
||||
var desired desiredState
|
||||
|
|
|
|||
|
|
@ -26,6 +26,10 @@ func newSparseMap(n int) *sparseMap {
|
|||
return &sparseMap{dense: nil, sparse: make([]int32, n)}
|
||||
}
|
||||
|
||||
func (s *sparseMap) cap() int {
|
||||
return len(s.sparse)
|
||||
}
|
||||
|
||||
func (s *sparseMap) size() int {
|
||||
return len(s.dense)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue