Files
lci/lib/miniImp/liveVariables.ml

270 lines
7.8 KiB
OCaml
Raw Normal View History

2024-12-21 02:16:04 +01:00
open Analysis
module Variable = struct
type t = string
let pp (ppf: out_channel) (v: t) : unit =
Printf.fprintf ppf "%s" v
let pplist (ppf: out_channel) (vv: t list) : unit =
List.iter (Printf.fprintf ppf "%s, ") vv
let compare a b =
String.compare a b
end
module RISCCfg = CfgRISC.RISCCfg
module DVCfg = Dataflow.Make (CfgRISC.RISCSimpleStatements) (Variable)
module DVCeltSet = Set.Make(Variable)
let variables_used (instr : DVCfg.elt) : DVCfg.internal list =
let helper (acc: DVCeltSet.t) (instr: DVCfg.elt) =
match instr with
| Nop
| LoadI (_, _) ->
acc
| BRegOp (_, r1, r2, _)
| Store (r1, r2) ->
2024-12-21 02:16:04 +01:00
DVCeltSet.add r1.index acc |>
DVCeltSet.add r2.index
| BImmOp (_, r1, _, _)
| URegOp (_, r1, _)
| Load (r1, _) ->
2024-12-21 02:16:04 +01:00
DVCeltSet.add r1.index acc
in
helper DVCeltSet.empty instr |> DVCeltSet.to_list
let variables_defined (instructions : DVCfg.elt) : DVCfg.internal list =
let helper (acc: DVCeltSet.t) (instr: DVCfg.elt) =
match instr with
| Nop
| Store (_, _) -> acc
2024-12-21 02:16:04 +01:00
| BRegOp (_, _, _, r3)
| BImmOp (_, _, _, r3)
| URegOp (_, _, r3)
| Load (_, r3)
| LoadI (_, r3) ->
2024-12-21 02:16:04 +01:00
DVCeltSet.add r3.index acc
in
helper DVCeltSet.empty instructions |> DVCeltSet.to_list
(* init function, assign the bottom to everything *)
let init : (DVCfg.elt list -> DVCfg.internalnode) =
(fun l -> {internalin = [];
internalout = [];
internalbetween = (List.init (List.length l) (fun _ -> ([], [])))})
let lub (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
let previnternalvar = Cfg.NodeMap.find node t.internalvar in
let code = match Cfg.NodeMap.find_opt node t.t.content with
None -> []
| Some c -> c
in
let newinternalbetween = (
List.map
(fun (code, (_i, o)) ->
(Utility.unique_union
(variables_used code)
(Utility.subtraction o (variables_defined code)), o))
(Utility.combine_twice code previnternalvar.internalbetween)
) in
let newinternalin =
match newinternalbetween with
| [] -> previnternalvar.internalout
| (i, _)::_ -> i
in
2024-12-21 02:16:04 +01:00
{ previnternalvar with
internalbetween = newinternalbetween;
internalin = newinternalin; }
2024-12-21 02:16:04 +01:00
let lucf (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
let previnternalvar = Cfg.NodeMap.find node t.internalvar in
let newinternalout = (
if Option.equal (=) (Some node) t.t.terminal then (
match t.t.inputOutputVar with
2024-12-21 02:16:04 +01:00
Some (_, o) -> [o]
| None -> []
) else (
let nextnodes = Cfg.NodeMap.find_opt node t.t.edges in
match nextnodes with
| None -> []
| Some (node, None) ->
(Cfg.NodeMap.find node t.internalvar).internalin
2024-12-21 02:16:04 +01:00
| Some (node1, Some node2) ->
Utility.unique_union
(Cfg.NodeMap.find node1 t.internalvar).internalin
(Cfg.NodeMap.find node2 t.internalvar).internalin
)
) in
let newinternalbetween = (
match List.rev previnternalvar.internalbetween with
| [] -> []
| (i, _o) :: btwrest ->
let btwrest = List.rev btwrest in
let newbtwrest = List.map2
(fun (i, _o) (nexti, _nexto) -> (i, nexti))
btwrest
(Utility.drop_first_element_list previnternalvar.internalbetween)
in
newbtwrest @ [(i, newinternalout)]
) in
{ previnternalvar with
internalout = newinternalout;
internalbetween = newinternalbetween; }
2024-12-21 02:16:04 +01:00
let update (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
let newt = {t with internalvar = (Cfg.NodeMap.add node
(lucf t node)
t.internalvar)} in
2024-12-21 02:16:04 +01:00
lub newt node
let compute_live_variables (cfg: RISCCfg.t) : DVCfg.t =
DVCfg.from_cfg cfg
|> DVCfg.fixed_point ~init:init ~update:update
module VariableMap = struct
include Map.Make(Variable)
let first_empty next start m l =
let bindings =
List.fold_left (
fun acc x ->
match find_opt x m with
| None -> acc
| Some x -> x :: acc) [] l |> List.sort Variable.compare in
let rec aux x =
if List.mem x bindings
then aux (next x)
else x
in
aux start
let first_empty_Variable m l =
let next = fun x -> x |> int_of_string |> (+) 1 |> string_of_int in
let start = "1" in
first_empty next start m l
let get_mapping m l r =
match find_opt r m with
| None -> (
let newr = first_empty_Variable m l in
let newm = add r newr m in
(newm, newr)
)
| Some r -> (m, r)
end
2024-12-21 02:16:04 +01:00
(* just rename the registers that dont share live status *)
let optimize_cfg (t: DVCfg.t) : DVCfg.t =
let replace_code ((vin, vout): Variable.t list * Variable.t list)
(a: Variable.t VariableMap.t)
(code: DVCfg.elt)
: (Variable.t VariableMap.t * DVCfg.elt) =
match code with
| Nop -> (
(a, Nop)
)
| BRegOp (brop, r1, r2, r3) -> (
let (newa, newr1) = VariableMap.get_mapping a vin r1.index in
let (newa, newr2) = VariableMap.get_mapping newa vin r2.index in
let (newa, newr3) = VariableMap.get_mapping newa vout r3.index in
(newa, BRegOp (brop, {index = newr1}, {index = newr2}, {index = newr3}))
)
| BImmOp (biop, r1, i, r3) -> (
let (newa, newr1) = VariableMap.get_mapping a vin r1.index in
let (newa, newr3) = VariableMap.get_mapping newa vout r3.index in
(newa, BImmOp (biop, {index = newr1}, i, {index = newr3}))
)
| URegOp (urop, r1, r3) -> (
let (newa, newr1) = VariableMap.get_mapping a vin r1.index in
let (newa, newr3) = VariableMap.get_mapping newa vout r3.index in
(newa, URegOp (urop, {index = newr1}, {index = newr3}))
)
| Load (r1, r3) -> (
let (newa, newr1) = VariableMap.get_mapping a vin r1.index in
let (newa, newr3) = VariableMap.get_mapping newa vout r3.index in
(newa, Load ({index = newr1}, {index = newr3}))
)
| LoadI (i, r3) -> (
let (newa, newr3) = VariableMap.get_mapping a vout r3.index in
(newa, LoadI (i, {index = newr3}))
)
| Store (r1, r3) -> (
let (newa, newr1) = VariableMap.get_mapping a vin r1.index in
let (newa, newr3) = VariableMap.get_mapping newa vout r3.index in
(newa, Store ({index = newr1}, {index = newr3}))
)
in
let aux (assignments: Variable.t VariableMap.t) (t: DVCfg.t) (node: Cfg.Node.t)
: (Variable.t VariableMap.t * DVCfg.t) =
let livevars = Cfg.NodeMap.find node t.internalvar in
let code =
match Cfg.NodeMap.find_opt node t.t.content with
| None -> []
| Some x -> x
in
let newcode, newassignments =
(List.fold_left2
(fun (acc, assignments) btw code ->
let na, nc = replace_code btw assignments code in
(acc @ [nc], na)
)
([], assignments)
livevars.internalbetween
code)
in
let newcontent = Cfg.NodeMap.add
node
newcode
t.t.content
in
let newt = { t with t = { t.t with content = newcontent } } in
(newassignments, newt)
in
(* --------- *)
let assignments = VariableMap.empty in
let a, newt =
Cfg.NodeSet.fold (* for each node we replace all the variables with the
optimized ones *)
(fun node (ass, t) -> aux ass t node)
t.t.nodes
(assignments, t)
in
2024-12-21 02:16:04 +01:00
{ newt with
t = { newt.t with
inputOutputVar =
match newt.t.inputOutputVar with
None -> None
| Some (i, o) -> (
match VariableMap.find_opt i a, VariableMap.find_opt o a with
| None, None -> Some (i, o)
| Some i, None -> Some (i, o)
| None, Some o -> Some (i, o)
| Some i, Some o -> Some (i, o)
)
}}
2024-12-21 02:16:04 +01:00
let compute_cfg (dvcfg: DVCfg.t) : RISCCfg.t =
DVCfg.to_cfg dvcfg