start work on specialized FORLOOP/FORPREP opcodes

pull/81/head
Dibyendu Majumdar 9 years ago
parent ee0b14d797
commit 3e61280b9d

@ -278,10 +278,15 @@ OP_RAVI_GETTABLE_AF,/* A B C R(A) := R(B)[RK(C)] where R(B) is array of floats a
OP_RAVI_SETTABLE_AI,/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
OP_RAVI_SETTABLE_AF,/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
OP_RAVI_FORLOOP_IP,
OP_RAVI_FORLOOP_IN,
OP_RAVI_FORPREP_IP,
OP_RAVI_FORPREP_IN,
} OpCode;
#define NUM_OPCODES (cast(int, OP_RAVI_SETTABLE_AF) + 1)
#define NUM_OPCODES (cast(int, OP_RAVI_FORPREP_IN) + 1)
/*===========================================================================
Notes:

@ -120,6 +120,11 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = {
"SETTABLE_AI",/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
"SETTABLE_AF",/* A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
"FORLOOP_IP",
"FORLOOP_IN",
"FORPREP_IP",
"FORPREP_IN",
NULL
};
@ -227,6 +232,11 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = {
, opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_AI A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of ints, and RK(C) is an int */
, opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_RAVI_SETTABLE_AF A B C R(A)[RK(B)] := RK(C) where RK(B) is an int, R(A) is array of floats, and RK(C) is an float */
, opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_RAVI_FORLOOP_IP */
, opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_RAVI_FORLOOP_IN */
, opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_RAVI_FORPREP_IP */
, opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_RAVI_FORPREP_IN */
};
@ -462,7 +472,11 @@ static void PrintCode(const Proto* f)
break;
case OP_JMP:
case OP_FORLOOP:
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_IN:
case OP_FORPREP:
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_IN:
case OP_TFORLOOP:
printf("\t; to %d", sbx + pc + 2);
break;

@ -1718,10 +1718,16 @@ static void repeatstat (LexState *ls, int line) {
leaveblock(fs); /* finish loop */
}
typedef struct Fornuminfo {
ravitype_t type;
int is_constant;
int int_value;
} Fornuminfo;
/* parse the single expressions needed in numerical for loops
* called by fornum()
*/
static int exp1 (LexState *ls, ravitype_t *type) {
static int exp1 (LexState *ls, Fornuminfo *info) {
/* Since the local variable in a fornum loop is local to the loop and does
* not use any variable in outer scope we don't need to check its
* type - also the loop is already optimised so no point trying to
@ -1731,24 +1737,38 @@ static int exp1 (LexState *ls, ravitype_t *type) {
int reg;
e.ravi_type = RAVI_TANY;
expr(ls, &e);
DEBUG_EXPR(raviY_printf(ls->fs, "fornum exp -> %e\n", &e));
info->is_constant = (e.k == VKINT);
info->int_value = info->is_constant ? e.u.ival : 0;
luaK_exp2nextreg(ls->fs, &e);
lua_assert(e.k == VNONRELOC);
reg = e.u.info;
*type = e.ravi_type;
info->type = e.ravi_type;
return reg;
}
/* parse a for loop body for both versions of the for loop
* called by fornum(), forlist()
*/
static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
static void forbody (LexState *ls, int base, int line, int nvars, int isnum, Fornuminfo *info) {
/* forbody -> DO block */
BlockCnt bl;
OpCode forprep_inst = OP_FORPREP, forloop_inst = OP_FORLOOP;
FuncState *fs = ls->fs;
int prep, endfor;
adjustlocalvars(ls, 3); /* control variables */
checknext(ls, TK_DO);
prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs);
if (isnum) {
if (info && info->is_constant && info->int_value > 0) {
forprep_inst = OP_RAVI_FORPREP_IP;
forloop_inst = OP_RAVI_FORLOOP_IP;
}
else if (info && info->is_constant && info->int_value < 0) {
forprep_inst = OP_RAVI_FORPREP_IN;
forloop_inst = OP_RAVI_FORLOOP_IN;
}
}
prep = isnum ? luaK_codeAsBx(fs, forprep_inst, base, NO_JUMP) : luaK_jump(fs);
enterblock(fs, &bl, 0); /* scope for declared variables */
adjustlocalvars(ls, nvars);
luaK_reserveregs(fs, nvars);
@ -1756,7 +1776,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {
leaveblock(fs); /* end of scope for declared variables */
luaK_patchtohere(fs, prep);
if (isnum) /* numeric for? */
endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP);
endfor = luaK_codeAsBx(fs, forloop_inst, base, NO_JUMP);
else { /* generic for */
luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars);
luaK_fixline(fs, line);
@ -1791,25 +1811,30 @@ static void fornum (LexState *ls, TString *varname, int line) {
vvar = &fs->f->locvars[fs->nlocvars - 1]; /* index variable - not yet active so get it from locvars*/
checknext(ls, '=');
/* get the type of each expression */
ravitype_t tidx = RAVI_TANY, tlimit = RAVI_TANY, tstep = RAVI_TNUMINT;
Fornuminfo tidx = { RAVI_TANY }, tlimit = { RAVI_TANY }, tstep = { RAVI_TNUMINT };
Fornuminfo *info = NULL;
exp1(ls, &tidx); /* initial value */
checknext(ls, ',');
exp1(ls, &tlimit); /* limit */
if (testnext(ls, ','))
exp1(ls, &tstep); /* optional step */
else { /* default step = 1 */
tstep.is_constant = 1;
tstep.int_value = 1;
luaK_codek(fs, fs->freereg, luaK_intK(fs, 1));
luaK_reserveregs(fs, 1);
}
if (tidx == tlimit && tlimit == tstep && (tidx == RAVI_TNUMFLT || tidx == RAVI_TNUMINT)) {
if (tidx.type == tlimit.type && tlimit.type == tstep.type && (tidx.type == RAVI_TNUMFLT || tidx.type == RAVI_TNUMINT)) {
if (tidx.type == RAVI_TNUMINT && tstep.is_constant)
info = &tstep;
/* Ok so we have an integer or double */
vidx->ravi_type = vlimit->ravi_type = vstep->ravi_type = vvar->ravi_type = tidx;
vidx->ravi_type = vlimit->ravi_type = vstep->ravi_type = vvar->ravi_type = tidx.type;
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for index %v\n", vidx));
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for limit %v\n", vlimit));
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for step %v\n", vstep));
DEBUG_VARS(raviY_printf(fs, "fornum -> setting type for variable %v\n", vvar));
}
forbody(ls, base, line, 1, 1);
forbody(ls, base, line, 1, 1, info);
}
/* parse a generic for loop, calls forbody()
@ -1837,7 +1862,7 @@ static void forlist (LexState *ls, TString *indexname) {
line = ls->linenumber;
adjust_assign(ls, 3, explist(ls, &e), &e);
luaK_checkstack(fs, 3); /* extra space to call generator */
forbody(ls, base, line, nvars - 3, 0);
forbody(ls, base, line, nvars - 3, 0, NULL);
}
/* initial parsing of a for loop - calls fornum() or forlist()

@ -1080,6 +1080,8 @@ newframe: /* reentry point when frame changes (call/return) */
goto newframe; /* restart luaV_execute over new Lua function */
}
}
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_IN:
case OP_FORLOOP: {
if (ttisinteger(ra)) { /* integer loop? */
lua_Integer step = ivalue(ra + 2);
@ -1103,6 +1105,8 @@ newframe: /* reentry point when frame changes (call/return) */
}
}
} break;
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_IN:
case OP_FORPREP: {
TValue *init = ra;
TValue *plimit = ra + 1;

@ -371,6 +371,10 @@ bool RaviCodeGenerator::canCompile(Proto *p) {
case OP_RAVI_TOARRAYF:
case OP_RAVI_MOVEAI:
case OP_RAVI_MOVEAF:
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_IN:
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_IN:
break;
default:
return false;
@ -863,6 +867,8 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
emit_JMP(def, A, j);
} break;
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_IN:
case OP_FORPREP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
@ -872,6 +878,8 @@ void RaviCodeGenerator::compile(lua_State *L, Proto *p) {
emit_FORPREP(def, L_ci, proto, A, j);
#endif
} break;
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_IN:
case OP_FORLOOP: {
int sbx = GETARG_sBx(i);
int j = sbx + pc + 1;
@ -1157,6 +1165,10 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
llvm::BasicBlock::Create(def->jitState->context(), "loadbool");
} break;
case OP_JMP:
case OP_RAVI_FORPREP_IP:
case OP_RAVI_FORPREP_IN:
case OP_RAVI_FORLOOP_IP:
case OP_RAVI_FORLOOP_IN:
case OP_FORLOOP:
case OP_FORPREP:
case OP_TFORLOOP: {
@ -1164,9 +1176,9 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
char temp[80];
if (op == OP_JMP)
targetname = "jmp";
else if (op == OP_FORLOOP)
else if (op == OP_FORLOOP || op == OP_RAVI_FORLOOP_IP || op == OP_RAVI_FORLOOP_IN)
targetname = "forbody";
else if (op == OP_FORPREP)
else if (op == OP_FORPREP || op == OP_RAVI_FORPREP_IP || op == OP_RAVI_FORPREP_IN)
#if RAVI_CODEGEN_FORPREP2
targetname = "forloop_ilt";
#else
@ -1184,7 +1196,7 @@ void RaviCodeGenerator::scan_jump_targets(RaviFunctionDef *def, Proto *p) {
llvm::BasicBlock::Create(def->jitState->context(), temp);
}
#if RAVI_CODEGEN_FORPREP2
if (op == OP_FORPREP) {
if (op == OP_FORPREP || op == OP_RAVI_FORPREP_IP || op == OP_RAVI_FORPREP_IN) {
lua_assert(def->jmp_targets[j].jmp2 == nullptr);
// first target (created above) is for int < limit
// Second target is for int > limit

Loading…
Cancel
Save