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:
Michael McLoughlin
2018-12-24 12:48:29 -08:00
parent 6d1424dc66
commit b3644ec7fc

View File

@@ -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 {