summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2017-03-29 00:16:46 -0400
committerQuentin Carbonneaux <quentin@c9x.me>2017-03-29 00:16:46 -0400
commit81e2fdacc536dab7ad3c1e1da313b80f5ae935b7 (patch)
tree91768d923da523502211c3c0b130351580852abb
parent02408ffd8f95a4334212e1d64de987f9192cb4d5 (diff)
downloadroux-81e2fdacc536dab7ad3c1e1da313b80f5ae935b7.tar.gz
improve global registers handling
The register allocation now has stricter assertions
about global registers.  The stricter assertions
required changes in the spiller:  We now correctly
indicate to the register allocator what registers
are used by "ret" instructions.
-rw-r--r--rega.c12
-rw-r--r--spill.c16
2 files changed, 18 insertions, 10 deletions
diff --git a/rega.c b/rega.c
index 9f02a63..3d83327 100644
--- a/rega.c
+++ b/rega.c
@@ -135,6 +135,7 @@ rfree(RMap *m, int t)
 {
 	int i, r;
 
+	assert(t >= Tmp0 || !(BIT(t) & RGLOB));
 	if (!bshas(m->b, t))
 		return -1;
 	for (i=0; m->t[i] != t; i++)
@@ -145,6 +146,7 @@ rfree(RMap *m, int t)
 	m->n--;
 	memmove(&m->t[i], &m->t[i+1], (m->n-i) * sizeof m->t[0]);
 	memmove(&m->r[i], &m->r[i+1], (m->n-i) * sizeof m->r[0]);
+	assert(t >= Tmp0 || t == r);
 	return r;
 }
 
@@ -385,13 +387,15 @@ doblk(Blk *b, RMap *cur)
 		default:
 			if (!req(i->to, R)) {
 				assert(rtype(i->to) == RTmp);
-				r = rfree(cur, i->to.val);
-				if (r == -1 && !isreg(i->to)) {
+				r = i->to.val;
+				if (r >= Tmp0 || !(BIT(r) & RGLOB))
+					r = rfree(cur, r);
+				if (r == -1) {
+					assert(!isreg(i->to));
 					*i = (Ins){.op = Onop};
 					continue;
 				}
-				if (i->to.val >= Tmp0)
-					i->to = TMP(r);
+				i->to = TMP(r);
 			}
 			break;
 		}
diff --git a/spill.c b/spill.c
index 5e2b9ec..0872fd5 100644
--- a/spill.c
+++ b/spill.c
@@ -298,7 +298,8 @@ void
 spill(Fn *fn)
 {
 	Blk *b, *s1, *s2, *hd, **bp;
-	int j, n, l, t, k, lvarg[2];
+	int j, l, t, k, lvarg[2];
+	uint n;
 	BSet u[1], v[1], w[1];
 	Ins *i;
 	Phi *p;
@@ -340,7 +341,6 @@ spill(Fn *fn)
 		if (s2 && s2->id <= b->id)
 		if (!hd || s2->id >= hd->id)
 			hd = s2;
-		r = 0;
 		if (hd) {
 			/* back-edge */
 			bszero(v);
@@ -352,8 +352,8 @@ spill(Fn *fn)
 				bscopy(w, u);
 				bsinter(u, hd->gen);
 				bsdiff(w, hd->gen);
-				if ((int)bscount(u) < n) { /* fixme */
-					j = bscount(w);   /* live through */
+				if (bscount(u) < n) {
+					j = bscount(w); /* live through */
 					l = hd->nlive[k];
 					limit(w, n - (l - j), 0);
 					bsunion(u, w);
@@ -370,14 +370,18 @@ spill(Fn *fn)
 				bsunion(v, u);
 			}
 			limit2(v, 0, 0, w);
-		} else
+		} else {
 			bscopy(v, b->out);
+			if (rtype(b->jmp.arg) == RCall)
+				v->t[0] |= retregs(b->jmp.arg, 0);
+		}
 		for (t=Tmp0; bsiter(b->out, &t); t++)
 			if (!bshas(v, t))
 				slot(t);
 		bscopy(b->out, v);
 
 		/* 2. process the block instructions */
+		r = v->t[0] & (BIT(Tmp0)-1);
 		curi = &insb[NIns];
 		for (i=&b->ins[b->nins]; i!=b->ins;) {
 			i--;
@@ -449,7 +453,7 @@ spill(Fn *fn)
 			if (r)
 				sethint(v, r);
 		}
-		assert(!(r & ~RGLOB) || b==fn->start);
+		assert(r == RGLOB || b == fn->start);
 
 		for (p=b->phi; p; p=p->link) {
 			assert(rtype(p->to) == RTmp);