summary refs log tree commit diff
path: root/lisc/mem.c
diff options
context:
space:
mode:
Diffstat (limited to 'lisc/mem.c')
-rw-r--r--lisc/mem.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/lisc/mem.c b/lisc/mem.c
new file mode 100644
index 0000000..bfc8218
--- /dev/null
+++ b/lisc/mem.c
@@ -0,0 +1,71 @@
+#include "lisc.h"
+
+/* Memory optimization:
+ *
+ * - replace alloced slots used only in
+ *   load/store operations
+ */
+
+/* require use, maintains use counts */
+void
+memopt(Fn *fn)
+{
+	Blk *b;
+	Ins *i, *l;
+	Tmp *t;
+	Use *u, *ue;
+	int a;
+
+	b = fn->start;
+	for (i=b->ins; i-b->ins < b->nins; i++) {
+		if (OAlloc > i->op || i->op > OAlloc1)
+			continue;
+		assert(NAlign == 3);
+		assert(rtype(i->to) == RTmp);
+		t = &fn->tmp[i->to.val];
+		for (u=t->use; u != &t->use[t->nuse]; u++) {
+			if (u->type != UIns)
+				goto NextIns;
+			l = u->u.ins;
+			if (l->op < OStorel || l->op > OStoreb)
+			if (l->op < OLoad || l->op > OLoad1)
+				goto NextIns;
+		}
+		/* get rid of the alloc and replace uses */
+		*i = (Ins){.op = ONop};
+		t->ndef--;
+		ue = &t->use[t->nuse];
+		for (u=t->use; u != ue; u++) {
+			l = u->u.ins;
+			if (OStorel <= l->op && l->op <= OStoreb) {
+				l->wide = (l->op == OStorel);
+				l->op = OCopy;
+				l->to = l->arg[1];
+				l->arg[1] = R;
+				t->nuse--;
+				t->ndef++;
+			} else
+				switch(l->op) {
+				case OLoad+Tl:
+					l->wide = 1;
+					l->op = OCopy;
+					break;
+				case OLoad+Tsw:
+				case OLoad+Tuw:
+					l->wide = 0;
+					l->op = OCopy;
+					break;
+				default:
+					/* keep l->wide */
+					a = l->op - OLoad;
+					l->op = OExt + a;
+					break;
+				}
+		}
+	NextIns:;
+	}
+	if (debug['M']) {
+		fprintf(stderr, "\n> After memory optimization:\n");
+		printfn(fn, stderr);
+	}
+}