diff options
Diffstat (limited to 'src/lj_opt_mem.c')
-rw-r--r-- | src/lj_opt_mem.c | 27 |
1 files changed, 23 insertions, 4 deletions
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index 281f29ad..079f7cfe 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
@@ -17,12 +17,13 @@ | |||
17 | #include "lj_ir.h" | 17 | #include "lj_ir.h" |
18 | #include "lj_jit.h" | 18 | #include "lj_jit.h" |
19 | #include "lj_iropt.h" | 19 | #include "lj_iropt.h" |
20 | #include "lj_ircall.h" | ||
20 | 21 | ||
21 | /* Some local macros to save typing. Undef'd at the end. */ | 22 | /* Some local macros to save typing. Undef'd at the end. */ |
22 | #define IR(ref) (&J->cur.ir[(ref)]) | 23 | #define IR(ref) (&J->cur.ir[(ref)]) |
23 | #define fins (&J->fold.ins) | 24 | #define fins (&J->fold.ins) |
24 | #define fleft (&J->fold.left) | 25 | #define fleft (J->fold.left) |
25 | #define fright (&J->fold.right) | 26 | #define fright (J->fold.right) |
26 | 27 | ||
27 | /* | 28 | /* |
28 | ** Caveat #1: return value is not always a TRef -- only use with tref_ref(). | 29 | ** Caveat #1: return value is not always a TRef -- only use with tref_ref(). |
@@ -309,7 +310,21 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J) | |||
309 | return 1; /* No conflict. Can fold to niltv. */ | 310 | return 1; /* No conflict. Can fold to niltv. */ |
310 | } | 311 | } |
311 | 312 | ||
312 | /* Check whether there's no aliasing NEWREF for the left operand. */ | 313 | /* Check whether there's no aliasing table.clear. */ |
314 | static int fwd_aa_tab_clear(jit_State *J, IRRef lim, IRRef ta) | ||
315 | { | ||
316 | IRRef ref = J->chain[IR_CALLS]; | ||
317 | while (ref > lim) { | ||
318 | IRIns *calls = IR(ref); | ||
319 | if (calls->op2 == IRCALL_lj_tab_clear && | ||
320 | (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) | ||
321 | return 0; /* Conflict. */ | ||
322 | ref = calls->prev; | ||
323 | } | ||
324 | return 1; /* No conflict. Can safely FOLD/CSE. */ | ||
325 | } | ||
326 | |||
327 | /* 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) | 328 | int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) |
314 | { | 329 | { |
315 | IRRef ta = fins->op1; | 330 | IRRef ta = fins->op1; |
@@ -320,7 +335,7 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | |||
320 | return 0; /* Conflict. */ | 335 | return 0; /* Conflict. */ |
321 | ref = newref->prev; | 336 | ref = newref->prev; |
322 | } | 337 | } |
323 | return 1; /* No conflict. Can safely FOLD/CSE. */ | 338 | return fwd_aa_tab_clear(J, lim, ta); |
324 | } | 339 | } |
325 | 340 | ||
326 | /* ASTORE/HSTORE elimination. */ | 341 | /* ASTORE/HSTORE elimination. */ |
@@ -855,6 +870,10 @@ TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J) | |||
855 | ref = store->prev; | 870 | ref = store->prev; |
856 | } | 871 | } |
857 | 872 | ||
873 | /* Search for aliasing table.clear. */ | ||
874 | if (!fwd_aa_tab_clear(J, lim, tab)) | ||
875 | return lj_ir_emit(J); | ||
876 | |||
858 | /* Try to find a matching load. Below the conflicting store, if any. */ | 877 | /* Try to find a matching load. Below the conflicting store, if any. */ |
859 | return lj_opt_cselim(J, lim); | 878 | return lj_opt_cselim(J, lim); |
860 | } | 879 | } |