summary refs log tree commit diff
path: root/mem.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2016-04-12 18:29:10 -0400
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2016-04-13 09:53:50 -0400
commit32d9e33191a08e9162cebfac6e19cbd56eb1b3b6 (patch)
treea9fa469fdf84f42097c2bbbc07d20862add264a4 /mem.c
parent02b70c0cb1203a9a3cc9a0bda0f013188a2a4942 (diff)
downloadroux-32d9e33191a08e9162cebfac6e19cbd56eb1b3b6.tar.gz
harden memopt()
Diffstat (limited to 'mem.c')
-rw-r--r--mem.c84
1 files changed, 55 insertions, 29 deletions
diff --git a/mem.c b/mem.c
index 521fa96..b94f0a7 100644
--- a/mem.c
+++ b/mem.c
@@ -1,12 +1,29 @@
 #include "all.h"
 
-/* Memory optimization:
- *
- * - replace alloced slots used only in
- *   load/store operations
- *   Assumption: all the accesses have the
- *   same size (this could be wrong...)
- */
+static int
+loadsz(Ins *l)
+{
+	switch (l->op) {
+	case OLoadsb: case OLoadub: return 1;
+	case OLoadsh: case OLoaduh: return 2;
+	case OLoadsw: case OLoaduw: return 4;
+	case OLoad: return KWIDE(l->cls) ? 8 : 4;
+	}
+	die("unreachable");
+}
+
+static int
+storesz(Ins *s)
+{
+	switch (s->op) {
+	case OStoreb: return 1;
+	case OStoreh: return 2;
+	case OStorew: case OStores: return 4;
+	case OStorel: case OStored: return 8;
+	}
+	die("unreachable");
+}
+
 
 /* require use, maintains use counts */
 void
@@ -16,8 +33,9 @@ memopt(Fn *fn)
 	Ins *i, *l;
 	Tmp *t;
 	Use *u, *ue;
-	int a;
+	int s, k;
 
+	/* promote uniform stack slots to temporaries */
 	b = fn->start;
 	for (i=b->ins; i-b->ins < b->nins; i++) {
 		if (OAlloc > i->op || i->op > OAlloc1)
@@ -25,13 +43,26 @@ memopt(Fn *fn)
 		/* specific to NAlign == 3 */
 		assert(rtype(i->to) == RTmp);
 		t = &fn->tmp[i->to.val];
+		k = -1;
+		s = -1;
 		for (u=t->use; u != &t->use[t->nuse]; u++) {
 			if (u->type != UIns)
-				goto NextIns;
+				goto Skip;
 			l = u->u.ins;
-			if (!isload(l->op)
-			&& (!isstore(l->op) || req(i->to, l->arg[0])))
-				goto NextIns;
+			if (isload(l->op))
+			if (s == -1 || s == loadsz(l)) {
+				s = loadsz(l);
+				continue;
+			}
+			if (isstore(l->op))
+			if (req(i->to, l->arg[1]) && !req(i->to, l->arg[0]))
+			if (s == -1 || s == storesz(l))
+			if (k == -1 || k == opdesc[l->op].argcls[0][0]) {
+				s = storesz(l);
+				k = opdesc[l->op].argcls[0][0];
+				continue;
+			}
+			goto Skip;
 		}
 		/* get rid of the alloc and replace uses */
 		*i = (Ins){.op = ONop};
@@ -40,39 +71,34 @@ memopt(Fn *fn)
 		for (u=t->use; u!=ue; u++) {
 			l = u->u.ins;
 			if (isstore(l->op)) {
-				if (l->op == OStores)
-					l->cls = Kd;
-				else if (l->op == OStored)
-					l->cls = Kd;
-				else if (l->op == OStorel)
-					l->cls = Kl;
-				else
-					l->cls = Kw;
+				l->cls = k;
 				l->op = OCopy;
 				l->to = l->arg[1];
 				l->arg[1] = R;
 				t->nuse--;
 				t->ndef++;
-			} else
+			} else {
+				if (k == -1)
+					err("slot %%%s is read but never stored to",
+						fn->tmp[l->arg[0].val].name);
 				/* try to turn loads into copies so we
 				 * can eliminate them later */
 				switch(l->op) {
 				case OLoad:
-					l->op = OCopy;
-					break;
 				case OLoadsw:
 				case OLoaduw:
-					l->cls = Kw;
-					l->op = OCopy;
+					if (KBASE(k) != KBASE(l->cls))
+						l->op = OCast;
+					else
+						l->op = OCopy;
 					break;
 				default:
-					/* keep l->cls */
-					a = l->op - OLoadsb;
-					l->op = OExtsb + a;
+					l->op = OExtsb + (l->op - OLoadsb);
 					break;
 				}
+			}
 		}
-	NextIns:;
+	Skip:;
 	}
 	if (debug['M']) {
 		fprintf(stderr, "\n> After memory optimization:\n");