1 type pseudoregister = Registers.register
2 type hwregister = I8051.register
3 module HwOrdReg = struct type t = hwregister let compare = compare end
4 module HwRegisterSet = Set.Make (HwOrdReg)
6 let hwregisterset_of_list =
8 (fun reg set -> HwRegisterSet.add reg set)
11 (* Pasted from Pottier's PP compiler *)
13 (* This module implements a data structure for interference graphs.
14 It provides functions that help construct, transform and inspect
15 interference graphs. *)
17 (* ------------------------------------------------------------------------- *)
19 (* Vertices are represented as integers. We need sets of vertices, maps over
20 vertices, maps of vertices to nonempty sets of vertices, maps of vertices
21 to nonempty sets of hardware registers, and priority sets over vertices. *)
23 module Vertex = struct
32 module Set = Set.Make(V)
34 module Map = MyMap.Make(V)
39 SetMap.MakeHomo(Vertex.Set)(Vertex.Map)
41 module I8051RegisterSetMap =
42 SetMap.MakeHetero(HwRegisterSet)(Vertex.Map)
45 PrioritySet.Make(Vertex)
47 (* ------------------------------------------------------------------------- *)
49 (* Each vertex maps to a set of pseudo-registers, which initially is a
50 singleton set, but can grow due to coalescing. Conversely, each
51 pseudo-register maps to a single vertex. *)
57 (* [empty] is the empty map. *)
61 (* [forward] maps a vertex to a set of pseudo-registers. *)
63 val forward: Vertex.t -> t -> pseudoregister Pset.set
65 (* [backward] maps a pseudo-register to a vertex. *)
67 val backward: pseudoregister -> t -> Vertex.t
69 (* [add r v m] adds a relation between pseudo-register [r] and
70 vertex [v], both of which are assumed fresh. *)
72 val add: pseudoregister -> Vertex.t -> t -> t
74 (* [fold f m accu] folds over all vertices. *)
76 val fold: (Vertex.t -> pseudoregister Pset.set -> 'a -> 'a) -> t -> 'a -> 'a
78 (* [coalesce x y m] coalesces vertices [x] and [y]. Vertex [x] is
79 removed and the pseudo-registers associated with it become
80 associated with [y] instead. *)
82 val coalesce: Vertex.t -> Vertex.t -> t -> t
84 (* [remove x m] removes vertex [x]. The pseudo-registers associated
85 with [x] disappear. *)
87 val remove: Vertex.t -> t -> t
89 (* [restrict] keeps only those vertices that satisfy predicate [p]. *)
91 val restrict: (Vertex.t -> bool) -> t -> t
96 forward: pseudoregister Pset.set Vertex.Map.t;
97 backward: (pseudoregister,Vertex.t) Pmap.map
101 forward = Vertex.Map.empty;
102 backward = Pmap.empty
106 Vertex.Map.find v m.forward
110 Pmap.find r m.backward
112 assert false (* bad pseudo-register *)
115 forward = Vertex.Map.add v (Pset.singleton r) m.forward;
116 backward = Pmap.add r v m.backward
120 Vertex.Map.fold f m.forward accu
123 let rx, forward = Vertex.Map.find_remove x m.forward in
124 let forward = Vertex.Map.update y (Pset.union rx) forward in
126 Pset.fold (fun r backward ->
127 Pmap.add r y backward
136 let rx, forward = Vertex.Map.find_remove x m.forward in
137 let backward = Pset.fold Pmap.remove rx m.backward in
144 forward = Vertex.Map.restrict p m.forward;
145 backward = Pmap.restrict (fun r -> p (backward r m)) m.backward
150 (* ------------------------------------------------------------------------- *)
156 (* A two-way correspondence between vertices and pseudo-registers.
157 This data structure is also used to keep a record of the set of
162 (* Interference edges between two vertices: ``these two vertices
163 cannot receive the same color''. *)
167 (* Interference edges between a vertex and a hardware register:
168 ``this vertex cannot receive this color''. *)
170 ivh: I8051RegisterSetMap.t;
172 (* Preference edges between two vertices: ``these two vertices
173 should preferably receive the same color''. *)
177 (* Preference edges between a vertex and a hardware register:
178 ``this vertex should preferably receive this color''. *)
180 pvh: I8051RegisterSetMap.t;
182 (* The degree of each vertex [v], that is, the number of vertices
183 and hardware registers that [v] interferes with, is recorded at
184 all times. We use a ``priority set'' so as to be able to
185 efficiently find a vertex of minimum degree. *)
187 degree: PrioritySet.t;
189 (* The degree of each *non-move-related* vertex [v]. This
190 information is partially redundant with the [degree] field
191 above. It is nevertheless required in order to be able to
192 efficiently find a *non-move-related* vertex of minimum
199 (* ------------------------------------------------------------------------- *)
201 (* Our graphs are made up of two subgraphs: the subgraph formed by the
202 interference edges alone and the one formed by the preference edges
205 In order to allow more code sharing, we define functions that allow
206 dealing with a single subgraph at a time. They provide operations
207 such as inspecting the neighbors of a vertex, adding edges,
208 removing edges, coalescing two vertices, removing a vertex, etc.
210 We first define functions that deal with a ``generic'' subgraph,
211 then (via inheritance) specialize them to deal with the
212 interference subgraph and the preference subgraph with their
213 specific features. *)
215 class virtual subgraph = object (self)
217 (* These methods provide access to the fields of the [graph] data
218 structure that define the subgraph of interest. All data is
219 stored in the [graph] data structure. The object [self] has no
220 state and holds no data. *)
222 method virtual getvv: graph -> VertexSetMap.t
223 method virtual setvv: graph -> VertexSetMap.t -> graph
224 method virtual getvh: graph -> I8051RegisterSetMap.t
225 method virtual setvh: graph -> I8051RegisterSetMap.t -> graph
227 (* Accessing the neighbors of a vertex and testing whether edges
230 method neighborsv graph v =
231 VertexSetMap.find v (self#getvv graph)
233 method existsvv graph v1 v2 =
234 Vertex.Set.mem v1 (self#neighborsv graph v2)
236 method neighborsh graph v =
237 I8051RegisterSetMap.find v (self#getvh graph)
239 method existsvh graph v h =
240 HwRegisterSet.mem h (self#neighborsh graph v)
242 (* [degree graph v] is the degree of vertex [v] with respect to the
245 method degree graph v =
246 Vertex.Set.cardinal (self#neighborsv graph v) + HwRegisterSet.cardinal (self#neighborsh graph v)
248 (* [hwregs graph] is the set of all hardware registers mentioned in
251 method hwregs graph =
252 let union _ = HwRegisterSet.union in
253 Vertex.Map.fold union (self#getvh graph) HwRegisterSet.empty
255 (* [iter graph fvv fvh] iterates over all edges in the subgraph.
256 Vertex-to-vertex edges are presented only once. *)
258 method iter graph fvv fvh =
259 Vertex.Map.iter (fun vertex neighbors ->
260 Vertex.Set.iter (fun neighbor ->
261 if vertex < neighbor then
264 ) (self#getvv graph);
265 Vertex.Map.iter (fun vertex neighbors ->
266 HwRegisterSet.iter (fun neighbor ->
271 (* [mkvv graph v1 v2] adds an edge between vertices [v1] and [v2]. *)
273 method mkvv graph v1 v2 =
275 graph (* avoid creating self-edge *)
276 else if self#existsvv graph v1 v2 then
277 graph (* avoid re-adding an existing edge *)
279 self#mkvvi graph v1 v2
281 method mkvvi graph v1 v2 =
282 self#setvv graph (VertexSetMap.mkbiedge v1 v2 (self#getvv graph))
284 (* [rmvv graph v1 v2] removes an edge between vertices [v1] and [v2].
285 [rmvvifx] removes an edge if it exists. *)
287 method rmvv graph v1 v2 =
288 assert (self#existsvv graph v1 v2);
289 self#setvv graph (VertexSetMap.rmbiedge v1 v2 (self#getvv graph))
291 method rmvvifx graph v1 v2 =
292 if self#existsvv graph v1 v2 then
293 self#rmvv graph v1 v2
297 (* [mkvh graph v h] adds an edge between vertex [v] and hardware
300 method mkvh graph v h =
301 if self#existsvh graph v h then
302 graph (* avoid re-adding an existing edge *)
306 method mkvhi graph v h =
307 self#setvh graph (I8051RegisterSetMap.update v (HwRegisterSet.add h) (self#getvh graph))
309 (* [rmvh v h] removes an edge between vertex [v] and hardware
310 register [h]. [rmvhifx] removes an edge if it exists. *)
312 method rmvh graph v h =
313 assert (self#existsvh graph v h);
314 self#setvh graph (I8051RegisterSetMap.update v (HwRegisterSet.remove h) (self#getvh graph))
316 method rmvhifx graph v h =
317 if self#existsvh graph v h then
322 (* [coalesce graph x y] turns every neighbor [w] or [h] of [x] into
323 a neighbor of [y] instead. [w] ranges over both vertices and
324 hardware registers. *)
326 method coalesce graph x y =
328 Vertex.Set.fold (fun w graph ->
329 self#mkvv (self#rmvv graph x w) y w
330 ) (self#neighborsv graph x) graph
333 HwRegisterSet.fold (fun h graph ->
334 self#mkvh (self#rmvh graph x h) y h
335 ) (self#neighborsh graph x) graph
339 (* [coalesceh graph x h] turns every neighbor [w] of [x] into a
340 neighbor of [h] instead. [w] ranges over both vertices and
341 hardware registers. Edges between two hardware registers are not
344 method coalesceh graph x h =
346 Vertex.Set.fold (fun w graph ->
347 self#mkvh (self#rmvv graph x w) w h
348 ) (self#neighborsv graph x) graph
351 HwRegisterSet.fold (fun k graph ->
353 ) (self#neighborsh graph x) graph
357 (* [remove graph x] removes all edges carried by vertex [x]. *)
359 method remove graph x =
361 Vertex.Set.fold (fun w graph ->
363 ) (self#neighborsv graph x) graph
366 HwRegisterSet.fold (fun h graph ->
368 ) (self#neighborsh graph x) graph
374 (* ------------------------------------------------------------------------- *)
376 (* The interference subgraph.
378 This is a subgraph with the following specific features: (1) the
379 degree of every vertex is recorded in the [degree] field of the
380 [graph] data structure; (2) the degree of every non-move-related
381 vertex is recorded in the [nmr] field of the [graph] data
382 structure; (3) creating an edge in the interference subgraph
383 automatically destroys a corresponding edge in the preference
386 class interference (preference : preference Lazy.t) = object (self)
388 inherit subgraph as super
390 method getvv graph = graph.ivv
391 method setvv graph m = { graph with ivv = m }
392 method getvh graph = graph.ivh
393 method setvh graph m = { graph with ivh = m }
395 (* Override the edge creation and destruction methods. *)
397 method mkvvi graph v1 v2 =
398 let graph = super#mkvvi graph v1 v2 in
399 let graph = (Lazy.force preference)#rmvvifx graph v1 v2 in (* do not constrain an existing preference edge *)
401 degree = PrioritySet.increment v1 1 (PrioritySet.increment v2 1 graph.degree);
402 nmr = PrioritySet.incrementifx v1 1 (PrioritySet.incrementifx v2 1 graph.nmr);
405 method rmvv graph v1 v2 =
406 let graph = super#rmvv graph v1 v2 in
408 degree = PrioritySet.increment v1 (-1) (PrioritySet.increment v2 (-1) graph.degree);
409 nmr = PrioritySet.incrementifx v1 (-1) (PrioritySet.incrementifx v2 (-1) graph.nmr);
412 method mkvhi graph v h =
413 let graph = super#mkvhi graph v h in
414 let graph = (Lazy.force preference)#rmvhifx graph v h in (* do not constrain an existing preference edge *)
416 degree = PrioritySet.increment v 1 graph.degree;
417 nmr = PrioritySet.incrementifx v 1 graph.nmr;
420 method rmvh graph v h =
421 let graph = super#rmvh graph v h in
423 degree = PrioritySet.increment v (-1) graph.degree;
424 nmr = PrioritySet.incrementifx v (-1) graph.nmr;
429 (* ------------------------------------------------------------------------- *)
431 (* The preference subgraph.
433 This is a subgraph with the following specific features: (1) an
434 edge in the preference subgraph cannot be created if a
435 corresponding edge exists in the interference subgraph; (2) adding
436 an edge can make a vertex move-related, which requires taking that
437 vertex out of the [nmr] set; conversely, removing an edge can make
438 a vertex non-move-related, which requires adding that vertex to the
441 and preference (interference : interference Lazy.t) = object (self)
443 inherit subgraph as super
445 method getvv graph = graph.pvv
446 method setvv graph m = { graph with pvv = m }
447 method getvh graph = graph.pvh
448 method setvh graph m = { graph with pvh = m }
450 (* [nmr graph v] tells whether vertex [v] is non-move-related. *)
453 Vertex.Set.is_empty (self#neighborsv graph v) &&
454 HwRegisterSet.is_empty (self#neighborsh graph v)
456 (* [mkcheck graph v] moves [v] out of the [nmr] set if [v] is
459 method mkcheck graph v =
460 if self#nmr graph v then
462 nmr = PrioritySet.remove v graph.nmr }
466 (* Override the edge creation methods. *)
468 method mkvvi graph v1 v2 =
469 if (Lazy.force interference)#existsvv graph v1 v2 then
470 graph (* avoid creating constrained preference edge *)
472 let graph = self#mkcheck graph v1 in
473 let graph = self#mkcheck graph v2 in
474 super#mkvvi graph v1 v2
476 method mkvhi graph v h =
477 if (Lazy.force interference)#existsvh graph v h then
478 graph (* avoid creating constrained preference edge *)
480 let graph = self#mkcheck graph v in
481 super#mkvhi graph v h
483 (* [rmcheck graph v] moves [v] into the [nmr] set if [v] is
486 method rmcheck graph v =
487 if self#nmr graph v then
489 nmr = PrioritySet.add v (PrioritySet.priority v graph.degree) graph.nmr
494 (* Override the edge destruction methods. *)
496 method rmvv graph v1 v2 =
497 let graph = super#rmvv graph v1 v2 in
498 let graph = self#rmcheck graph v1 in
499 let graph = self#rmcheck graph v2 in
502 method rmvh graph v h =
503 let graph = super#rmvh graph v h in
504 let graph = self#rmcheck graph v in
509 (* ------------------------------------------------------------------------- *)
511 (* Because the interference and preference subgraphs are mutually
512 referential, a recursive definition is required. It is made
513 somewhat inelegant by Objective Caml's insistence on using the
516 let rec interference = lazy (new interference preference)
517 and preference = lazy (new preference interference)
518 let interference = Lazy.force interference
519 let preference = Lazy.force preference
521 (* ------------------------------------------------------------------------- *)
523 (* Inspecting interference graphs. *)
525 (* [ipp graph v] is the set of vertices that the vertex [v] interferes
529 interference#neighborsv graph v
531 (* [iph graph v] is the set of hardware registers that the vertex [v]
535 interference#neighborsh graph v
537 (* [ppp graph v] is the set of vertices that should preferably be
538 assigned the same color as the vertex [v]. *)
541 preference#neighborsv graph v
543 (* [pph graph v] is the set of hardware registers that [v] should
544 preferably be assigned. *)
547 preference#neighborsh graph v
549 (* [degree graph v] is the degree of the vertex [v], that is, the number
550 of vertices and hardware registers that [v] interferes with. *)
553 PrioritySet.priority v graph.degree
555 (* [lowest graph] returns [Some (v, d)], where the vertex [v] has
556 minimum degree [d], or returns [None] if the graph is empty. *)
559 PrioritySet.lowest graph.degree
561 (* [lowest_non_move_related graph] returns [Some (v, d)], where the
562 vertex [v] has minimum degree [d] among the vertices that are not
563 move-related, or returns [None] if all vertices are move-related. A
564 vertex is move-related if it carries a preference edge. *)
566 let lowest_non_move_related graph =
567 PrioritySet.lowest graph.nmr
569 (* [fold f graph accu] folds over all vertices. *)
571 let fold f graph accu =
572 RegMap.fold (fun v _ accu -> f v accu) graph.regmap accu
574 (* [minimum f graph] returns a vertex [v] such that the value of [f x]
575 is minimal. The values returned by [f] are compared using Objective
576 Caml's generic comparison operator [<]. If the graph is empty,
577 [None] is returned. *)
579 let minimum f graph =
598 (* [pppick graph p] returns an arbitrary preference edge that
599 satisfies the predicate [p], if the graph contains one. *)
605 VertexSetMap.pick graph.pvv p
607 (* [phpick graph p] returns an arbitrary preference edge that
608 satisfies the predicate [p], if the graph contains one. *)
611 Vertex.t * I8051.register
614 I8051RegisterSetMap.pick graph.pvh p
616 (* ------------------------------------------------------------------------- *)
618 (* Constructing interference graphs. *)
620 (* [create regs] creates an interference graph whose vertices are
621 the pseudo-registers [regs] and that does not have any edges. *)
624 let _, regmap, degree =
625 Pset.fold (fun r (v, regmap, degree) ->
627 RegMap.add r v regmap,
628 PrioritySet.add v 0 degree
629 ) regs (Positive.One, RegMap.empty, PrioritySet.empty)
633 ivv = Vertex.Map.empty;
634 ivh = Vertex.Map.empty;
635 pvv = Vertex.Map.empty;
636 pvh = Vertex.Map.empty;
641 (* [lookup graph r] returns the graph vertex associated with
642 pseudo-register [r]. *)
645 RegMap.backward r graph.regmap
647 (* Conversely, [registers graph v] returns the set of pseudo-registers
648 associated with vertex [v]. *)
650 let registers graph v =
651 RegMap.forward v graph.regmap
653 (* [mkipp graph regs1 regs2] adds interference edges between all pairs
654 of pseudo-registers [r1] and [r2], where [r1] ranges over [regs1],
655 [r2] ranges over [regs2], and [r1] and [r2] are distinct. *)
657 let mkipp graph regs1 regs2 =
658 Pset.fold (fun r1 graph ->
659 let v1 = lookup graph r1 in
660 Pset.fold (fun r2 graph ->
661 interference#mkvv graph v1 (lookup graph r2)
665 (* [mkiph graph regs hwregs] adds interference edges between all pairs
666 of a pseudo-register [r] and a hardware register [hwr], where [r]
667 ranges over [regs] and [hwr] ranges over [hwregs]. *)
669 let mkiph graph regs hwregs =
670 Pset.fold (fun r graph ->
671 let v = lookup graph r in
672 HwRegisterSet.fold (fun h graph ->
673 interference#mkvh graph v h
677 (* [mki graph regs1 regs2] adds interference edges between all pairs
678 of (pseudo- or hardware) registers [r1] and [r2], where [r1] ranges
679 over [regs1], [r2] ranges over [regs2], and [r1] and [r2] are
682 let mki graph (regs1, hwregs1) (regs2, hwregs2) =
683 let graph = mkipp graph regs1 regs2 in
684 let graph = mkiph graph regs1 hwregs2 in
685 let graph = mkiph graph regs2 hwregs1 in
688 (* [mkppp graph r1 r2] adds a preference edge between the
689 pseudo-registers [r1] and [r2]. *)
691 let mkppp graph r1 r2 =
692 let v1 = lookup graph r1
693 and v2 = lookup graph r2 in
694 let graph = preference#mkvv graph v1 v2 in
697 (* [mkpph graph r h] adds a preference edge between the
698 pseudo-register [r] and the hardware register [h]. *)
700 let mkpph graph r h =
701 let v = lookup graph r in
702 let graph = preference#mkvh graph v h in
705 (* ------------------------------------------------------------------------- *)
708 (* Displaying interference graphs. *)
713 HwRegisterSet.union (interference#hwregs graph) (preference#hwregs graph)
715 let print_vertex graph v =
716 Pset.print (registers graph v)
720 fprintf f "graph G {\n";
721 (* fprintf f "size=\"6, 3\";\n"; (* in inches *)*)
722 fprintf f "orientation = landscape;\n";
723 fprintf f "rankdir = LR;\n";
724 fprintf f "ratio = compress;\n\n"; (* compress or fill or auto *)
726 RegMap.fold (fun vertex regs () ->
727 fprintf f "r%d [ label=\"%s\" ] ;\n" vertex (Pset.print regs)
730 HwRegisterSet.iter (fun hwr ->
731 let name = I8051.print_register hwr in
732 fprintf f "hwr%s [ label=\"$%s\" ] ;\n" name name
735 interference#iter graph
736 (fun vertex neighbor ->
737 fprintf f "r%d -- r%d ;\n" vertex neighbor)
738 (fun vertex neighbor ->
739 fprintf f "r%d -- hwr%s ;\n" vertex (I8051.print_register neighbor));
741 preference#iter graph
742 (fun vertex neighbor ->
743 fprintf f "r%d -- r%d [ style = dashed ] ;\n" vertex neighbor)
744 (fun vertex neighbor ->
745 fprintf f "r%d -- hwr%s [ style = dashed ] ;\n" vertex (I8051.print_register neighbor));
750 (* ------------------------------------------------------------------------- *)
754 (* [coalesce graph v1 v2] is a new graph where the vertices [v1] and [v2]
755 are coalesced. The new coalesced vertex is known under the name [v2]. *)
757 let coalesce graph x y =
759 assert (x <> y); (* attempt to coalesce one vertex with itself *)
760 assert (not (interference#existsvv graph x y)); (* attempt to coalesce two interfering vertices *)
762 (* Perform coalescing in the two subgraphs. *)
764 let graph = interference#coalesce graph x y in
765 let graph = preference#coalesce graph x y in
767 (* Remove [x] from all tables. *)
771 regmap = RegMap.coalesce x y graph.regmap;
772 ivh = Vertex.Map.remove x graph.ivh;
773 pvh = Vertex.Map.remove x graph.pvh;
774 degree = PrioritySet.remove x graph.degree;
775 nmr = PrioritySet.remove x graph.nmr;
778 (* [coalesceh graph v h] coalesces the vertex [v] with the hardware register
779 [h]. This produces a new graph where [v] no longer exists and all edges
780 leading to [v] are replaced with edges leading to [h]. *)
782 let coalesceh graph x h =
784 assert (not (interference#existsvh graph x h)); (* attempt to coalesce interfering entities *)
786 (* Perform coalescing in the two subgraphs. *)
788 let graph = interference#coalesceh graph x h in
789 let graph = preference#coalesceh graph x h in
791 (* Remove [x] from all tables. *)
795 regmap = RegMap.remove x graph.regmap;
796 ivh = Vertex.Map.remove x graph.ivh;
797 pvh = Vertex.Map.remove x graph.pvh;
798 degree = PrioritySet.remove x graph.degree;
799 nmr = PrioritySet.remove x graph.nmr;
802 (* ------------------------------------------------------------------------- *)
804 (* [freeze graph x] is a new graph where all preference edges carried
805 by [x] are removed. *)
808 preference#remove graph x
810 (* ------------------------------------------------------------------------- *)
814 (* [remove graph v] is a new graph where vertex [v] is removed. *)
818 (* Remove all edges carried by [v]. *)
820 let graph = interference#remove graph v in
821 let graph = preference#remove graph v in
823 (* Remove [v] from all tables. *)
827 regmap = RegMap.remove v graph.regmap;
828 degree = PrioritySet.remove v graph.degree;
829 nmr = PrioritySet.remove v graph.nmr;
832 (* ------------------------------------------------------------------------- *)
834 (* [mkdeg graph] recomputes degree information from scratch. *)
838 fold (fun v (degree, nmr) ->
839 let d = interference#degree graph v in
840 PrioritySet.add v d degree,
841 if preference#nmr graph v then PrioritySet.add v d nmr else nmr
842 ) graph (PrioritySet.empty, PrioritySet.empty)
849 (* [restrict graph p] is a new graph where only those vertices that
850 satisfy predicate [p] are kept. The same effect could be obtained
851 by repeated application of [remove], but [restrict] is likely to be
852 more efficient if many vertices are removed. *)
854 let restrict graph p =
857 regmap = RegMap.restrict p graph.regmap;
858 ivv = VertexSetMap.restrict p graph.ivv;
859 ivh = Vertex.Map.restrict p graph.ivh;
860 pvv = VertexSetMap.restrict p graph.pvv;
861 pvh = Vertex.Map.restrict p graph.pvh;
864 (* [droph graph] is a new graph where all information concerning hardware
865 registers has been dropped. *)
870 ivh = Vertex.Map.empty;
871 pvh = Vertex.Map.empty;