commit 15e25a61b38b250c7543437a093a9efe076cce0a
parent c5ea06c1360a7bb93cf1a5303f804855a38a82ef
Author: Quentin Carbonneaux <quentin@c9x.me>
Date: Tue, 13 Dec 2022 11:34:20 +0100
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.
Diffstat:
M | mem.c | | | 18 | +++++++++++++++--- |
1 file changed, 15 insertions(+), 3 deletions(-)
diff --git 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];