aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2026-03-22 11:20:14 +0100
committerlemon <lsof@mailbox.org>2026-03-22 11:21:01 +0100
commitadf244459ef6946c2050764906357a4ec4010b3f (patch)
tree25b577bfd5dee23329570e5acd7dadf191650843
parentf9e3a52eaa6ae91388aa247182da6df3cc8d5a05 (diff)
mem2reg: improve on f9e3a52eaa
Move the alloca to the beginning of the block and do a 2nd pass on those odd cases.
-rw-r--r--src/ir_mem2reg.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/ir_mem2reg.c b/src/ir_mem2reg.c
index 043ac9b..b3e6e73 100644
--- a/src/ir_mem2reg.c
+++ b/src/ir_mem2reg.c
@@ -241,7 +241,10 @@ mem2reg(Function *fn)
sortrpo(fn);
Block *blk = fn->entry;
+ bool again = 0, neveragain = 0;
+Again:
do {
+ if (!neveragain || blk == fn->entry)
for (int i = 0; i < blk->ins.n; ++i) {
enum irclass k = 0;
int sz = 0;
@@ -257,10 +260,16 @@ mem2reg(Function *fn)
do {
if (use->u == USERJUMP) goto Skip;
Instr *m = &instrtab[use->u];
- if (use->blk->id < sb.lastvisit) {
- /* alloca appears after some of its uses; happens rarely, only
+ if (use->blk->id < blk->id) {
+ assert(!neveragain);
+ /* alloca appears after some of its uses; happens rarely, like
* generated with code with gotos into loops. breaks this algo
* due to reprocessing sealed blocks */
+ /* move to entry block and reprocess later */
+ vpush(&fn->entry->ins, var);
+ extern int allocinstr(void);
+ instrtab[blk->ins.p[i] = allocinstr()] = (Instr){Onop};
+ again = 1;
goto Skip;
}
if (oisload(m->op) && (!sz || sz == loadsz(m->op))) {
@@ -305,6 +314,13 @@ mem2reg(Function *fn)
++sb.lastvisit;
tryseal(&sb, blk);
} while ((blk = blk->lnext) != fn->entry);
+ if (again) {
+ memset(sb.sealed, 0, BSSIZE(fn->nblk) * sizeof *sb.sealed);
+ neveragain = 1;
+ sb.lastvisit = 0;
+ again = 0;
+ goto Again;
+ }
do {
/* remove phis marked for deletion */