qbe

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

commit b2a25215fcc71c86e0120c7bac14f679b70a3a3c
parent fd33b2ef25ff55217e229666c4d2f0877aac2515
Author: Quentin Carbonneaux <quentin@c9x.me>
Date:   Mon, 25 Oct 2021 13:39:20 +0200

spill: fix regs assertions

Some arm64 abi tests have been failing
for some time now. This fixes them by
being a bit more careful with liveset
management in spill.c.

A late bsclr() call in spill.c may drop
legitimately live registers in e.g.,

  R12 =w add R12, 1

While it hurts for regs, it does not
matter for ssa temps because those cannot
be both in the arguments & return (by the
ssa invariant). I added a check before
bsclr() to make sure we are clearing
only ssa temps.

One might be surprised that any ssa temp
may be live at this point. The reason why
this is the case is the special handling
of dead return values earlier in spill().
I think that it is the only case where
the return value can be (awkwardly) live
at the same time as the arguments, and I
think this never happens with registers
(i.e., we never have dead register-
assigning instructions). I added an
assert to check the latter invariant.

Finally, there was a simple bug in the
arm64 abi which I fixed: In case the return
happens via a pointer, x8 needs to be marked
live at the beginning of the function. This
was caught by test/abi4.ssa.

Diffstat:
Marm64/abi.c | 1+
Mspill.c | 6+++++-
2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/arm64/abi.c b/arm64/abi.c @@ -448,6 +448,7 @@ selpar(Fn *fn, Ins *i0, Ins *i1) if (cr.class & Cptr) { fn->retr = newtmp("abi", Kl, fn); emit(Ocopy, Kl, fn->retr, TMP(R8), R); + fn->reg |= BIT(R8); } } diff --git a/spill.c b/spill.c @@ -428,6 +428,7 @@ spill(Fn *fn) else { /* make sure we have a reg * for the result */ + assert(t >= Tmp0 && "dead reg"); bsset(v, t); bsset(w, t); } @@ -476,7 +477,10 @@ spill(Fn *fn) if (!req(i->to, R)) { t = i->to.val; store(i->to, tmp[t].slot); - bsclr(v, t); + if (t >= Tmp0) + /* in case i->to was a + * dead temporary */ + bsclr(v, t); } emiti(*i); r = v->t[0]; /* Tmp0 is NBit */