diff options
Diffstat (limited to '')
-rw-r--r-- | src/lj_opt_fold.c | 127 |
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) | |||
282 | LJFOLDF(kfold_strto) | 282 | LJFOLDF(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 | ||
290 | LJFOLD(SNEW STRREF KINT) | 290 | LJFOLD(SNEW KPTR KINT) |
291 | LJFOLDF(kfold_snew) | 291 | LJFOLDF(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 | |||
297 | LJFOLD(SNEW any KINT) | ||
298 | LJFOLDF(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 | |||
305 | LJFOLD(STRREF KGC KINT) | ||
306 | LJFOLDF(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 | |||
313 | LJFOLD(STRREF SNEW any) | ||
314 | LJFOLDF(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 | ||
346 | LJFOLD(LT KGC KGC) | 375 | LJFOLD(CALLN CARG IRCALL_lj_str_cmp) |
347 | LJFOLD(GE KGC KGC) | 376 | LJFOLDF(kfold_strcmp) |
348 | LJFOLD(LE KGC KGC) | ||
349 | LJFOLD(GT KGC KGC) | ||
350 | LJFOLDF(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) | |||
1103 | LJFOLD(ULOAD any) | 1130 | LJFOLD(ULOAD any) |
1104 | LJFOLDX(lj_opt_fwd_uload) | 1131 | LJFOLDX(lj_opt_fwd_uload) |
1105 | 1132 | ||
1106 | LJFOLD(TLEN any) | 1133 | LJFOLD(CALLL any IRCALL_lj_tab_len) |
1107 | LJFOLDX(lj_opt_fwd_tlen) | 1134 | LJFOLDX(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. */ |
1196 | LJFOLD(FLOAD KGC IRFL_STR_LEN) | 1223 | LJFOLD(FLOAD KGC IRFL_STR_LEN) |
1197 | LJFOLDF(fload_str_len) | 1224 | LJFOLDF(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 | ||
1231 | LJFOLD(FLOAD SNEW IRFL_STR_LEN) | ||
1232 | LJFOLDF(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 | |||
1204 | LJFOLD(FLOAD any IRFL_STR_LEN) | 1241 | LJFOLD(FLOAD any IRFL_STR_LEN) |
1205 | LJFOLDX(lj_opt_cse) | 1242 | LJFOLDX(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. */ | 1256 | LJFOLD(XLOAD KPTR any) |
1220 | LJFOLD(XLOAD STRREF any) | 1257 | LJFOLDF(xload_kptr) |
1221 | LJFOLDF(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. */ | ||
1266 | LJFOLD(XLOAD any any) | ||
1267 | LJFOLDF(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) | |||
1279 | LJFOLDX(lj_opt_dse_fstore) | 1324 | LJFOLDX(lj_opt_dse_fstore) |
1280 | 1325 | ||
1281 | LJFOLD(NEWREF any any) /* Treated like a store. */ | 1326 | LJFOLD(NEWREF any any) /* Treated like a store. */ |
1327 | LJFOLD(CALLS any any) | ||
1328 | LJFOLD(CALLL any any) /* Safeguard fallback. */ | ||
1282 | LJFOLD(TNEW any any) | 1329 | LJFOLD(TNEW any any) |
1283 | LJFOLD(TDUP any) | 1330 | LJFOLD(TDUP any) |
1284 | LJFOLDF(store_raw) | 1331 | LJFOLDX(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. */ | ||
1450 | TRef 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 |