summary refs log tree commit diff
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin@c9x.me>2022-12-13 11:34:20 +0100
committerQuentin Carbonneaux <quentin@c9x.me>2022-12-14 23:05:35 +0100
commit15e25a61b38b250c7543437a093a9efe076cce0a (patch)
tree51708b5c1a4a3503fe09061bf7663b14f771eb1a
parentc5ea06c1360a7bb93cf1a5303f804855a38a82ef (diff)
downloadroux-15e25a61b38b250c7543437a093a9efe076cce0a.tar.gz
fix coalesce() to produce valid ssa
When multiple stack slots are coalesced
one 'alloc' instruction is kept in the il
and the other ones are removed and have
their uses replaced by the result of the
selected one. To produce valid ssa, it
must be ensured that the uses that get
replaced are dominated by the selected
'alloc' instruction. This patch ensures
dominance by moving the selected alloc up
in the start block as necessary.
-rw-r--r--mem.c18
1 files changed, 15 insertions, 3 deletions
diff --git a/mem.c b/mem.c
index a574e1f..7570f19 100644
--- a/mem.c
+++ b/mem.c
@@ -197,7 +197,7 @@ coalesce(Fn *fn)
 	Blk *b, **ps, *succ[3];
 	Ins *i;
 	Use *u;
-	Tmp *t;
+	Tmp *t, *ts;
 	Ref *arg;
 	bits x;
 	int n, m, nsl, ip, *stk;
@@ -213,6 +213,7 @@ coalesce(Fn *fn)
 		t->visit = -1;
 		if (t->alias.type == ALoc)
 		if (t->alias.slot == &t->alias)
+		if (t->bid == fn->start->id)
 		if (t->alias.u.loc.sz != -1) {
 			t->visit = nsl;
 			vgrow(&sl, ++nsl);
@@ -356,11 +357,22 @@ coalesce(Fn *fn)
 
 	/* substitute fused slots */
 	for (s=sl; s<&sl[nsl]; s++) {
-		if (s->s == s)
-			continue;
 		t = &fn->tmp[s->t];
 		assert(t->ndef == 1 && t->def);
+		if (s->s == s)
+			continue;
 		*t->def = (Ins){.op = Onop};
+		ts = &fn->tmp[s->s->t];
+		assert(t->bid == ts->bid);
+		if (t->def < ts->def) {
+			/* make sure the slot we
+			 * selected has a def that
+			 * dominates its new uses
+			 */
+			*t->def = *ts->def;
+			*ts->def = (Ins){.op = Onop};
+			ts->def = t->def;
+		}
 		for (u=t->use; u<&t->use[t->nuse]; u++) {
 			if (u->type == UJmp) {
 				b = fn->rpo[u->bid];