]> Joshua Wise's Git repositories - snipe.git/blame - codegen/liveness.sml
Initial import of l2c
[snipe.git] / codegen / liveness.sml
CommitLineData
0a24e44d 1(* L2 Compiler
12aa4087 2 * Turns pseudoasm into liveness-annotated pseudoasm
0a24e44d 3 * Author: Chris Lu <czl@andrew.cmu.edu>
12aa4087
JW
4 * Author: Joshua Wise <jwise@andrew.cmu.edu>
5 *)
6
7signature LIVENESS =
8sig
12aa4087 9
0a24e44d
JW
10 type live = int * x86.oper list
11 type pseudoasm = x86.insn list
12 type livenesses = x86.oper list list
13
14 type ident = int
15 datatype pred = DEF of x86.oper | USE of x86.oper | SUCC of ident
16
17 val liveness : pseudoasm -> livenesses
18 val prettyprint : x86.oper list -> string
12aa4087
JW
19end
20
21structure Liveness :> LIVENESS =
22struct
23 structure T = Temp
24 structure X = x86
12aa4087 25
0a24e44d
JW
26
27 type live = int * x86.oper list
28 type pseudoasm = X.insn list
29 type numasm = (int * X.insn) list
30 type livenesses = X.oper list list
31
32 type ident = int
33 datatype pred = DEF of X.oper | USE of X.oper | SUCC of ident
34
35 (* val number : pseudoasm -> numasm
36 * numbers the instructions!
37 *)
38
39 fun number instrs =
40 let
41 val nums = List.tabulate (List.length instrs, (fn i => i))
42 in
43 ListPair.zip (nums,instrs)
44 end
45
46 (* val defusesucc : numasm -> (ident * pred list) list
47 * generates def/use/succ predicates according to rules
48 *)
49
50 fun defusesucc l =
51 let
52 fun findlabel (lb) =
53 Option.valOf
54 (foldr (fn ((n, X.LABEL lb'), NONE) => if (Label.compare (lb, lb') = EQUAL) then SOME n else NONE
55 | (_, old) => old) NONE l)
56
57 (* val defhit/usehit : X.oper -> pred list
58 * helper functions to discard constant operands *)
59 fun defhit (a as X.CONST(_)) = nil
60 | defhit (a) = [DEF(a)]
61
62 fun usehit (a as X.CONST(_)) = nil
63 | usehit (a) = [USE(a)]
64
65 (* val gendef : ident * X.insn -> ident * pred list
66 * generates the def/use/succ predicates for a single insn
67 *)
68 fun gendef (n, X.DIRECTIVE(_)) = (n, nil)
69 | gendef (n, X.COMMENT(_)) = (n, nil)
70 | gendef (n, X.MOVL(dest, src)) = (n, defhit dest @ usehit src @ [SUCC(n+1)])
71 | gendef (n, X.SUBL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
72 | gendef (n, X.IMUL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
73 | gendef (n, X.IMUL3(dest, src, _)) = (n, defhit dest @ usehit src @ [SUCC(n+1)])
74 | gendef (n, X.ADDL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
75 | gendef (n, X.IDIVL(src)) = (n, usehit src @ [DEF(X.REG(X.EAX)), DEF(X.REG(X.EDX)),
76 USE(X.REG(X.EAX)), USE(X.REG(X.EDX)),
77 SUCC(n+1)])
78 | gendef (n, X.CLTD) = (n, [USE(X.REG(X.EAX)), DEF(X.REG(X.EDX)), SUCC(n+1)])
79 | gendef (n, X.SALL(dest, shft)) = (n, defhit dest @ usehit shft @ usehit dest @ [SUCC(n+1)])
80 | gendef (n, X.SARL(dest, shft)) = (n, defhit dest @ usehit shft @ usehit dest @ [SUCC(n+1)])
81 | gendef (n, X.NEG(src)) = (n, defhit src @ usehit src @ [SUCC(n+1)])
82 | gendef (n, X.NOTL(src)) = (n, defhit src @ usehit src @ [SUCC(n+1)])
83 | gendef (n, X.ANDL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
84 | gendef (n, X.ORL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
85 | gendef (n, X.XORL(dest, src)) = (n, defhit dest @ usehit dest @ usehit src @ [SUCC(n+1)])
86 | gendef (n, X.CMPL(dest, src)) = (n, usehit dest @ usehit src @ [SUCC(n+1)])
87 | gendef (n, X.TEST(dest, src)) = (n, usehit dest @ usehit src @ [SUCC(n+1)])
88 | gendef (n, X.SETNE(dest)) = (n, defhit dest @ [SUCC(n+1)])
89 | gendef (n, X.SETE(dest)) = (n, defhit dest @ [SUCC(n+1)])
90 | gendef (n, X.SETLE(dest)) = (n, defhit dest @ [SUCC(n+1)])
91 | gendef (n, X.SETL(dest)) = (n, defhit dest @ [SUCC(n+1)])
92 | gendef (n, X.SETGE(dest)) = (n, defhit dest @ [SUCC(n+1)])
93 | gendef (n, X.SETG(dest)) = (n, defhit dest @ [SUCC(n+1)])
94 | gendef (n, X.MOVZBL(dest, src)) = (n, defhit dest @ usehit src @ [SUCC(n+1)])
95 | gendef (n, X.RET) = (n, nil)
96 | gendef (n, X.LABEL l) = (n, [SUCC (n+1)])
97 | gendef (n, X.JMP l) = (n, [SUCC (findlabel l)])
98 | gendef (n, X.JE l) = (n, [SUCC (n+1), SUCC (findlabel l)])
99 | gendef (n, X.JNE l) = (n, [SUCC (n+1), SUCC (findlabel l)])
100 in
101 List.map gendef l
102 end
103
104 (* val uselive : (ident * pred list) list -> live list
105 * generates liveness for 'use' rules to get the iterative analyzer started
106 *)
107 fun uselive preds =
108 List.map
109 (fn (n, l) => (n, List.foldr
110 (fn (a,b) => case a of USE(x) => x::b | _ => b)
111 nil
112 l
113 )
114 )
115 preds
116
117 (* val subsetlive : (ident * pred list) * (ident * pred list) -> bool
118 * true if first is subset of second
119 *)
120
121 fun subsetlive (l1,l2) =
122 ListPair.all
123 (fn ((n1,a),(n2,b)) => (n1 = n2) andalso List.all
124 (fn x => List.exists (fn y => X.opereq (x,y)) b)
125 a
126 )
127 (l1,l2)
128
129 (* val liveiter : live list -> (ident * pred list) list -> live list
130 * iteratively generates livenesses from def/use/succ rules
131 * it must be fed a liveness list generated from the use rule as it only
132 * processes the second rule :
12aa4087 133 *
0a24e44d
JW
134 * use(l',x)
135 * !def(l,x)
136 * succ(l,l')
137 * --------------
138 * live(l,x)
12aa4087 139 *)
0a24e44d
JW
140
141 fun liveiter l p =
12aa4087 142 let
0a24e44d
JW
143 (* val succs : pred list -> l
144 * generates a list of lines that succeed a line given the predicates
145 * for that line
146 *)
147 fun succs (SUCC(a)::l) = a::(succs l)
148 | succs (_::l) = succs l
149 | succs nil = nil
150
151 (* val lives : ident list -> live list -> X.oper list
152 * scans l for live variables in succeeding lines *)
153 fun lives l' idents =
154 List.foldr
155 (fn ((_,a),b) => a @ b)
156 nil
157 (List.filter (fn (n,_) => List.exists (fn a => a = n) idents) l')
12aa4087 158
0a24e44d
JW
159 (* val isndef : X.oper -> pred list -> bool
160 * checks to see if x is defined in a predicate list *)
161 fun isndef x (DEF(y)::l) = not (X.opereq (x,y)) andalso isndef x l
162 | isndef x (a::l) = isndef x l
163 | isndef x nil = true
164
165 (* val addonce : X.oper list -> X.oper -> X.oper list
166 * eliminates duplicates, which speeds up compilation
167 *)
168 fun addonce l oper =
169 if (List.exists (fn x => X.opereq (x,oper)) l)
170 then l
171 else oper::l
172
173 (* val liveadd : live -> live list -> live list *)
174 fun liveadd (n,oper) lives = List.map
175 (fn (x,a) => if (x = n) then (x,addonce a oper) else (x,a))
176 lives
177
178 (* this does the dirty work!
179 * for each line, checks if the live variables in succeeding lines are
180 * not defined here; if so, it accumulates them onto the inital list
181 *
182 * changing the first foldr to a foldl slows down liveness by a factor
183 * of at least 100 on cedar-anastulate.l2
184 *)
185 val newl = List.foldr
186 (fn ((n, a), b) => List.foldr
187 (fn (a',b') => if (isndef a' a) then liveadd (n, a') b' else b')
188 b
189 (lives b (succs a))
190 )
191 l
192 p
12aa4087 193 in
0a24e44d 194 if subsetlive (newl, l) then l else liveiter newl p
12aa4087 195 end
0a24e44d
JW
196
197 (* val liveness : pseudoasm -> livenesses
198 * analyzes liveness of variables in the given pseudo-asm
199 *)
200
201 fun liveness instrs =
12aa4087 202 let
0a24e44d
JW
203 val preds = defusesucc (number instrs)
204 val init = uselive preds
205 val (_,lives) = ListPair.unzip (liveiter init preds)
12aa4087 206 in
0a24e44d 207 lives
12aa4087 208 end
0a24e44d
JW
209
210 fun prettyprint (a::l) = (X.prettyprint_oper a) ^ ", " ^ prettyprint l
211 | prettyprint nil = "-\n"
212
12aa4087 213end
This page took 0.041869 seconds and 4 git commands to generate.