Record y = select(x, ...) idiom.

This commit is contained in:
Mike Pall 2010-09-13 01:23:19 +02:00
parent 4ba0eb5f80
commit c88169dc46
3 changed files with 61 additions and 1 deletions

View File

@ -256,7 +256,7 @@ typedef struct jit_State {
uint8_t mergesnap; /* Allowed to merge with next snapshot. */
uint8_t needsnap; /* Need snapshot before recording next bytecode. */
IRType1 guardemit; /* Accumulated IRT_GUARD for emitted instructions. */
uint8_t unused1;
uint8_t bcskip; /* Number of bytecode instructions to skip. */
FoldState fold; /* Fold state. */

View File

@ -1949,6 +1949,18 @@ static void rec_func_jit(jit_State *J, TraceNo lnk)
/* -- Vararg handling ----------------------------------------------------- */
/* Detect y = select(x, ...) idiom. */
static int select_detect(jit_State *J)
{
BCIns ins = J->pc[1];
if (bc_op(ins) == BC_CALLM && bc_b(ins) == 2 && bc_c(ins) == 1) {
cTValue *func = &J->L->base[bc_a(ins)];
if (tvisfunc(func) && funcV(func)->c.ffid == FF_select)
return 1;
}
return 0;
}
/* Record vararg instruction. */
static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
{
@ -1997,7 +2009,48 @@ static void rec_varg(jit_State *J, BCReg dst, ptrdiff_t nresults)
J->base[dst+i] = TREF_NIL;
if (dst + (BCReg)nresults > J->maxslot)
J->maxslot = dst + (BCReg)nresults;
} else if (select_detect(J)) { /* y = select(x, ...) */
TRef tridx = J->base[dst-1];
TRef tr = TREF_NIL;
ptrdiff_t idx = select_mode(J, tridx, &J->L->base[dst-1]);
if (idx < 0) goto nyivarg;
if (idx != 0 && tref_isk(tridx)) {
emitir(IRTGI(idx <= nvararg ? IR_GE : IR_LT),
fr, lj_ir_kint(J, frofs+8*(int32_t)idx));
frofs -= 8; /* Bias for 1-based index. */
} else if (idx <= nvararg) { /* Compute size. */
TRef tmp = emitir(IRTI(IR_ADD), fr, lj_ir_kint(J, -frofs));
if (numparams)
emitir(IRTGI(IR_GE), tmp, lj_ir_kint(J, 0));
tr = emitir(IRTI(IR_BSHR), tmp, lj_ir_kint(J, 3));
if (idx != 0) {
tridx = emitir(IRTI(IR_ADD), tridx, lj_ir_kint(J, -1));
rec_idx_abc(J, tr, tridx, (uint32_t)nvararg);
}
} else {
TRef tmp = lj_ir_kint(J, frofs);
if (idx != 0) {
TRef tmp2 = emitir(IRTI(IR_BSHL), tridx, lj_ir_kint(J, 3));
tmp = emitir(IRTI(IR_ADD), tmp2, tmp);
} else {
tr = lj_ir_kint(J, 0);
}
emitir(IRTGI(IR_LT), fr, tmp);
}
if (idx != 0 && idx <= nvararg) {
IRType t;
TRef aref, vbase = emitir(IRTI(IR_SUB), REF_BASE, fr);
vbase = emitir(IRT(IR_ADD, IRT_PTR), vbase, lj_ir_kint(J, frofs-8));
t = itype2irt(&J->L->base[idx-2-nvararg]);
aref = emitir(IRT(IR_AREF, IRT_PTR), vbase, tridx);
tr = emitir(IRTG(IR_ALOAD, t), aref, 0);
if (irtype_ispri(t)) tr = TREF_PRI(t); /* Canonicalize primitives. */
}
J->base[dst-2] = tr;
J->maxslot = dst-1;
J->bcskip = 2; /* Skip CALLM + select. */
} else {
nyivarg:
setintV(&J->errinfo, BC_VARG);
lj_trace_err_info(J, LJ_TRERR_NYIBC);
}
@ -2058,6 +2111,12 @@ void lj_record_ins(jit_State *J)
J->mergesnap = 1;
}
/* Skip some bytecodes. */
if (LJ_UNLIKELY(J->bcskip > 0)) {
J->bcskip--;
return;
}
/* Record only closed loops for root traces. */
pc = J->pc;
if (J->framedepth == 0 &&

View File

@ -386,6 +386,7 @@ static void trace_start(jit_State *J)
J->cur.snapmap = J->snapmapbuf;
J->mergesnap = 0;
J->needsnap = 0;
J->bcskip = 0;
J->guardemit.irt = 0;
setgcref(J->cur.startpt, obj2gco(J->pt));