summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--lisc/lisc.h6
-rw-r--r--lisc/rega.c26
-rw-r--r--lisc/spill.c26
-rw-r--r--lisc/util.c21
4 files changed, 68 insertions, 11 deletions
diff --git a/lisc/lisc.h b/lisc/lisc.h
index 0912b1f..35113ff 100644
--- a/lisc/lisc.h
+++ b/lisc/lisc.h
@@ -246,7 +246,10 @@ struct Tmp {
 	uint cost;
 	short slot;
 	short wide;
-	int hint;
+	struct {
+		int r;
+		ulong m;
+	} hint;
 	int phi;
 };
 
@@ -335,6 +338,7 @@ void idup(Ins **, Ins *, ulong);
 Ins *icpy(Ins *, Ins *, ulong);
 void *vnew(ulong, size_t);
 void vgrow(void *, ulong);
+int phicls(int, Tmp *);
 Ref newtmp(char *, Fn *);
 Ref getcon(int64_t, Fn *);
 void addcon(Con *, Con *);
diff --git a/lisc/rega.c b/lisc/rega.c
index 8d1bb1a..a55a871 100644
--- a/lisc/rega.c
+++ b/lisc/rega.c
@@ -25,10 +25,7 @@ static int cpm, npm;   /* capacity and size of pm */
 static int *
 hint(int t)
 {
-	if (tmp[t].phi)
-		return &tmp[tmp[t].phi].hint;
-	else
-		return &tmp[t].hint;
+	return &tmp[phicls(t, tmp)].hint.r;
 }
 
 static int
@@ -75,6 +72,7 @@ radd(RMap *m, int t, int r)
 static Ref
 ralloc(RMap *m, int t)
 {
+	ulong regs;
 	int r;
 
 	if (t < Tmp0) {
@@ -87,10 +85,16 @@ ralloc(RMap *m, int t)
 		return TMP(r);
 	}
 	r = *hint(t);
-	if (r == -1 || BGET(m->b, r))
-		for (r=RAX; BGET(m->b, r); r++)
-			if (r+1 == RAX+NReg)
-				diag("rega: no more regs");
+	if (r == -1 || BGET(m->b, r)) {
+		regs = tmp[phicls(t, tmp)].hint.m;
+		regs |= m->b.t[0];
+		for (r=RAX; r<RAX+NReg && (regs & BIT(r)); r++)
+			;
+		if (r == RAX+NReg)
+			for (r=RAX; BGET(m->b, r); r++)
+				if (r+1 == RAX+NReg)
+					diag("rega: no more regs");
+	}
 	radd(m, t, r);
 	if (*hint(t) == -1)
 		*hint(t) = r;
@@ -323,6 +327,10 @@ doblk(Blk *b, RMap *cur)
 				i = dopm(b, i, cur);
 				continue;
 			}
+			if (isreg(i->to))
+			if (rtype(i->arg[0]) == RTmp)
+			if (*hint(i->arg[0].val) == -1)
+				*hint(i->arg[0].val) = i->to.val;
 			/* fall through */
 		default:
 			if (!req(i->to, R)) {
@@ -377,7 +385,7 @@ rega(Fn *fn)
 	end = alloc(fn->nblk * sizeof end[0]);
 	beg = alloc(fn->nblk * sizeof beg[0]);
 	for (t=Tmp0; t<fn->ntmp; t++)
-		tmp[t].hint = -1;
+		*hint(t) = -1;
 	for (b=fn->start, i=b->ins; i-b->ins < b->nins; i++)
 		if (i->op != OCopy || !isreg(i->arg[0]))
 			break;
diff --git a/lisc/spill.c b/lisc/spill.c
index 662df3f..b0dcd1b 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -211,6 +211,16 @@ limit(Bits *b, int k, Bits *fst)
 }
 
 static void
+sethint(Bits *u, ulong r)
+{
+	int t;
+
+	for (t=Tmp0; t<ntmp; t++)
+		if (BGET(*u, t))
+			tmp[phicls(t, tmp)].hint.m |= r;
+}
+
+static void
 reloads(Bits *u, Bits *v)
 {
 	int t;
@@ -223,8 +233,10 @@ reloads(Bits *u, Bits *v)
 static Ins *
 dopm(Blk *b, Ins *i, Bits *v)
 {
+	int n;
 	Bits u;
 	Ins *i1;
+	ulong r;
 
 	/* consecutive moves from
 	 * registers need to handled
@@ -244,9 +256,15 @@ dopm(Blk *b, Ins *i, Bits *v)
 	if (i > b->ins && (i-1)->op == OCall) {
 		v->t[0] &= ~calldef(*(i-1), 0);
 		limit(v, NReg - NRSave, 0);
+		r = 0;
+		for (n=0; n<NRSave; n++)
+			r |= BIT(rsave[n]);
 		v->t[0] |= calluse(*(i-1), 0);
-	} else
+	} else {
 		limit(v, NReg, 0);
+		r = v->t[0];
+	}
+	sethint(v, r);
 	reloads(&u, v);
 	do
 		emiti(*--i1);
@@ -276,6 +294,7 @@ spill(Fn *fn)
 	int j, s;
 	Phi *p;
 	Mem *ma;
+	ulong r;
 
 	tmp = fn->tmp;
 	ntmp = fn->ntmp;
@@ -342,6 +361,7 @@ spill(Fn *fn)
 
 		/* 2. process the block instructions */
 		curi = &insb[NIns];
+		r = 0;
 		for (i=&b->ins[b->nins]; i!=b->ins;) {
 			assert(bcnt(&v) <= NReg);
 			i--;
@@ -400,11 +420,15 @@ spill(Fn *fn)
 						i->arg[m] = slot(t);
 					}
 				}
+			r = v.t[0] & (BIT(Tmp0)-1);
+			if (r)
+				sethint(&v, r);
 			reloads(&u, &v);
 			if (s != -1)
 				store(i->to, s);
 			emiti(*i);
 		}
+		assert(!r || b==fn->start);
 
 		for (p=b->phi; p; p=p->link) {
 			assert(rtype(p->to) == RTmp);
diff --git a/lisc/util.c b/lisc/util.c
index 993a3d7..7d03053 100644
--- a/lisc/util.c
+++ b/lisc/util.c
@@ -166,6 +166,27 @@ vgrow(void *vp, ulong len)
 	*(Vec **)vp = v1;
 }
 
+int
+phicls(int t, Tmp *tmp /*, int c*/)
+{
+	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 t1;
+#endif
+}
+
 Ref
 newtmp(char *prfx, Fn *fn)
 {