heptagon/compiler/utilities/minils/interference_graph.ml
2011-05-25 09:12:13 +02:00

164 lines
3.8 KiB
OCaml

open Graph
type ilink =
| Iinterference
| Iaffinity
| Isame_value
type ivar =
| Ivar of Idents.var_ident
| Ifield of ivar * Names.field_name
module IvarEnv =
Map.Make (struct
type t = ivar
let compare = compare
end)
module IvarSet =
Set.Make (struct
type t = ivar
let compare = compare
end)
let rec ivar_to_string = function
| Ivar n -> Idents.name n
| Ifield(iv,f) -> (ivar_to_string iv)^"."^(Names.shortname f)
module VertexValue = struct
type t = ivar list ref
(*let compare = compare
let hash = Hashtbl.hash
let equal = (=)
let default = []*)
end
module EdgeValue = struct
type t = ilink
let default = Iinterference
let compare = compare
end
module G =
struct
include Imperative.Graph.AbstractLabeled(VertexValue)(EdgeValue)
let add_edge_v g n1 v n2 =
add_edge_e g (E.create n1 v n2)
let mem_edge_v g n1 n2 v =
try
(E.label (find_edge g n1 n2)) = v
with
Not_found -> false
let filter_succ g v n =
fold_succ_e (fun e acc -> if (E.label e) = v then (E.dst e)::acc else acc) g n []
let coalesce g n1 n2 =
if n1 <> n2 then (
iter_succ_e (fun e -> add_edge_e g (E.create n1 (E.label e) (E.dst e))) g n2;
let r = V.label n1 in
r := !(V.label n2) @ !r;
remove_vertex g n2
)
let vertices g =
fold_vertex (fun v acc -> v::acc) g []
let filter_vertices f g =
fold_vertex (fun v acc -> if f v then v::acc else acc) g []
end
type interference_graph = {
g_type : Types.ty;
g_graph : G.t;
g_hash : (ivar, G.V.t) Hashtbl.t
}
(** Functions to create graphs and nodes *)
let mk_node x =
G.V.create (ref [x])
let add_node g n =
G.add_vertex g.g_graph n;
List.iter (fun x -> Hashtbl.add g.g_hash x n) !(G.V.label n)
(* Hashtbl.add g.g_tag_hash n.g_tag n;
n.g_graph <- Some g*)
let node_for_value g x =
Hashtbl.find g.g_hash x
let mk_graph nodes ty =
let g = { g_graph = G.create ();
g_type = ty;
g_hash = Hashtbl.create 100 } in
List.iter (add_node g) nodes;
g
(** Functions to read the graph *)
let interfere g n1 n2 =
G.mem_edge_v g.g_graph n1 n2 Iinterference
let affinity g n1 n2 =
G.mem_edge_v g.g_graph n1 n2 Iaffinity
let have_same_value g n1 n2 =
G.mem_edge_v g.g_graph n1 n2 Isame_value
let interfere_with g n =
G.filter_succ g.g_graph Iinterference n
let affinity_with g n =
G.filter_succ g.g_graph Iaffinity n
let has_same_value_as g n =
G.filter_succ g.g_graph Isame_value n
(** Functions to modify the graph *)
let add_interference_link g n1 n2 =
if n1 <> n2 then (
G.remove_edge g.g_graph n1 n2;
G.add_edge_v g.g_graph n1 Iinterference n2
)
let add_affinity_link g n1 n2 =
if n1 <> n2 && not (G.mem_edge g.g_graph n1 n2) then (
G.remove_edge g.g_graph n1 n2;
G.add_edge_v g.g_graph n1 Iaffinity n2
)
let add_same_value_link g n1 n2 =
if n1 <> n2 && not (interfere g n1 n2) then (
G.remove_edge g.g_graph n1 n2;
G.add_edge_v g.g_graph n1 Isame_value n2
)
let coalesce g n1 n2 =
let find_wrong_same_value () =
let filter_same_value e acc =
if (G.E.label e) = Isame_value && not(have_same_value g n2 (G.E.dst e)) then
(G.E.dst e)::acc
else
acc
in
G.fold_succ_e filter_same_value g.g_graph n1 []
in
(* remove same value links no longer true *)
List.iter (fun n -> G.remove_edge g.g_graph n n1) (find_wrong_same_value ());
(* update the hash table*)
List.iter (fun x -> Hashtbl.replace g.g_hash x n1) !(G.V.label n2);
(* coalesce nodes in the graph*)
G.coalesce g.g_graph n1 n2
(** Iterates [f] on all the couple of nodes interfering in the graph g *)
let iter_interf f g =
let do_f e =
if G.E.label e = Iinterference then
f g (G.E.src e) (G.E.dst e)
in
G.iter_edges_e do_f g.g_graph