From c9a0b9ea9e78f476cf42bd38543ceb2218fa8670 Mon Sep 17 00:00:00 2001 From: Mike Pall Date: Mon, 20 Dec 2010 15:26:05 +0100 Subject: [PATCH] Improve alias analysis for cdata allocations. --- src/lj_opt_mem.c | 58 +++++++++++++++++++++++++++++++++++------------- 1 file changed, 43 insertions(+), 15 deletions(-) diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index c7e8df60..db0ef21e 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c @@ -37,10 +37,22 @@ typedef enum { /* -- ALOAD/HLOAD forwarding and ASTORE/HSTORE elimination ---------------- */ +/* Simplified escape analysis: check for intervening stores. */ +static AliasRet aa_escape(jit_State *J, IRIns *ir, IRIns *stop) +{ + IRRef ref = ir - J->cur.ir; /* The reference that might be stored. */ + for (ir++; ir < stop; ir++) + if (ir->op2 == ref && + (ir->o == IR_ASTORE || ir->o == IR_HSTORE || + ir->o == IR_USTORE || ir->o == IR_FSTORE)) + return ALIAS_MAY; /* Reference was stored and might alias. */ + return ALIAS_NO; /* Reference was not stored. */ +} + /* Alias analysis for two different table references. */ static AliasRet aa_table(jit_State *J, IRRef ta, IRRef tb) { - IRIns *ir, *taba = IR(ta), *tabb = IR(tb); + IRIns *taba = IR(ta), *tabb = IR(tb); int newa, newb; lua_assert(ta != tb); lua_assert(irt_istab(taba->t) && irt_istab(tabb->t)); @@ -50,21 +62,11 @@ static AliasRet aa_table(jit_State *J, IRRef ta, IRRef tb) if (newa && newb) return ALIAS_NO; /* Two different allocations never alias. */ if (newb) { /* At least one allocation? */ - IRRef tmp = ta; ta = tb; tb = tmp; + IRIns *tmp = taba; taba = tabb; tabb = tmp; } else if (!newa) { return ALIAS_MAY; /* Anything else: we just don't know. */ } - /* Now ta holds the allocation, tb the other table reference. - ** The allocation might be stored and reloaded as tb. So perform a - ** simplified escape analysis: check for intervening stores which have - ** the allocation as the right operand. - */ - for (ir = IR(ta+1); ir < IR(tb); ir++) - if (ir->op2 == ta && - (ir->o == IR_ASTORE || ir->o == IR_HSTORE || - ir->o == IR_USTORE || ir->o == IR_FSTORE)) - return ALIAS_MAY; /* Allocation was stored and might alias. */ - return ALIAS_NO; /* Allocation doesn't alias the other reference. */ + return aa_escape(J, taba, tabb); } /* Alias analysis for array and hash access using key-based disambiguation. */ @@ -525,6 +527,33 @@ doemit: /* -- XLOAD forwarding and XSTORE elimination ----------------------------- */ +/* Find cdata allocation for a reference (if any). */ +static IRIns *aa_findcnew(jit_State *J, IRIns *ir) +{ + while (ir->o == IR_ADD) { + if (!irref_isk(ir->op1)) { + IRIns *ir1 = aa_findcnew(J, IR(ir->op1)); /* Left-recursion. */ + if (ir1) return ir1; + } + if (irref_isk(ir->op2)) return NULL; + ir = IR(ir->op2); /* Flatten right-recursion. */ + } + return ir->o == IR_CNEW ? ir : NULL; +} + +/* Alias analysis for two cdata allocations. */ +static AliasRet aa_cnew(jit_State *J, IRIns *refa, IRIns *refb) +{ + IRIns *cnewa = aa_findcnew(J, refa); + IRIns *cnewb = aa_findcnew(J, refb); + if (cnewa == cnewb) + return ALIAS_MAY; /* Same allocation or neither is an allocation. */ + if (cnewa && cnewb) + return ALIAS_NO; /* Two different allocations never alias. */ + if (cnewb) { cnewa = cnewb; refb = refa; } + return aa_escape(J, cnewa, refb); +} + /* Alias analysis for XLOAD/XSTORE. */ static AliasRet aa_xref(jit_State *J, IRIns *xa, IRIns *xb) { @@ -570,8 +599,7 @@ static AliasRet aa_xref(jit_State *J, IRIns *xa, IRIns *xb) return ALIAS_MAY; } /* NYI: structural disambiguation. */ - /* NYI: disambiguate new allocations. */ - return ALIAS_MAY; + return aa_cnew(J, basea, baseb); /* Try to disambiguate allocations. */ } /* XLOAD forwarding. */