Skip to content

Commit 3c8545c

Browse files
committed
cmd/compile: reduce allocations in prove by reusing posets
In prove, reuse posets between different functions by storing them in the per-worker cache. Allocation count regression caused by prove improvements is down from 5% to 3% after this CL. Updates #25179 Change-Id: I6d14003109833d9b3ef5165fdea00aa9c9e952e8 Reviewed-on: https://go-review.googlesource.com/110455 Run-TryBot: Giovanni Bajo <rasky@develer.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: David Chase <drchase@google.com>
1 parent 67656ba commit 3c8545c

File tree

5 files changed

+48
-11
lines changed

5 files changed

+48
-11
lines changed

src/cmd/compile/internal/ssa/cache.go

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ type Cache struct {
2424
domblockstore []ID // scratch space for computing dominators
2525
scrSparseSet []*sparseSet // scratch sparse sets to be re-used.
2626
scrSparseMap []*sparseMap // scratch sparse maps to be re-used.
27+
scrPoset []*poset // scratch poset to be reused
2728

2829
ValueToProgAfter []*obj.Prog
2930
debugState debugState

src/cmd/compile/internal/ssa/func.go

+15
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,21 @@ func (f *Func) retSparseMap(ss *sparseMap) {
130130
f.Cache.scrSparseMap = append(f.Cache.scrSparseMap, ss)
131131
}
132132

133+
// newPoset returns a new poset from the internal cache
134+
func (f *Func) newPoset() *poset {
135+
if len(f.Cache.scrPoset) > 0 {
136+
po := f.Cache.scrPoset[len(f.Cache.scrPoset)-1]
137+
f.Cache.scrPoset = f.Cache.scrPoset[:len(f.Cache.scrPoset)-1]
138+
return po
139+
}
140+
return newPoset()
141+
}
142+
143+
// retPoset returns a poset to the internal cache
144+
func (f *Func) retPoset(po *poset) {
145+
f.Cache.scrPoset = append(f.Cache.scrPoset, po)
146+
}
147+
133148
// newValue allocates a new Value with the given fields and places it at the end of b.Values.
134149
func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value {
135150
var v *Value

src/cmd/compile/internal/ssa/poset.go

+9-6
Original file line numberDiff line numberDiff line change
@@ -152,13 +152,8 @@ type poset struct {
152152
undo []posetUndo // undo chain
153153
}
154154

155-
func newPoset(unsigned bool) *poset {
156-
var flags uint8
157-
if unsigned {
158-
flags |= posetFlagUnsigned
159-
}
155+
func newPoset() *poset {
160156
return &poset{
161-
flags: flags,
162157
values: make(map[ID]uint32),
163158
constants: make([]*Value, 0, 8),
164159
nodes: make([]posetNode, 1, 16),
@@ -168,6 +163,14 @@ func newPoset(unsigned bool) *poset {
168163
}
169164
}
170165

166+
func (po *poset) SetUnsigned(uns bool) {
167+
if uns {
168+
po.flags |= posetFlagUnsigned
169+
} else {
170+
po.flags &^= posetFlagUnsigned
171+
}
172+
}
173+
171174
// Handle children
172175
func (po *poset) setchl(i uint32, l posetEdge) { po.nodes[i].l = l }
173176
func (po *poset) setchr(i uint32, r posetEdge) { po.nodes[i].r = r }

src/cmd/compile/internal/ssa/poset_test.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ func testPosetOps(t *testing.T, unsigned bool, ops []posetTestOp) {
6464
}
6565
}
6666

67-
po := newPoset(unsigned)
67+
po := newPoset()
68+
po.SetUnsigned(unsigned)
6869
for idx, op := range ops {
6970
t.Logf("op%d%v", idx, op)
7071
switch op.typ {

src/cmd/compile/internal/ssa/prove.go

+21-4
Original file line numberDiff line numberDiff line change
@@ -181,10 +181,12 @@ type factsTable struct {
181181
var checkpointFact = fact{}
182182
var checkpointBound = limitFact{}
183183

184-
func newFactsTable() *factsTable {
184+
func newFactsTable(f *Func) *factsTable {
185185
ft := &factsTable{}
186-
ft.order[0] = newPoset(false) // signed
187-
ft.order[1] = newPoset(true) // unsigned
186+
ft.order[0] = f.newPoset() // signed
187+
ft.order[1] = f.newPoset() // unsigned
188+
ft.order[0].SetUnsigned(false)
189+
ft.order[1].SetUnsigned(true)
188190
ft.facts = make(map[pair]relation)
189191
ft.stack = make([]fact, 4)
190192
ft.limits = make(map[ID]limit)
@@ -666,7 +668,8 @@ var (
666668
// its negation. If either leads to a contradiction, it can trim that
667669
// successor.
668670
func prove(f *Func) {
669-
ft := newFactsTable()
671+
ft := newFactsTable(f)
672+
ft.checkpoint()
670673

671674
// Find length and capacity ops.
672675
var zero *Value
@@ -794,6 +797,20 @@ func prove(f *Func) {
794797
ft.restore()
795798
}
796799
}
800+
801+
ft.restore()
802+
803+
// Return the posets to the free list
804+
for _, po := range ft.order {
805+
// Make sure it's empty as it should be. A non-empty poset
806+
// might cause errors and miscompilations if reused.
807+
if checkEnabled {
808+
if err := po.CheckEmpty(); err != nil {
809+
f.Fatalf("prove poset not empty after function %s: %v", f.Name, err)
810+
}
811+
}
812+
f.retPoset(po)
813+
}
797814
}
798815

799816
// getBranch returns the range restrictions added by p

0 commit comments

Comments
 (0)