summary refs log tree commit diff
path: root/load.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-24 10:31:50 -0500
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-24 10:31:50 -0500
commit0699cd2e575bcaa951cb7d97bc77ab9acb2c9970 (patch)
treeca2569cbf21c747e9393d025b2bc5b93973ee7bf /load.c
parent1bb7652484e1c7ca2cd7fcab858b4bbb18509879 (diff)
downloadroux-0699cd2e575bcaa951cb7d97bc77ab9acb2c9970.tar.gz
improve the range of action of load elimination
When eliminating `load %foo`, don't limit the
search to the live range of %foo, but to the
live range of its aliasing information.

For example, if %foo is a constant offset into
a stack-allocated slot,

    %foo =l add %slot, 42

the search will proceed on all the code in
which %slot is live, not only below the
definition of %foo, like before.
Diffstat (limited to 'load.c')
-rw-r--r--load.c53
1 files changed, 48 insertions, 5 deletions
diff --git a/load.c b/load.c
index 3e22b57..4805720 100644
--- a/load.c
+++ b/load.c
@@ -113,8 +113,9 @@ mask(int cls, Ref *r, bits msk, Loc *l)
 static Ref
 load(Slice sl, bits msk, Loc *l)
 {
-	Ref r;
-	int ld, cls, all;
+	Alias *a;
+	Ref r, r1;
+	int ld, cls, all, c;
 
 	ld = (int[]){
 		[1] = Oloadub,
@@ -127,12 +128,54 @@ load(Slice sl, bits msk, Loc *l)
 		cls = sl.cls;
 	else
 		cls = sl.sz > 4 ? Kl : Kw;
-	r = iins(cls, ld, sl.ref, R, l);
+	r = sl.ref;
+	/* sl.ref might not be live here,
+	 * but its alias base ref will be
+	 * (see killsl() below) */
+	if (rtype(r) == RTmp) {
+		a = &curf->tmp[r.val].alias;
+		switch (a->type) {
+		default:
+			die("unreachable");
+		case ALoc:
+		case AEsc:
+		case AUnk:
+			r = a->base;
+			if (!a->offset)
+				break;
+			r1 = getcon(a->offset, curf);
+			r = iins(Kl, Oadd, r, r1, l);
+			break;
+		case ACon:
+		case ASym:
+			c = curf->ncon++;
+			vgrow(&curf->con, curf->ncon);
+			curf->con[c].type = CAddr;
+			strcpy(curf->con[c].label, a->label);
+			curf->con[c].bits.i = a->offset;
+			curf->con[c].local = 0;
+			r = CON(c);
+			break;
+		}
+	}
+	r = iins(cls, ld, r, R, l);
 	if (!all)
 		mask(cls, &r, msk, l);
 	return r;
 }
 
+static int
+killsl(Ref r, Slice sl)
+{
+	Alias *a;
+
+	if (rtype(sl.ref) != RTmp)
+		return 0;
+	a = &curf->tmp[sl.ref.val].alias;
+	assert(a->type==ALoc || a->type==AEsc || a->type==AUnk);
+	return req(a->base, r);
+}
+
 /* returns a ref containing the contents of the slice
  * passed as argument, all the bits set to 0 in the
  * mask argument are zeroed in the result;
@@ -181,7 +224,7 @@ def(Slice sl, bits msk, Blk *b, Ins *i, Loc *il)
 
 	while (i > b->ins) {
 		--i;
-		if (req(i->to, sl.ref)
+		if (killsl(i->to, sl)
 		|| (i->op == Ocall && escapes(sl.ref, curf)))
 			goto Load;
 		ld = isload(i->op);
@@ -251,7 +294,7 @@ def(Slice sl, bits msk, Blk *b, Ins *i, Loc *il)
 		}
 
 	for (p=b->phi; p; p=p->link)
-		if (req(p->to, sl.ref))
+		if (killsl(p->to, sl))
 			/* scanning predecessors in that
 			 * case would be unsafe */
 			goto Load;