pass: tweak ordering in liveness analysis
Previously we updated the set of live in registers before live out. This was extremely inefficient, since on each pass through live in depends on live out. We also change to processing the instructions in reverse order, which is more likely to be efficient, although we should replace this with topological sort order soon.
This commit is contained in:
32
pass/reg.go
32
pass/reg.go
@@ -15,9 +15,15 @@ func Liveness(fn *avo.Function) error {
|
|||||||
|
|
||||||
is := fn.Instructions()
|
is := fn.Instructions()
|
||||||
|
|
||||||
// Initialize to empty sets.
|
// Process instructions in reverse: poor approximation to topological sort.
|
||||||
|
// TODO(mbm): process instructions in topological sort order
|
||||||
|
for l, r := 0, len(is)-1; l < r; l, r = l+1, r-1 {
|
||||||
|
is[l], is[r] = is[r], is[l]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize.
|
||||||
for _, i := range is {
|
for _, i := range is {
|
||||||
i.LiveIn = reg.NewEmptySet()
|
i.LiveIn = reg.NewSetFromSlice(i.InputRegisters())
|
||||||
i.LiveOut = reg.NewEmptySet()
|
i.LiveOut = reg.NewEmptySet()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -26,15 +32,6 @@ func Liveness(fn *avo.Function) error {
|
|||||||
changes := false
|
changes := false
|
||||||
|
|
||||||
for _, i := range is {
|
for _, i := range is {
|
||||||
// in[n] = use[n] UNION (out[n] - def[n])
|
|
||||||
nin := len(i.LiveIn)
|
|
||||||
i.LiveIn.Update(reg.NewSetFromSlice(i.InputRegisters()))
|
|
||||||
def := reg.NewSetFromSlice(i.OutputRegisters())
|
|
||||||
i.LiveIn.Update(i.LiveOut.Difference(def))
|
|
||||||
if len(i.LiveIn) != nin {
|
|
||||||
changes = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// out[n] = UNION[s IN succ[n]] in[s]
|
// out[n] = UNION[s IN succ[n]] in[s]
|
||||||
nout := len(i.LiveOut)
|
nout := len(i.LiveOut)
|
||||||
for _, s := range i.Succ {
|
for _, s := range i.Succ {
|
||||||
@@ -46,6 +43,19 @@ func Liveness(fn *avo.Function) error {
|
|||||||
if len(i.LiveOut) != nout {
|
if len(i.LiveOut) != nout {
|
||||||
changes = true
|
changes = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// in[n] = use[n] UNION (out[n] - def[n])
|
||||||
|
nin := len(i.LiveIn)
|
||||||
|
def := reg.NewSetFromSlice(i.OutputRegisters())
|
||||||
|
i.LiveIn.Update(i.LiveOut.Difference(def))
|
||||||
|
for r := range i.LiveOut {
|
||||||
|
if _, found := def[r]; !found {
|
||||||
|
i.LiveIn.Add(r)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(i.LiveIn) != nin {
|
||||||
|
changes = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if !changes {
|
if !changes {
|
||||||
|
|||||||
Reference in New Issue
Block a user