Home My Page Projects Code Snippets Project Openings SML/NJ
Summary Activity Forums Tracker Lists Tasks Docs Surveys News SCM Files

SCM Repository

[smlnj] Annotation of /sml/trunk/src/MLRISC/x86/ra/x86Spill.sml
ViewVC logotype

Annotation of /sml/trunk/src/MLRISC/x86/ra/x86Spill.sml

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1009 - (view) (download)

1 : monnier 247 (* X86Spill.sml
2 :     *
3 :     * X86 spilling is complicated business.
4 : monnier 498 * Allen: and it just got more complicated; now we have to recognize the regmap.
5 : george 545 * I've also improved the spilling code so that more instructions are
6 :     * recognized. Addressing modes are now folded into the existing instruction
7 :     * whenever possible. This eliminates some redundant temporaries which were
8 :     * introduced before.
9 : monnier 247 *)
10 :     signature X86SPILL = sig
11 :     structure I : X86INSTR
12 : george 889 structure CB : CELLS_BASIS = CellsBasis
13 : monnier 247 val spill :
14 : george 889 I.instruction * CB.cell * I.operand ->
15 :     {code:I.instruction list, proh:CB.cell list, newReg:CB.cell option}
16 : monnier 247
17 :     val reload :
18 : george 889 I.instruction * CB.cell * I.operand ->
19 :     {code:I.instruction list, proh:CB.cell list, newReg:CB.cell option}
20 : monnier 247
21 :     val fspill :
22 : george 889 I.instruction * CB.cell * I.operand ->
23 :     {code:I.instruction list, proh:CB.cell list, newReg:CB.cell option}
24 : monnier 247
25 :     val freload :
26 : george 889 I.instruction * CB.cell * I.operand ->
27 :     {code:I.instruction list, proh:CB.cell list, newReg:CB.cell option}
28 : monnier 247 end
29 :    
30 :    
31 :     functor X86Spill(structure Instr: X86INSTR
32 : monnier 498 structure Props: INSN_PROPERTIES where I = Instr
33 :     ) : X86SPILL = struct
34 : monnier 247
35 : monnier 429 structure I = Instr
36 :     structure C = I.C
37 : george 889 structure CB = CellsBasis
38 : monnier 247
39 : monnier 411 fun error msg = MLRiscErrorMsg.impossible("X86Spill: "^ msg)
40 : monnier 247
41 :     fun immed(I.Immed _) = true
42 :     | immed(I.ImmedLabel _) = true
43 :     | immed _ = false
44 :    
45 :     fun immedOrReg(I.Direct r) = true
46 : monnier 498 | immedOrReg(I.Immed _) = true
47 :     | immedOrReg(I.ImmedLabel _) = true
48 :     | immedOrReg _ = false
49 : monnier 247
50 : george 545 fun isMemory(I.MemReg _) = true
51 :     | isMemory(I.Displace _) = true
52 :     | isMemory(I.Indexed _) = true
53 :     | isMemory(I.LabelEA _) = true
54 :     | isMemory _ = false
55 :    
56 : monnier 498 (* Annotate instruction *)
57 : george 1003 fun annotate(instr,[]) = instr
58 :     | annotate(instr,a::an) = annotate(I.ANNOTATION{i=instr,a=a},an)
59 : monnier 247
60 : george 1003 fun mark(instr, an) = annotate(I.INSTR instr, an)
61 :    
62 :     fun liveKill(add, rmv) ({regs, spilled}, reg) =
63 :     {regs=rmv(reg, regs), spilled=add(reg, spilled)}
64 :    
65 :     val fLiveKill = liveKill (C.addFreg, C.rmvFreg)
66 :     val rLiveKill = liveKill (C.addReg, C.rmvReg)
67 :    
68 : monnier 498 val newReg = C.newReg
69 :    
70 : george 1003
71 :     fun spill(instr, reg, spillLoc) = let
72 :     fun x86Spill(instr, an) = let
73 :     fun done(instr, an) = {code=[mark(instr, an)], proh=[], newReg=NONE}
74 :     in
75 : monnier 498 case instr of
76 : george 1003 I.CALL{opnd=addr, defs, uses, return, cutsTo, mem, pops} =>
77 :     done(I.CALL{opnd=addr, defs=C.rmvReg(reg,defs),
78 :     return=return, uses=uses,
79 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)
80 : george 545 | I.MOVE{mvOp as (I.MOVZBL|I.MOVSBL|I.MOVZWL|I.MOVSWL), src, dst} =>
81 : george 1003 let val tmpR = newReg() val tmp = I.Direct tmpR
82 :     in {proh=[tmpR], newReg=SOME tmpR,
83 :     code=[mark(I.MOVE{mvOp=mvOp, src=src, dst=tmp}, an),
84 :     I.move{mvOp=I.MOVL, src=tmp, dst=spillLoc}]
85 :     }
86 :     end
87 : monnier 498 | I.MOVE{mvOp, src as I.Direct rs, dst} =>
88 : george 1003 if CB.sameColor(rs,reg) then {code=[], proh=[], newReg=NONE}
89 : monnier 498 else done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
90 :     | I.MOVE{mvOp, src, dst=I.Direct _} =>
91 :     if Props.eqOpn(src, spillLoc) then {code=[], proh=[], newReg=NONE}
92 : george 1003 else if immed src then
93 :     done(I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}, an)
94 : monnier 498 else
95 : george 1003 let val tmpR = newReg()
96 :     val tmp = I.Direct tmpR
97 :     in {proh=[tmpR],
98 :     newReg=SOME tmpR,
99 :     code=[mark(I.MOVE{mvOp=mvOp, src=src, dst=tmp}, an),
100 :     I.move{mvOp=mvOp, src=tmp, dst=spillLoc}]
101 :     }
102 :     end
103 : monnier 498 | I.LEA{addr, r32} =>
104 : george 1003 let val tmpR = newReg()
105 :     in {proh=[tmpR],
106 :     newReg=SOME tmpR,
107 :     code=[mark(I.LEA{addr=addr, r32=tmpR}, an),
108 :     I.move{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]
109 :     }
110 :     end
111 : george 545 | I.BINARY{binOp=I.XORL, src as I.Direct rs, dst=I.Direct rd} =>
112 : george 1003 if CB.sameColor(rs,rd) then
113 :     {proh=[],
114 :     code=[mark(I.MOVE{mvOp=I.MOVL, src=I.Immed 0, dst=spillLoc}, an)],
115 :     newReg=NONE
116 :     }
117 :     else
118 :     {proh=[],
119 :     code=[mark(I.BINARY{binOp=I.XORL, src=src, dst=spillLoc}, an)],
120 :     newReg=NONE
121 :     }
122 : george 897 | I.BINARY{binOp, src, dst} => let (* note: dst = reg *)
123 :     fun multBinOp(I.MULL|I.MULW|I.MULB|I.IMULL|I.IMULW|I.IMULB) = true
124 :     | multBinOp _ = false
125 : george 1003 in
126 : george 897 if multBinOp binOp then let
127 : george 1003 (* destination must remain a register *)
128 : george 897 val tmpR = newReg()
129 :     val tmp = I.Direct tmpR
130 :     in
131 :     {proh=[tmpR],
132 : george 1003 code= [I.move{mvOp=I.MOVL, src=spillLoc, dst=tmp},
133 :     I.binary{binOp=binOp, src=src, dst=tmp},
134 :     I.move{mvOp=I.MOVL, src=tmp, dst=spillLoc}],
135 : george 897 newReg=SOME tmpR
136 :     }
137 :     end
138 :     else if immedOrReg src then
139 :     (* can replace the destination directly *)
140 :     done(I.BINARY{binOp=binOp, src=src, dst=spillLoc}, an)
141 : george 1003 else let
142 : george 897 (* a memory src and non multBinOp
143 :     * --- cannot have two memory operands
144 :     *)
145 :     val tmpR = newReg()
146 :     val tmp = I.Direct tmpR
147 :     in
148 :     { proh=[tmpR],
149 : george 1003 code=[I.move{mvOp=I.MOVL, src=src, dst=tmp},
150 :     I.binary{binOp=binOp, src=tmp, dst=spillLoc}],
151 : george 897 newReg=NONE
152 :     }
153 : george 1003 end
154 :     end
155 : leunga 797 | I.CMPXCHG{lock,sz,src,dst} =>
156 : george 1003 if immedOrReg src then
157 :     {proh=[],
158 :     code=[mark(I.CMPXCHG{lock=lock,sz=sz,src=src,dst=spillLoc},an)],
159 :     newReg=NONE
160 :     }
161 :     else
162 : leunga 797 let val tmpR = newReg()
163 : george 1003 val tmp = I.Direct tmpR
164 :     in {proh=[],
165 :     code=[I.move{mvOp=I.MOVL, src=src, dst=tmp},
166 :     mark(I.CMPXCHG{lock=lock,sz=sz,src=tmp,dst=spillLoc},an)],
167 :     newReg=NONE
168 :     }
169 :     end
170 : monnier 498 | I.MULTDIV _ => error "spill: MULTDIV"
171 :     | I.MUL3{src1, src2, dst} =>
172 : george 1003 let val tmpR = newReg()
173 :     in {proh=[tmpR], newReg=SOME tmpR,
174 :     code=[mark(I.MUL3{src1=src1, src2=src2, dst=tmpR}, an),
175 :     I.move{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]
176 :     }
177 :     end
178 : monnier 498 | I.UNARY{unOp, opnd} => done(I.UNARY{unOp=unOp, opnd=spillLoc}, an)
179 : george 545 | I.SET{cond, opnd} => done(I.SET{cond=cond, opnd=spillLoc}, an)
180 : monnier 498 | I.POP _ => done(I.POP spillLoc, an)
181 :     | I.FNSTSW => error "spill: FNSTSW"
182 :     | _ => error "spill"
183 : george 1003 end (* x86Spill *)
184 : monnier 247
185 : george 1003 fun f(I.INSTR instr, an) = x86Spill(instr, an)
186 :     | f(I.ANNOTATION{a, i}, an) = f(i, a::an)
187 :     | f(I.KILL lk, an) =
188 :     {code=[annotate(I.KILL(rLiveKill (lk, reg)), an)],
189 :     proh=[],
190 :     newReg=NONE}
191 :     | f _ = error "spill:f"
192 :     in f(instr, [])
193 :     end
194 : monnier 247
195 : george 1003 fun reload(instr, reg, spillLoc) = let
196 :     fun x86Reload(instr, reg, spillLoc, an) = let
197 :     fun operand(rt, opnd) =
198 :     (case opnd
199 :     of I.Direct r => if CB.sameColor(r,reg) then I.Direct rt else opnd
200 :     | I.Displace{base, disp, mem} =>
201 :     if CB.sameColor(base,reg)
202 :     then I.Displace{base=rt, disp=disp, mem=mem}
203 :     else opnd
204 :     | I.Indexed{base=NONE, index, scale, disp, mem=mem} =>
205 :     if CB.sameColor(index,reg) then
206 :     I.Indexed{base=NONE, index=rt, scale=scale, disp=disp, mem=mem}
207 :     else opnd
208 :     | I.Indexed{base as SOME b, index, scale, disp, mem=mem} =>
209 :     if CB.sameColor(b,reg) then
210 :     operand(rt, I.Indexed{base=SOME rt, index=index,
211 :     scale=scale, disp=disp, mem=mem})
212 :     else if CB.sameColor(index,reg) then
213 :     I.Indexed{base=base, index=rt, scale=scale, disp=disp, mem=mem}
214 :     else opnd
215 :     | opnd => opnd
216 :     (*esac*))
217 : monnier 498
218 : george 1003 fun done(instr, an) = {code=[mark(instr, an)], proh=[], newReg=NONE}
219 : monnier 498
220 : george 1003 (* This version assumes that the value of tmpR is killed *)
221 :     fun withTmp(f, an) =
222 :     case spillLoc of
223 :     I.Direct tmpR =>
224 :     {newReg=NONE,
225 :     proh=[],
226 :     code=[mark(f tmpR, an)]
227 :     }
228 :     | _ =>
229 :     let val tmpR = newReg()
230 :     in {newReg=NONE,
231 :     proh=[tmpR],
232 :     code=[I.move{mvOp=I.MOVL, src=spillLoc, dst=I.Direct tmpR},
233 :     mark(f tmpR, an)
234 :     ]
235 :     }
236 :     end
237 : monnier 498
238 : george 1003 (* This version assumes that the value of tmpR is available afterwards *)
239 :     fun withTmpAvail(f, an) =
240 :     case spillLoc of
241 :     I.Direct tmpR =>
242 :     {newReg=SOME tmpR,
243 :     proh=[tmpR],
244 :     code=[mark(f tmpR, an)]
245 :     }
246 :     | _ =>
247 :     let val tmpR = newReg()
248 :     val tmp = I.Direct tmpR
249 :     in {newReg=SOME tmpR,
250 :     proh=[tmpR],
251 :     code=[I.move{mvOp=I.MOVL, src=spillLoc, dst=I.Direct tmpR},
252 :     mark(f tmpR, an)
253 :     ]
254 :     }
255 :     end
256 : george 545
257 : george 1003 fun replace(opn as I.Direct r) =
258 :     if CB.sameColor(r,reg) then spillLoc else opn
259 :     | replace opn = opn
260 : george 545
261 : george 1003 (* Fold in a memory operand if possible. Makes sure that both operands
262 :     * are not in memory. lsrc cannot be immediate.
263 :     *)
264 :     fun reloadCmp(cmp, lsrc, rsrc, an) =
265 :     let fun reloadIt() =
266 :     withTmp(fn tmpR =>
267 :     cmp{lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)}, an)
268 :     in if immedOrReg lsrc andalso immedOrReg rsrc then
269 :     let val lsrc' = replace lsrc
270 :     val rsrc' = replace rsrc
271 :     in if isMemory lsrc' andalso isMemory rsrc' then
272 :     reloadIt()
273 :     else
274 :     done(cmp{lsrc=lsrc', rsrc=rsrc'}, an)
275 :     end
276 :     else reloadIt()
277 :     end
278 : leunga 646
279 : george 1003 fun reloadBT(bitOp, lsrc, rsrc, an) =
280 :     reloadCmp(fn {lsrc,rsrc} => I.BITOP{bitOp=bitOp,lsrc=lsrc,rsrc=rsrc},
281 :     lsrc, rsrc, an)
282 : george 545
283 : george 1003 (* Fold in a memory operand if possible. Makes sure that the right
284 :     * operand is not in memory and left operand is not an immediate.
285 :     * lsrc rsrc
286 :     * AL, imm8 opc1 A8
287 :     * EAX, imm32 opc1 A9
288 :     * r/m8, imm8 opc2 F6/0 ib
289 :     * r/m32, imm32 opc2 F7/0 id
290 :     * r/m32, r32 opc3 85/r
291 :     *)
292 :     fun reloadTest(test, lsrc, rsrc, an) =
293 :     let fun reloadIt() =
294 :     withTmp(fn tmpR =>
295 :     test{lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)}, an)
296 :     in if immedOrReg lsrc andalso immedOrReg rsrc then
297 :     let val lsrc = replace lsrc
298 :     val rsrc = replace rsrc
299 :     in if isMemory rsrc then
300 :     if isMemory lsrc then reloadIt()
301 :     else (* it is commutative! *)
302 :     done(test{lsrc=rsrc, rsrc=lsrc}, an)
303 :     else
304 :     done(test{lsrc=lsrc, rsrc=rsrc}, an)
305 :     end
306 :     else reloadIt()
307 :     end
308 : george 545
309 : george 1003 fun reloadPush(push, arg as I.Direct _, an) =
310 :     done(push(replace arg), an)
311 :     | reloadPush(push, arg, an) =
312 :     withTmpAvail(fn tmpR => push(operand(tmpR, arg)), an)
313 : george 545
314 : george 1003 fun reloadReal(realOp, opnd, an) =
315 :     withTmpAvail(fn tmpR => realOp(operand(tmpR, opnd)), an)
316 :     in
317 :     case instr
318 :     of I.JMP(I.Direct _, labs) => done(I.JMP(spillLoc, labs), an)
319 :     | I.JMP(opnd, labs) => withTmp(fn t => I.JMP(operand(t, opnd), labs), an)
320 :     | I.JCC{opnd=I.Direct _, cond} => done(I.JCC{opnd=spillLoc, cond=cond}, an)
321 :     | I.JCC{opnd, cond} =>
322 :     withTmp(fn t => I.JCC{opnd=operand(t,opnd), cond=cond}, an)
323 :     | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
324 :     withTmp(fn t =>
325 :     I.CALL{opnd=operand(t, opnd), defs=defs, return=return,pops=pops,
326 :     uses=C.rmvReg(reg, uses), cutsTo=cutsTo, mem=mem}, an)
327 :     | I.MOVE{mvOp, src as I.Direct _, dst as I.Direct _} =>
328 :     done(I.MOVE{mvOp=mvOp, src=replace src, dst=dst},an)
329 :     | I.MOVE{mvOp, src, dst as I.Direct _} =>
330 :     withTmpAvail(fn t =>I.MOVE{mvOp=mvOp, src=operand(t, src), dst=dst},an)
331 :     | I.MOVE{mvOp, src as I.Direct _, dst} =>
332 :     if Props.eqOpn(dst, spillLoc) then {code=[], proh=[], newReg=NONE}
333 :     else withTmpAvail (* dst is not the spill reg *)
334 :     (fn t =>
335 :     I.MOVE{mvOp=mvOp, src=operand(t, src), dst=operand(t, dst)}, an)
336 :     | I.MOVE{mvOp, src, dst} =>
337 :     withTmpAvail (* dst is not the spill reg *)
338 :     (fn t =>
339 :     I.MOVE{mvOp=mvOp, src=operand(t, src), dst=operand(t, dst)}, an)
340 :     | I.LEA{r32, addr} =>
341 :     withTmpAvail(fn tmpR => I.LEA{r32=r32, addr=operand(tmpR, addr)}, an)
342 :     | I.CMPL{lsrc, rsrc} => reloadCmp(I.CMPL, lsrc, rsrc, an)
343 :     | I.CMPW{lsrc, rsrc} => reloadCmp(I.CMPW, lsrc, rsrc, an)
344 :     | I.CMPB{lsrc, rsrc} => reloadCmp(I.CMPB, lsrc, rsrc, an)
345 :     | I.TESTL{lsrc, rsrc} => reloadTest(I.TESTL, lsrc, rsrc, an)
346 :     | I.TESTW{lsrc, rsrc} => reloadTest(I.TESTW, lsrc, rsrc, an)
347 :     | I.TESTB{lsrc, rsrc} => reloadTest(I.TESTB, lsrc, rsrc, an)
348 :     | I.BITOP{bitOp,lsrc, rsrc} => reloadBT(bitOp, lsrc, rsrc, an)
349 :     | I.BINARY{binOp, src, dst as I.Direct _} =>
350 :     (case src of
351 :     I.Direct _ =>
352 :     done(I.BINARY{binOp=binOp, src=replace src, dst=dst},an)
353 :     | _ => withTmp(fn tmpR =>
354 :     I.BINARY{binOp=binOp, src=operand(tmpR, src), dst=dst}, an)
355 :     )
356 :     | I.BINARY{binOp, src, dst} =>
357 :     withTmp(fn tmpR => I.BINARY{binOp=binOp, src=operand(tmpR, src),
358 :     dst=operand(tmpR, dst)}, an)
359 :     | I.CMPXCHG{lock,sz,src,dst} =>
360 :     withTmp(fn tmpR => I.CMPXCHG{lock=lock, sz=sz,
361 :     src=operand(tmpR, src),
362 :     dst=operand(tmpR, dst)},an)
363 :     | I.MULTDIV{multDivOp, src as I.Direct _} =>
364 :     done(I.MULTDIV{multDivOp=multDivOp, src=replace src}, an)
365 :     | I.MULTDIV{multDivOp, src} =>
366 :     withTmp(fn tmpR =>
367 :     I.MULTDIV{multDivOp=multDivOp, src=operand(tmpR, src)}, an)
368 :     | I.MUL3{src1, src2, dst} =>
369 :     withTmp(fn tmpR =>
370 :     I.MUL3{src1=operand(tmpR, src1), src2=src2,
371 :     dst=if CB.sameColor(dst,reg)
372 :     then error "reload:MUL3" else dst}, an)
373 :     | I.UNARY{unOp, opnd} =>
374 :     withTmpAvail
375 :     (fn tmpR => I.UNARY{unOp=unOp, opnd=operand(tmpR, opnd)}, an)
376 :     | I.SET{cond, opnd} =>
377 :     withTmpAvail(fn tmpR => I.SET{cond=cond, opnd=operand(tmpR, opnd)}, an)
378 :     | I.PUSHL arg => reloadPush(I.PUSHL, arg, an)
379 :     | I.PUSHW arg => reloadPush(I.PUSHW, arg, an)
380 :     | I.PUSHB arg => reloadPush(I.PUSHB, arg, an)
381 :     | I.FILD opnd => reloadReal(I.FILD, opnd, an)
382 :     | I.FILDL opnd => reloadReal(I.FILDL, opnd, an)
383 :     | I.FILDLL opnd => reloadReal(I.FILDLL, opnd, an)
384 :     | I.FLDT opnd => reloadReal(I.FLDT, opnd, an)
385 :     | I.FLDL opnd => reloadReal(I.FLDL, opnd, an)
386 :     | I.FLDS opnd => reloadReal(I.FLDS, opnd, an)
387 :     | I.FSTPT opnd => reloadReal(I.FSTPT, opnd, an)
388 :     | I.FSTPL opnd => reloadReal(I.FSTPL, opnd, an)
389 :     | I.FSTPS opnd => reloadReal(I.FSTPS, opnd, an)
390 :     | I.FSTL opnd => reloadReal(I.FSTL, opnd, an)
391 :     | I.FSTS opnd => reloadReal(I.FSTS, opnd, an)
392 :     | I.FUCOM opnd => reloadReal(I.FUCOM, opnd, an)
393 :     | I.FUCOMP opnd => reloadReal(I.FUCOMP, opnd, an)
394 :     | I.FENV{fenvOp, opnd} => reloadReal(fn opnd =>
395 :     I.FENV{fenvOp=fenvOp,opnd=opnd}, opnd, an)
396 :     | I.FBINARY{binOp, src, dst} =>
397 :     withTmpAvail(fn tmpR =>
398 :     I.FBINARY{binOp=binOp, src=operand(tmpR, src), dst=dst}, an)
399 :     | I.FIBINARY{binOp, src} =>
400 :     withTmpAvail
401 :     (fn tmpR => I.FIBINARY{binOp=binOp, src=operand(tmpR, src)}, an)
402 : leunga 731
403 : george 1003 (* Pseudo fp instrctions *)
404 :     | I.FMOVE{fsize,src,dst} =>
405 :     withTmpAvail
406 :     (fn tmpR => I.FMOVE{fsize=fsize, src=operand(tmpR, src),
407 :     dst=operand(tmpR, dst)}, an)
408 :     | I.FILOAD{isize,ea,dst} =>
409 :     withTmpAvail
410 :     (fn tmpR => I.FILOAD{isize=isize, ea=operand(tmpR, ea),
411 :     dst=operand(tmpR, dst)}, an)
412 :     | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
413 :     withTmpAvail(fn tmpR =>
414 :     I.FBINOP{fsize=fsize, binOp=binOp, lsrc=operand(tmpR, lsrc),
415 :     rsrc=operand(tmpR, rsrc), dst=operand(tmpR, dst)}, an)
416 :     | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
417 :     withTmpAvail(fn tmpR =>
418 :     I.FIBINOP{isize=isize, binOp=binOp, lsrc=operand(tmpR, lsrc),
419 :     rsrc=operand(tmpR, rsrc), dst=operand(tmpR, dst)}, an)
420 :     | I.FUNOP{fsize,unOp,src,dst} =>
421 :     withTmpAvail(fn tmpR =>
422 :     I.FUNOP{fsize=fsize, unOp=unOp, src=operand(tmpR, src),
423 :     dst=operand(tmpR, dst)}, an)
424 :     | I.FCMP{fsize,lsrc,rsrc} =>
425 :     withTmpAvail(fn tmpR =>
426 :     I.FCMP{fsize=fsize,
427 :     lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)
428 :     }, an)
429 : leunga 731
430 : george 1003 | _ => error "reload"
431 :     end (*x86Reload*)
432 : monnier 247
433 : george 1003 fun f(I.ANNOTATION{a, i}, an) = f(i, a::an)
434 :     | f(I.INSTR i, an) = x86Reload(i, reg, spillLoc, an)
435 :     | f(I.LIVE lk, an) =
436 :     {code=[annotate(I.LIVE(rLiveKill (lk, reg)), an)],
437 :     proh=[],
438 :     newReg=NONE}
439 :     | f _ = error "reload: f"
440 :     in f(instr, [])
441 :     end (* reload *)
442 :    
443 :    
444 :    
445 :    
446 :     fun fspill(instr, reg, spillLoc) = let
447 :     fun x86Fspill(instr, reg, spillLoc, an) = let
448 :     fun withTmp(f, fsize, an) = let
449 :     val tmpR = C.newFreg()
450 :     val tmp = I.FPR tmpR
451 :     in
452 :     { proh=[tmpR],
453 :     code=[mark(f tmp, an),
454 :     I.fmove{fsize=fsize, src=tmp, dst=spillLoc}],
455 :     newReg=SOME tmpR (* XXX Should we propagate the definition? *)
456 :     }
457 : leunga 731 end
458 : george 1003 in
459 :     case instr
460 :     of I.FSTPL _ => {proh=[], code=[mark(I.FSTPL spillLoc, an)], newReg=NONE}
461 : george 545 | I.FSTPS _ => {proh=[], code=[mark(I.FSTPS spillLoc, an)], newReg=NONE}
462 : leunga 695 | I.FSTPT _ => {proh=[], code=[mark(I.FSTPT spillLoc, an)], newReg=NONE}
463 : leunga 579 | I.FSTL _ => {proh=[], code=[mark(I.FSTL spillLoc, an)], newReg=NONE}
464 :     | I.FSTS _ => {proh=[], code=[mark(I.FSTS spillLoc, an)], newReg=NONE}
465 : blume 839 | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
466 : monnier 429 {proh=[],
467 : leunga 815 code=[mark(I.CALL{opnd=opnd, defs=C.rmvFreg(reg,defs),
468 : george 1003 return=return, uses=uses,
469 :     cutsTo=cutsTo, mem=mem, pops=pops}, an)],
470 : monnier 498 newReg=NONE}
471 : leunga 731
472 :     (* Pseudo fp instrctions *)
473 :     | I.FMOVE{fsize as I.FP64,src,dst} =>
474 : george 1003 if Props.eqOpn(src,spillLoc) then
475 :     {proh=[], code=[], newReg=NONE}
476 :     else
477 :     {proh=[],code=[mark(I.FMOVE{fsize=fsize,src=src,dst=spillLoc},an)],
478 :     newReg=NONE} (* XXX bad for single precision *)
479 : leunga 731 | I.FMOVE _ => error "non-double precision not yet supported"
480 :     | I.FILOAD{isize,ea,dst} =>
481 : george 1003 {proh=[],code=[mark(I.FILOAD{isize=isize,ea=ea,dst=spillLoc},an)],
482 :     newReg=NONE} (* XXX bad for single precision *)
483 : leunga 731 | I.FBINOP{fsize as I.FP64,binOp,lsrc,rsrc,dst} =>
484 : george 1003 {proh=[],code=[mark(I.FBINOP{fsize=fsize,binOp=binOp,
485 :     lsrc=lsrc, rsrc=rsrc,
486 :     dst=spillLoc},an)],
487 :     newReg=NONE}
488 : leunga 731 | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
489 : george 1003 withTmp(fn tmpR =>
490 :     I.FBINOP{fsize=fsize, binOp=binOp,
491 :     lsrc=lsrc, rsrc=rsrc, dst=tmpR},
492 :     fsize, an)
493 : leunga 731 | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
494 : george 1003 withTmp(fn tmpR =>
495 :     I.FIBINOP{isize=isize, binOp=binOp,
496 :     lsrc=lsrc, rsrc=rsrc, dst=tmpR},
497 :     I.FP64, an) (* XXX *)
498 : leunga 731 | I.FUNOP{fsize,unOp,src,dst} =>
499 : george 1003 {proh=[],code=[mark(I.FUNOP{fsize=fsize,unOp=unOp,
500 :     src=src,dst=spillLoc},an)],
501 :     newReg=NONE}
502 : monnier 247 | _ => error "fspill"
503 : george 1003 (*esac*)
504 :     end (* x86Fspill *)
505 :     fun f(I.ANNOTATION{a,i}, an) = f(i, a::an)
506 :     | f(I.INSTR(i), an) = x86Fspill(i, reg, spillLoc, an)
507 :     | f(I.KILL lk, an) =
508 :     {code=[annotate(I.KILL(fLiveKill (lk, reg)), an)],
509 :     proh=[],
510 :     newReg=NONE}
511 :     | f _ = error "fspill:f"
512 :     in f(instr, [])
513 :     end
514 : monnier 247
515 : leunga 731
516 : george 1003 fun freload(instr, reg, spillLoc) = let
517 :     fun x86Freload(instr, reg, spillLoc, an) = let
518 :     fun rename(src as I.FDirect f) =
519 :     if CB.sameColor(f,reg) then spillLoc else src
520 :     | rename(src as I.FPR f) =
521 :     if CB.sameColor(f,reg) then spillLoc else src
522 :     | rename src = src
523 : leunga 731
524 : george 1003 fun withTmp(fsize, f, an) =
525 :     case spillLoc of
526 :     I.FDirect _ => {newReg=NONE, proh=[], code=[mark(f spillLoc, an)]}
527 :     | I.FPR _ => {newReg=NONE, proh=[], code=[mark(f spillLoc, an)]}
528 :     | _ =>
529 :     let val ftmpR = C.newFreg()
530 :     val ftmp = I.FPR(ftmpR)
531 :     in {newReg=NONE,
532 :     proh=[ftmpR],
533 :     code=[I.fmove{fsize=fsize, src=spillLoc, dst=ftmp},
534 :     mark(f ftmp, an)
535 :     ]
536 :     }
537 :     end
538 :     in
539 :     (case instr of
540 :     I.FLDT opnd => {code=[mark(I.FLDT spillLoc, an)], proh=[], newReg=NONE}
541 :     | I.FLDL opnd => {code=[mark(I.FLDL spillLoc, an)], proh=[], newReg=NONE}
542 :     | I.FLDS opnd => {code=[mark(I.FLDS spillLoc, an)], proh=[], newReg=NONE}
543 :     | I.FUCOM opnd => {code=[mark(I.FUCOM spillLoc, an)],proh=[],newReg=NONE}
544 :     | I.FUCOMP opnd => {code=[mark(I.FUCOMP spillLoc, an)],proh=[],newReg=NONE}
545 :     | I.FBINARY{binOp, src=I.FDirect f, dst} =>
546 :     if CB.sameColor(f,reg) then
547 :     {code=[mark(I.FBINARY{binOp=binOp, src=spillLoc, dst=dst}, an)],
548 :     proh=[],
549 :     newReg=NONE}
550 :     else error "freload:FBINARY"
551 : leunga 731
552 : george 1003 (* Pseudo fp instructions.
553 :     *)
554 :     | I.FMOVE{fsize as I.FP64,src,dst} =>
555 :     if Props.eqOpn(dst,spillLoc) then
556 :     {code=[], proh=[], newReg=NONE}
557 :     else
558 :     {code=[mark(I.FMOVE{fsize=fsize,src=spillLoc,dst=dst},an)],
559 :     proh=[], newReg=NONE}
560 :     | I.FMOVE _ => error "non-double precision not yet supported"
561 :     | I.FBINOP{fsize,binOp,lsrc,rsrc,dst} =>
562 :     {code=[mark(I.FBINOP{fsize=fsize,binOp=binOp,
563 :     lsrc=rename lsrc, rsrc=rename rsrc,dst=dst},an)],
564 :     proh=[], newReg=NONE}
565 :     | I.FIBINOP{isize,binOp,lsrc,rsrc,dst} =>
566 :     {code=[mark(I.FIBINOP{isize=isize,binOp=binOp,
567 :     lsrc=rename lsrc,rsrc=rename rsrc,dst=dst},an)],
568 :     proh=[], newReg=NONE}
569 :     | I.FUNOP{fsize,unOp,src,dst} =>
570 :     {code=[mark(I.FUNOP{fsize=fsize,unOp=unOp,
571 :     src=rename src, dst=dst},an)],
572 :     proh=[], newReg=NONE}
573 :     | I.FCMP{fsize,lsrc,rsrc} =>
574 :     (* Make sure that both the lsrc and rsrc cannot be in memory *)
575 :     (case (lsrc, rsrc) of
576 :     (I.FPR fs1, I.FPR fs2) =>
577 :     (case (CB.sameColor(fs1,reg), CB.sameColor(fs2,reg)) of
578 :     (true, true) =>
579 :     withTmp(fsize,
580 :     fn tmp => I.FCMP{fsize=fsize,lsrc=tmp, rsrc=tmp}, an)
581 :     | (true, false) =>
582 :     {code=[mark(I.FCMP{fsize=fsize,lsrc=spillLoc,rsrc=rsrc},an)],
583 :     proh=[], newReg=NONE}
584 :     | (false, true) =>
585 :     {code=[mark(I.FCMP{fsize=fsize,lsrc=lsrc,rsrc=spillLoc},an)],
586 :     proh=[], newReg=NONE}
587 :     | _ => error "fcmp.1"
588 :     )
589 :     | (I.FPR _, _) =>
590 :     withTmp(fsize,
591 :     fn tmp => I.FCMP{fsize=fsize,lsrc=tmp, rsrc=rsrc}, an)
592 :     | (_, I.FPR _) =>
593 :     withTmp(fsize,
594 :     fn tmp => I.FCMP{fsize=fsize,lsrc=rsrc, rsrc=tmp}, an)
595 :     | _ => error "fcmp.2"
596 :     )
597 :     | I.CALL{opnd, defs, uses, return, cutsTo, mem, pops} =>
598 :     {proh=[],
599 :     code=[mark(I.CALL{opnd=opnd, defs=C.rmvFreg(reg,defs),
600 :     return=return, pops=pops,
601 :     uses=uses, cutsTo=cutsTo, mem=mem}, an)],
602 :     newReg=NONE}
603 :     | _ => error "freload"
604 :     (*esac*))
605 :     end (* x86Freload *)
606 : monnier 498
607 : george 1003 fun f(I.ANNOTATION{a, i}, an) = f(i, a::an)
608 :     | f(I.INSTR i, an) = x86Freload(i, reg, spillLoc, an)
609 :     | f(I.LIVE lk, an) =
610 :     {code=[annotate(I.LIVE(fLiveKill (lk, reg)), an)],
611 :     proh=[],
612 :     newReg=NONE}
613 :     | f _ = error "freload.f"
614 :    
615 :     in f(instr, [])
616 :     end
617 : monnier 411 end

root@smlnj-gforge.cs.uchicago.edu
ViewVC Help
Powered by ViewVC 1.0.0