瀏覽代碼

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.
Quentin Carbonneaux 3 年之前
父節點
當前提交
15e25a61b3
共有 1 個文件被更改,包括 15 次插入3 次删除
  1. 15 3
      mem.c

+ 15 - 3
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];