diff options
| author | 2026-03-22 11:20:14 +0100 | |
|---|---|---|
| committer | 2026-03-22 11:21:01 +0100 | |
| commit | adf244459ef6946c2050764906357a4ec4010b3f (patch) | |
| tree | 25b577bfd5dee23329570e5acd7dadf191650843 | |
| parent | f9e3a52eaa6ae91388aa247182da6df3cc8d5a05 (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.c | 20 |
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 */ |