Skip to content

Commit

Permalink
Jump via ret*: labels to a single stop:
Browse files Browse the repository at this point in the history
This keeps the phi node constant size wrt the number of basic blocks.

I'm very proud of this idea.
  • Loading branch information
katef committed Jul 3, 2024
1 parent b11d542 commit 0ae60db
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 16 deletions.
69 changes: 56 additions & 13 deletions src/libfsm/print/llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@ print_decl(FILE *f, const char *name, unsigned n)
fprintf(f, "\t%%%s%u = ", name, n);
}

static void
print_ret(FILE *f, long l)
{
fprintf(f, "\tret i32 %ld\n", l);
}

static void
vprint_label(FILE *f, bool decl, const char *fmt, va_list ap)
{
Expand Down Expand Up @@ -528,23 +522,72 @@ fsm_print_llvmfrag(FILE *f, const struct dfavm_assembler_ir *a,

print_jump(f, a->linked);

print_label(f, true, "fail");
print_ret(f, -1);

/*
* We're jumping to ret*: labels, and having each jump
* to a single stop: with a phi instruction.
*
* This looks like:
*
* stop:
* %ret = phi i32
* [u0x1, %ret0], ; "abc"
* [u0x2, %ret1], ; "xyz"
* [u0x3, %ret2], ; "abc", "xyz"
* [-1, %fail]
* ret i32 %ret
* fail:
* br label %stop
* ret0:
* br label %stop
* ret1:
* br label %stop
* ret2:
* br label %stop
*
* And we jump to stop: via the ret*: labels rather than
* to a phi node directly. This helps for two reasons:
*
* - We don't need to track every location in the DFA
* that can stop. In other words, many basic blocks
* jump to the same ret*: label.
*
* - The number of basic blocks grows quadratically
* (as DFA grow quadratically), but the set of endids
* remains constant. So the phi list is small.
*
* llvm doesn't find this optimisation for us.
*/
print_label(f, true, "stop");
fprintf(f, "\t%%ret = phi i32\n");
for (size_t i = 0; i < retlist.count; i++) {
fprintf(f, "\t ");

if (opt->endleaf != NULL) {
print_label(f, true, "ret%zu", i);
if (-1 == opt->endleaf(f,
retlist.a[i].ids, retlist.a[i].count,
opt->endleaf_opaque))
&i)) // XXX: passing &i rather than opt->endleaf_opaque is a hack
{
return -1;
}
} else {
print_label(f, true, "ret%zu", i);
print_ret(f, retlist.a[i].ir_state - ir->states);
fprintf(f, "[%td, %%ret%zu],\n",
retlist.a[i].ir_state - ir->states, i);
}
}
fprintf(f, "\t%s[-1, %%fail]\n", " ");
fprintf(f, "\tret i32 %%ret\n");

print_label(f, true, "fail");
fprintf(f, "\tbr ");
print_label(f, false, "stop");
fprintf(f, "\n");

for (size_t i = 0; i < retlist.count; i++) {
print_label(f, true, "ret%zu", i);
fprintf(f, "\tbr ");
print_label(f, false, "stop");
fprintf(f, "\n");
}
}

struct frame frame = { 0, 0, 0 };
Expand Down
7 changes: 4 additions & 3 deletions src/re/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -503,10 +503,11 @@ endleaf_llvm(FILE *f,
unsigned n;
size_t i;

assert(endleaf_opaque == NULL);
/* hack for llvm codegen only */
const size_t *ret = endleaf_opaque;
assert(ret != NULL);

(void) f;
(void) endleaf_opaque;

n = 0;

Expand All @@ -516,7 +517,7 @@ endleaf_llvm(FILE *f,
}
}

fprintf(f, "\tret i32 u%#x", (unsigned) n);
fprintf(f, "[u%#x, %%ret%zu],", (unsigned) n, *ret);

fprintf(f, " ; ");

Expand Down

0 comments on commit 0ae60db

Please sign in to comment.