mirror of
git://c9x.me/qbe.git
synced 2026-04-05 18:09:47 +00:00
do not account for interferences in phi classes
Before this commit, I tried to make sure that
two interfering temporaries never ended up in
the same phi class.
This was to make sure that their register hints
were not counterproductively stepping on each
other's toes. The idea is fine, but:
* the implementation is clumsy because it
mixes the orthogonal concepts of
(i) interference and (ii) phi classes;
* the hinting process in the register
allocator is hard to understand because
the disjoint-set data structure used for
phi classes is cut in arbitrary places.
After this commit, the phi classes *really* are
phi classes represented with a proper disjoint-set
data structure.
This commit is contained in:
parent
51c46ba691
commit
425a2ed09c
52
live.c
52
live.c
@ -19,46 +19,13 @@ liveon(BSet *v, Blk *b, Blk *s)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
phitmp(int t, Tmp *tmp)
|
||||
{
|
||||
int tp;
|
||||
|
||||
tp = tmp[t].phi;
|
||||
return tp ? tp : t;
|
||||
}
|
||||
|
||||
static void
|
||||
phifix(int t1, int *phi, Tmp *tmp)
|
||||
{
|
||||
int t, t2;
|
||||
|
||||
/* detect temporaries arguments
|
||||
* of the same phi node that
|
||||
* interfere and separate them
|
||||
*/
|
||||
t = phitmp(t1, tmp);
|
||||
t2 = phi[t];
|
||||
if (t2 && t2 != t1) {
|
||||
if (t != t1) {
|
||||
tmp[t1].phi = t1;
|
||||
t = t1;
|
||||
} else {
|
||||
tmp[t2].phi = t2;
|
||||
phi[t2] = t2;
|
||||
}
|
||||
}
|
||||
phi[t] = t1;
|
||||
}
|
||||
|
||||
static void
|
||||
bset(Ref r, Blk *b, int *nlv, int *phi, Tmp *tmp)
|
||||
bset(Ref r, Blk *b, int *nlv, Tmp *tmp)
|
||||
{
|
||||
|
||||
if (rtype(r) != RTmp)
|
||||
return;
|
||||
bsset(b->gen, r.val);
|
||||
phifix(r.val, phi, tmp);
|
||||
if (!bshas(b->in, r.val)) {
|
||||
nlv[KBASE(tmp[r.val].cls)]++;
|
||||
bsset(b->in, r.val);
|
||||
@ -74,13 +41,11 @@ filllive(Fn *f)
|
||||
Blk *b;
|
||||
Ins *i;
|
||||
int k, t, m[2], n, chg, nlv[2];
|
||||
int *phi;
|
||||
BSet u[1], v[1];
|
||||
Mem *ma;
|
||||
|
||||
bsinit(u, f->ntmp);
|
||||
bsinit(v, f->ntmp);
|
||||
phi = emalloc(f->ntmp * sizeof phi[0]);
|
||||
for (b=f->start; b; b=b->link) {
|
||||
bsinit(b->in, f->ntmp);
|
||||
bsinit(b->out, f->ntmp);
|
||||
@ -102,21 +67,18 @@ Again:
|
||||
}
|
||||
chg |= !bsequal(b->out, u);
|
||||
|
||||
memset(phi, 0, f->ntmp * sizeof phi[0]);
|
||||
memset(nlv, 0, sizeof nlv);
|
||||
b->out->t[0] |= T.rglob;
|
||||
bscopy(b->in, b->out);
|
||||
for (t=0; bsiter(b->in, &t); t++) {
|
||||
phifix(t, phi, f->tmp);
|
||||
for (t=0; bsiter(b->in, &t); t++)
|
||||
nlv[KBASE(f->tmp[t].cls)]++;
|
||||
}
|
||||
if (rtype(b->jmp.arg) == RCall) {
|
||||
assert((int)bscount(b->in) == T.nrglob &&
|
||||
nlv[0] == T.nrglob &&
|
||||
nlv[1] == 0);
|
||||
b->in->t[0] |= T.retregs(b->jmp.arg, nlv);
|
||||
} else
|
||||
bset(b->jmp.arg, b, nlv, phi, f->tmp);
|
||||
bset(b->jmp.arg, b, nlv, f->tmp);
|
||||
for (k=0; k<2; k++)
|
||||
b->nlive[k] = nlv[k];
|
||||
for (i=&b->ins[b->nins]; i!=b->ins;) {
|
||||
@ -145,17 +107,16 @@ Again:
|
||||
nlv[KBASE(f->tmp[t].cls)]--;
|
||||
bsset(b->gen, t);
|
||||
bsclr(b->in, t);
|
||||
phi[phitmp(t, f->tmp)] = 0;
|
||||
}
|
||||
for (k=0; k<2; k++)
|
||||
switch (rtype(i->arg[k])) {
|
||||
case RMem:
|
||||
ma = &f->mem[i->arg[k].val];
|
||||
bset(ma->base, b, nlv, phi, f->tmp);
|
||||
bset(ma->index, b, nlv, phi, f->tmp);
|
||||
bset(ma->base, b, nlv, f->tmp);
|
||||
bset(ma->index, b, nlv, f->tmp);
|
||||
break;
|
||||
default:
|
||||
bset(i->arg[k], b, nlv, phi, f->tmp);
|
||||
bset(i->arg[k], b, nlv, f->tmp);
|
||||
break;
|
||||
}
|
||||
for (k=0; k<2; k++)
|
||||
@ -167,7 +128,6 @@ Again:
|
||||
chg = 0;
|
||||
goto Again;
|
||||
}
|
||||
free(phi);
|
||||
|
||||
if (debug['L']) {
|
||||
fprintf(stderr, "\n> Liveness analysis:\n");
|
||||
|
||||
17
ssa.c
17
ssa.c
@ -40,7 +40,7 @@ filluse(Fn *fn)
|
||||
Blk *b;
|
||||
Phi *p;
|
||||
Ins *i;
|
||||
int m, t, w;
|
||||
int m, t, tp, w;
|
||||
uint a;
|
||||
Tmp *tmp;
|
||||
|
||||
@ -49,8 +49,8 @@ filluse(Fn *fn)
|
||||
for (t=Tmp0; t<fn->ntmp; t++) {
|
||||
tmp[t].ndef = 0;
|
||||
tmp[t].nuse = 0;
|
||||
tmp[t].phi = 0;
|
||||
tmp[t].cls = 0;
|
||||
tmp[t].phi = 0;
|
||||
tmp[t].width = WFull;
|
||||
if (tmp[t].use == 0)
|
||||
tmp[t].use = vnew(0, sizeof(Use), Pfn);
|
||||
@ -58,16 +58,17 @@ filluse(Fn *fn)
|
||||
for (b=fn->start; b; b=b->link) {
|
||||
for (p=b->phi; p; p=p->link) {
|
||||
assert(rtype(p->to) == RTmp);
|
||||
t = p->to.val;
|
||||
tmp[t].ndef++;
|
||||
tmp[t].cls = p->cls;
|
||||
tmp[t].phi = p->to.val;
|
||||
tp = p->to.val;
|
||||
tmp[tp].ndef++;
|
||||
tmp[tp].cls = p->cls;
|
||||
tp = phicls(tp, fn->tmp);
|
||||
for (a=0; a<p->narg; a++)
|
||||
if (rtype(p->arg[a]) == RTmp) {
|
||||
t = p->arg[a].val;
|
||||
adduse(&tmp[t], UPhi, b, p);
|
||||
if (!tmp[t].phi)
|
||||
tmp[t].phi = p->to.val;
|
||||
t = phicls(t, fn->tmp);
|
||||
if (t != tp)
|
||||
tmp[t].phi = tp;
|
||||
}
|
||||
}
|
||||
for (i=b->ins; i-b->ins < b->nins; i++) {
|
||||
|
||||
14
util.c
14
util.c
@ -249,24 +249,16 @@ clsmerge(short *pk, short k)
|
||||
}
|
||||
|
||||
int
|
||||
phicls(int t, Tmp *tmp /*, int c*/)
|
||||
phicls(int t, Tmp *tmp)
|
||||
{
|
||||
if (tmp[t].phi)
|
||||
return tmp[t].phi;
|
||||
return t;
|
||||
#if 0
|
||||
int t1;
|
||||
|
||||
t1 = tmp[t].phi;
|
||||
if (!t1)
|
||||
t1 = t;
|
||||
if (t != t1) {
|
||||
t1 = phitmp(t1, tmp, c);
|
||||
if (c)
|
||||
return t;
|
||||
t1 = phicls(t1, tmp);
|
||||
tmp[t].phi = t1;
|
||||
}
|
||||
return t1;
|
||||
#endif
|
||||
}
|
||||
|
||||
Ref
|
||||
|
||||
Loading…
Reference in New Issue
Block a user