Improve alias analysis of upvalues using a disambiguation hash value.

All upvalue objects hold a disambiguation hash value now.
It's built from the parent prototype and the slot number.
Different hash values imply the upvalues cannot alias.
Same hash values don't imply anything (collision or different closures).
Upvalue disambiguation makes use of a reduced hash due to IR contraints.
This commit is contained in:
Mike Pall 2010-01-09 23:59:43 +01:00
parent 2cc554db0c
commit 99d153bef9
7 changed files with 32 additions and 13 deletions

View File

@ -397,6 +397,8 @@ local function dump_ir(tr, dumpsnap, dumpreg)
local litn = litname[op]
if litn and litn[op2] then
out:write(" ", litn[op2])
elseif op == "UREFO " or op == "UREFC " then
out:write(format(" #%-3d", shr(op2, 8)))
else
out:write(format(" #%-3d", op2))
end

View File

@ -1105,7 +1105,7 @@ static void asm_fuseahuref(ASMState *as, IRRef ref, RegSet allow)
case IR_UREFC:
if (irref_isk(ir->op1)) {
GCfunc *fn = ir_kfunc(IR(ir->op1));
GCupval *uv = &gcref(fn->l.uvptr[ir->op2])->uv;
GCupval *uv = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv;
as->mrm.ofs = ptr2addr(&uv->tv);
as->mrm.base = as->mrm.idx = RID_NONE;
return;
@ -1702,7 +1702,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
Reg dest = ra_dest(as, ir, RSET_GPR);
if (irref_isk(ir->op1)) {
GCfunc *fn = ir_kfunc(IR(ir->op1));
MRef *v = &gcref(fn->l.uvptr[ir->op2])->uv.v;
MRef *v = &gcref(fn->l.uvptr[(ir->op2 >> 8)])->uv.v;
emit_rma(as, XO_MOV, dest, v);
} else {
Reg uv = ra_scratch(as, RSET_GPR);
@ -1716,7 +1716,7 @@ static void asm_uref(ASMState *as, IRIns *ir)
emit_rmro(as, XO_MOV, dest, uv, offsetof(GCupval, v));
}
emit_rmro(as, XO_MOV, uv, func,
(int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)ir->op2);
(int32_t)offsetof(GCfuncL, uvptr) + 4*(int32_t)(ir->op2 >> 8));
}
}
}

View File

@ -169,10 +169,11 @@ GCfunc *lj_func_newL_gc(lua_State *L, GCproto *pt, GCfuncL *parent)
nuv = fn->l.nupvalues;
base = L->base;
for (i = 0; i < nuv; i++) {
ptrdiff_t v = pt->uv[i];
uint32_t v = pt->uv[i];
GCupval *uv;
if ((v & 0x8000)) {
uv = func_finduv(L, base + (v & 0xff));
uv->dhash = (uint32_t)(uintptr_t)gcref(parent->pt) ^ (v << 24);
} else {
uv = &gcref(puv[v])->uv;
}

View File

@ -397,7 +397,7 @@ typedef struct GCupval {
};
};
MRef v; /* Points to stack slot (open) or above (closed). */
int32_t unusedv; /* For consistent alignment. */
uint32_t dhash; /* Disambiguation hash: dh1 != dh2 => cannot alias. */
} GCupval;
#define uvprev(uv_) (&gcref((uv_)->prev)->uv)

View File

@ -1146,12 +1146,12 @@ LJFOLDF(cse_uref)
if (LJ_LIKELY(J->flags & JIT_F_OPT_CSE)) {
IRRef ref = J->chain[fins->o];
GCfunc *fn = ir_kfunc(fleft);
GCupval *uv = gco2uv(gcref(fn->l.uvptr[fins->op2]));
GCupval *uv = gco2uv(gcref(fn->l.uvptr[(fins->op2 >> 8)]));
while (ref > 0) {
IRIns *ir = IR(ref);
if (irref_isk(ir->op1)) {
GCfunc *fn2 = ir_kfunc(IR(ir->op1));
if (gco2uv(gcref(fn2->l.uvptr[ir->op2])) == uv) {
if (gco2uv(gcref(fn2->l.uvptr[(ir->op2 >> 8)])) == uv) {
if (fins->o == IR_UREFO && gcstep_barrier(J, ref))
break;
return ref;

View File

@ -277,12 +277,17 @@ static AliasRet aa_uref(IRIns *refa, IRIns *refb)
{
if (refa->o != refb->o)
return ALIAS_NO; /* Different UREFx type. */
if (refa->op1 != refb->op1)
return ALIAS_MAY; /* Different function. */
else if (refa->op2 == refb->op2)
return ALIAS_MUST; /* Same function, same upvalue idx. */
else
return ALIAS_NO; /* Same function, different upvalue idx. */
if (refa->op1 == refb->op1) { /* Same function. */
if (refa->op2 == refb->op2)
return ALIAS_MUST; /* Same function, same upvalue idx. */
else
return ALIAS_NO; /* Same function, different upvalue idx. */
} else { /* Different functions, check disambiguation hash values. */
if (((refa->op2 ^ refb->op2) & 0xff))
return ALIAS_NO; /* Upvalues with different hash values cannot alias. */
else
return ALIAS_MAY; /* No conclusion can be drawn for same hash value. */
}
}
/* ULOAD forwarding. */

View File

@ -781,6 +781,15 @@ static TRef rec_idx(jit_State *J, RecordIndex *ix)
/* -- Upvalue access ------------------------------------------------------ */
/* Shrink disambiguation hash into an 8 bit value. */
static uint32_t shrink_dhash(uint32_t lo, uint32_t hi)
{
lo ^= hi; hi = lj_rol(hi, 14);
lo -= hi; hi = lj_rol(hi, 5);
hi ^= lo; hi -= lj_rol(lo, 27);
return (hi & 0xff);
}
/* Record upvalue load/store. */
static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
{
@ -788,6 +797,8 @@ static TRef rec_upvalue(jit_State *J, uint32_t uv, TRef val)
TRef fn = getcurrf(J);
IRRef uref;
int needbarrier = 0;
/* Note: this effectively limits LJ_MAX_UPVAL to 127. */
uv = (uv << 8) | shrink_dhash(uvp->dhash, uvp->dhash-0x04c11db7);
if (!uvp->closed) {
/* In current stack? */
if (uvval(uvp) >= J->L->stack && uvval(uvp) < J->L->maxstack) {