diff options
author | Mike Pall <mike> | 2010-03-15 17:02:53 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-03-15 17:02:53 +0100 |
commit | c4727220e889dccf06427fd6e473741c0829e344 (patch) | |
tree | cb52697fe78bec674692a3d925e20edc7da956f8 /src/lj_record.c | |
parent | 24402ede0421876b3e681b153c5355e206376799 (diff) | |
download | luajit-c4727220e889dccf06427fd6e473741c0829e344.tar.gz luajit-c4727220e889dccf06427fd6e473741c0829e344.tar.bz2 luajit-c4727220e889dccf06427fd6e473741c0829e344.zip |
Add array bounds check elimination (-Oabc, on by default).
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 40 |
1 files changed, 39 insertions, 1 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 0b0768d6..33272316 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -806,6 +806,44 @@ static void rec_mm_comp(jit_State *J, RecordIndex *ix, int op) | |||
806 | 806 | ||
807 | /* -- Indexed access ------------------------------------------------------ */ | 807 | /* -- Indexed access ------------------------------------------------------ */ |
808 | 808 | ||
809 | /* Record bounds-check. */ | ||
810 | static void rec_idx_abc(jit_State *J, TRef asizeref, TRef ikey, uint32_t asize) | ||
811 | { | ||
812 | /* Try to emit invariant bounds checks. */ | ||
813 | if ((J->flags & (JIT_F_OPT_LOOP|JIT_F_OPT_ABC)) == | ||
814 | (JIT_F_OPT_LOOP|JIT_F_OPT_ABC)) { | ||
815 | IRRef ref = tref_ref(ikey); | ||
816 | IRIns *ir = IR(ref); | ||
817 | int32_t ofs = 0; | ||
818 | IRRef ofsref = 0; | ||
819 | /* Handle constant offsets. */ | ||
820 | if (ir->o == IR_ADD && irref_isk(ir->op2)) { | ||
821 | ofsref = ir->op2; | ||
822 | ofs = IR(ofsref)->i; | ||
823 | ref = ir->op1; | ||
824 | ir = IR(ref); | ||
825 | } | ||
826 | /* Got scalar evolution analysis results for this reference? */ | ||
827 | if (ref == J->scev.idx) { | ||
828 | int32_t stop; | ||
829 | lua_assert(irt_isint(J->scev.t) && ir->o == IR_SLOAD); | ||
830 | stop = lj_num2int(numV(&(J->L->base - J->baseslot)[ir->op1 + FORL_STOP])); | ||
831 | /* Runtime value for stop of loop is within bounds? */ | ||
832 | if ((int64_t)stop + ofs < (int64_t)asize) { | ||
833 | /* Emit invariant bounds check for stop. */ | ||
834 | emitir(IRTG(IR_ABC, IRT_PTR), asizeref, ofs == 0 ? J->scev.stop : | ||
835 | emitir(IRTI(IR_ADD), J->scev.stop, ofsref)); | ||
836 | /* Emit invariant bounds check for start, if not const or negative. */ | ||
837 | if (!(J->scev.dir && J->scev.start && | ||
838 | (int64_t)IR(J->scev.start)->i + ofs >= 0)) | ||
839 | emitir(IRTG(IR_ABC, IRT_PTR), asizeref, ikey); | ||
840 | return; | ||
841 | } | ||
842 | } | ||
843 | } | ||
844 | emitir(IRTGI(IR_ABC), asizeref, ikey); /* Emit regular bounds check. */ | ||
845 | } | ||
846 | |||
809 | /* Record indexed key lookup. */ | 847 | /* Record indexed key lookup. */ |
810 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | 848 | static TRef rec_idx_key(jit_State *J, RecordIndex *ix) |
811 | { | 849 | { |
@@ -827,7 +865,7 @@ static TRef rec_idx_key(jit_State *J, RecordIndex *ix) | |||
827 | asizeref = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); | 865 | asizeref = emitir(IRTI(IR_FLOAD), ix->tab, IRFL_TAB_ASIZE); |
828 | if ((MSize)k < t->asize) { /* Currently an array key? */ | 866 | if ((MSize)k < t->asize) { /* Currently an array key? */ |
829 | TRef arrayref; | 867 | TRef arrayref; |
830 | emitir(IRTGI(IR_ABC), asizeref, ikey); /* Bounds check. */ | 868 | rec_idx_abc(J, asizeref, ikey, t->asize); |
831 | arrayref = emitir(IRT(IR_FLOAD, IRT_PTR), ix->tab, IRFL_TAB_ARRAY); | 869 | arrayref = emitir(IRT(IR_FLOAD, IRT_PTR), ix->tab, IRFL_TAB_ARRAY); |
832 | return emitir(IRT(IR_AREF, IRT_PTR), arrayref, ikey); | 870 | return emitir(IRT(IR_AREF, IRT_PTR), arrayref, ikey); |
833 | } else { /* Currently not in array (may be an array extension)? */ | 871 | } else { /* Currently not in array (may be an array extension)? */ |