domblockstore []ID // scratch space for computing dominators
scrSparseSet []*sparseSet // scratch sparse sets to be re-used.
scrSparseMap []*sparseMap // scratch sparse maps to be re-used.
+ scrPoset []*poset // scratch poset to be reused
ValueToProgAfter []*obj.Prog
debugState debugState
f.Cache.scrSparseMap = append(f.Cache.scrSparseMap, ss)
}
+// newPoset returns a new poset from the internal cache
+func (f *Func) newPoset() *poset {
+ if len(f.Cache.scrPoset) > 0 {
+ po := f.Cache.scrPoset[len(f.Cache.scrPoset)-1]
+ f.Cache.scrPoset = f.Cache.scrPoset[:len(f.Cache.scrPoset)-1]
+ return po
+ }
+ return newPoset()
+}
+
+// retPoset returns a poset to the internal cache
+func (f *Func) retPoset(po *poset) {
+ f.Cache.scrPoset = append(f.Cache.scrPoset, po)
+}
+
// newValue allocates a new Value with the given fields and places it at the end of b.Values.
func (f *Func) newValue(op Op, t *types.Type, b *Block, pos src.XPos) *Value {
var v *Value
undo []posetUndo // undo chain
}
-func newPoset(unsigned bool) *poset {
- var flags uint8
- if unsigned {
- flags |= posetFlagUnsigned
- }
+func newPoset() *poset {
return &poset{
- flags: flags,
values: make(map[ID]uint32),
constants: make([]*Value, 0, 8),
nodes: make([]posetNode, 1, 16),
}
}
+func (po *poset) SetUnsigned(uns bool) {
+ if uns {
+ po.flags |= posetFlagUnsigned
+ } else {
+ po.flags &^= posetFlagUnsigned
+ }
+}
+
// Handle children
func (po *poset) setchl(i uint32, l posetEdge) { po.nodes[i].l = l }
func (po *poset) setchr(i uint32, r posetEdge) { po.nodes[i].r = r }
}
}
- po := newPoset(unsigned)
+ po := newPoset()
+ po.SetUnsigned(unsigned)
for idx, op := range ops {
t.Logf("op%d%v", idx, op)
switch op.typ {
var checkpointFact = fact{}
var checkpointBound = limitFact{}
-func newFactsTable() *factsTable {
+func newFactsTable(f *Func) *factsTable {
ft := &factsTable{}
- ft.order[0] = newPoset(false) // signed
- ft.order[1] = newPoset(true) // unsigned
+ ft.order[0] = f.newPoset() // signed
+ ft.order[1] = f.newPoset() // unsigned
+ ft.order[0].SetUnsigned(false)
+ ft.order[1].SetUnsigned(true)
ft.facts = make(map[pair]relation)
ft.stack = make([]fact, 4)
ft.limits = make(map[ID]limit)
// its negation. If either leads to a contradiction, it can trim that
// successor.
func prove(f *Func) {
- ft := newFactsTable()
+ ft := newFactsTable(f)
+ ft.checkpoint()
// Find length and capacity ops.
var zero *Value
ft.restore()
}
}
+
+ ft.restore()
+
+ // Return the posets to the free list
+ for _, po := range ft.order {
+ // Make sure it's empty as it should be. A non-empty poset
+ // might cause errors and miscompilations if reused.
+ if checkEnabled {
+ if err := po.CheckEmpty(); err != nil {
+ f.Fatalf("prove poset not empty after function %s: %v", f.Name, err)
+ }
+ }
+ f.retPoset(po)
+ }
}
// getBranch returns the range restrictions added by p