diff options
| -rw-r--r-- | src/ir_mem2reg.c | 6 | ||||
| -rw-r--r-- | test/18-goto2.c | 24 |
2 files changed, 30 insertions, 0 deletions
diff --git a/src/ir_mem2reg.c b/src/ir_mem2reg.c index ae41833..043ac9b 100644 --- a/src/ir_mem2reg.c +++ b/src/ir_mem2reg.c @@ -257,6 +257,12 @@ 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 + * generated with code with gotos into loops. breaks this algo + * due to reprocessing sealed blocks */ + goto Skip; + } if (oisload(m->op) && (!sz || sz == loadsz(m->op))) { sz = loadsz(m->op); k = loadcls(m->op); diff --git a/test/18-goto2.c b/test/18-goto2.c new file mode 100644 index 0000000..8742d35 --- /dev/null +++ b/test/18-goto2.c @@ -0,0 +1,24 @@ +/* EXPECT: +ok +*/ + +void h(int x){} + +/* isolated mem2reg bug from something in regalloc: the goto into the loop past + * the `int nqueue` declaration caused a miscompilation */ +void test(void) { + int curi = 5; + goto start2; + for (curi; curi >= 0; curi--) { + int nqueue; + start2: + for (nqueue = 2; nqueue > 0; ) { + h(nqueue--); + } + } +} +int puts(const char *); +int main(void) { + test(); + puts("ok"); +} |