pass: naive implementation of liveness
This commit is contained in:
62
pass/reg.go
Normal file
62
pass/reg.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package pass
|
||||
|
||||
import (
|
||||
"github.com/mmcloughlin/avo"
|
||||
"github.com/mmcloughlin/avo/reg"
|
||||
)
|
||||
|
||||
// Liveness computes register liveness.
|
||||
func Liveness(fn *avo.Function) error {
|
||||
is := fn.Instructions()
|
||||
|
||||
// Initialize to empty sets.
|
||||
for _, i := range is {
|
||||
i.LiveIn = map[reg.ID]bool{}
|
||||
i.LiveOut = map[reg.ID]bool{}
|
||||
}
|
||||
|
||||
// Iterative dataflow analysis.
|
||||
for {
|
||||
changes := false
|
||||
|
||||
for _, i := range is {
|
||||
// in[n] = use[n] UNION (out[n] - def[n])
|
||||
nin := len(i.LiveIn)
|
||||
for _, r := range i.InputRegisters() {
|
||||
i.LiveIn[r.ID()] = true
|
||||
}
|
||||
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 {
|
||||
changes = true
|
||||
}
|
||||
|
||||
// out[n] = UNION[s IN succ[n]] in[s]
|
||||
nout := len(i.LiveOut)
|
||||
for _, s := range i.Succ {
|
||||
if s == nil {
|
||||
continue
|
||||
}
|
||||
for id := range s.LiveIn {
|
||||
i.LiveOut[id] = true
|
||||
}
|
||||
}
|
||||
if len(i.LiveOut) != nout {
|
||||
changes = true
|
||||
}
|
||||
}
|
||||
|
||||
if !changes {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user