break phi-classes following interferences

This commit is contained in:
Quentin Carbonneaux 2015-10-27 14:21:33 -04:00
parent 614130e431
commit d43ebe8f58

View file

@ -19,15 +19,31 @@ liveon(Blk *b, Blk *s)
}
static void
bset(Ref r, Blk *b, int *nlv)
bset(Ref r, Blk *b, int *nlv, short *phi, Tmp *tmp)
{
int t, t1, t2;
if (rtype(r) != RTmp)
return;
BSET(b->gen, r.val);
if (!BGET(b->in, r.val)) {
t1 = r.val;
BSET(b->gen, t1);
if (!BGET(b->in, t1)) {
++*nlv;
BSET(b->in, r.val);
BSET(b->in, t1);
}
/* detect temporaries in the same
* phi-class that interfere and
* separate them
*/
t = phirepr(tmp, t1);
t2 = phi[t];
if (t2 && t2 != t1) {
if (tmp[t1].phi != t1)
tmp[t1].phi = t1;
else
tmp[t2].phi = t2;
}
phi[t] = t1;
}
/* liveness analysis
@ -38,11 +54,13 @@ filllive(Fn *f)
{
Blk *b;
Ins *i;
int z, m, n, chg, nlv;
int t, z, m, n, chg, nlv;
short *phi;
Bits u, v;
Mem *ma;
assert(f->ntmp <= NBit*BITS);
phi = emalloc(f->ntmp * sizeof phi[0]);
for (b=f->start; b; b=b->link) {
b->in = (Bits){{0}};
b->out = (Bits){{0}};
@ -66,9 +84,13 @@ Again:
}
chg |= memcmp(&b->out, &u, sizeof(Bits));
b->in = b->out;
nlv = bcnt(&b->in);
bset(b->jmp.arg, b, &nlv);
memset(phi, 0, f->ntmp * sizeof phi[0]);
b->in = (Bits){{0}};
nlv = 0;
for (t=0; t<f->ntmp; t++)
if (BGET(b->out, t))
bset(TMP(t), b, &nlv, phi, f->tmp);
bset(b->jmp.arg, b, &nlv, phi, f->tmp);
b->nlive = nlv;
for (i=&b->ins[b->nins]; i!=b->ins;) {
if ((--i)->op == OCall) {
@ -83,16 +105,18 @@ Again:
assert(rtype(i->to) == RTmp);
nlv -= BGET(b->in, i->to.val);
BCLR(b->in, i->to.val);
t = phirepr(f->tmp, i->to.val);
phi[t] = 0;
}
for (m=0; m<2; m++)
switch (rtype(i->arg[m])) {
case RAMem:
ma = &f->mem[i->arg[m].val & AMask];
bset(ma->base, b, &nlv);
bset(ma->index, b, &nlv);
bset(ma->base, b, &nlv, phi, f->tmp);
bset(ma->index, b, &nlv, phi, f->tmp);
break;
default:
bset(i->arg[m], b, &nlv);
bset(i->arg[m], b, &nlv, phi, f->tmp);
break;
}
if (nlv > b->nlive)
@ -103,6 +127,7 @@ Again:
chg = 0;
goto Again;
}
free(phi);
if (debug['L']) {
fprintf(stderr, "\n> Liveness analysis:\n");