diff options
author | Mike Pall <mike> | 2014-04-01 01:55:12 +0200 |
---|---|---|
committer | Mike Pall <mike> | 2014-04-01 01:55:12 +0200 |
commit | 423f10fb40a273cf3c9dc605b86469efa8c089a3 (patch) | |
tree | b9df5221c62225ba19e67f444d6787cdd3052713 | |
parent | caefd06871a6e2e673520d8565a51257e735a097 (diff) | |
download | luajit-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.c | 28 |
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. */ | ||
313 | static 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. */ |
313 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | 327 | int 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 | } |