diff options
author | Mike Pall <mike> | 2010-02-15 01:07:30 +0100 |
---|---|---|
committer | Mike Pall <mike> | 2010-02-15 01:07:30 +0100 |
commit | b6e4fde0dca25e911e2f1f614692f44c6923b1dc (patch) | |
tree | b6a25f20a2c7db6e4444f547fd34ff35d2e1db4f /src/lj_record.c | |
parent | 2a2f8ed6a144fe763379f9cf0eb6a45750432a47 (diff) | |
download | luajit-b6e4fde0dca25e911e2f1f614692f44c6923b1dc.tar.gz luajit-b6e4fde0dca25e911e2f1f614692f44c6923b1dc.tar.bz2 luajit-b6e4fde0dca25e911e2f1f614692f44c6923b1dc.zip |
Improve FOR loop const specialization and integerness checks.
Diffstat (limited to 'src/lj_record.c')
-rw-r--r-- | src/lj_record.c | 90 |
1 files changed, 61 insertions, 29 deletions
diff --git a/src/lj_record.c b/src/lj_record.c index 2709ea01..deb5b2bb 100644 --- a/src/lj_record.c +++ b/src/lj_record.c | |||
@@ -249,33 +249,65 @@ nocanon: | |||
249 | J->mergesnap = 1; /* In case recording continues. */ | 249 | J->mergesnap = 1; /* In case recording continues. */ |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Peek before FORI to find a const initializer, otherwise load from slot. */ | 252 | /* Search bytecode backwards for a int/num constant slot initializer. */ |
253 | static TRef fori_arg(jit_State *J, const BCIns *pc, BCReg slot, IRType t) | 253 | static TRef find_kinit(jit_State *J, const BCIns *endpc, BCReg slot, IRType t) |
254 | { | 254 | { |
255 | /* A store to slot-1 means there's no conditional assignment for slot. */ | 255 | /* This algorithm is rather simplistic and assumes quite a bit about |
256 | if (bc_a(pc[-1]) == slot-1 && bcmode_a(bc_op(pc[-1])) == BCMdst) { | 256 | ** how the bytecode is generated. It works fine for FORI initializers, |
257 | BCIns ins = pc[0]; | 257 | ** but it won't necessarily work in other cases (e.g. iterator arguments). |
258 | if (bc_a(ins) == slot) { | 258 | ** It doesn't do anything fancy, either (like backpropagating MOVs). |
259 | if (bc_op(ins) == BC_KSHORT) { | 259 | */ |
260 | int32_t k = (int32_t)(int16_t)bc_d(ins); | 260 | const BCIns *pc, *startpc = proto_bc(J->pt); |
261 | if (t == IRT_INT) | 261 | for (pc = endpc-1; pc > startpc; pc--) { |
262 | return lj_ir_kint(J, k); | 262 | BCIns ins = *pc; |
263 | else | 263 | BCOp op = bc_op(ins); |
264 | return lj_ir_knum(J, cast_num(k)); | 264 | /* First try to find the last instruction that stores to this slot. */ |
265 | } else if (bc_op(ins) == BC_KNUM) { | 265 | if (bcmode_a(op) == BCMbase && bc_a(ins) <= slot) { |
266 | lua_Number n = proto_knum(J->pt, bc_d(ins)); | 266 | return 0; /* Multiple results, e.g. from a CALL or KNIL. */ |
267 | if (t == IRT_INT) | 267 | } else if (bcmode_a(op) == BCMdst && bc_a(ins) == slot) { |
268 | return lj_ir_kint(J, lj_num2int(n)); | 268 | if (op == BC_KSHORT || op == BC_KNUM) { /* Found const. initializer. */ |
269 | else | 269 | /* Now try to verify there's no forward jump across it. */ |
270 | return lj_ir_knum(J, n); | 270 | const BCIns *kpc = pc; |
271 | for ( ; pc > startpc; pc--) | ||
272 | if (bc_op(*pc) == BC_JMP) { | ||
273 | const BCIns *target = pc+bc_j(*pc)+1; | ||
274 | if (target > kpc && target <= endpc) | ||
275 | return 0; /* Conditional assignment. */ | ||
276 | } | ||
277 | if (op == BC_KSHORT) { | ||
278 | int32_t k = (int32_t)(int16_t)bc_d(ins); | ||
279 | return t == IRT_INT ? lj_ir_kint(J, k) : lj_ir_knum(J, cast_num(k)); | ||
280 | } else { | ||
281 | lua_Number n = proto_knum(J->pt, bc_d(ins)); | ||
282 | if (t == IRT_INT) { | ||
283 | int32_t k = lj_num2int(n); | ||
284 | if (n == cast_num(k)) /* -0 is ok here. */ | ||
285 | return lj_ir_kint(J, k); | ||
286 | return 0; /* Type mismatch. */ | ||
287 | } else { | ||
288 | return lj_ir_knum(J, n); | ||
289 | } | ||
290 | } | ||
271 | } | 291 | } |
292 | return 0; /* Non-constant initializer. */ | ||
272 | } | 293 | } |
273 | } | 294 | } |
274 | if (J->base[slot]) | 295 | return 0; /* No assignment to this slot found? */ |
275 | return J->base[slot]; | 296 | } |
276 | if (t == IRT_INT) | 297 | |
277 | t |= IRT_GUARD; | 298 | /* Peek before FORI to find a const initializer. Otherwise load from slot. */ |
278 | return sloadt(J, (int32_t)slot, t, IRSLOAD_READONLY|IRSLOAD_INHERIT); | 299 | static TRef fori_arg(jit_State *J, const BCIns *fori, BCReg slot, IRType t) |
300 | { | ||
301 | TRef tr = find_kinit(J, fori, slot, t); | ||
302 | if (!tr) { | ||
303 | tr = J->base[slot]; | ||
304 | if (!tr) { | ||
305 | if (t == IRT_INT) | ||
306 | t |= IRT_GUARD; | ||
307 | tr = sloadt(J, (int32_t)slot, t, IRSLOAD_READONLY|IRSLOAD_INHERIT); | ||
308 | } | ||
309 | } | ||
310 | return tr; | ||
279 | } | 311 | } |
280 | 312 | ||
281 | /* Simulate the runtime behavior of the FOR loop iterator. | 313 | /* Simulate the runtime behavior of the FOR loop iterator. |
@@ -311,8 +343,8 @@ static LoopEvent rec_for(jit_State *J, const BCIns *fori, int isforl) | |||
311 | idx = tr[FORL_IDX]; | 343 | idx = tr[FORL_IDX]; |
312 | if (!idx) idx = sloadt(J, (int32_t)(ra+FORL_IDX), IRT_NUM, 0); | 344 | if (!idx) idx = sloadt(J, (int32_t)(ra+FORL_IDX), IRT_NUM, 0); |
313 | t = tref_type(idx); | 345 | t = tref_type(idx); |
314 | stop = fori_arg(J, fori-2, ra+FORL_STOP, t); | 346 | stop = fori_arg(J, fori, ra+FORL_STOP, t); |
315 | step = fori_arg(J, fori-1, ra+FORL_STEP, t); | 347 | step = fori_arg(J, fori, ra+FORL_STEP, t); |
316 | tr[FORL_IDX] = idx = emitir(IRT(IR_ADD, t), idx, step); | 348 | tr[FORL_IDX] = idx = emitir(IRT(IR_ADD, t), idx, step); |
317 | } else { /* Handle FORI/JFORI opcodes. */ | 349 | } else { /* Handle FORI/JFORI opcodes. */ |
318 | BCReg i; | 350 | BCReg i; |
@@ -2134,8 +2166,8 @@ static void rec_setup_forl(jit_State *J, const BCIns *fori) | |||
2134 | cTValue *forbase = &J->L->base[ra]; | 2166 | cTValue *forbase = &J->L->base[ra]; |
2135 | IRType t = (J->flags & JIT_F_OPT_NARROW) ? lj_opt_narrow_forl(forbase) | 2167 | IRType t = (J->flags & JIT_F_OPT_NARROW) ? lj_opt_narrow_forl(forbase) |
2136 | : IRT_NUM; | 2168 | : IRT_NUM; |
2137 | TRef stop = fori_arg(J, fori-2, ra+FORL_STOP, t); | 2169 | TRef stop = fori_arg(J, fori, ra+FORL_STOP, t); |
2138 | TRef step = fori_arg(J, fori-1, ra+FORL_STEP, t); | 2170 | TRef step = fori_arg(J, fori, ra+FORL_STEP, t); |
2139 | int dir = (0 <= numV(&forbase[FORL_STEP])); | 2171 | int dir = (0 <= numV(&forbase[FORL_STEP])); |
2140 | lua_assert(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI); | 2172 | lua_assert(bc_op(*fori) == BC_FORI || bc_op(*fori) == BC_JFORI); |
2141 | if (!tref_isk(step)) { | 2173 | if (!tref_isk(step)) { |
@@ -2165,7 +2197,7 @@ static void rec_setup_forl(jit_State *J, const BCIns *fori) | |||
2165 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; | 2197 | k = (int32_t)(dir ? 0x7fffffff : 0x80000000) - k; |
2166 | emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); | 2198 | emitir(IRTGI(dir ? IR_LE : IR_GE), stop, lj_ir_kint(J, k)); |
2167 | } | 2199 | } |
2168 | if (t == IRT_INT) | 2200 | if (t == IRT_INT && !find_kinit(J, fori, ra+FORL_IDX, IRT_INT)) |
2169 | t |= IRT_GUARD; | 2201 | t |= IRT_GUARD; |
2170 | J->base[ra+FORL_EXT] = sloadt(J, (int32_t)(ra+FORL_IDX), t, IRSLOAD_INHERIT); | 2202 | J->base[ra+FORL_EXT] = sloadt(J, (int32_t)(ra+FORL_IDX), t, IRSLOAD_INHERIT); |
2171 | J->maxslot = ra+FORL_EXT+1; | 2203 | J->maxslot = ra+FORL_EXT+1; |