summaryrefslogtreecommitdiff
path: root/src/lj_opt_fold.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_opt_fold.c')
-rw-r--r--src/lj_opt_fold.c127
1 files changed, 92 insertions, 35 deletions
diff --git a/src/lj_opt_fold.c b/src/lj_opt_fold.c
index 2102561d..98266d21 100644
--- a/src/lj_opt_fold.c
+++ b/src/lj_opt_fold.c
@@ -282,21 +282,50 @@ LJFOLD(STRTO KGC)
282LJFOLDF(kfold_strto) 282LJFOLDF(kfold_strto)
283{ 283{
284 TValue n; 284 TValue n;
285 if (lj_str_numconv(strdata(ir_kstr(fleft)), &n)) 285 if (lj_str_tonum(ir_kstr(fleft), &n))
286 return lj_ir_knum(J, numV(&n)); 286 return lj_ir_knum(J, numV(&n));
287 return FAILFOLD; 287 return FAILFOLD;
288} 288}
289 289
290LJFOLD(SNEW STRREF KINT) 290LJFOLD(SNEW KPTR KINT)
291LJFOLDF(kfold_snew) 291LJFOLDF(kfold_snew_kptr)
292{
293 GCstr *s = lj_str_new(J->L, (const char *)ir_kptr(fleft), (size_t)fright->i);
294 return lj_ir_kstr(J, s);
295}
296
297LJFOLD(SNEW any KINT)
298LJFOLDF(kfold_snew_empty)
292{ 299{
293 if (fright->i == 0) 300 if (fright->i == 0)
294 return lj_ir_kstr(J, lj_str_new(J->L, "", 0)); 301 return lj_ir_kstr(J, lj_str_new(J->L, "", 0));
302 return NEXTFOLD;
303}
304
305LJFOLD(STRREF KGC KINT)
306LJFOLDF(kfold_strref)
307{
308 GCstr *str = ir_kstr(fleft);
309 lua_assert((MSize)fright->i < str->len);
310 return lj_ir_kptr(J, (char *)strdata(str) + fright->i);
311}
312
313LJFOLD(STRREF SNEW any)
314LJFOLDF(kfold_strref_snew)
315{
295 PHIBARRIER(fleft); 316 PHIBARRIER(fleft);
296 if (irref_isk(fleft->op1) && irref_isk(fleft->op2)) { 317 if (irref_isk(fins->op2) && fright->i == 0) {
297 const char *s = strdata(ir_kstr(IR(fleft->op1))); 318 return fleft->op1; /* strref(snew(ptr, len), 0) ==> ptr */
298 int32_t ofs = IR(fleft->op2)->i; 319 } else {
299 return lj_ir_kstr(J, lj_str_new(J->L, s+ofs, (size_t)fright->i)); 320 /* Reassociate: strref(snew(strref(str, a), len), b) ==> strref(str, a+b) */
321 IRIns *ir = IR(fleft->op1);
322 IRRef1 str = ir->op1; /* IRIns * is not valid across emitir. */
323 lua_assert(ir->o == IR_STRREF);
324 PHIBARRIER(ir);
325 fins->op2 = emitir(IRTI(IR_ADD), ir->op2, fins->op2); /* Clobbers fins! */
326 fins->op1 = str;
327 fins->ot = IRT(IR_STRREF, IRT_PTR);
328 return RETRYFOLD;
300 } 329 }
301 return NEXTFOLD; 330 return NEXTFOLD;
302} 331}
@@ -343,16 +372,13 @@ LJFOLDF(kfold_intcomp)
343 } 372 }
344} 373}
345 374
346LJFOLD(LT KGC KGC) 375LJFOLD(CALLN CARG IRCALL_lj_str_cmp)
347LJFOLD(GE KGC KGC) 376LJFOLDF(kfold_strcmp)
348LJFOLD(LE KGC KGC)
349LJFOLD(GT KGC KGC)
350LJFOLDF(kfold_strcomp)
351{ 377{
352 if (irt_isstr(fins->t)) { 378 if (irref_isk(fleft->op1) && irref_isk(fleft->op2)) {
353 GCstr *a = ir_kstr(fleft); 379 GCstr *a = ir_kstr(IR(fleft->op1));
354 GCstr *b = ir_kstr(fright); 380 GCstr *b = ir_kstr(IR(fleft->op2));
355 return CONDFOLD(lj_ir_strcmp(a, b, (IROp)fins->o)); 381 return INTFOLD(lj_str_cmp(a, b));
356 } 382 }
357 return NEXTFOLD; 383 return NEXTFOLD;
358} 384}
@@ -1070,7 +1096,8 @@ LJFOLDF(merge_eqne_snew_kgc)
1070 uint16_t ot = (uint16_t)(len == 1 ? IRT(IR_XLOAD, IRT_I8) : 1096 uint16_t ot = (uint16_t)(len == 1 ? IRT(IR_XLOAD, IRT_I8) :
1071 len == 2 ? IRT(IR_XLOAD, IRT_U16) : 1097 len == 2 ? IRT(IR_XLOAD, IRT_U16) :
1072 IRTI(IR_XLOAD)); 1098 IRTI(IR_XLOAD));
1073 TRef tmp = emitir(ot, strref, len > 1 ? IRXLOAD_UNALIGNED : 0); 1099 TRef tmp = emitir(ot, strref,
1100 IRXLOAD_READONLY | (len > 1 ? IRXLOAD_UNALIGNED : 0));
1074 TRef val = lj_ir_kint(J, kfold_xload(IR(tref_ref(tmp)), strdata(kstr))); 1101 TRef val = lj_ir_kint(J, kfold_xload(IR(tref_ref(tmp)), strdata(kstr)));
1075 if (len == 3) 1102 if (len == 3)
1076 tmp = emitir(IRTI(IR_BAND), tmp, 1103 tmp = emitir(IRTI(IR_BAND), tmp,
@@ -1103,8 +1130,8 @@ LJFOLDX(lj_opt_fwd_hload)
1103LJFOLD(ULOAD any) 1130LJFOLD(ULOAD any)
1104LJFOLDX(lj_opt_fwd_uload) 1131LJFOLDX(lj_opt_fwd_uload)
1105 1132
1106LJFOLD(TLEN any) 1133LJFOLD(CALLL any IRCALL_lj_tab_len)
1107LJFOLDX(lj_opt_fwd_tlen) 1134LJFOLDX(lj_opt_fwd_tab_len)
1108 1135
1109/* Upvalue refs are really loads, but there are no corresponding stores. 1136/* Upvalue refs are really loads, but there are no corresponding stores.
1110** So CSE is ok for them, except for UREFO across a GC step (see below). 1137** So CSE is ok for them, except for UREFO across a GC step (see below).
@@ -1194,13 +1221,23 @@ LJFOLDF(fload_tab_ah)
1194 1221
1195/* Strings are immutable, so we can safely FOLD/CSE the related FLOAD. */ 1222/* Strings are immutable, so we can safely FOLD/CSE the related FLOAD. */
1196LJFOLD(FLOAD KGC IRFL_STR_LEN) 1223LJFOLD(FLOAD KGC IRFL_STR_LEN)
1197LJFOLDF(fload_str_len) 1224LJFOLDF(fload_str_len_kgc)
1198{ 1225{
1199 if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) 1226 if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD))
1200 return INTFOLD((int32_t)ir_kstr(fleft)->len); 1227 return INTFOLD((int32_t)ir_kstr(fleft)->len);
1201 return NEXTFOLD; 1228 return NEXTFOLD;
1202} 1229}
1203 1230
1231LJFOLD(FLOAD SNEW IRFL_STR_LEN)
1232LJFOLDF(fload_str_len_snew)
1233{
1234 if (LJ_LIKELY(J->flags & JIT_F_OPT_FOLD)) {
1235 PHIBARRIER(fleft);
1236 return fleft->op2;
1237 }
1238 return NEXTFOLD;
1239}
1240
1204LJFOLD(FLOAD any IRFL_STR_LEN) 1241LJFOLD(FLOAD any IRFL_STR_LEN)
1205LJFOLDX(lj_opt_cse) 1242LJFOLDX(lj_opt_cse)
1206 1243
@@ -1216,20 +1253,28 @@ LJFOLDF(fwd_sload)
1216 return J->slot[fins->op1]; 1253 return J->slot[fins->op1];
1217} 1254}
1218 1255
1219/* Strings are immutable, so we can safely FOLD/CSE an XLOAD of a string. */ 1256LJFOLD(XLOAD KPTR any)
1220LJFOLD(XLOAD STRREF any) 1257LJFOLDF(xload_kptr)
1221LJFOLDF(xload_str)
1222{ 1258{
1223 if (irref_isk(fleft->op1) && irref_isk(fleft->op2)) { 1259 /* Only fold read-only integer loads for now. */
1224 GCstr *str = ir_kstr(IR(fleft->op1)); 1260 if ((fins->op2 & IRXLOAD_READONLY) && irt_isinteger(fins->t))
1225 int32_t ofs = IR(fleft->op2)->i; 1261 return INTFOLD(kfold_xload(fins, ir_kptr(fleft)));
1226 lua_assert((MSize)ofs < str->len); 1262 return NEXTFOLD;
1227 lua_assert((MSize)(ofs + (1<<((fins->op2>>8)&3))) <= str->len); 1263}
1228 return INTFOLD(kfold_xload(fins, strdata(str)+ofs)); 1264
1265/* CSE for XLOAD depends on the type, but not on the IRXLOAD_* flags. */
1266LJFOLD(XLOAD any any)
1267LJFOLDF(fwd_xload)
1268{
1269 IRRef ref = J->chain[IR_XLOAD];
1270 IRRef op1 = fins->op1;
1271 while (ref > op1) {
1272 if (IR(ref)->op1 == op1 && irt_sametype(IR(ref)->t, fins->t))
1273 return ref;
1274 ref = IR(ref)->prev;
1229 } 1275 }
1230 return CSEFOLD; 1276 return EMITFOLD;
1231} 1277}
1232/* No XLOAD of non-strings (yet), so we don't need a (XLOAD any any) rule. */
1233 1278
1234/* -- Write barriers ------------------------------------------------------ */ 1279/* -- Write barriers ------------------------------------------------------ */
1235 1280
@@ -1279,12 +1324,11 @@ LJFOLD(FSTORE any any)
1279LJFOLDX(lj_opt_dse_fstore) 1324LJFOLDX(lj_opt_dse_fstore)
1280 1325
1281LJFOLD(NEWREF any any) /* Treated like a store. */ 1326LJFOLD(NEWREF any any) /* Treated like a store. */
1327LJFOLD(CALLS any any)
1328LJFOLD(CALLL any any) /* Safeguard fallback. */
1282LJFOLD(TNEW any any) 1329LJFOLD(TNEW any any)
1283LJFOLD(TDUP any) 1330LJFOLD(TDUP any)
1284LJFOLDF(store_raw) 1331LJFOLDX(lj_ir_emit)
1285{
1286 return EMITFOLD;
1287}
1288 1332
1289/* ------------------------------------------------------------------------ */ 1333/* ------------------------------------------------------------------------ */
1290 1334
@@ -1402,6 +1446,19 @@ TRef LJ_FASTCALL lj_opt_cse(jit_State *J)
1402 } 1446 }
1403} 1447}
1404 1448
1449/* CSE with explicit search limit. */
1450TRef LJ_FASTCALL lj_opt_cselim(jit_State *J, IRRef lim)
1451{
1452 IRRef ref = J->chain[fins->o];
1453 IRRef2 op12 = (IRRef2)fins->op1 + ((IRRef2)fins->op2 << 16);
1454 while (ref > lim) {
1455 if (IR(ref)->op12 == op12)
1456 return ref;
1457 ref = IR(ref)->prev;
1458 }
1459 return lj_ir_emit(J);
1460}
1461
1405/* ------------------------------------------------------------------------ */ 1462/* ------------------------------------------------------------------------ */
1406 1463
1407#undef IR 1464#undef IR