refactor to use reg.Set

This commit is contained in:
Michael McLoughlin
2018-12-03 22:39:43 -08:00
parent faafa00e40
commit 9376a230cf
6 changed files with 118 additions and 30 deletions

4
ast.go
View File

@@ -47,8 +47,8 @@ type Instruction struct {
Succ []*Instruction Succ []*Instruction
// LiveIn/LiveOut are sets of live register IDs pre/post execution. // LiveIn/LiveOut are sets of live register IDs pre/post execution.
LiveIn map[reg.ID]bool LiveIn reg.Set
LiveOut map[reg.ID]bool LiveOut reg.Set
} }
func (i *Instruction) node() {} func (i *Instruction) node() {}

View File

@@ -11,8 +11,8 @@ func Liveness(fn *avo.Function) error {
// Initialize to empty sets. // Initialize to empty sets.
for _, i := range is { for _, i := range is {
i.LiveIn = map[reg.ID]bool{} i.LiveIn = reg.NewEmptySet()
i.LiveOut = map[reg.ID]bool{} i.LiveOut = reg.NewEmptySet()
} }
// Iterative dataflow analysis. // Iterative dataflow analysis.
@@ -22,18 +22,9 @@ func Liveness(fn *avo.Function) error {
for _, i := range is { for _, i := range is {
// in[n] = use[n] UNION (out[n] - def[n]) // in[n] = use[n] UNION (out[n] - def[n])
nin := len(i.LiveIn) nin := len(i.LiveIn)
for _, r := range i.InputRegisters() { i.LiveIn.Update(reg.NewSetFromSlice(i.InputRegisters()))
i.LiveIn[r.ID()] = true def := reg.NewSetFromSlice(i.OutputRegisters())
} i.LiveIn.Update(i.LiveOut.Difference(def))
def := map[reg.ID]bool{}
for _, r := range i.OutputRegisters() {
def[r.ID()] = true
}
for id := range i.LiveOut {
if !def[id] {
i.LiveIn[id] = true
}
}
if len(i.LiveIn) != nin { if len(i.LiveIn) != nin {
changes = true changes = true
} }
@@ -44,9 +35,7 @@ func Liveness(fn *avo.Function) error {
if s == nil { if s == nil {
continue continue
} }
for id := range s.LiveIn { i.LiveOut.Update(s.LiveIn)
i.LiveOut[id] = true
}
} }
if len(i.LiveOut) != nout { if len(i.LiveOut) != nout {
changes = true changes = true
@@ -60,3 +49,7 @@ func Liveness(fn *avo.Function) error {
return nil return nil
} }
func AllocateRegisters(fn *avo.Function) error {
return nil
}

View File

@@ -50,14 +50,9 @@ func AssertLiveness(t *testing.T, ctx *build.Context, in, out [][]reg.Register)
} }
} }
func AssertRegistersMatchSet(t *testing.T, rs []reg.Register, s map[reg.ID]bool) { func AssertRegistersMatchSet(t *testing.T, rs []reg.Register, s reg.Set) {
if len(rs) != len(s) { if !s.Equals(reg.NewSetFromSlice(rs)) {
t.Fatalf("size mismatch") t.Fatalf("register slice does not match set: %#v and %#v", rs, s)
}
for _, r := range rs {
if _, found := s[r.ID()]; !found {
t.Fatalf("missing register ID %v", r.ID())
}
} }
} }

71
reg/set.go Normal file
View File

@@ -0,0 +1,71 @@
package reg
// Set is a set of registers.
type Set map[ID]Register
// NewEmptySet builds an empty register set.
func NewEmptySet() Set {
return Set{}
}
// NewSetFromSlice forms a set from the given register list.
func NewSetFromSlice(rs []Register) Set {
s := NewEmptySet()
for _, r := range rs {
s.Add(r)
}
return s
}
// Clone returns a copy of s.
func (s Set) Clone() Set {
c := NewEmptySet()
for _, r := range s {
c.Add(r)
}
return c
}
// Add r to s.
func (s Set) Add(r Register) {
s[r.ID()] = r
}
// Discard removes r from s, if present.
func (s Set) Discard(r Register) {
delete(s, r.ID())
}
// Update adds every register in t to s.
func (s Set) Update(t Set) {
for _, r := range t {
s.Add(r)
}
}
// Difference returns the set of registers in s but not t.
func (s Set) Difference(t Set) Set {
d := s.Clone()
d.DifferenceUpdate(t)
return d
}
// DifferenceUpdate removes every element of t from s.
func (s Set) DifferenceUpdate(t Set) {
for _, r := range t {
s.Discard(r)
}
}
// Equals returns true if s and t contain the same registers.
func (s Set) Equals(t Set) bool {
if len(s) != len(t) {
return false
}
for _, r := range s {
if _, found := t[r.ID()]; !found {
return false
}
}
return true
}

12
reg/set_test.go Normal file
View File

@@ -0,0 +1,12 @@
package reg
import "testing"
func TestFamilyRegisterSets(t *testing.T) {
fs := []*Family{GeneralPurpose, SIMD}
for _, f := range fs {
if len(f.Set()) != len(f.Registers()) {
t.Fatal("family set and list should have same size")
}
}
}

View File

@@ -2,7 +2,6 @@ package reg
import ( import (
"fmt" "fmt"
"math"
) )
type Size uint type Size uint
@@ -41,6 +40,24 @@ func (f *Family) Virtual(id VID, s Size) Virtual {
return NewVirtual(id, f.Kind, s) return NewVirtual(id, f.Kind, s)
} }
// Registers returns the registers in this family.
func (f *Family) Registers() []Physical {
rs := make([]Physical, 0, len(f.registers))
for _, r := range f.registers {
rs = append(rs, r)
}
return rs
}
// Set returns the set of registers in the family.
func (f *Family) Set() Set {
s := NewEmptySet()
for _, r := range f.registers {
s.Add(r)
}
return s
}
type private interface { type private interface {
private() private()
} }
@@ -82,7 +99,7 @@ func (v virtual) VirtualID() VID { return v.id }
func (v virtual) Kind() Kind { return v.kind } func (v virtual) Kind() Kind { return v.kind }
func (v virtual) ID() ID { func (v virtual) ID() ID {
return (ID(math.MaxUint16) << 16) | ID(v.VirtualID()) return (ID(1) << 31) | ID(v.VirtualID())
} }
func (v virtual) Asm() string { func (v virtual) Asm() string {
@@ -106,7 +123,7 @@ type register struct {
} }
func (r register) PhysicalID() PID { return r.id } func (r register) PhysicalID() PID { return r.id }
func (r register) ID() ID { return ID(r.id) } func (r register) ID() ID { return (ID(r.Mask()) << 16) | ID(r.id) }
func (r register) Kind() Kind { return r.kind } func (r register) Kind() Kind { return r.kind }
func (r register) Asm() string { return r.name } func (r register) Asm() string { return r.name }
func (r register) private() {} func (r register) private() {}