-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy pathliveness.sml
213 lines (182 loc) · 6.67 KB
/
liveness.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
signature LIVENESS =
sig
structure I : sig
datatype status = INGRAPH of int (* degree *)
| REMOVED
| COLORED of string
datatype node = NODE of {temp: Temp.temp,
adj: node list ref,
status: status ref}
end
datatype igraph = IGRAPH of {graph: I.node list,
moves: (I.node*I.node) list}
val interferenceGraph : Flow.flowgraph -> igraph
val show : TextIO.outstream * igraph -> unit
end
structure TempKey : ORD_KEY =
struct
type ord_key = Temp.temp
fun compare (t1,t2) = String.compare(Temp.makestring t1,Temp.makestring t2)
end
structure Liveness :> LIVENESS =
struct
structure I =
struct
datatype status = INGRAPH of int (* degree *)
| REMOVED
| COLORED of string
datatype node = NODE of {temp: Temp.temp,
adj: node list ref,
status: status ref}
end
datatype igraph = IGRAPH of {graph: I.node list,
moves: (I.node*I.node) list}
structure F = Flow
structure S = ListSetFn(TempKey)
structure T = Temp
structure TT = Temp.Table
structure GT = IntMapTable(type key=int fun getInt n = n)
structure Frame = MipsFrame
type liveSet = S.set
type liveMap = liveSet GT.table
type tempEdge = {src:Temp.temp,dst:Temp.temp}
fun show(output, IGRAPH{graph,moves}) =
let
fun p_status s =
case s of
I.INGRAPH(d) => "INGRAPH(" ^ Int.toString(d) ^ ")"
| I.REMOVED => "REMOVED"
| I.COLORED(r) => "COLORED(" ^ r ^ ")"
fun do1(node as I.NODE{temp,adj,status}) =
TextIO.output(
output,
("{temp=" ^ (T.makestring temp) ^ "," ^
"status=" ^ p_status (!status) ^ "}\n"))
in
app do1 graph
end
fun interferenceGraph flowgraph =
let
fun println s = print(s ^ "\n")
fun look(table: liveMap,key) = valOf(GT.look(table,key))
(* recursively compute liveSet, until reaches a fix point *)
fun iter(livein_map,liveout_map) =
let
(* Record whether we've reached a fix point *)
val changed = ref false
(* Given livein map, compute liveout set for node n *)
fun compute_out(mi,F.Node{succ,...}) =
foldl (fn (F.Node{id,liveout,...},s) => S.union(look(mi,id),s))
S.empty (!succ)
(* Compute new livein and liveout map *)
val (new_livein_map, new_liveout_map) =
foldl
(fn (x as F.Node{id,def,use,...}, (mi,mo)) =>
let
val oldin = look(mi,id) (* Save old livein set *)
val oldout = look(mo,id) (* Save old liveout set *)
val usex = S.addList(S.empty,use)
val defx = S.addList(S.empty,def)
val newin = S.union(usex,S.difference(oldout,defx))
val newout = compute_out(mi,x)
in
if S.equal(newin,oldin) andalso S.equal(newout,oldout)
then () else changed := true;
(GT.enter(mi,id,newin),GT.enter(mo,id,newout))
end
) (livein_map,liveout_map) flowgraph
in
if !changed then iter (new_livein_map,new_liveout_map)
else new_liveout_map
end
(* Make a empty map that maps each node in graph to an empty set *)
fun make_empty_map () =
foldl (fn (F.Node{id,...},m) => GT.enter(m,id,S.empty)) GT.empty
(List.rev flowgraph)
(* A map from a graph node id to its liveout set *)
val liveout_map : liveMap = iter ((make_empty_map ()), (make_empty_map ()))
(* set liveout for each node *)
val _ =
app
(fn F.Node{id,liveout,...} =>
case GT.look(liveout_map,id) of
SOME s => liveout := S.listItems(s)
| NONE => ErrorMsg.impossible("liveout map is not one-to-one")
) flowgraph;
in
(* now for each node n in the flow graph, suppose
* there is a newly define temp d, and temporaries
* t1, ..., tn are in liveout set of node n. Then,
* we add edge (d,t1), ..., (d,tn) to the igraph.
* Mappings between temps and igraph nodes are also recorded.
* The rules for adding interference edges are:
* 1. At any nonmove instruction that defines a variable a, where the
* live-out variables are b1,...bj, add interference edges
* (a,b1),...,(a,bj).
* 2. At a move instruction a <- c, where variables b1,...,bj are live-out,
* add interference edges (a,b1),...,(a,bj) for any bi that is not
* the same as c. *)
let
fun find_edges(node as F.Node{def,liveout,...}) : tempEdge list =
let
fun f t = foldl
(fn (t',l) => (* don't add self-edge *)
if t <> t' then {src=t,dst=t'}::l else l)
nil (!liveout)
in foldl (fn (t,l) => (f t) @ l) nil def end
val all_edges : tempEdge list =
foldl (fn (n,l) => find_edges(n) @ l) nil flowgraph
val (tmap, outgraph) =
foldl
(fn (t,(table,nodes)) =>
case TT.look(table,t) of
NONE =>
let
val nn = I.NODE{temp=t,
adj=ref nil,
status=ref(I.INGRAPH(0))}
in
(TT.enter(table,t,nn), nn::nodes)
end
| SOME _ => (table,nodes)
)
(TT.empty,nil)
(foldl
(fn (F.Node{def,use,...},acc) => acc@def@use)
nil flowgraph)
fun looktemp t = valOf(TT.look(tmap,t))
val allmoves =
foldl
(fn (F.Node{def,use,ismove,...}, moves) =>
if ismove then
let val ([src],[dst]) = (use,def)
in (looktemp(src),looktemp(dst)) :: moves end
else moves
) nil flowgraph
in
app
(fn {src,dst} => (* don't add duplicate edges *)
let
val (srcn as I.NODE{temp=t1,adj=adj1,status=st1},
dstn as I.NODE{temp=t2,adj=adj2,status=st2})
= (looktemp(src),looktemp(dst))
val d1 = case (!st1) of I.INGRAPH(d) => d
val d2 = case (!st2) of I.INGRAPH(d) => d
in
if
List.exists (fn x => x = dstn) (!adj1) andalso
List.exists (fn x => x = srcn) (!adj2)
then ()
else
let in
adj1 := dstn::(!adj1);
adj2 := srcn::(!adj2);
st1 := I.INGRAPH(d1+1);
st2 := I.INGRAPH(d2+1)
end
end
) all_edges;
IGRAPH{graph=outgraph, moves=allmoves}
end
end
end