qbe

Internal scc patchset buffer for QBE
Log | Files | Refs | README | LICENSE

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:
Mmem.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];