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 /src | |
| parent | caefd06871a6e2e673520d8565a51257e735a097 (diff) | |
| download | luajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.tar.gz luajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.tar.bz2 luajit-423f10fb40a273cf3c9dc605b86469efa8c089a3.zip | |
Fix alias analysis for table.len vs. table.clear.
Diffstat (limited to 'src')
| -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 | } |
