aboutsummaryrefslogtreecommitdiff
path: root/src/lj_opt_mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lj_opt_mem.c')
-rw-r--r--src/lj_opt_mem.c27
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. */
314static 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. */
313int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) 328int 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}