refactor to use reg.Set
This commit is contained in:
4
ast.go
4
ast.go
@@ -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() {}
|
||||||
|
|||||||
27
pass/reg.go
27
pass/reg.go
@@ -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
|
||||||
|
}
|
||||||
|
|||||||
@@ -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
71
reg/set.go
Normal 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
12
reg/set_test.go
Normal 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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
23
reg/types.go
23
reg/types.go
@@ -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() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user