diff options
| author | Mike Pall <mike> | 2010-09-21 01:31:04 +0200 |
|---|---|---|
| committer | Mike Pall <mike> | 2010-09-21 01:31:04 +0200 |
| commit | 23b5c56d41d24a29cfd17d943a9a849a7b9ac20c (patch) | |
| tree | 27096e71daf2e1f3da188969e49b03c90bbd384a /src | |
| parent | 52b922c1e941cfc56ae76954a80c429782a33ca6 (diff) | |
| download | luajit-23b5c56d41d24a29cfd17d943a9a849a7b9ac20c.tar.gz luajit-23b5c56d41d24a29cfd17d943a9a849a7b9ac20c.tar.bz2 luajit-23b5c56d41d24a29cfd17d943a9a849a7b9ac20c.zip | |
Improve alias analysis: disambiguate new allocations.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lj_opt_mem.c | 80 |
1 files changed, 54 insertions, 26 deletions
diff --git a/src/lj_opt_mem.c b/src/lj_opt_mem.c index 8674ddea..4d2e9664 100644 --- a/src/lj_opt_mem.c +++ b/src/lj_opt_mem.c | |||
| @@ -37,54 +37,79 @@ typedef enum { | |||
| 37 | 37 | ||
| 38 | /* -- ALOAD/HLOAD forwarding and ASTORE/HSTORE elimination ---------------- */ | 38 | /* -- ALOAD/HLOAD forwarding and ASTORE/HSTORE elimination ---------------- */ |
| 39 | 39 | ||
| 40 | /* Alias analysis for two different table references. */ | ||
| 41 | static AliasRet aa_table(jit_State *J, IRRef ta, IRRef tb) | ||
| 42 | { | ||
| 43 | IRIns *ir, *taba = IR(ta), *tabb = IR(tb); | ||
| 44 | int newa, newb; | ||
| 45 | lua_assert(ta != tb); | ||
| 46 | /* Disambiguate new allocations. */ | ||
| 47 | newa = (taba->o == IR_TNEW || taba->o == IR_TDUP); | ||
| 48 | newb = (tabb->o == IR_TNEW || tabb->o == IR_TDUP); | ||
| 49 | if (newa && newb) | ||
| 50 | return ALIAS_NO; /* Two different allocations never alias. */ | ||
| 51 | if (newb) { /* At least one allocation? */ | ||
| 52 | IRRef tmp = ta; ta = tb; tb = tmp; | ||
| 53 | } else if (!newa) { | ||
| 54 | return ALIAS_MAY; /* Anything else: we just don't know. */ | ||
| 55 | } | ||
| 56 | /* Now ta holds the allocation, tb the other table reference. | ||
| 57 | ** The allocation might be stored and reloaded as tb. So perform a | ||
| 58 | ** simplified escape analysis: check for intervening stores which have | ||
| 59 | ** the allocation as the right operand. | ||
| 60 | */ | ||
| 61 | for (ir = IR(ta+1); ir < IR(tb); ir++) | ||
| 62 | if (ir->op2 == ta && | ||
| 63 | (ir->o == IR_ASTORE || ir->o == IR_HSTORE || | ||
| 64 | ir->o == IR_USTORE || ir->o == IR_FSTORE)) | ||
| 65 | return ALIAS_MAY; /* Allocation was stored and might alias. */ | ||
| 66 | return ALIAS_NO; /* Allocation doesn't alias the other reference. */ | ||
| 67 | } | ||
| 68 | |||
| 40 | /* Alias analysis for array and hash access using key-based disambiguation. */ | 69 | /* Alias analysis for array and hash access using key-based disambiguation. */ |
| 41 | static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) | 70 | static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) |
| 42 | { | 71 | { |
| 43 | IRRef ka = refa->op2; | 72 | IRRef ka = refa->op2; |
| 44 | IRRef kb = refb->op2; | 73 | IRRef kb = refb->op2; |
| 45 | IRIns *keya, *keyb; | 74 | IRIns *keya, *keyb; |
| 75 | IRRef ta, tb; | ||
| 46 | if (refa == refb) | 76 | if (refa == refb) |
| 47 | return ALIAS_MUST; /* Shortcut for same refs. */ | 77 | return ALIAS_MUST; /* Shortcut for same refs. */ |
| 48 | keya = IR(ka); | 78 | keya = IR(ka); |
| 49 | if (keya->o == IR_KSLOT) { ka = keya->op1; keya = IR(ka); } | 79 | if (keya->o == IR_KSLOT) { ka = keya->op1; keya = IR(ka); } |
| 50 | keyb = IR(kb); | 80 | keyb = IR(kb); |
| 51 | if (keyb->o == IR_KSLOT) { kb = keyb->op1; keyb = IR(kb); } | 81 | if (keyb->o == IR_KSLOT) { kb = keyb->op1; keyb = IR(kb); } |
| 82 | ta = (refa->o==IR_HREFK || refa->o==IR_AREF) ? IR(refa->op1)->op1 : refa->op1; | ||
| 83 | tb = (refb->o==IR_HREFK || refb->o==IR_AREF) ? IR(refb->op1)->op1 : refb->op1; | ||
| 52 | if (ka == kb) { | 84 | if (ka == kb) { |
| 53 | /* Same key. Check for same table with different ref (NEWREF vs. HREF). */ | 85 | /* Same key. Check for same table with different ref (NEWREF vs. HREF). */ |
| 54 | IRIns *ta = refa; | 86 | if (ta == tb) |
| 55 | IRIns *tb = refb; | ||
| 56 | if (ta->o == IR_HREFK || ta->o == IR_AREF) ta = IR(ta->op1); | ||
| 57 | if (tb->o == IR_HREFK || tb->o == IR_AREF) tb = IR(tb->op1); | ||
| 58 | if (ta->op1 == tb->op1) | ||
| 59 | return ALIAS_MUST; /* Same key, same table. */ | 87 | return ALIAS_MUST; /* Same key, same table. */ |
| 60 | else | 88 | else |
| 61 | return ALIAS_MAY; /* Same key, possibly different table. */ | 89 | return aa_table(J, ta, tb); /* Same key, possibly different table. */ |
| 62 | } | 90 | } |
| 63 | if (irref_isk(ka) && irref_isk(kb)) | 91 | if (irref_isk(ka) && irref_isk(kb)) |
| 64 | return ALIAS_NO; /* Different constant keys. */ | 92 | return ALIAS_NO; /* Different constant keys. */ |
| 65 | if (refa->o == IR_AREF) { | 93 | if (refa->o == IR_AREF) { |
| 66 | /* Disambiguate array references based on index arithmetic. */ | 94 | /* Disambiguate array references based on index arithmetic. */ |
| 95 | int32_t ofsa = 0, ofsb = 0; | ||
| 96 | IRRef basea = ka, baseb = kb; | ||
| 67 | lua_assert(refb->o == IR_AREF); | 97 | lua_assert(refb->o == IR_AREF); |
| 68 | if (refa->op1 == refb->op1) { | 98 | /* Gather base and offset from t[base] or t[base+-ofs]. */ |
| 69 | /* Same table, different non-const array keys. */ | 99 | if (keya->o == IR_ADD && irref_isk(keya->op2)) { |
| 70 | int32_t ofsa = 0, ofsb = 0; | 100 | basea = keya->op1; |
| 71 | IRRef basea = ka, baseb = kb; | 101 | ofsa = IR(keya->op2)->i; |
| 72 | /* Gather base and offset from t[base] or t[base+-ofs]. */ | 102 | if (basea == kb && ofsa != 0) |
| 73 | if (keya->o == IR_ADD && irref_isk(keya->op2)) { | 103 | return ALIAS_NO; /* t[base+-ofs] vs. t[base]. */ |
| 74 | basea = keya->op1; | ||
| 75 | ofsa = IR(keya->op2)->i; | ||
| 76 | if (basea == kb && ofsa != 0) | ||
| 77 | return ALIAS_NO; /* t[base+-ofs] vs. t[base]. */ | ||
| 78 | } | ||
| 79 | if (keyb->o == IR_ADD && irref_isk(keyb->op2)) { | ||
| 80 | baseb = keyb->op1; | ||
| 81 | ofsb = IR(keyb->op2)->i; | ||
| 82 | if (ka == baseb && ofsb != 0) | ||
| 83 | return ALIAS_NO; /* t[base] vs. t[base+-ofs]. */ | ||
| 84 | } | ||
| 85 | if (basea == baseb && ofsa != ofsb) | ||
| 86 | return ALIAS_NO; /* t[base+-o1] vs. t[base+-o2] and o1 != o2. */ | ||
| 87 | } | 104 | } |
| 105 | if (keyb->o == IR_ADD && irref_isk(keyb->op2)) { | ||
| 106 | baseb = keyb->op1; | ||
| 107 | ofsb = IR(keyb->op2)->i; | ||
| 108 | if (ka == baseb && ofsb != 0) | ||
| 109 | return ALIAS_NO; /* t[base] vs. t[base+-ofs]. */ | ||
| 110 | } | ||
| 111 | if (basea == baseb && ofsa != ofsb) | ||
| 112 | return ALIAS_NO; /* t[base+-o1] vs. t[base+-o2] and o1 != o2. */ | ||
| 88 | } else { | 113 | } else { |
| 89 | /* Disambiguate hash references based on the type of their keys. */ | 114 | /* Disambiguate hash references based on the type of their keys. */ |
| 90 | lua_assert((refa->o==IR_HREF || refa->o==IR_HREFK || refa->o==IR_NEWREF) && | 115 | lua_assert((refa->o==IR_HREF || refa->o==IR_HREFK || refa->o==IR_NEWREF) && |
| @@ -92,7 +117,10 @@ static AliasRet aa_ahref(jit_State *J, IRIns *refa, IRIns *refb) | |||
| 92 | if (!irt_sametype(keya->t, keyb->t)) | 117 | if (!irt_sametype(keya->t, keyb->t)) |
| 93 | return ALIAS_NO; /* Different key types. */ | 118 | return ALIAS_NO; /* Different key types. */ |
| 94 | } | 119 | } |
| 95 | return ALIAS_MAY; /* Anything else: we just don't know. */ | 120 | if (ta == tb) |
| 121 | return ALIAS_MAY; /* Same table, cannot disambiguate keys. */ | ||
| 122 | else | ||
| 123 | return aa_table(J, ta, tb); /* Try to disambiguate tables. */ | ||
| 96 | } | 124 | } |
| 97 | 125 | ||
| 98 | /* Array and hash load forwarding. */ | 126 | /* Array and hash load forwarding. */ |
