Fixes defined variables, fixes live variables, implements reduces registers, fixes risc semantic
This commit is contained in:
@ -50,13 +50,13 @@ let variables_used (instr : DVCfg.elt) : DVCfg.internal list =
|
||||
| Nop
|
||||
| LoadI (_, _) ->
|
||||
acc
|
||||
| Store (r1, r2)
|
||||
| BRegOp (_, r1, r2, _) ->
|
||||
DVCeltSet.add r1.index acc |>
|
||||
DVCeltSet.add r2.index
|
||||
| BImmOp (_, r1, _, _)
|
||||
| URegOp (_, r1, _)
|
||||
| Load (r1, _)
|
||||
| Store (r1, _) ->
|
||||
| Load (r1, _) ->
|
||||
DVCeltSet.add r1.index acc
|
||||
in
|
||||
|
||||
@ -71,24 +71,18 @@ let variables_used_all (instructions : DVCfg.elt list) : DVCfg.internal list =
|
||||
let variables_defined (instructions : DVCfg.elt) : DVCfg.internal list =
|
||||
let helper (acc: DVCeltSet.t) (instr: DVCfg.elt) =
|
||||
match instr with
|
||||
| Nop -> acc
|
||||
| Nop
|
||||
| Store (_, _) -> acc
|
||||
| BRegOp (_, _, _, r3)
|
||||
| BImmOp (_, _, _, r3)
|
||||
| URegOp (_, _, r3)
|
||||
| Load (_, r3)
|
||||
| LoadI (_, r3)
|
||||
| Store (_, r3) ->
|
||||
| LoadI (_, r3) ->
|
||||
DVCeltSet.add r3.index acc
|
||||
in
|
||||
|
||||
helper DVCeltSet.empty instructions |> DVCeltSet.to_list
|
||||
|
||||
let variables_defined_all (instructions : DVCfg.elt list) : DVCfg.internal list =
|
||||
List.fold_left (fun (acc: DVCeltSet.t) (instr: DVCfg.elt) ->
|
||||
DVCeltSet.union acc (variables_defined instr |> DVCeltSet.of_list)
|
||||
) DVCeltSet.empty instructions |> DVCeltSet.to_list
|
||||
|
||||
|
||||
|
||||
(* init function, assign the bottom to everything *)
|
||||
let _init_bottom : (DVCfg.elt list -> DVCfg.internalnode) =
|
||||
@ -104,91 +98,91 @@ let init_top (all_variables) : (DVCfg.elt list -> DVCfg.internalnode) =
|
||||
(fun _ -> (all_variables, all_variables)))})
|
||||
|
||||
|
||||
(* piece of code that computes vout for the whole block, not used,
|
||||
use lub below *)
|
||||
let _dumb_lub (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
|
||||
let previnternalvar = Cfg.NodeMap.find node t.internalvar in
|
||||
let code = Cfg.NodeMap.find node t.t.content in
|
||||
{ previnternalvar with
|
||||
internalout =
|
||||
Utility.unique_union (variables_defined_all code) (previnternalvar.internalin)
|
||||
}
|
||||
|
||||
|
||||
(* We consider only the propagation in the middle elements during the lub.
|
||||
This incurs in a performance penality, but it is simpler to implement.
|
||||
Each node is connected to one previus node.
|
||||
*)
|
||||
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)) ->
|
||||
(i, Utility.unique_union i (variables_defined code)))
|
||||
(List.combine code previnternalvar.internalbetween)
|
||||
) in
|
||||
|
||||
let newinternalout =
|
||||
match newinternalbetween with
|
||||
| [] -> previnternalvar.internalin
|
||||
| _ -> (snd (Utility.last_list newinternalbetween))
|
||||
in
|
||||
|
||||
{ previnternalvar with
|
||||
internalbetween =
|
||||
List.mapi (* we don't NEED the index but i = 0 is easier to write than
|
||||
to check if vinout is None *)
|
||||
(fun i (ithcode, vinout, ithcodeprev) ->
|
||||
if i = 0 then
|
||||
let dvin = previnternalvar.internalin in
|
||||
(dvin, Utility.unique_union dvin (variables_defined ithcode))
|
||||
else (
|
||||
let ithcodeprev = match ithcodeprev with
|
||||
None -> ([], [])
|
||||
| Some x -> x
|
||||
in
|
||||
match vinout with
|
||||
None ->
|
||||
([], variables_defined ithcode)
|
||||
| Some prevdvbtw ->
|
||||
(snd prevdvbtw,
|
||||
Utility.unique_union
|
||||
(variables_defined ithcode)
|
||||
(ithcodeprev |> fst)
|
||||
))
|
||||
)
|
||||
(* ugly code that zips the three lists that we need to compute each vin
|
||||
and vout for the middle of the code *)
|
||||
(Utility.combine_thrice
|
||||
code
|
||||
(Utility.pad_opt
|
||||
(Utility.prev previnternalvar.internalbetween None) None (List.length code))
|
||||
(Utility.pad previnternalvar.internalbetween None (List.length code))
|
||||
);
|
||||
internalout =
|
||||
match previnternalvar.internalbetween with
|
||||
[] -> previnternalvar.internalin
|
||||
| _ -> (snd (Utility.last_list previnternalvar.internalbetween))
|
||||
}
|
||||
internalbetween = newinternalbetween;
|
||||
internalout = newinternalout }
|
||||
|
||||
let lucf (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
|
||||
let previnternalvar = Cfg.NodeMap.find node t.internalvar in
|
||||
|
||||
if Option.equal (=) (Some node) t.t.initial then
|
||||
(* if L is initial set dvin to the "in" register *)
|
||||
let newinternalin = (
|
||||
match t.t.inputOutputVar with
|
||||
Some (i, _) -> [i]
|
||||
| None -> []
|
||||
) in
|
||||
|
||||
let newinternalbetween = ( (* set the dvin of each to the previous dvout *)
|
||||
match previnternalvar.internalbetween with
|
||||
[] -> []
|
||||
| [(_i, o)] -> [(newinternalin, o)]
|
||||
| (_i, o) :: btwrest ->
|
||||
(newinternalin, o) :: (
|
||||
List.map (fun ((_i, o), (_previ, prevo)) -> (prevo, o))
|
||||
(Utility.combine_twice btwrest previnternalvar.internalbetween)
|
||||
)
|
||||
) in
|
||||
{ previnternalvar with
|
||||
internalin =
|
||||
match t.t.inputOutputVar with
|
||||
Some (i, _) -> [i]
|
||||
| None -> []
|
||||
}
|
||||
internalin = newinternalin;
|
||||
internalbetween = newinternalbetween }
|
||||
else
|
||||
(* if L is not initial set dvin to the intersection of the previous node's
|
||||
dvouts *)
|
||||
let prevnodes = Cfg.NodeMap.find node t.t.reverseEdges in
|
||||
let newinternalin = (
|
||||
match prevnodes with
|
||||
| [] ->
|
||||
[]
|
||||
| [prevnode] ->
|
||||
(Cfg.NodeMap.find prevnode t.internalvar).internalout
|
||||
| [prevnode1; prevnode2] ->
|
||||
Utility.unique_intersection
|
||||
(Cfg.NodeMap.find prevnode1 t.internalvar).internalout
|
||||
(Cfg.NodeMap.find prevnode2 t.internalvar).internalout
|
||||
| prevnode :: restnodes ->
|
||||
List.fold_left (* intersection of all previous nodes' dvout *)
|
||||
(fun acc prevnode ->
|
||||
Utility.unique_intersection
|
||||
acc
|
||||
(Cfg.NodeMap.find prevnode t.internalvar).internalout)
|
||||
(Cfg.NodeMap.find prevnode t.internalvar).internalout
|
||||
restnodes
|
||||
) in
|
||||
|
||||
let newinternalbetween =
|
||||
match previnternalvar.internalbetween with
|
||||
[] -> []
|
||||
| [(_i, o)] -> [(newinternalin, o)]
|
||||
| (_i, o) :: btwrest ->
|
||||
(newinternalin, o) :: (
|
||||
List.map (fun ((_i, o), (_previ, prevo)) -> (prevo, o))
|
||||
(Utility.combine_twice btwrest previnternalvar.internalbetween)
|
||||
)
|
||||
in
|
||||
{ previnternalvar with
|
||||
internalin =
|
||||
match prevnodes with
|
||||
[] -> []
|
||||
| [prevnode] -> (Cfg.NodeMap.find prevnode t.internalvar).internalout
|
||||
| [prevnode1; prevnode2] ->
|
||||
Utility.unique_intersection
|
||||
(Cfg.NodeMap.find prevnode1 t.internalvar).internalout
|
||||
(Cfg.NodeMap.find prevnode2 t.internalvar).internalout
|
||||
| _ ->
|
||||
List.fold_left (* intersection of all previous nodes' dvout *)
|
||||
(fun acc prevnode ->
|
||||
Utility.unique_intersection acc (Cfg.NodeMap.find prevnode t.internalvar).internalout)
|
||||
[]
|
||||
prevnodes
|
||||
}
|
||||
internalin = newinternalin;
|
||||
internalbetween = newinternalbetween }
|
||||
|
||||
|
||||
let update (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
|
||||
@ -198,10 +192,16 @@ let update (t: DVCfg.t) (node: Cfg.Node.t) : DVCfg.internalnode =
|
||||
|
||||
let compute_defined_variables (cfg: RISCCfg.t) : DVCfg.t =
|
||||
let all_variables = List.fold_left
|
||||
(fun acc (_, code) -> Utility.unique_union acc (variables_all code))
|
||||
(fun acc (_, code) ->
|
||||
Utility.unique_union acc (variables_all code))
|
||||
[]
|
||||
(Cfg.NodeMap.to_list cfg.content)
|
||||
in
|
||||
let all_variables =
|
||||
match cfg.inputOutputVar with
|
||||
| None -> all_variables
|
||||
| Some (i, o) -> Utility.unique_union all_variables [i;o]
|
||||
in
|
||||
DVCfg.from_cfg cfg
|
||||
|> DVCfg.fixed_point ~init:(init_top all_variables) ~update:update
|
||||
|
||||
|
||||
Reference in New Issue
Block a user