open ERTL
let instruction_successors (i : instruction) =
match i with
| IReturn _
| ITailCall _ ->
Label.Set.empty
| INewFrame l
| IDeleteFrame l
| IGetHwReg (_, _, l)
| ISetHwReg (_, _, l)
| IGetStack (_, _, l)
| ISetStack (_, _, l)
| IGetGlobal (_, _, l)
| ISetGlobal (_, _, l)
| IConst (_, _, l)
| IUnOp (_, _, _, l)
| IBinOp (_, _, _, _, l)
| ICall (_, _, l)
| ILoad (_, _, _, l)
| IStore (_, _, _, l)
| IGoto l ->
Label.Set.singleton l
| IUnBranch (_, _, l1, l2)
| IBinBranch (_, _, _, l1, l2) ->
Label.Set.couple l1 l2
module L = struct
type t =
Register.Set.t * MIPS.RegisterSet.t
type property =
t
let bottom =
Register.Set.empty, MIPS.RegisterSet.empty
let psingleton r =
Register.Set.singleton r, MIPS.RegisterSet.empty
let hsingleton hwr =
Register.Set.empty, MIPS.RegisterSet.singleton hwr
let join (rset1, hwrset1) (rset2, hwrset2) =
(Register.Set.union rset1 rset2, MIPS.RegisterSet.union hwrset1 hwrset2)
let diff (rset1, hwrset1) (rset2, hwrset2) =
(Register.Set.diff rset1 rset2, MIPS.RegisterSet.diff hwrset1 hwrset2)
let equal (rset1, hwrset1) (rset2, hwrset2) =
Register.Set.equal rset1 rset2 && MIPS.RegisterSet.equal hwrset1 hwrset2
let is_maximal _ =
false
end
module F = Fix.Make (Label.ImperativeMap) (L)
let defined (i : instruction) : L.t =
match i with
| IGetHwReg (r, _, _)
| IGetStack (r, _, _)
| IConst (r, _, _)
| IUnOp (_, r, _, _)
| IBinOp (_, r, _, _, _)
| ILoad (r, _, _, _)
| IGetGlobal (r, _, _) ->
L.psingleton r
| ICall _ ->
Register.Set.empty, MIPS.caller_saved
| ISetHwReg (hwr, _, _) ->
L.hsingleton hwr
| INewFrame _
| IDeleteFrame _
| ISetStack _
| IStore _
| ISetGlobal _
| IGoto _
| IUnBranch _
| IBinBranch _
| IReturn _
| ITailCall _ ->
L.bottom
let saved =
MIPS.RegisterSet.add MIPS.ra MIPS.callee_saved
let used (i : instruction) : L.t =
match i with
| IGetHwReg (_, hwr, _) ->
L.hsingleton hwr
| INewFrame _
| IDeleteFrame _
| IGetStack _
| IConst _
| IGoto _
| IGetGlobal _ ->
L.bottom
| ISetHwReg (_, r, _)
| ISetStack (_, r, _)
| IUnOp (_, _, r, _)
| ILoad (_, r, _, _)
| ISetGlobal (_, r, _)
| IUnBranch (_, r, _, _) ->
L.psingleton r
| IBinOp (_, _, r1, r2, _)
| IStore (r1, _, r2, _)
| IBinBranch (_, r1, r2, _, _) ->
Register.Set.couple r1 r2, MIPS.RegisterSet.empty
| ICall (_, nparams, _) ->
Register.Set.empty,
MIPS.RegisterSet.of_list (Misc.prefix nparams MIPS.parameters)
| IReturn false ->
Register.Set.empty,
saved
| IReturn true ->
Register.Set.empty,
MIPS.RegisterSet.add MIPS.result saved
| ITailCall (_, nparams) ->
Register.Set.empty,
MIPS.RegisterSet.union
saved
(MIPS.RegisterSet.of_list (Misc.prefix nparams MIPS.parameters))
let eliminable ((pliveafter, hliveafter) : L.t) (i : instruction) : Label.t option =
match i with
| IGetHwReg (r, _, l)
| IGetStack (r, _, l)
| IGetGlobal (r, _, l)
| IConst (r, _, l)
| IUnOp (_, r, _, l)
| IBinOp (_, r, _, _, l)
| ILoad (r, _, _, l) ->
if Register.Set.mem r pliveafter then None else Some l
| ISetHwReg (hwr, _, l) ->
if MIPS.RegisterSet.mem hwr hliveafter then None else Some l
| IReturn _
| ITailCall _
| INewFrame _
| IDeleteFrame _
| ISetStack _
| ISetGlobal _
| ICall _
| IStore _
| IGoto _
| IUnBranch _
| IBinBranch _ ->
None
let instruction_semantics (i : instruction) (liveafter : L.t) : L.t =
match eliminable liveafter i with
| None ->
L.join (L.diff liveafter (defined i)) (used i)
| Some _ ->
liveafter
type valuation =
Label.t -> L.t
let analyze (proc : procedure) : valuation =
let livebefore label (liveafter : valuation) : L.t =
let i : instruction = Label.Map.find label proc.graph in
instruction_semantics i (liveafter label)
in
let liveafter label (liveafter : valuation) : L.t =
let i : instruction = Label.Map.find label proc.graph in
Label.Set.fold (fun successor accu ->
L.join (livebefore successor liveafter) accu
) (instruction_successors i) L.bottom
in
F.lfp liveafter