Repository navigation
Conversation
hhugo
force-pushed
the
pr4e-register-allocation
branch
from
September 20, 2026 21:37
3a9714d to
6294953
Compare
hhugo
force-pushed
the
pr4e-register-allocation
branch
2 times, most recently
from
September 28, 2026 22:21
1387b90 to
746dc10
Compare
This was referenced Sep 30, 2026
[compiled] gains [cell_of_tag], the memory cell holding each logical tag once a rule has matched, and [compile_ir] expresses the bindings in cells. It is the identity for now: a tag's canonical cell has the tag's number. The register allocation of the next commit shares cells between tags. [gen_definition] takes the automaton and the cell count instead of a [compiled] record it had to be given a copy of. Generated code is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
The construction gives every tag write a fresh register and copies the accepting path's registers into canonical cells: two cells per tag and a copy per tag on every accept. A register allocation pass now maps registers and canonical cells onto memory cells. Two cells may share a memory cell unless one is written while the other is live. Liveness is a backward analysis over the automaton; operation lists are parallel moves, and a failure in a state reads the canonical cells of the rules that may be marked there, i.e. those with an accepting state from which it is reachable through non-accepting states. Cells that do not interfere are merged where that removes an operation, a register with the canonical cell of its tag and the two sides of a copy, and the classes are colored greedily. Liveness also shows which writes are dead, e.g. those of a rule that a higher-priority rule always beats: they are dropped first, repeatedly, since dropping a copy may make its source dead. Most tags end up with one cell written directly by the transitions and no final copy; a tag keeps a register apart from its canonical cell exactly when sharing would corrupt a value read later: two live paths disagreeing about it, a write between the mark of its rule and a failure, or an accepting path setting it while another path holds it. Tags of different rules share cells when their lifetimes allow, so [cell_of_tag] is no longer the identity. Over test/codegen/test_gen.ml: copies 21 -> 0, cells 42 -> 21. Realistic lexer: copies 2 -> 0, cells 4 -> 1. Every captured value pinned in test/basic.ml is unchanged. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
A codegen test for the dead writes of a rule that never wins, and codegen tests for three shapes where a tag needs a second cell: two live starts for one capture, a tag recorded again after an accepting state of its rule on the way to a possible failure, and a tag that an accepting path sets while another path holds it. Behaviour tests pin the sub-matches of the last shape, and those of rules whose tags share cells, including after falling back from one rule to another. The Current/Goal notes of the optimization-tracking tests record one cell per tag and the cells shared across rules. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
hhugo
force-pushed
the
pr4e-register-allocation
branch
from
October 5, 2026 15:05
746dc10 to
a96fb86
Compare
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Register allocation for the tagged DFA, from liveness and interference. Stacked on #209 (base: the
pr4d-tdfa1branch), three commits. An alternative to #207 that also covers what #175 set out to do; only one of #207 and this PR should land.After #204 every tag write gets a fresh register and every accepting state copies the accepting path's registers into canonical cells: two cells per tag and a copy per tag on accept. This pass maps registers and canonical cells onto memory cells with one criterion: two cells may share a memory cell unless one is written while the other is live.
The three special cases #207 needs fall out of the criterion: two live paths disagreeing about a tag, a write between the mark of a rule and a failure, an accepting path setting a tag another path holds. So does #175's cross-rule sharing, so
compiledgainscell_of_tagandcompile_irexpresses the bindings in cells.test_gen.ml(common tests): copiestest_gen.ml: cellsEvery captured value pinned in
test/basic.mlis unchanged.Commits
cell_of_tagplumbing, identity for now; generated code unchanged.src/compiler/sedlex.ml).Verification
The #202 oracle, run locally with the TDFA(1) interpreter and no cell snapshot: no disagreement on the hand-written cases nor on 6M random cases (half of them two-rule, which is what exercises sharing), and again on 3M after adding dead-write elimination. With the "a failure reads the marked rule's cells" part of liveness removed, the same sweep finds wrong captures.
🤖 Generated with Claude Code