|
@@ -21,6 +21,7 @@
|
|
/* Some local macros to save typing. Undef'd at the end. */
|
|
/* Some local macros to save typing. Undef'd at the end. */
|
|
#define IR(ref) (&J->cur.ir[(ref)])
|
|
#define IR(ref) (&J->cur.ir[(ref)])
|
|
#define fins (&J->fold.ins)
|
|
#define fins (&J->fold.ins)
|
|
|
|
+#define fright (&J->fold.right)
|
|
|
|
|
|
/*
|
|
/*
|
|
** Caveat #1: return value is not always a TRef -- only use with tref_ref().
|
|
** Caveat #1: return value is not always a TRef -- only use with tref_ref().
|
|
@@ -220,6 +221,34 @@ TRef LJ_FASTCALL lj_opt_fwd_hload(jit_State *J)
|
|
return EMITFOLD;
|
|
return EMITFOLD;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+/* Check whether HREF of TNEW/TDUP can be folded to niltv. */
|
|
|
|
+int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J)
|
|
|
|
+{
|
|
|
|
+ IRRef lim = fins->op1; /* Search limit. */
|
|
|
|
+ IRRef ref;
|
|
|
|
+
|
|
|
|
+ /* The key for an ASTORE may end up in the hash part after a NEWREF. */
|
|
|
|
+ if (irt_isnum(fright->t) && J->chain[IR_NEWREF] > lim) {
|
|
|
|
+ ref = J->chain[IR_ASTORE];
|
|
|
|
+ while (ref > lim) {
|
|
|
|
+ if (ref < J->chain[IR_NEWREF])
|
|
|
|
+ return 0; /* Conflict. */
|
|
|
|
+ ref = IR(ref)->prev;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Search for conflicting stores. */
|
|
|
|
+ ref = J->chain[IR_HSTORE];
|
|
|
|
+ while (ref > lim) {
|
|
|
|
+ IRIns *store = IR(ref);
|
|
|
|
+ if (aa_ahref(J, fins, IR(store->op1)) != ALIAS_NO)
|
|
|
|
+ return 0; /* Conflict. */
|
|
|
|
+ ref = store->prev;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return 1; /* No conflict. Can fold to niltv. */
|
|
|
|
+}
|
|
|
|
+
|
|
/* ASTORE/HSTORE elimination. */
|
|
/* ASTORE/HSTORE elimination. */
|
|
TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J)
|
|
TRef LJ_FASTCALL lj_opt_dse_ahstore(jit_State *J)
|
|
{
|
|
{
|
|
@@ -530,5 +559,6 @@ int lj_opt_fwd_wasnonnil(jit_State *J, IROpT loadop, IRRef xref)
|
|
|
|
|
|
#undef IR
|
|
#undef IR
|
|
#undef fins
|
|
#undef fins
|
|
|
|
+#undef fright
|
|
|
|
|
|
#endif
|
|
#endif
|