module Vertex = struct
module V = struct
type t = int
let compare = compare
end
include V
module Set = Set.Make(V)
module Map = MyMap.Make(V)
end
module VertexSetMap =
SetMap.MakeHomo(Vertex.Set)(Vertex.Map)
module MIPSRegisterSetMap =
SetMap.MakeHetero(MIPS.RegisterSet)(Vertex.Map)
module PrioritySet =
PrioritySet.Make(Vertex)
module RegMap : sig
type t
val empty: t
val forward: Vertex.t -> t -> Register.Set.t
val backward: Register.t -> t -> Vertex.t
val add: Register.t -> Vertex.t -> t -> t
val fold: (Vertex.t -> Register.Set.t -> 'a -> 'a) -> t -> 'a -> 'a
val coalesce: Vertex.t -> Vertex.t -> t -> t
val remove: Vertex.t -> t -> t
val restrict: (Vertex.t -> bool) -> t -> t
end = struct
type t = {
forward: Register.Set.t Vertex.Map.t;
backward: Vertex.t Register.Map.t
}
let empty = {
forward = Vertex.Map.empty;
backward = Register.Map.empty
}
let forward v m =
Vertex.Map.find v m.forward
let backward r m =
try
Register.Map.find r m.backward
with Not_found ->
assert false
let add r v m = {
forward = Vertex.Map.add v (Register.Set.singleton r) m.forward;
backward = Register.Map.add r v m.backward
}
let fold f m accu =
Vertex.Map.fold f m.forward accu
let coalesce x y m =
let rx, forward = Vertex.Map.find_remove x m.forward in
let forward = Vertex.Map.update y (Register.Set.union rx) forward in
let backward =
Register.Set.fold (fun r backward ->
Register.Map.add r y backward
) rx m.backward
in
{
forward = forward;
backward = backward
}
let remove x m =
let rx, forward = Vertex.Map.find_remove x m.forward in
let backward = Register.Set.fold Register.Map.remove rx m.backward in
{
forward = forward;
backward = backward
}
let restrict p m = {
forward = Vertex.Map.restrict p m.forward;
backward = Register.Map.restrict (fun r -> p (backward r m)) m.backward
}
end
type graph = {
regmap: RegMap.t;
ivv: VertexSetMap.t;
ivh: MIPSRegisterSetMap.t;
pvv: VertexSetMap.t;
pvh: MIPSRegisterSetMap.t;
degree: PrioritySet.t;
nmr: PrioritySet.t;
}
let exists graph v =
try
let _ = RegMap.forward v graph.regmap in
true
with Not_found ->
false
class virtual subgraph = object (self)
method virtual getvv: graph -> VertexSetMap.t
method virtual setvv: graph -> VertexSetMap.t -> graph
method virtual getvh: graph -> MIPSRegisterSetMap.t
method virtual setvh: graph -> MIPSRegisterSetMap.t -> graph
method neighborsv graph v =
VertexSetMap.find v (self#getvv graph)
method existsvv graph v1 v2 =
Vertex.Set.mem v1 (self#neighborsv graph v2)
method neighborsh graph v =
MIPSRegisterSetMap.find v (self#getvh graph)
method existsvh graph v h =
MIPS.RegisterSet.mem h (self#neighborsh graph v)
method degree graph v =
Vertex.Set.cardinal (self#neighborsv graph v) + MIPS.RegisterSet.cardinal (self#neighborsh graph v)
method hwregs graph =
let union _ = MIPS.RegisterSet.union in
Vertex.Map.fold union (self#getvh graph) MIPS.RegisterSet.empty
method iter graph fvv fvh =
Vertex.Map.iter (fun vertex neighbors ->
Vertex.Set.iter (fun neighbor ->
if vertex < neighbor then
fvv vertex neighbor
) neighbors
) (self#getvv graph);
Vertex.Map.iter (fun vertex neighbors ->
MIPS.RegisterSet.iter (fun neighbor ->
fvh vertex neighbor
) neighbors
) (self#getvh graph)
method mkvv graph v1 v2 =
if v1 = v2 then
graph
else if self#existsvv graph v1 v2 then
graph
else
self#mkvvi graph v1 v2
method mkvvi graph v1 v2 =
self#setvv graph (VertexSetMap.mkbiedge v1 v2 (self#getvv graph))
method rmvv graph v1 v2 =
assert (self#existsvv graph v1 v2);
self#setvv graph (VertexSetMap.rmbiedge v1 v2 (self#getvv graph))
method rmvvifx graph v1 v2 =
if self#existsvv graph v1 v2 then
self#rmvv graph v1 v2
else
graph
method mkvh graph v h =
if self#existsvh graph v h then
graph
else
self#mkvhi graph v h
method mkvhi graph v h =
self#setvh graph (MIPSRegisterSetMap.update v (MIPS.RegisterSet.add h) (self#getvh graph))
method rmvh graph v h =
assert (self#existsvh graph v h);
self#setvh graph (MIPSRegisterSetMap.update v (MIPS.RegisterSet.remove h) (self#getvh graph))
method rmvhifx graph v h =
if self#existsvh graph v h then
self#rmvh graph v h
else
graph
method coalesce graph x y =
let graph =
Vertex.Set.fold (fun w graph ->
self#mkvv (self#rmvv graph x w) y w
) (self#neighborsv graph x) graph
in
let graph =
MIPS.RegisterSet.fold (fun h graph ->
self#mkvh (self#rmvh graph x h) y h
) (self#neighborsh graph x) graph
in
graph
method coalesceh graph x h =
let graph =
Vertex.Set.fold (fun w graph ->
self#mkvh (self#rmvv graph x w) w h
) (self#neighborsv graph x) graph
in
let graph =
MIPS.RegisterSet.fold (fun k graph ->
self#rmvh graph x k
) (self#neighborsh graph x) graph
in
graph
method remove graph x =
let graph =
Vertex.Set.fold (fun w graph ->
self#rmvv graph x w
) (self#neighborsv graph x) graph
in
let graph =
MIPS.RegisterSet.fold (fun h graph ->
self#rmvh graph x h
) (self#neighborsh graph x) graph
in
graph
end
class interference (preference : preference Lazy.t) = object (self)
inherit subgraph as super
method getvv graph = graph.ivv
method setvv graph m = { graph with ivv = m }
method getvh graph = graph.ivh
method setvh graph m = { graph with ivh = m }
method mkvvi graph v1 v2 =
let graph = super#mkvvi graph v1 v2 in
let graph = (Lazy.force preference)#rmvvifx graph v1 v2 in
{ graph with
degree = PrioritySet.increment v1 1 (PrioritySet.increment v2 1 graph.degree);
nmr = PrioritySet.incrementifx v1 1 (PrioritySet.incrementifx v2 1 graph.nmr);
}
method rmvv graph v1 v2 =
let graph = super#rmvv graph v1 v2 in
{ graph with
degree = PrioritySet.increment v1 (-1) (PrioritySet.increment v2 (-1) graph.degree);
nmr = PrioritySet.incrementifx v1 (-1) (PrioritySet.incrementifx v2 (-1) graph.nmr);
}
method mkvhi graph v h =
let graph = super#mkvhi graph v h in
let graph = (Lazy.force preference)#rmvhifx graph v h in
{ graph with
degree = PrioritySet.increment v 1 graph.degree;
nmr = PrioritySet.incrementifx v 1 graph.nmr;
}
method rmvh graph v h =
let graph = super#rmvh graph v h in
{ graph with
degree = PrioritySet.increment v (-1) graph.degree;
nmr = PrioritySet.incrementifx v (-1) graph.nmr;
}
end
and preference (interference : interference Lazy.t) = object (self)
inherit subgraph as super
method getvv graph = graph.pvv
method setvv graph m = { graph with pvv = m }
method getvh graph = graph.pvh
method setvh graph m = { graph with pvh = m }
method nmr graph v =
Vertex.Set.is_empty (self#neighborsv graph v) &&
MIPS.RegisterSet.is_empty (self#neighborsh graph v)
method mkcheck graph v =
if self#nmr graph v then
{ graph with
nmr = PrioritySet.remove v graph.nmr }
else
graph
method mkvvi graph v1 v2 =
if (Lazy.force interference)#existsvv graph v1 v2 then
graph
else
let graph = self#mkcheck graph v1 in
let graph = self#mkcheck graph v2 in
super#mkvvi graph v1 v2
method mkvhi graph v h =
if (Lazy.force interference)#existsvh graph v h then
graph
else
let graph = self#mkcheck graph v in
super#mkvhi graph v h
method rmcheck graph v =
if self#nmr graph v then
{ graph with
nmr = PrioritySet.add v (PrioritySet.priority v graph.degree) graph.nmr
}
else
graph
method rmvv graph v1 v2 =
let graph = super#rmvv graph v1 v2 in
let graph = self#rmcheck graph v1 in
let graph = self#rmcheck graph v2 in
graph
method rmvh graph v h =
let graph = super#rmvh graph v h in
let graph = self#rmcheck graph v in
graph
end
let rec interference = lazy (new interference preference)
and preference = lazy (new preference interference)
let interference = Lazy.force interference
let preference = Lazy.force preference
let ipp graph v =
assert (exists graph v);
interference#neighborsv graph v
let iph graph v =
assert (exists graph v);
interference#neighborsh graph v
let ppp graph v =
assert (exists graph v);
preference#neighborsv graph v
let pph graph v =
assert (exists graph v);
preference#neighborsh graph v
let degree graph v =
assert (exists graph v);
PrioritySet.priority v graph.degree
let lowest graph =
PrioritySet.lowest graph.degree
let lowest_non_move_related graph =
PrioritySet.lowest graph.nmr
let fold f graph accu =
RegMap.fold (fun v _ accu -> f v accu) graph.regmap accu
let minimum f graph =
match
fold (fun w accu ->
let dw = f w in
match accu with
| None ->
Some (dw, w)
| Some (dv, v) ->
if dw < dv then
Some (dw, w)
else
accu
) graph None
with
| None ->
None
| Some (_, v) ->
Some v
type ppedge =
Vertex.t * Vertex.t
let pppick graph p =
VertexSetMap.pick graph.pvv p
type phedge =
Vertex.t * MIPS.register
let phpick graph p =
MIPSRegisterSetMap.pick graph.pvh p
let create regs =
let (_ : int), regmap, degree =
Register.Set.fold (fun r (v, regmap, degree) ->
v+1,
RegMap.add r v regmap,
PrioritySet.add v 0 degree
) regs (0, RegMap.empty, PrioritySet.empty)
in
{
regmap = regmap;
ivv = Vertex.Map.empty;
ivh = Vertex.Map.empty;
pvv = Vertex.Map.empty;
pvh = Vertex.Map.empty;
degree = degree;
nmr = degree
}
let lookup graph r =
RegMap.backward r graph.regmap
let registers graph v =
assert (exists graph v);
RegMap.forward v graph.regmap
let mkipp graph regs1 regs2 =
Register.Set.fold (fun r1 graph ->
let v1 = lookup graph r1 in
Register.Set.fold (fun r2 graph ->
interference#mkvv graph v1 (lookup graph r2)
) regs2 graph
) regs1 graph
let mkiph graph regs hwregs =
Register.Set.fold (fun r graph ->
let v = lookup graph r in
MIPS.RegisterSet.fold (fun h graph ->
interference#mkvh graph v h
) hwregs graph
) regs graph
let mki graph (regs1, hwregs1) (regs2, hwregs2) =
let graph = mkipp graph regs1 regs2 in
let graph = mkiph graph regs1 hwregs2 in
let graph = mkiph graph regs2 hwregs1 in
graph
let mkppp graph r1 r2 =
let v1 = lookup graph r1
and v2 = lookup graph r2 in
let graph = preference#mkvv graph v1 v2 in
graph
let mkpph graph r h =
let v = lookup graph r in
let graph = preference#mkvh graph v h in
graph
open Printf
let hwregs graph =
MIPS.RegisterSet.union (interference#hwregs graph) (preference#hwregs graph)
let print_vertex graph v =
Register.Set.print (registers graph v)
let print f graph =
fprintf f "graph G {\n";
fprintf f "orientation = landscape;\n";
fprintf f "rankdir = LR;\n";
fprintf f "ratio = compress;\n\n";
RegMap.fold (fun vertex regs () ->
fprintf f "r%d [ label=\"%s\" ] ;\n" vertex (Register.Set.print regs)
) graph.regmap ();
MIPS.RegisterSet.iter (fun hwr ->
let name = MIPS.print hwr in
fprintf f "hwr%s [ label=\"$%s\" ] ;\n" name name
) (hwregs graph);
interference#iter graph
(fun vertex neighbor ->
fprintf f "r%d -- r%d ;\n" vertex neighbor)
(fun vertex neighbor ->
fprintf f "r%d -- hwr%s ;\n" vertex (MIPS.print neighbor));
preference#iter graph
(fun vertex neighbor ->
fprintf f "r%d -- r%d [ style = dashed ] ;\n" vertex neighbor)
(fun vertex neighbor ->
fprintf f "r%d -- hwr%s [ style = dashed ] ;\n" vertex (MIPS.print neighbor));
fprintf f "\n}\n"
let coalesce graph x y =
assert (exists graph x);
assert (exists graph y);
assert (x <> y);
assert (not (interference#existsvv graph x y));
let graph = interference#coalesce graph x y in
let graph = preference#coalesce graph x y in
{
graph with
regmap = RegMap.coalesce x y graph.regmap;
ivh = Vertex.Map.remove x graph.ivh;
pvh = Vertex.Map.remove x graph.pvh;
degree = PrioritySet.remove x graph.degree;
nmr = PrioritySet.remove x graph.nmr;
}
let coalesceh graph x h =
assert (exists graph x);
assert (not (interference#existsvh graph x h));
let graph = interference#coalesceh graph x h in
let graph = preference#coalesceh graph x h in
{
graph with
regmap = RegMap.remove x graph.regmap;
ivh = Vertex.Map.remove x graph.ivh;
pvh = Vertex.Map.remove x graph.pvh;
degree = PrioritySet.remove x graph.degree;
nmr = PrioritySet.remove x graph.nmr;
}
let freeze graph x =
assert (exists graph x);
preference#remove graph x
let remove graph v =
assert (exists graph v);
let graph = interference#remove graph v in
let graph = preference#remove graph v in
{
graph with
regmap = RegMap.remove v graph.regmap;
degree = PrioritySet.remove v graph.degree;
nmr = PrioritySet.remove v graph.nmr;
}
let mkdeg graph =
let degree, nmr =
fold (fun v (degree, nmr) ->
let d = interference#degree graph v in
PrioritySet.add v d degree,
if preference#nmr graph v then PrioritySet.add v d nmr else nmr
) graph (PrioritySet.empty, PrioritySet.empty)
in
{ graph with
degree = degree;
nmr = nmr;
}
let restrict graph p =
mkdeg {
graph with
regmap = RegMap.restrict p graph.regmap;
ivv = VertexSetMap.restrict p graph.ivv;
ivh = Vertex.Map.restrict p graph.ivh;
pvv = VertexSetMap.restrict p graph.pvv;
pvh = Vertex.Map.restrict p graph.pvh;
}
let droph graph =
mkdeg {
graph with
ivh = Vertex.Map.empty;
pvh = Vertex.Map.empty;
}