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 247 - (view) (download)
Original Path: sml/branches/SMLNJ/src/MLRISC/x86/ra/x86Spill.sml

1 : monnier 247 (* X86Spill.sml
2 :     *
3 :     * X86 spilling is complicated business.
4 :     *)
5 :     signature X86SPILL = sig
6 :     structure I : X86INSTR
7 :     val spill :
8 :     I.instruction * int * I.operand ->
9 :     {code:I.instruction list, proh:int list, instr:I.instruction option}
10 :    
11 :     val reload :
12 :     I.instruction * int * I.operand -> {code:I.instruction list, proh:int list}
13 :    
14 :     val fspill :
15 :     I.instruction * int * I.operand ->
16 :     {code:I.instruction list, proh:int list, instr:I.instruction option}
17 :    
18 :     val freload :
19 :     I.instruction * int * I.operand -> {code:I.instruction list, proh:int list}
20 :     end
21 :    
22 :    
23 :     functor X86Spill(structure Instr: X86INSTR
24 :     structure Asm : EMITTER_NEW where I = Instr (* XXX *)
25 :    
26 :     ) : X86SPILL = struct
27 :    
28 :     (* XXX: Looks like the wrong thing is done with CMPL.
29 :     * That is to say, does not recognize memory arguments.
30 :     *)
31 :     structure I = Instr
32 :     structure C = I.C
33 :    
34 :     fun error msg = MLRiscErrorMsg.impossible ("X86Spill: " ^ msg)
35 :    
36 :     type s = I.instruction * int * I.operand ->
37 :     {code:I.instruction list, proh:int list, instr:I.instruction option}
38 :     type r = I.instruction * int * I.operand -> {code:I.instruction list, proh:int list}
39 :    
40 :     val newReg = C.newReg
41 :    
42 :     fun immed(I.Immed _) = true
43 :     | immed(I.ImmedLabel _) = true
44 :     | immed(I.Const _) = true
45 :     | immed(I.LabelEA _) = true
46 :     | immed _ = false
47 :    
48 :     fun immedOrReg(I.Direct r) = true
49 :     | immedOrReg opnd = immed opnd
50 :    
51 :     fun eqEA(I.Displace{base=b1, disp=d1}, I.Displace{base=b2, disp=d2}) =
52 :     b1=b2 andalso
53 :     (case (d1, d2)
54 :     of (I.Immed i1, I.Immed i2) => i1 = i2
55 :     | _ => false
56 :     (*esac*))
57 :     | eqEA _ = false
58 :    
59 :     (* XXX:: Need to go through all the cases where 'done' is used
60 :     * to make sure that a the src cannot contain the register
61 :     * being spilled.
62 :     *)
63 :     fun spill(instr, reg, spillLoc) = let
64 :     fun done code = {code=code, proh=[], instr=NONE}
65 :     fun rewrite new old = if old=reg then new else old
66 :     in
67 :     case instr
68 :     of I.CALL(opnd, (r,f,c), uses) => let
69 :     val tmpR = newReg()
70 :     in
71 :     {proh=[tmpR],
72 :     instr=SOME(I.CALL(opnd, (map (rewrite tmpR) r,f,c), uses)),
73 :     code=[I.MOVE{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}] }
74 :     end
75 :     | I.MOVE{mvOp=I.MOVZX, src, dst} => let(* dst must always be a register *)
76 :     val tmpR = newReg()
77 :     in
78 :     {proh=[tmpR],
79 :     instr=SOME(I.MOVE{mvOp=I.MOVZX, src=src, dst=I.Direct tmpR}),
80 :     code=[I.MOVE{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]}
81 :     end
82 :     | I.MOVE{mvOp, src as I.Direct rs, dst} =>
83 :     if rs=reg then {code=[], proh=[], instr=NONE}
84 :     else done [I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}]
85 :     | I.MOVE{mvOp, src, dst=I.Direct _} =>
86 :     if immed src then done [I.MOVE{mvOp=mvOp, src=src, dst=spillLoc}]
87 :     else if eqEA(src, spillLoc) then {code=[], proh=[], instr=NONE}
88 :     else let
89 :     val tmpR = newReg()
90 :     in
91 :     {instr=SOME(I.MOVE{mvOp=mvOp, src=src, dst=I.Direct tmpR}),
92 :     proh=[tmpR],
93 :     code=[I.MOVE{mvOp=mvOp, src=I.Direct tmpR, dst=spillLoc}]}
94 :     end
95 :     | I.LEA{addr, r32} => let
96 :     val tmpR = newReg()
97 :     in {instr=SOME(I.LEA{addr=addr, r32=tmpR}),
98 :     proh=[tmpR],
99 :     code=[I.MOVE{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]}
100 :     end
101 :     | I.BINARY{binOp, src, dst} =>
102 :     if immedOrReg src then
103 :     {instr=SOME(I.BINARY{binOp=binOp, src=src, dst=spillLoc}),
104 :     proh=[],
105 :     code=[]}
106 :     else let
107 :     val tmpR = newReg()
108 :     in
109 :     {instr=SOME(I.MOVE{mvOp=I.MOVL, src=src, dst=I.Direct tmpR}),
110 :     proh=[tmpR],
111 :     code=[I.BINARY{binOp=binOp, src=I.Direct tmpR, dst=spillLoc}]}
112 :     end
113 :     | I.MULTDIV _ => error "spill: MULTDIV"
114 :     | I.MUL3{src1, src2, dst} => let
115 :     val tmpR = newReg()
116 :     in
117 :     {instr=SOME(I.MUL3{src1=src1, src2=src2, dst=tmpR}),
118 :     proh=[tmpR],
119 :     code=[I.MOVE{mvOp=I.MOVL, src=I.Direct tmpR, dst=spillLoc}]}
120 :     end
121 :     | I.UNARY{unOp, opnd} => done [I.UNARY{unOp=unOp, opnd=spillLoc}]
122 :     | I.POP _ => done [I.POP spillLoc]
123 :     | I.COPY _ => error "spill: COPY"
124 :     | I.FNSTSW => error "spill: FNSTSW"
125 :     | _ => error "spill"
126 :     end
127 :    
128 :     fun reload(instr, reg, spillLoc) = let
129 :     fun operand(rt, opnd) =
130 :     (case opnd
131 :     of I.Direct r => if r=reg then I.Direct rt else opnd
132 :     | I.Displace{base, disp} =>
133 :     if base=reg then I.Displace{base=rt, disp=disp} else opnd
134 :     | I.Indexed{base=NONE, index, scale, disp} =>
135 :     if index=reg then
136 :     I.Indexed{base=NONE, index=rt, scale=scale, disp=disp}
137 :     else opnd
138 :     | I.Indexed{base as SOME b, index, scale, disp} =>
139 :     if b=reg then
140 :     operand(rt, I.Indexed{base=SOME rt, index=index,
141 :     scale=scale, disp=disp})
142 :     else if index=reg then
143 :     I.Indexed{base=base, index=rt, scale=scale, disp=disp}
144 :     else opnd
145 :     | opnd => opnd
146 :     (*esac*))
147 :    
148 :     fun uses(I.Direct r) = r = reg (* XXX *)
149 :     | uses(I.Displace{base, disp}) = base=reg
150 :     | uses(I.Indexed{base=NONE, index, scale, disp}) = index=reg
151 :     | uses(I.Indexed{base=SOME b, index, scale, disp})= b=reg orelse index=reg
152 :     | uses _ = false
153 :     fun done c = {code=c, proh=[]}
154 :     fun rewrite rt r = if r=reg then rt else r
155 :     fun ldSpillLoc (tmpR) = I.MOVE{mvOp=I.MOVL, src=spillLoc, dst=I.Direct tmpR}
156 :     fun withTmp f = let
157 :     val tmpR = newReg()
158 :     in {code=[ldSpillLoc(tmpR), f tmpR], proh=[tmpR]}
159 :     end
160 :     in
161 :     case instr
162 :     of I.JMP(I.Direct _, labs) => {code=[I.JMP(spillLoc, labs)], proh=[]}
163 :     | I.JMP(opnd, labs) => withTmp(fn tmpR => I.JMP(operand(tmpR, opnd), labs))
164 :     | I.JCC{opnd=I.Direct _, cond} => done[I.JCC{opnd=spillLoc, cond=cond}]
165 :     | I.JCC{opnd, cond} =>
166 :     withTmp(fn tmpR => I.JCC{opnd=operand(tmpR, opnd), cond=cond})
167 :     | I.CALL(opnd, defs, uses as (r,f,c)) =>
168 :     withTmp(fn tmpR =>
169 :     I.CALL(operand(tmpR, opnd), defs, (map (rewrite tmpR) r, f,c)))
170 :     | I.MOVE{mvOp, src, dst as I.Direct _} =>
171 :     withTmp(fn tmpR =>I.MOVE{mvOp=mvOp, src=operand(tmpR, src), dst=dst})
172 :     | I.MOVE{mvOp, src as I.Direct _, dst} =>
173 :     if eqEA(dst, spillLoc) then {code=[], proh=[]}
174 :     else withTmp
175 :     (fn tmpR =>
176 :     I.MOVE{mvOp=mvOp, src=operand(tmpR, src), dst=operand(tmpR, dst)})
177 :     | I.MOVE{mvOp, src, dst} =>
178 :     withTmp
179 :     (fn tmpR =>
180 :     I.MOVE{mvOp=mvOp, src=operand(tmpR, src), dst=operand(tmpR, dst)})
181 :     | I.LEA{r32, addr} =>
182 :     withTmp(fn tmpR => I.LEA{r32=r32, addr=operand(tmpR, addr)})
183 :     | I.CMP{lsrc, rsrc} =>
184 :     withTmp(fn tmpR => I.CMP{lsrc=operand(tmpR, lsrc), rsrc=operand(tmpR, rsrc)})
185 :     | I.BINARY{binOp, src, dst as I.Direct _} =>
186 :     withTmp(fn tmpR => I.BINARY{binOp=binOp, src=operand(tmpR, src), dst=dst})
187 :     | I.BINARY{binOp, src, dst} =>
188 :     withTmp
189 :     (fn tmpR =>
190 :     I.BINARY{binOp=binOp, src=operand(tmpR, src), dst=operand(tmpR,dst)})
191 :     | I.MULTDIV{multDivOp, src} =>
192 :     withTmp(fn tmpR => I.MULTDIV{multDivOp=multDivOp, src=operand(tmpR, src)})
193 :     | I.MUL3{src1, src2, dst} =>
194 :     withTmp(fn tmpR =>
195 :     I.MUL3{src1=operand(tmpR, src1), src2=src2,
196 :     dst=if dst = reg then error "reload:MUL3" else dst})
197 :     | I.UNARY{unOp, opnd} =>
198 :     withTmp(fn tmpR => I.UNARY{unOp=unOp, opnd=operand(tmpR, opnd)})
199 :     | I.PUSH arg => withTmp(fn tmpR => I.PUSH(operand(tmpR, arg)))
200 :     | I.COPY _ => error "reload:COPY"
201 :     | I.FILD opnd => withTmp(fn tmpR => I.FILD(operand(tmpR, opnd)))
202 :     | I.FLD opnd =>
203 :     withTmp (fn tmpR => I.FLD(operand(tmpR, opnd)))
204 :     | I.FSTP opnd =>
205 :     withTmp(fn tmpR => I.FSTP(operand(tmpR, opnd)))
206 :     | I.FBINARY{binOp, src, dst} =>
207 :     withTmp(fn tmpR =>
208 :     I.FBINARY{binOp=binOp, src=operand(tmpR, src), dst=dst})
209 :    
210 :     | _ => error "reload"
211 :     end (*reload*)
212 :    
213 :     fun fspill(instr, reg, spillLoc) =
214 :     (case instr
215 :     of I.FSTP _ => {proh=[], instr=NONE, code=[I.FSTP spillLoc]}
216 :     | _ => error "fspill"
217 :     (*esac*))
218 :    
219 :     fun freload(instr, reg, spillLoc) =
220 :     (case instr
221 :     of I.FLD opnd => {code=[I.FLD spillLoc], proh=[]}
222 :     | I.FBINARY{binOp, src=I.FDirect f, dst} =>
223 :     if f = reg then
224 :     {code=[I.FBINARY{binOp=binOp, src=spillLoc, dst=dst}],
225 :     proh=[]}
226 :     else error "freload:FBINARY"
227 :     | _ => error "freload"
228 :     (*esac*))
229 :     end

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