aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/lj_opt_fold.c2
-rw-r--r--src/lj_opt_narrow.c33
2 files changed, 25 insertions, 10 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 8fc646c9..d650f09c 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -644,6 +644,8 @@ LJFOLD(TOINT ADD any)
644LJFOLD(TOINT SUB any) 644LJFOLD(TOINT SUB any)
645LJFOLD(TOBIT ADD KNUM) 645LJFOLD(TOBIT ADD KNUM)
646LJFOLD(TOBIT SUB KNUM) 646LJFOLD(TOBIT SUB KNUM)
647LJFOLD(TOI64 ADD any)
648LJFOLD(TOI64 SUB any)
647LJFOLDF(narrow_convert) 649LJFOLDF(narrow_convert)
648{ 650{
649 PHIBARRIER(fleft); 651 PHIBARRIER(fleft);
diff --git a/src/lj_opt_narrow.c b/src/lj_opt_narrow.c
index 688cc7b4..b6615f32 100644
--- a/src/lj_opt_narrow.c
+++ b/src/lj_opt_narrow.c
@@ -193,15 +193,15 @@ typedef struct NarrowConv {
193} NarrowConv; 193} NarrowConv;
194 194
195/* Lookup a reference in the backpropagation cache. */ 195/* Lookup a reference in the backpropagation cache. */
196static IRRef narrow_bpc_get(jit_State *J, IRRef1 key, IRRef mode) 196static BPropEntry *narrow_bpc_get(jit_State *J, IRRef1 key, IRRef mode)
197{ 197{
198 ptrdiff_t i; 198 ptrdiff_t i;
199 for (i = 0; i < BPROP_SLOTS; i++) { 199 for (i = 0; i < BPROP_SLOTS; i++) {
200 BPropEntry *bp = &J->bpropcache[i]; 200 BPropEntry *bp = &J->bpropcache[i];
201 if (bp->key == key && bp->mode <= mode) /* Stronger checks are ok, too. */ 201 if (bp->key == key && bp->mode <= mode) /* Stronger checks are ok, too. */
202 return bp->val; 202 return bp;
203 } 203 }
204 return 0; 204 return NULL;
205} 205}
206 206
207/* Add an entry to the backpropagation cache. */ 207/* Add an entry to the backpropagation cache. */
@@ -225,6 +225,10 @@ static int narrow_conv_backprop(NarrowConv *nc, IRRef ref, int depth)
225 /* Check the easy cases first. */ 225 /* Check the easy cases first. */
226 if (ir->o == IR_TONUM) { /* Undo inverse conversion. */ 226 if (ir->o == IR_TONUM) { /* Undo inverse conversion. */
227 *nc->sp++ = NARROWINS(NARROW_REF, ir->op1); 227 *nc->sp++ = NARROWINS(NARROW_REF, ir->op1);
228 if (nc->mode == IRTOINT_TRUNCI64) {
229 *nc->sp++ = NARROWINS(NARROW_REF, IRTOINT_SEXT64);
230 *nc->sp++ = NARROWINS(IRT(IR_TOI64, IRT_I64), 0);
231 }
228 return 0; 232 return 0;
229 } else if (ir->o == IR_KNUM) { /* Narrow FP constant. */ 233 } else if (ir->o == IR_KNUM) { /* Narrow FP constant. */
230 lua_Number n = ir_knum(ir)->n; 234 lua_Number n = ir_knum(ir)->n;
@@ -257,12 +261,17 @@ static int narrow_conv_backprop(NarrowConv *nc, IRRef ref, int depth)
257 /* Backpropagate across ADD/SUB. */ 261 /* Backpropagate across ADD/SUB. */
258 if (ir->o == IR_ADD || ir->o == IR_SUB) { 262 if (ir->o == IR_ADD || ir->o == IR_SUB) {
259 /* Try cache lookup first. */ 263 /* Try cache lookup first. */
260 IRRef bpref, mode = nc->mode; 264 IRRef mode = nc->mode;
265 BPropEntry *bp;
261 if (mode == IRTOINT_INDEX && depth > 0) 266 if (mode == IRTOINT_INDEX && depth > 0)
262 mode = IRTOINT_CHECK; /* Inner conversions need a stronger check. */ 267 mode = IRTOINT_CHECK; /* Inner conversions need a stronger check. */
263 bpref = narrow_bpc_get(nc->J, (IRRef1)ref, mode); 268 bp = narrow_bpc_get(nc->J, (IRRef1)ref, mode);
264 if (bpref) { 269 if (bp) {
265 *nc->sp++ = NARROWINS(NARROW_REF, bpref); 270 *nc->sp++ = NARROWINS(NARROW_REF, bp->val);
271 if (mode == IRTOINT_TRUNCI64 && mode != bp->mode) {
272 *nc->sp++ = NARROWINS(NARROW_REF, IRTOINT_SEXT64);
273 *nc->sp++ = NARROWINS(IRT(IR_TOI64, IRT_I64), 0);
274 }
266 return 0; 275 return 0;
267 } 276 }
268 if (++depth < NARROW_MAX_BACKPROP && nc->sp < nc->maxsp) { 277 if (++depth < NARROW_MAX_BACKPROP && nc->sp < nc->maxsp) {
@@ -270,7 +279,8 @@ static int narrow_conv_backprop(NarrowConv *nc, IRRef ref, int depth)
270 int count = narrow_conv_backprop(nc, ir->op1, depth); 279 int count = narrow_conv_backprop(nc, ir->op1, depth);
271 count += narrow_conv_backprop(nc, ir->op2, depth); 280 count += narrow_conv_backprop(nc, ir->op2, depth);
272 if (count <= nc->lim) { /* Limit total number of conversions. */ 281 if (count <= nc->lim) { /* Limit total number of conversions. */
273 *nc->sp++ = NARROWINS(IRTI(ir->o), ref); 282 IRType t = mode == IRTOINT_TRUNCI64 ? IRT_I64 : IRT_INT;
283 *nc->sp++ = NARROWINS(IRT(ir->o, t), ref);
274 return count; 284 return count;
275 } 285 }
276 nc->sp = savesp; /* Too many conversions, need to backtrack. */ 286 nc->sp = savesp; /* Too many conversions, need to backtrack. */
@@ -301,7 +311,9 @@ static IRRef narrow_conv_emit(jit_State *J, NarrowConv *nc)
301 *sp++ = emitir_raw(convot, ref, convop2); /* Raw emit avoids a loop. */ 311 *sp++ = emitir_raw(convot, ref, convop2); /* Raw emit avoids a loop. */
302 } else if (op == NARROW_INT) { 312 } else if (op == NARROW_INT) {
303 lua_assert(next < last); 313 lua_assert(next < last);
304 *sp++ = lj_ir_kint(J, *next++); 314 *sp++ = nc->mode == IRTOINT_TRUNCI64 ?
315 lj_ir_kint64(J, (int64_t)(int32_t)*next++) :
316 lj_ir_kint(J, *next++);
305 } else { /* Regular IROpT. Pops two operands and pushes one result. */ 317 } else { /* Regular IROpT. Pops two operands and pushes one result. */
306 IRRef mode = nc->mode; 318 IRRef mode = nc->mode;
307 lua_assert(sp >= nc->stack+2); 319 lua_assert(sp >= nc->stack+2);
@@ -316,7 +328,8 @@ static IRRef narrow_conv_emit(jit_State *J, NarrowConv *nc)
316 } 328 }
317 sp[-1] = emitir(op+guardot, sp[-1], sp[0]); 329 sp[-1] = emitir(op+guardot, sp[-1], sp[0]);
318 /* Add to cache. */ 330 /* Add to cache. */
319 narrow_bpc_set(J, narrow_ref(ref), narrow_ref(sp[-1]), mode); 331 if (narrow_ref(ref))
332 narrow_bpc_set(J, narrow_ref(ref), narrow_ref(sp[-1]), mode);
320 } 333 }
321 } 334 }
322 lua_assert(sp == nc->stack+1); 335 lua_assert(sp == nc->stack+1);