aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/ir_mem2reg.c6
-rw-r--r--test/18-goto2.c24
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");
+}