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 9f714056..cc177d39 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(). |
@@ -308,7 +309,21 @@ int LJ_FASTCALL lj_opt_fwd_href_nokey(jit_State *J) | |||
308 | return 1; /* No conflict. Can fold to niltv. */ | 309 | return 1; /* No conflict. Can fold to niltv. */ |
309 | } | 310 | } |
310 | 311 | ||
311 | /* Check whether there's no aliasing NEWREF for the left operand. */ | 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 | |||
326 | /* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ | ||
312 | 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) |
313 | { | 328 | { |
314 | IRRef ta = fins->op1; | 329 | IRRef ta = fins->op1; |
@@ -319,7 +334,7 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) | |||
319 | return 0; /* Conflict. */ | 334 | return 0; /* Conflict. */ |
320 | ref = newref->prev; | 335 | ref = newref->prev; |
321 | } | 336 | } |
322 | return 1; /* No conflict. Can safely FOLD/CSE. */ | 337 | return fwd_aa_tab_clear(J, lim, ta); |
323 | } | 338 | } |
324 | 339 | ||
325 | /* ASTORE/HSTORE elimination. */ | 340 | /* ASTORE/HSTORE elimination. */ |
@@ -854,6 +869,10 @@ TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J) | |||
854 | ref = store->prev; | 869 | ref = store->prev; |
855 | } | 870 | } |
856 | 871 | ||
872 | /* Search for aliasing table.clear. */ | ||
873 | if (!fwd_aa_tab_clear(J, lim, tab)) | ||
874 | return lj_ir_emit(J); | ||
875 | |||
857 | /* Try to find a matching load. Below the conflicting store, if any. */ | 876 | /* Try to find a matching load. Below the conflicting store, if any. */ |
858 | return lj_opt_cselim(J, lim); | 877 | return lj_opt_cselim(J, lim); |
859 | } | 878 | } |