-
Notifications
You must be signed in to change notification settings - Fork 1
/
color.sml
141 lines (126 loc) · 3.74 KB
/
color.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
(* color.sml
*
* The graph-coloring part of a simple register allocator.
*
* Copyright (c) 2005 by Matthias Blume ([email protected])
*)
structure Color : sig
val color : { interference: Liveness.igraph,
initial: Frame.allocation,
spillCost: Liveness.IGraph.node -> int,
registers : Frame.register list }
-> Frame.allocation * LVar.lvar list
end = struct
structure Frame = Frame
structure L = Liveness
structure IG = L.IGraph
structure TT = LVar.Map
structure GT = IG.Map
structure TS = LVar.Set
fun color { interference, initial, spillCost, registers } =
let val k = length registers
val L.IGRAPH { graph, tnode, gtemp, moves } = interference
val nodes = IG.nodes graph
fun adjacent n = let
fun uniq ([], u) = u
| uniq (h :: t, u) =
uniq (t, if List.exists (fn n => IG.eq (h, n)) u then u
else h :: u)
in
uniq (IG.adj n, [])
end
val degreeOf = length o adjacent
fun spillCost' n = spillCost n - degreeOf n
(* eligible nodes -- not precolored *)
val nodes' =
List.filter (fn n => not (TT.inDomain (initial, gtemp n)))
nodes
fun categ (n, (low, high, m)) = let
val d = degreeOf n
val m' = GT.insert (m, n, d)
in
if d < k then (n :: low, high, m') else (low, n :: high, m')
end
val (low, high, dm) = foldl categ ([], [], GT.empty) nodes'
fun select (n, low, high, dm) = let
val adj = adjacent n
val dm = #1 (GT.remove (dm, n))
fun otherThan n1 n2 = not (IG.eq (n1, n2))
fun lowerDegree (a, (low, high, dm)) =
case GT.find (dm, a) of
NONE => (low, high, dm)
| SOME d => let
val d' = d - 1
val dm = GT.insert (dm, a, d')
in
if d = k then
(a :: low, List.filter (otherThan a) high, dm)
else (low, high, dm)
end
val (low, high, dm) = foldl lowerDegree (low, high, dm) adj
in
(low, high, dm, adj)
end
fun pickColor (n, adj, (allocation, spills)) = let
fun remove (a, avail) =
case TT.find (allocation, gtemp a) of
NONE => avail
| SOME r => List.filter (fn r' => r <> r') avail
fun biasedPick [] = (allocation, gtemp n :: spills)
| biasedPick avail = let
fun frequency c = let
fun cColored x =
case TT.find (allocation, gtemp x) of
NONE => false
| SOME c' => c = c'
fun count ([], cnt) = cnt
| count ((n1, n2) :: ml, cnt) =
if IG.eq (n1, n) andalso cColored n2
orelse IG.eq (n2, n) andalso cColored n1 then
count (ml, cnt + 1)
else count (ml, cnt)
in
count (moves, 0)
end
fun loop ([], best, _) =
(TT.insert (allocation, gtemp n, best), spills)
| loop (c :: cs, b, m) = let
val cfreq = frequency c
in
if cfreq > m then loop (cs, c, cfreq)
else loop (cs, b, m)
end
in
loop (avail, Frame.boguscolor, ~1)
end
(* (* for unbiased coloring... *)
fun biasedPick [] = ErrorMsg.impossible "run out of registers"
| biasedPick (first :: _) =
TT.enter (allocation, gtemp n, first)
*)
in
biasedPick (foldl remove registers adj)
end
fun try ([], [], _) = (initial, [])
| try ([], h1 :: hn, dm) = let
fun cheapest (h1, _, [], hn') = (h1, hn')
| cheapest (h1, c1, h2 :: hn, hn') = let
val c2 = spillCost' h2
in
if c2 < c1 then
cheapest (h2, c2, hn, h1 :: hn')
else
cheapest (h1, c1, hn, h2 :: hn')
end
val (h1', hn') = cheapest (h1, spillCost' h1, hn, [])
in
finish (h1', select (h1', [], hn', dm))
end
| try (l1 :: ln, high, dm) =
finish (l1, select (l1, ln, high, dm))
and finish (n, (low, high, dm, adj)) =
pickColor (n, adj, try (low, high, dm))
in
try (low, high, dm)
end
end