aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Pall <mike>2014-04-01 01:55:12 +0200
committerMike Pall <mike>2014-04-01 01:55:12 +0200
commit423f10fb40a273cf3c9dc605b86469efa8c089a3 (patch)
treeb9df5221c62225ba19e67f444d6787cdd3052713
parentcaefd06871a6e2e673520d8565a51257e735a097 (diff)
downloadluajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.tar.gz
luajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.tar.bz2
luajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.zip
Fix alias analysis for table.len vs. table.clear.
-rw-r--r--src/lj_opt_mem.c28
1 files changed, 19 insertions, 9 deletions
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c
index 21c861bb..902392b5 100644
--- a/src/lj_opt_mem.c
+++ b/src/lj_opt_mem.c
@@ -309,6 +309,20 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J)
309 return 1; /* No conflict. Can fold to niltv. */ 309 return 1; /* No conflict. Can fold to niltv. */
310} 310}
311 311
312/* Check whether there's no aliasing table.clear. */
313static int fwd_aa_tab_clear(jit_State *J, IRRef lim, IRRef ta)
314{
315 IRRef ref = J->chain[IR_CALLS];
316 while (ref > lim) {
317 IRIns *calls = IR(ref);
318 if (calls->op2 == IRCALL_lj_tab_clear &&
319 (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO))
320 return 0; /* Conflict. */
321 ref = calls->prev;
322 }
323 return 1; /* No conflict. Can safely FOLD/CSE. */
324}
325
312/* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ 326/* Check whether there's no aliasing NEWREF/table.clear for the left operand. */
313int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) 327int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim)
314{ 328{
@@ -320,15 +334,7 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim)
320 return 0; /* Conflict. */ 334 return 0; /* Conflict. */
321 ref = newref->prev; 335 ref = newref->prev;
322 } 336 }
323 ref = J->chain[IR_CALLS]; 337 return fwd_aa_tab_clear(J, lim, ta);
324 while (ref > lim) {
325 IRIns *calls = IR(ref);
326 if (calls->op2 == IRCALL_lj_tab_clear &&
327 (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO))
328 return 0; /* Conflict. */
329 ref = calls->prev;
330 }
331 return 1; /* No conflict. Can safely FOLD/CSE. */
332} 338}
333 339
334/* ASTORE/HSTORE elimination. */ 340/* ASTORE/HSTORE elimination. */
@@ -862,6 +868,10 @@ TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J)
862 ref = store->prev; 868 ref = store->prev;
863 } 869 }
864 870
871 /* Search for aliasing table.clear. */
872 if (!fwd_aa_tab_clear(J, lim, tab))
873 return lj_ir_emit(J);
874
865 /* Try to find a matching load. Below the conflicting store, if any. */ 875 /* Try to find a matching load. Below the conflicting store, if any. */
866 return lj_opt_cselim(J, lim); 876 return lj_opt_cselim(J, lim);
867} 877}