diff options
author | Mike Pall <mike> | 2011-06-20 21:51:31 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2011-06-20 21:51:31 +0200 |
commit | 4df40a228fe2d7aabf75aa5f75af66eec15e03c5 (patch) | |
tree | 156b36489fed98897ce9eafc88879a8fd40f030c /src | |
parent | 31d566428fe85cdd8c94a01ccab5a2d602286db8 (diff) | |
download | luajit-4df40a228fe2d7aabf75aa5f75af66eec15e03c5.tar.gz luajit-4df40a228fe2d7aabf75aa5f75af66eec15e03c5.tar.bz2 luajit-4df40a228fe2d7aabf75aa5f75af66eec15e03c5.zip |
Fix recording of loops with instable directions in side traces.
Diffstat (limited to 'src')
-rw-r--r-- | src/lj_record.c | 13 |
1 files changed, 7 insertions, 6 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index edfff50b..63d5e4c1 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -333,14 +333,15 @@ static LoopEvent rec_for_iter(IROp *op, cTValue *o, int isforl) | |||
333 | } | 333 | } |
334 | 334 | ||
335 | /* Record checks for FOR loop overflow and step direction. */ | 335 | /* Record checks for FOR loop overflow and step direction. */ |
336 | static void rec_for_check(jit_State *J, IRType t, int dir, TRef stop, TRef step) | 336 | static void rec_for_check(jit_State *J, IRType t, int dir, |
337 | TRef stop, TRef step, int init) | ||
337 | { | 338 | { |
338 | if (!tref_isk(step)) { | 339 | if (!tref_isk(step)) { |
339 | /* Non-constant step: need a guard for the direction. */ | 340 | /* Non-constant step: need a guard for the direction. */ |
340 | TRef zero = (t == IRT_INT) ? lj_ir_kint(J, 0) : lj_ir_knum_zero(J); | 341 | TRef zero = (t == IRT_INT) ? lj_ir_kint(J, 0) : lj_ir_knum_zero(J); |
341 | emitir(IRTG(dir ? IR_GE : IR_LT, t), step, zero); | 342 | emitir(IRTG(dir ? IR_GE : IR_LT, t), step, zero); |
342 | /* Add hoistable overflow checks for a narrowed FORL index. */ | 343 | /* Add hoistable overflow checks for a narrowed FORL index. */ |
343 | if (t == IRT_INT) { | 344 | if (init && t == IRT_INT) { |
344 | if (tref_isk(stop)) { | 345 | if (tref_isk(stop)) { |
345 | /* Constant stop: optimize check away or to a range check for step. */ | 346 | /* Constant stop: optimize check away or to a range check for step. */ |
346 | int32_t k = IR(tref_ref(stop))->i; | 347 | int32_t k = IR(tref_ref(stop))->i; |
@@ -357,7 +358,7 @@ static void rec_for_check(jit_State *J, IRType t, int dir, TRef stop, TRef step) | |||
357 | emitir(IRTI(IR_USE), tr, 0); /* ADDOV is weak. Avoid dead result. */ | 358 | emitir(IRTI(IR_USE), tr, 0); /* ADDOV is weak. Avoid dead result. */ |
358 | } | 359 | } |
359 | } | 360 | } |
360 | } else if (t == IRT_INT && !tref_isk(stop)) { | 361 | } else if (init && t == IRT_INT && !tref_isk(stop)) { |
361 | /* Constant step: optimize overflow check to a range check for stop. */ | 362 | /* Constant step: optimize overflow check to a range check for stop. */ |
362 | int32_t k = IR(tref_ref(step))->i; | 363 | int32_t k = IR(tref_ref(step))->i; |
363 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; | 364 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; |
@@ -384,8 +385,7 @@ static void rec_for_loop(jit_State *J, const BCIns *fori, ScEvEntry *scev, | |||
384 | scev->dir = dir; | 385 | scev->dir = dir; |
385 | scev->stop = tref_ref(stop); | 386 | scev->stop = tref_ref(stop); |
386 | scev->step = tref_ref(step); | 387 | scev->step = tref_ref(step); |
387 | if (init) | 388 | rec_for_check(J, t, dir, stop, step, init); |
388 | rec_for_check(J, t, dir, stop, step); | ||
389 | scev->start = tref_ref(find_kinit(J, fori, ra+FORL_IDX, IRT_INT)); | 389 | scev->start = tref_ref(find_kinit(J, fori, ra+FORL_IDX, IRT_INT)); |
390 | tc = (LJ_DUALNUM && | 390 | tc = (LJ_DUALNUM && |
391 | !(scev->start && irref_isk(scev->stop) && irref_isk(scev->step) && | 391 | !(scev->start && irref_isk(scev->stop) && irref_isk(scev->step) && |
@@ -447,7 +447,8 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
447 | } | 447 | } |
448 | tr[FORL_EXT] = tr[FORL_IDX]; | 448 | tr[FORL_EXT] = tr[FORL_IDX]; |
449 | stop = tr[FORL_STOP]; | 449 | stop = tr[FORL_STOP]; |
450 | rec_for_check(J, t, rec_for_direction(&tv[FORL_STEP]), stop, tr[FORL_STEP]); | 450 | rec_for_check(J, t, rec_for_direction(&tv[FORL_STEP]), |
451 | stop, tr[FORL_STEP], 1); | ||
451 | } | 452 | } |
452 | 453 | ||
453 | ev = rec_for_iter(&op, tv, isforl); | 454 | ev = rec_for_iter(&op, tv, isforl); |