summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-08-08 00:18:31 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2015-09-15 23:01:30 -0400
commit1721fe43137e54e05a62663235a5a8cebb7f4761 (patch)
tree3c8f9ea661ebced5787b0b701ce1f630e4750ade
parent83131357f7a15ee28208e41b1503937df34b99ba (diff)
downloadroux-1721fe43137e54e05a62663235a5a8cebb7f4761.tar.gz
fix a bug in setloc
The way we detected if limit had spilled a variable
was incorrect.  This is because two consecutive calls
to limit could require a spill of the same variable.
Instead, we now use a return value from limit.

Note that this is still not so ideal.  Indeed, it works
properly only when limit spills one value only, if not,
we should return a bitset.  In the current use scheme
of limit, this invariant is true but ideally we would
like to call limit with *all arguments added at once*,
not one after the other.
-rw-r--r--lisc/spill.c34
1 files changed, 17 insertions, 17 deletions
diff --git a/lisc/spill.c b/lisc/spill.c
index 7361b11..ca7d962 100644
--- a/lisc/spill.c
+++ b/lisc/spill.c
@@ -184,16 +184,15 @@ emit(short op, Ref to, Ref arg0, Ref arg1)
 	*--curi = (Ins){op, to, {arg0, arg1}};
 }
 
-static Bits
+static int
 limit(Bits *b, int k, Bits *fst)
 {
 	static int *tarr, maxt;
 	int i, t, nt;
-	Bits res;
 
 	nt = bcnt(b);
 	if (nt <= k)
-		return *b;
+		return 0;
 	if (nt > maxt) {
 		free(tarr);
 		tarr = alloc(nt * sizeof tarr[0]);
@@ -201,8 +200,10 @@ limit(Bits *b, int k, Bits *fst)
 	}
 	i = 0;
 	for (t=0; t<ntmp; t++)
-		if (BGET(*b, t))
+		if (BGET(*b, t)) {
+			BCLR(*b, t);
 			tarr[i++] = t;
+		}
 	assert(i == nt);
 	if (!fst)
 		qsort(tarr, nt, sizeof tarr[0], tcmp0);
@@ -210,15 +211,16 @@ limit(Bits *b, int k, Bits *fst)
 		f = fst;
 		qsort(tarr, nt, sizeof tarr[0], tcmp1);
 	}
-	res = (Bits){{0}};
 	for (i=0; i<k && i<nt; i++)
-		BSET(res, tarr[i]);
+		BSET(*b, tarr[i]);
 	for (; i<nt; i++) {
 		slot(tarr[i]);
-		if (curi)
+		if (curi) {
 			emit(OLoad, TMP(tarr[i]), slot(tarr[i]), R);
+			t = tarr[i];
+		}
 	}
-	return res;
+	return t;
 }
 
 static void
@@ -243,9 +245,7 @@ setloc(Ref *pr, Bits *v, Bits *w)
 		return;
 	t = pr->val;
 	BSET(*v, t);
-	*v = limit(v, nreg, w);
-	if (curi->op == OLoad)
-	if (curi->to.val == t)
+	if (limit(v, nreg, w) == t)
 		/* if t was spilled by limit,
 		 * it was not live so we don't
 		 * have to reload it */
@@ -313,11 +313,11 @@ spill(Fn *fn)
 				for (z=0; z<BITS; z++)
 					w.t[z] &= ~v.t[z];
 				j = bcnt(&w);   /* live through */
-				w = limit(&w, NReg - (l - j), 0);
+				limit(&w, NReg - (l - j), 0);
 				for (z=0; z<BITS; z++)
 					v.t[z] |= w.t[z];
 			} else if (j > NReg)
-				v = limit(&v, NReg, 0);
+				limit(&v, NReg, 0);
 		} else if (s1) {
 			v = s1->in;
 			w = s1->in;
@@ -327,7 +327,7 @@ spill(Fn *fn)
 					w.t[z] &= s2->in.t[z];
 				}
 			assert(bcnt(&w) <= NReg);
-			v = limit(&v, NReg, &w);
+			limit(&v, NReg, &w);
 		}
 		b->out = v;
 		assert(bcnt(&v) <= NReg);
@@ -347,7 +347,7 @@ spill(Fn *fn)
 				if (BGET(v, j))
 					BCLR(v, j);
 				else
-					v = limit(&v, nreg-1, &w);
+					limit(&v, nreg-1, &w);
 				s = tmp[j].spill;
 				break;
 			case RReg:
@@ -356,13 +356,13 @@ spill(Fn *fn)
 					BCLR(br, j);
 					nreg++;
 				} else
-					v = limit(&v, nreg-1, &w);
+					limit(&v, nreg-1, &w);
 				break;
 			case -1:;
 			}
 			w = (Bits){{0}};
-			setloc(&i->arg[1], &v, &w);
 			setloc(&i->arg[0], &v, &w);
+			setloc(&i->arg[1], &v, &w);
 			if (s)
 				emit(OStore, R, i->to, SLOT(s));
 			emit(i->op, i->to, i->arg[0], i->arg[1]);