diff options
Diffstat (limited to 'src/lj_opt_split.c')
-rw-r--r-- | src/lj_opt_split.c | 154 |
1 files changed, 146 insertions, 8 deletions
diff --git a/src/lj_opt_split.c b/src/lj_opt_split.c index 8d7cd4c2..79ac3cce 100644 --- a/src/lj_opt_split.c +++ b/src/lj_opt_split.c | |||
@@ -8,14 +8,15 @@ | |||
8 | 8 | ||
9 | #include "lj_obj.h" | 9 | #include "lj_obj.h" |
10 | 10 | ||
11 | #if LJ_HASJIT && (LJ_SOFTFP || (LJ_32 && LJ_HASFFI)) | 11 | #if LJ_HASJIT && (LJ_SOFTFP32 || (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" |
18 | #include "lj_iropt.h" | 18 | #include "lj_iropt.h" |
19 | #include "lj_dispatch.h" | ||
19 | #include "lj_vm.h" | 20 | #include "lj_vm.h" |
20 | 21 | ||
21 | /* SPLIT pass: | 22 | /* SPLIT pass: |
@@ -139,6 +140,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); | 140 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
140 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 141 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
141 | } | 142 | } |
143 | #endif | ||
142 | 144 | ||
143 | /* Emit a CALLN with one split 64 bit argument and a 32 bit argument. */ | 145 | /* 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, | 146 | static IRRef split_call_li(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -155,7 +157,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); | 157 | ir->prev = tmp = split_emit(J, IRTI(IR_CALLN), tmp, id); |
156 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); | 158 | return split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), tmp, tmp); |
157 | } | 159 | } |
158 | #endif | ||
159 | 160 | ||
160 | /* Emit a CALLN with two split 64 bit arguments. */ | 161 | /* Emit a CALLN with two split 64 bit arguments. */ |
161 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, | 162 | static IRRef split_call_ll(jit_State *J, IRRef1 *hisubst, IRIns *oir, |
@@ -192,9 +193,121 @@ static IRRef split_ptr(jit_State *J, IRIns *oir, IRRef ref) | |||
192 | nref = ir->op1; | 193 | nref = ir->op1; |
193 | if (ofs == 0) return nref; | 194 | if (ofs == 0) return nref; |
194 | } | 195 | } |
195 | return split_emit(J, IRTI(IR_ADD), nref, lj_ir_kint(J, ofs)); | 196 | return split_emit(J, IRT(IR_ADD, IRT_PTR), nref, lj_ir_kint(J, ofs)); |
197 | } | ||
198 | |||
199 | #if LJ_HASFFI | ||
200 | static IRRef split_bitshift(jit_State *J, IRRef1 *hisubst, | ||
201 | IRIns *oir, IRIns *nir, IRIns *ir) | ||
202 | { | ||
203 | IROp op = ir->o; | ||
204 | IRRef kref = nir->op2; | ||
205 | if (irref_isk(kref)) { /* Optimize constant shifts. */ | ||
206 | int32_t k = (IR(kref)->i & 63); | ||
207 | IRRef lo = nir->op1, hi = hisubst[ir->op1]; | ||
208 | if (op == IR_BROL || op == IR_BROR) { | ||
209 | if (op == IR_BROR) k = (-k & 63); | ||
210 | if (k >= 32) { IRRef t = lo; lo = hi; hi = t; k -= 32; } | ||
211 | if (k == 0) { | ||
212 | passthrough: | ||
213 | J->cur.nins--; | ||
214 | ir->prev = lo; | ||
215 | return hi; | ||
216 | } else { | ||
217 | TRef k1, k2; | ||
218 | IRRef t1, t2, t3, t4; | ||
219 | J->cur.nins--; | ||
220 | k1 = lj_ir_kint(J, k); | ||
221 | k2 = lj_ir_kint(J, (-k & 31)); | ||
222 | t1 = split_emit(J, IRTI(IR_BSHL), lo, k1); | ||
223 | t2 = split_emit(J, IRTI(IR_BSHL), hi, k1); | ||
224 | t3 = split_emit(J, IRTI(IR_BSHR), lo, k2); | ||
225 | t4 = split_emit(J, IRTI(IR_BSHR), hi, k2); | ||
226 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t4); | ||
227 | return split_emit(J, IRTI(IR_BOR), t2, t3); | ||
228 | } | ||
229 | } else if (k == 0) { | ||
230 | goto passthrough; | ||
231 | } else if (k < 32) { | ||
232 | if (op == IR_BSHL) { | ||
233 | IRRef t1 = split_emit(J, IRTI(IR_BSHL), hi, kref); | ||
234 | IRRef t2 = split_emit(J, IRTI(IR_BSHR), lo, lj_ir_kint(J, (-k&31))); | ||
235 | return split_emit(J, IRTI(IR_BOR), t1, t2); | ||
236 | } else { | ||
237 | IRRef t1 = ir->prev, t2; | ||
238 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
239 | nir->o = IR_BSHR; | ||
240 | t2 = split_emit(J, IRTI(IR_BSHL), hi, lj_ir_kint(J, (-k&31))); | ||
241 | ir->prev = split_emit(J, IRTI(IR_BOR), t1, t2); | ||
242 | return split_emit(J, IRTI(op), hi, kref); | ||
243 | } | ||
244 | } else { | ||
245 | if (op == IR_BSHL) { | ||
246 | if (k == 32) | ||
247 | J->cur.nins--; | ||
248 | else | ||
249 | lo = ir->prev; | ||
250 | ir->prev = lj_ir_kint(J, 0); | ||
251 | return lo; | ||
252 | } else { | ||
253 | lua_assert(op == IR_BSHR || op == IR_BSAR); | ||
254 | if (k == 32) { | ||
255 | J->cur.nins--; | ||
256 | ir->prev = hi; | ||
257 | } else { | ||
258 | nir->op1 = hi; | ||
259 | } | ||
260 | if (op == IR_BSHR) | ||
261 | return lj_ir_kint(J, 0); | ||
262 | else | ||
263 | return split_emit(J, IRTI(IR_BSAR), hi, lj_ir_kint(J, 31)); | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | return split_call_li(J, hisubst, oir, ir, | ||
268 | op - IR_BSHL + IRCALL_lj_carith_shl64); | ||
196 | } | 269 | } |
197 | 270 | ||
271 | static IRRef split_bitop(jit_State *J, IRRef1 *hisubst, | ||
272 | IRIns *nir, IRIns *ir) | ||
273 | { | ||
274 | IROp op = ir->o; | ||
275 | IRRef hi, kref = nir->op2; | ||
276 | if (irref_isk(kref)) { /* Optimize bit operations with lo constant. */ | ||
277 | int32_t k = IR(kref)->i; | ||
278 | if (k == 0 || k == -1) { | ||
279 | if (op == IR_BAND) k = ~k; | ||
280 | if (k == 0) { | ||
281 | J->cur.nins--; | ||
282 | ir->prev = nir->op1; | ||
283 | } else if (op == IR_BXOR) { | ||
284 | nir->o = IR_BNOT; | ||
285 | nir->op2 = 0; | ||
286 | } else { | ||
287 | J->cur.nins--; | ||
288 | ir->prev = kref; | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | hi = hisubst[ir->op1]; | ||
293 | kref = hisubst[ir->op2]; | ||
294 | if (irref_isk(kref)) { /* Optimize bit operations with hi constant. */ | ||
295 | int32_t k = IR(kref)->i; | ||
296 | if (k == 0 || k == -1) { | ||
297 | if (op == IR_BAND) k = ~k; | ||
298 | if (k == 0) { | ||
299 | return hi; | ||
300 | } else if (op == IR_BXOR) { | ||
301 | return split_emit(J, IRTI(IR_BNOT), hi, 0); | ||
302 | } else { | ||
303 | return kref; | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | return split_emit(J, IRTI(op), hi, kref); | ||
308 | } | ||
309 | #endif | ||
310 | |||
198 | /* Substitute references of a snapshot. */ | 311 | /* Substitute references of a snapshot. */ |
199 | static void split_subst_snap(jit_State *J, SnapShot *snap, IRIns *oir) | 312 | static void split_subst_snap(jit_State *J, SnapShot *snap, IRIns *oir) |
200 | { | 313 | { |
@@ -214,7 +327,7 @@ static void split_ir(jit_State *J) | |||
214 | IRRef nins = J->cur.nins, nk = J->cur.nk; | 327 | IRRef nins = J->cur.nins, nk = J->cur.nk; |
215 | MSize irlen = nins - nk; | 328 | MSize irlen = nins - nk; |
216 | MSize need = (irlen+1)*(sizeof(IRIns) + sizeof(IRRef1)); | 329 | MSize need = (irlen+1)*(sizeof(IRIns) + sizeof(IRRef1)); |
217 | IRIns *oir = (IRIns *)lj_str_needbuf(J->L, &G(J->L)->tmpbuf, need); | 330 | IRIns *oir = (IRIns *)lj_buf_tmp(J->L, need); |
218 | IRRef1 *hisubst; | 331 | IRRef1 *hisubst; |
219 | IRRef ref, snref; | 332 | IRRef ref, snref; |
220 | SnapShot *snap; | 333 | SnapShot *snap; |
@@ -241,6 +354,8 @@ static void split_ir(jit_State *J) | |||
241 | ir->prev = ref; /* Identity substitution for loword. */ | 354 | ir->prev = ref; /* Identity substitution for loword. */ |
242 | hisubst[ref] = 0; | 355 | hisubst[ref] = 0; |
243 | } | 356 | } |
357 | if (irt_is64(ir->t) && ir->o != IR_KNULL) | ||
358 | ref++; | ||
244 | } | 359 | } |
245 | 360 | ||
246 | /* Process old IR instructions. */ | 361 | /* Process old IR instructions. */ |
@@ -321,7 +436,8 @@ static void split_ir(jit_State *J) | |||
321 | nir->o = IR_CONV; /* Pass through loword. */ | 436 | nir->o = IR_CONV; /* Pass through loword. */ |
322 | nir->op2 = (IRT_INT << 5) | IRT_INT; | 437 | nir->op2 = (IRT_INT << 5) | IRT_INT; |
323 | hi = split_emit(J, IRT(ir->o == IR_NEG ? IR_BXOR : IR_BAND, IRT_SOFTFP), | 438 | hi = split_emit(J, IRT(ir->o == IR_NEG ? IR_BXOR : IR_BAND, IRT_SOFTFP), |
324 | hisubst[ir->op1], hisubst[ir->op2]); | 439 | hisubst[ir->op1], |
440 | lj_ir_kint(J, (int32_t)(0x7fffffffu + (ir->o == IR_NEG)))); | ||
325 | break; | 441 | break; |
326 | case IR_SLOAD: | 442 | case IR_SLOAD: |
327 | if ((nir->op2 & IRSLOAD_CONVERT)) { /* Convert from int to number. */ | 443 | if ((nir->op2 & IRSLOAD_CONVERT)) { /* Convert from int to number. */ |
@@ -336,15 +452,24 @@ static void split_ir(jit_State *J) | |||
336 | case IR_STRTO: | 452 | case IR_STRTO: |
337 | hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref); | 453 | hi = split_emit(J, IRT(IR_HIOP, IRT_SOFTFP), nref, nref); |
338 | break; | 454 | break; |
455 | case IR_FLOAD: | ||
456 | lua_assert(ir->op1 == REF_NIL); | ||
457 | hi = lj_ir_kint(J, *(int32_t*)((char*)J2GG(J) + ir->op2 + LJ_LE*4)); | ||
458 | nir->op2 += LJ_BE*4; | ||
459 | break; | ||
339 | case IR_XLOAD: { | 460 | case IR_XLOAD: { |
340 | IRIns inslo = *nir; /* Save/undo the emit of the lo XLOAD. */ | 461 | IRIns inslo = *nir; /* Save/undo the emit of the lo XLOAD. */ |
341 | J->cur.nins--; | 462 | J->cur.nins--; |
342 | hi = split_ptr(J, oir, ir->op1); /* Insert the hiref ADD. */ | 463 | hi = split_ptr(J, oir, ir->op1); /* Insert the hiref ADD. */ |
464 | #if LJ_BE | ||
465 | hi = split_emit(J, IRT(IR_XLOAD, IRT_INT), hi, ir->op2); | ||
466 | inslo.t.irt = IRT_SOFTFP | (inslo.t.irt & IRT_GUARD); | ||
467 | #endif | ||
343 | nref = lj_ir_nextins(J); | 468 | nref = lj_ir_nextins(J); |
344 | nir = IR(nref); | 469 | nir = IR(nref); |
345 | *nir = inslo; /* Re-emit lo XLOAD immediately before hi XLOAD. */ | 470 | *nir = inslo; /* Re-emit lo XLOAD. */ |
346 | hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), hi, ir->op2); | ||
347 | #if LJ_LE | 471 | #if LJ_LE |
472 | hi = split_emit(J, IRT(IR_XLOAD, IRT_SOFTFP), hi, ir->op2); | ||
348 | ir->prev = nref; | 473 | ir->prev = nref; |
349 | #else | 474 | #else |
350 | ir->prev = hi; hi = nref; | 475 | ir->prev = hi; hi = nref; |
@@ -438,6 +563,19 @@ static void split_ir(jit_State *J) | |||
438 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : | 563 | irt_isi64(ir->t) ? IRCALL_lj_carith_powi64 : |
439 | IRCALL_lj_carith_powu64); | 564 | IRCALL_lj_carith_powu64); |
440 | break; | 565 | break; |
566 | case IR_BNOT: | ||
567 | hi = split_emit(J, IRTI(IR_BNOT), hiref, 0); | ||
568 | break; | ||
569 | case IR_BSWAP: | ||
570 | ir->prev = split_emit(J, IRTI(IR_BSWAP), hiref, 0); | ||
571 | hi = nref; | ||
572 | break; | ||
573 | case IR_BAND: case IR_BOR: case IR_BXOR: | ||
574 | hi = split_bitop(J, hisubst, nir, ir); | ||
575 | break; | ||
576 | case IR_BSHL: case IR_BSHR: case IR_BSAR: case IR_BROL: case IR_BROR: | ||
577 | hi = split_bitshift(J, hisubst, oir, nir, ir); | ||
578 | break; | ||
441 | case IR_FLOAD: | 579 | case IR_FLOAD: |
442 | lua_assert(ir->op2 == IRFL_CDATA_INT64); | 580 | lua_assert(ir->op2 == IRFL_CDATA_INT64); |
443 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); | 581 | hi = split_emit(J, IRTI(IR_FLOAD), nir->op1, IRFL_CDATA_INT64_4); |