diff options
Diffstat (limited to 'src/lj_opt_split.c')
-rw-r--r-- | src/lj_opt_split.c | 131 |
1 files changed, 128 insertions, 3 deletions
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 5a8c33b9..89db0e92 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -11,7 +11,7 @@ | |||
11 | #if LJ_HASJIT && (LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) | 11 | #if LJ_HASJIT && (LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) |
12 | 12 | ||
13 | #include "lj_err.h" | 13 | #include "lj_err.h" |
14 | #include "lj_str.h" | 14 | #include "lj_buf.h" |
15 | #include "lj_ir.h" | 15 | #include "lj_ir.h" |
16 | #include "lj_jit.h" | 16 | #include "lj_jit.h" |
17 | #include "lj_ircall.h" | 17 | #include "lj_ircall.h" |
@@ -139,6 +139,7 @@ static IRRef split_call_l(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
139 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 139 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
140 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 140 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
141 | } | 141 | } |
142 | #endif | ||
142 | 143 | ||
143 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ | 144 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ |
144 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 145 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -155,7 +156,6 @@ static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, | |||
155 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); | 156 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
156 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 157 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
157 | } | 158 | } |
158 | #endif | ||
159 | 159 | ||
160 | /* Emit a CALLN with two split 64 bit arguments. */ | 160 | /* Emit a CALLN with two split 64 bit arguments. */ |
161 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 161 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -195,6 +195,118 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref) | |||
195 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); | 195 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); |
196 | } | 196 | } |
197 | 197 | ||
198 | #if LJ_HASFFI | ||
199 | static IRRef split_bitshift(jit_State *J, IRRef1 *hisubst, | ||
200 | IRIns *oir, IRIns *nir, IRIns *ir) | ||
201 | { | ||
202 | IROp op = ir->o; | ||
203 | IRRef kref = nir->op2; | ||
204 | if (irref_isk(kref)) { /* Optimize constant shifts. */ | ||
205 | int32_t k = (IR(kref)->i & 63); | ||
206 | IRRef lo = nir->op1, hi = hisubst[ir->op1]; | ||
207 | if (op == IR_BROL || op == IR_BROR) { | ||
208 | if (op == IR_BROR) k = (-k & 63); | ||
209 | if (k >= 32) { IRRef t = lo; lo = hi; hi = t; k -= 32; } | ||
210 | if (k == 0) { | ||
211 | passthrough: | ||
212 | J->cur.nins--; | ||
213 | ir->prev = lo; | ||
214 | return hi; | ||
215 | } else { | ||
216 | TRef k1, k2; | ||
217 | IRRef t1, t2, t3, t4; | ||
218 | J->cur.nins--; | ||
219 | k1 = lj_ir_kint(J, k); | ||
220 | k2 = lj_ir_kint(J, (-k & 31)); | ||
221 | t1 = split_emit(J, IRTI(IR_BSHL), lo, k1); | ||
222 | t2 = split_emit(J, IRTI(IR_BSHL), hi, k1); | ||
223 | t3 = split_emit(J, IRTI(IR_BSHR), lo, k2); | ||
224 | t4 = split_emit(J, IRTI(IR_BSHR), hi, k2); | ||
225 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t4); | ||
226 | return split_emit(J, IRTI(IR_BOR), t2, t3); | ||
227 | } | ||
228 | } else if (k == 0) { | ||
229 | goto passthrough; | ||
230 | } else if (k < 32) { | ||
231 | if (op == IR_BSHL) { | ||
232 | IRRef t1 = split_emit(J, IRTI(IR_BSHL), hi, kref); | ||
233 | IRRef t2 = split_emit(J, IRTI(IR_BSHR), lo, lj_ir_kint(J, (-k&31))); | ||
234 | return split_emit(J, IRTI(IR_BOR), t1, t2); | ||
235 | } else { | ||
236 | IRRef t1 = ir->prev, t2; | ||
237 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
238 | nir->o = IR_BSHR; | ||
239 | t2 = split_emit(J, IRTI(IR_BSHL), hi, lj_ir_kint(J, (-k&31))); | ||
240 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t2); | ||
241 | return split_emit(J, IRTI(op), hi, kref); | ||
242 | } | ||
243 | } else { | ||
244 | if (op == IR_BSHL) { | ||
245 | if (k == 32) | ||
246 | J->cur.nins--; | ||
247 | else | ||
248 | lo = ir->prev; | ||
249 | ir->prev = lj_ir_kint(J, 0); | ||
250 | return lo; | ||
251 | } else { | ||
252 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
253 | if (k == 32) { | ||
254 | J->cur.nins--; | ||
255 | ir->prev = hi; | ||
256 | } else { | ||
257 | nir->op1 = hi; | ||
258 | } | ||
259 | if (op == IR_BSHR) | ||
260 | return lj_ir_kint(J, 0); | ||
261 | else | ||
262 | return split_emit(J, IRTI(IR_BSAR), hi, lj_ir_kint(J, 31)); | ||
263 | } | ||
264 | } | ||
265 | } | ||
266 | return split_call_li(J, hisubst, oir, ir, | ||
267 | op - IR_BSHL + IRCALL_lj_carith_shl64); | ||
268 | } | ||
269 | |||
270 | static IRRef split_bitop(jit_State *J, IRRef1 *hisubst, | ||
271 | IRIns *nir, IRIns *ir) | ||
272 | { | ||
273 | IROp op = ir->o; | ||
274 | IRRef hi, kref = nir->op2; | ||
275 | if (irref_isk(kref)) { /* Optimize bit operations with lo constant. */ | ||
276 | int32_t k = IR(kref)->i; | ||
277 | if (k == 0 || k == -1) { | ||
278 | if (op == IR_BAND) k = ~k; | ||
279 | if (k == 0) { | ||
280 | J->cur.nins--; | ||
281 | ir->prev = nir->op1; | ||
282 | } else if (op == IR_BXOR) { | ||
283 | nir->o = IR_BNOT; | ||
284 | nir->op2 = 0; | ||
285 | } else { | ||
286 | J->cur.nins--; | ||
287 | ir->prev = kref; | ||
288 | } | ||
289 | } | ||
290 | } | ||
291 | hi = hisubst[ir->op1]; | ||
292 | kref = hisubst[ir->op2]; | ||
293 | if (irref_isk(kref)) { /* Optimize bit operations with hi constant. */ | ||
294 | int32_t k = IR(kref)->i; | ||
295 | if (k == 0 || k == -1) { | ||
296 | if (op == IR_BAND) k = ~k; | ||
297 | if (k == 0) { | ||
298 | return hi; | ||
299 | } else if (op == IR_BXOR) { | ||
300 | return split_emit(J, IRTI(IR_BNOT), hi, 0); | ||
301 | } else { | ||
302 | return kref; | ||
303 | } | ||
304 | } | ||
305 | } | ||
306 | return split_emit(J, IRTI(op), hi, kref); | ||
307 | } | ||
308 | #endif | ||
309 | |||
198 | /* Substitute references of a snapshot. */ | 310 | /* Substitute references of a snapshot. */ |
199 | static void split_subst_snap(jit_State *J, SnapShot *snap, IRIns *oir) | 311 | static void split_subst_snap(jit_State *J, SnapShot *snap, IRIns *oir) |
200 | { | 312 | { |
@@ -214,7 +326,7 @@ static void split_ir(jit_State *J) | |||
214 | IRRef nins = J->cur.nins, nk = J->cur.nk; | 326 | IRRef nins = J->cur.nins, nk = J->cur.nk; |
215 | MSize irlen = nins - nk; | 327 | MSize irlen = nins - nk; |
216 | MSize need = (irlen+1)*(sizeof(IRIns) + sizeof(IRRef1)); | 328 | MSize need = (irlen+1)*(sizeof(IRIns) + sizeof(IRRef1)); |
217 | IRIns *oir = (IRIns *)lj_str_needbuf(J->L, &G(J->L)->tmpbuf, need); | 329 | IRIns *oir = (IRIns *)lj_buf_tmp(J->L, need); |
218 | IRRef1 *hisubst; | 330 | IRRef1 *hisubst; |
219 | IRRef ref, snref; | 331 | IRRef ref, snref; |
220 | SnapShot *snap; | 332 | SnapShot *snap; |
@@ -438,6 +550,19 @@ static void split_ir(jit_State *J) | |||
438 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 550 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
439 | IRCALL_lj_carith_powu64); | 551 | IRCALL_lj_carith_powu64); |
440 | break; | 552 | break; |
553 | case IR_BNOT: | ||
554 | hi = split_emit(J, IRTI(IR_BNOT), hiref, 0); | ||
555 | break; | ||
556 | case IR_BSWAP: | ||
557 | ir->prev = split_emit(J, IRTI(IR_BSWAP), hiref, 0); | ||
558 | hi = nref; | ||
559 | break; | ||
560 | case IR_BAND: case IR_BOR: case IR_BXOR: | ||
561 | hi = split_bitop(J, hisubst, nir, ir); | ||
562 | break; | ||
563 | case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR: | ||
564 | hi = split_bitshift(J, hisubst, oir, nir, ir); | ||
565 | break; | ||
441 | case IR_FLOAD: | 566 | case IR_FLOAD: |
442 | lua_assert(ir->op2 == IRFL_CDATA_INT64); | 567 | lua_assert(ir->op2 == IRFL_CDATA_INT64); |
443 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); | 568 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); |