summaryrefslogtreecommitdiff
path: root/src/lj_record.c
diff options
context:
space:
mode:
authorMike Pall <mike>2010-03-15 17:02:53 +0100
committerMike Pall <mike>2010-03-15 17:02:53 +0100
commitc4727220e889dccf06427fd6e473741c0829e344 (patch)
treecb52697fe78bec674692a3d925e20edc7da956f8 /src/lj_record.c
parent24402ede0421876b3e681b153c5355e206376799 (diff)
downloadluajit-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.c40
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. */
810static 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. */
810static TRef rec_idx_key(jit_State *J, RecordIndex *ix) 848static 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)? */