From 423f10fb40a273cf3c9dc605b86469efa8c089a3 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Tue, 1 Apr 2014 01:55:12 +0200 Subject: [PATCH] Fix alias analysis for table.len vs. table.clear. --- src/lj_opt_mem.c | 28 +++++++++++++++++++--------- 1 file 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) return 1; /* No conflict. Can fold to niltv. */ } +/* Check whether there's no aliasing table.clear. */ +static int fwd_aa_tab_clear(jit_State *J, IRRef lim, IRRef ta) +{ + IRRef ref = J->chain[IR_CALLS]; + while (ref > lim) { + IRIns *calls = IR(ref); + if (calls->op2 == IRCALL_lj_tab_clear && + (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) + return 0; /* Conflict. */ + ref = calls->prev; + } + return 1; /* No conflict. Can safely FOLD/CSE. */ +} + /* Check whether there's no aliasing NEWREF/table.clear for the left operand. */ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) { @@ -320,15 +334,7 @@ int LJ_FASTCALL lj_opt_fwd_tptr(jit_State *J, IRRef lim) return 0; /* Conflict. */ ref = newref->prev; } - ref = J->chain[IR_CALLS]; - while (ref > lim) { - IRIns *calls = IR(ref); - if (calls->op2 == IRCALL_lj_tab_clear && - (ta == calls->op1 || aa_table(J, ta, calls->op1) != ALIAS_NO)) - return 0; /* Conflict. */ - ref = calls->prev; - } - return 1; /* No conflict. Can safely FOLD/CSE. */ + return fwd_aa_tab_clear(J, lim, ta); } /* ASTORE/HSTORE elimination. */ @@ -862,6 +868,10 @@ TRef LJ_FASTCALL lj_opt_fwd_tab_len(jit_State *J) ref = store->prev; } + /* Search for aliasing table.clear. */ + if (!fwd_aa_tab_clear(J, lim, tab)) + return lj_ir_emit(J); + /* Try to find a matching load. Below the conflicting store, if any. */ return lj_opt_cselim(J, lim); }