From b2a25215fcc71c86e0120c7bac14f679b70a3a3c Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Mon, 25 Oct 2021 13:39:20 +0200 Subject: 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. --- spill.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'spill.c') diff --git a/spill.c b/spill.c index baceccc..4c11d9f 100644 --- 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 */ -- cgit 1.4.1