diff options
| author | Mike Pall <mike> | 2010-06-30 23:30:08 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-06-30 23:30:08 +0200 |
| commit | bbd1584d5f26e7eb674fb1721de9915e4dda489c (patch) | |
| tree | f4c36d47afcf9b2a7c03f3ec181d9cd00cfc0924 | |
| parent | 9f6707ddbb25287948d58555818e68ab742083be (diff) | |
| download | luajit-bbd1584d5f26e7eb674fb1721de9915e4dda489c.tar.gz luajit-bbd1584d5f26e7eb674fb1721de9915e4dda489c.tar.bz2 luajit-bbd1584d5f26e7eb674fb1721de9915e4dda489c.zip | |
Do not eliminate PHIs for values only referenced from side exits.
| -rw-r--r-- | src/lj_opt_loop.c | 51 |
1 files changed, 28 insertions, 23 deletions
diff --git a/src/lj_opt_loop.c b/src/lj_opt_loop.c index 48207dd5..f370d59f 100644 --- a/src/lj_opt_loop.c +++ b/src/lj_opt_loop.c | |||
| @@ -101,7 +101,8 @@ | |||
| 101 | /* -- PHI elimination ----------------------------------------------------- */ | 101 | /* -- PHI elimination ----------------------------------------------------- */ |
| 102 | 102 | ||
| 103 | /* Emit or eliminate collected PHIs. */ | 103 | /* Emit or eliminate collected PHIs. */ |
| 104 | static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi) | 104 | static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi, |
| 105 | SnapNo onsnap) | ||
| 105 | { | 106 | { |
| 106 | int pass2 = 0; | 107 | int pass2 = 0; |
| 107 | IRRef i, nslots; | 108 | IRRef i, nslots; |
| @@ -120,11 +121,21 @@ static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi) | |||
| 120 | } | 121 | } |
| 121 | /* Pass #2: traverse variant part and clear marks of non-redundant PHIs. */ | 122 | /* Pass #2: traverse variant part and clear marks of non-redundant PHIs. */ |
| 122 | if (pass2) { | 123 | if (pass2) { |
| 124 | SnapNo s; | ||
| 123 | for (i = J->cur.nins-1; i > invar; i--) { | 125 | for (i = J->cur.nins-1; i > invar; i--) { |
| 124 | IRIns *ir = IR(i); | 126 | IRIns *ir = IR(i); |
| 125 | if (!irref_isk(ir->op1)) irt_clearmark(IR(ir->op1)->t); | 127 | if (!irref_isk(ir->op1)) irt_clearmark(IR(ir->op1)->t); |
| 126 | if (!irref_isk(ir->op2)) irt_clearmark(IR(ir->op2)->t); | 128 | if (!irref_isk(ir->op2)) irt_clearmark(IR(ir->op2)->t); |
| 127 | } | 129 | } |
| 130 | for (s = J->cur.nsnap-1; s >= onsnap; s--) { | ||
| 131 | SnapShot *snap = &J->cur.snap[s]; | ||
| 132 | SnapEntry *map = &J->cur.snapmap[snap->mapofs]; | ||
| 133 | MSize n, nent = snap->nent; | ||
| 134 | for (n = 0; n < nent; n++) { | ||
| 135 | IRRef ref = snap_ref(map[n]); | ||
| 136 | if (!irref_isk(ref)) irt_clearmark(IR(ref)->t); | ||
| 137 | } | ||
| 138 | } | ||
| 128 | } | 139 | } |
| 129 | /* Pass #3: add PHIs for variant slots without a corresponding SLOAD. */ | 140 | /* Pass #3: add PHIs for variant slots without a corresponding SLOAD. */ |
| 130 | nslots = J->baseslot+J->maxslot; | 141 | nslots = J->baseslot+J->maxslot; |
| @@ -133,11 +144,7 @@ static void loop_emit_phi(jit_State *J, IRRef1 *subst, IRRef1 *phi, IRRef nphi) | |||
| 133 | while (!irref_isk(ref) && ref != subst[ref]) { | 144 | while (!irref_isk(ref) && ref != subst[ref]) { |
| 134 | IRIns *ir = IR(ref); | 145 | IRIns *ir = IR(ref); |
| 135 | irt_clearmark(ir->t); /* Unmark potential uses, too. */ | 146 | irt_clearmark(ir->t); /* Unmark potential uses, too. */ |
| 136 | if (irt_isphi(ir->t)) { | 147 | if (irt_isphi(ir->t) || irt_ispri(ir->t)) |
| 137 | irt_clearmark(IR(subst[ref])->t); | ||
| 138 | break; | ||
| 139 | } | ||
| 140 | if (irt_ispri(ir->t)) | ||
| 141 | break; | 148 | break; |
| 142 | irt_setphi(ir->t); | 149 | irt_setphi(ir->t); |
| 143 | if (nphi >= LJ_MAX_PHI) | 150 | if (nphi >= LJ_MAX_PHI) |
| @@ -222,7 +229,8 @@ static void loop_unroll(jit_State *J) | |||
| 222 | IRRef1 phi[LJ_MAX_PHI]; | 229 | IRRef1 phi[LJ_MAX_PHI]; |
| 223 | uint32_t nphi = 0; | 230 | uint32_t nphi = 0; |
| 224 | IRRef1 *subst; | 231 | IRRef1 *subst; |
| 225 | SnapShot *osnap; | 232 | SnapNo onsnap; |
| 233 | SnapShot *osnap, *loopsnap; | ||
| 226 | SnapEntry *loopmap, *psentinel; | 234 | SnapEntry *loopmap, *psentinel; |
| 227 | IRRef ins, invar; | 235 | IRRef ins, invar; |
| 228 | 236 | ||
| @@ -244,20 +252,17 @@ static void loop_unroll(jit_State *J) | |||
| 244 | ** from the loop snapshot entries for each new snapshot. | 252 | ** from the loop snapshot entries for each new snapshot. |
| 245 | ** Caveat: both calls may reallocate J->cur.snap and J->cur.snapmap! | 253 | ** Caveat: both calls may reallocate J->cur.snap and J->cur.snapmap! |
| 246 | */ | 254 | */ |
| 247 | { | 255 | onsnap = J->cur.nsnap; |
| 248 | MSize nsnap = J->cur.nsnap; | 256 | lj_snap_grow_buf(J, 2*onsnap-2); |
| 249 | SnapShot *loopsnap; | 257 | lj_snap_grow_map(J, J->cur.nsnapmap*2+(onsnap-2)*J->cur.snap[onsnap-1].nent); |
| 250 | lj_snap_grow_buf(J, 2*nsnap-2); | ||
| 251 | lj_snap_grow_map(J, J->cur.nsnapmap*2+(nsnap-2)*J->cur.snap[nsnap-1].nent); | ||
| 252 | 258 | ||
| 253 | /* The loop snapshot is used for fallback substitutions. */ | 259 | /* The loop snapshot is used for fallback substitutions. */ |
| 254 | loopsnap = &J->cur.snap[nsnap-1]; | 260 | loopsnap = &J->cur.snap[onsnap-1]; |
| 255 | loopmap = &J->cur.snapmap[loopsnap->mapofs]; | 261 | loopmap = &J->cur.snapmap[loopsnap->mapofs]; |
| 256 | /* The PC of snapshot #0 and the loop snapshot must match. */ | 262 | /* The PC of snapshot #0 and the loop snapshot must match. */ |
| 257 | psentinel = &loopmap[loopsnap->nent]; | 263 | psentinel = &loopmap[loopsnap->nent]; |
| 258 | lua_assert(*psentinel == J->cur.snapmap[J->cur.snap[0].nent]); | 264 | lua_assert(*psentinel == J->cur.snapmap[J->cur.snap[0].nent]); |
| 259 | *psentinel = SNAP(255, 0, 0); /* Replace PC with temporary sentinel. */ | 265 | *psentinel = SNAP(255, 0, 0); /* Replace PC with temporary sentinel. */ |
| 260 | } | ||
| 261 | 266 | ||
| 262 | /* Start substitution with snapshot #1 (#0 is empty for root traces). */ | 267 | /* Start substitution with snapshot #1 (#0 is empty for root traces). */ |
| 263 | osnap = &J->cur.snap[1]; | 268 | osnap = &J->cur.snap[1]; |
| @@ -308,11 +313,11 @@ static void loop_unroll(jit_State *J) | |||
| 308 | lua_assert(J->cur.nsnapmap <= J->sizesnapmap); | 313 | lua_assert(J->cur.nsnapmap <= J->sizesnapmap); |
| 309 | *psentinel = J->cur.snapmap[J->cur.snap[0].nent]; /* Restore PC. */ | 314 | *psentinel = J->cur.snapmap[J->cur.snap[0].nent]; /* Restore PC. */ |
| 310 | 315 | ||
| 311 | loop_emit_phi(J, subst, phi, nphi); | 316 | loop_emit_phi(J, subst, phi, nphi, onsnap); |
| 312 | } | 317 | } |
| 313 | 318 | ||
| 314 | /* Undo any partial changes made by the loop optimization. */ | 319 | /* Undo any partial changes made by the loop optimization. */ |
| 315 | static void loop_undo(jit_State *J, IRRef ins, MSize nsnap) | 320 | static void loop_undo(jit_State *J, IRRef ins, SnapNo nsnap) |
| 316 | { | 321 | { |
| 317 | ptrdiff_t i; | 322 | ptrdiff_t i; |
| 318 | SnapShot *snap = &J->cur.snap[nsnap-1]; | 323 | SnapShot *snap = &J->cur.snap[nsnap-1]; |
| @@ -346,7 +351,7 @@ static TValue *cploop_opt(lua_State *L, lua_CFunction dummy, void *ud) | |||
| 346 | int lj_opt_loop(jit_State *J) | 351 | int lj_opt_loop(jit_State *J) |
| 347 | { | 352 | { |
| 348 | IRRef nins = J->cur.nins; | 353 | IRRef nins = J->cur.nins; |
| 349 | MSize nsnap = J->cur.nsnap; | 354 | SnapNo nsnap = J->cur.nsnap; |
| 350 | int errcode = lj_vm_cpcall(J->L, NULL, J, cploop_opt); | 355 | int errcode = lj_vm_cpcall(J->L, NULL, J, cploop_opt); |
| 351 | if (LJ_UNLIKELY(errcode)) { | 356 | if (LJ_UNLIKELY(errcode)) { |
| 352 | lua_State *L = J->L; | 357 | lua_State *L = J->L; |
