summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2017-05-16 11:33:41 -0400
committerQuentin Carbonneaux <quentin@c9x.me>2017-05-16 11:33:41 -0400
commit425a2ed09c08222e1254d93dba24c7a50e7a08b9 (patch)
tree8637b9bcc9574e44e078994a4ea514289729e106
parent51c46ba6914741cbca54d3351f8cf8d2689fd3dc (diff)
downloadroux-425a2ed09c08222e1254d93dba24c7a50e7a08b9.tar.gz
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.
-rw-r--r--live.c52
-rw-r--r--ssa.c17
-rw-r--r--util.c16
3 files changed, 19 insertions, 66 deletions
diff --git a/live.c b/live.c
index 6e63705..4198995 100644
--- a/live.c
+++ b/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");
diff --git a/ssa.c b/ssa.c
index 632ebbe..9aff73c 100644
--- a/ssa.c
+++ b/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++) {
diff --git a/util.c b/util.c
index 4144f87..cb6e75c 100644
--- a/util.c
+++ b/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)
-			tmp[t].phi = t1;
-	}
+		return t;
+	t1 = phicls(t1, tmp);
+	tmp[t].phi = t1;
 	return t1;
-#endif
 }
 
 Ref