The symbolic checker currently works by tracking a single symbolic vreg label for each "alloc" (physical register or stack slot). On definition of a vreg into an alloc, the label is updated to the new vreg's name. This worked quite well when the regalloc was simpler, but in the presence of redundant move elimination, it started to become apparent that the analysis has a shortcoming: when multiple vregs have the same value, and the regalloc has deduced this, it can make use of an alloc that is labeled with one vreg but use it as another vreg and the checker will not validate the use. In other words, the regalloc became smart enough to avoid emitting unnecessary moves, but the checker was relying on those moves to know the most up-to-date symbolic name for a value in a physical location. In a sense, a register or stackslot can contain *both* vreg1 and vreg2, and the regalloc can use it as either. The stopgap measure of emitting more DefAllocs as part of the redundant move elimination never quite sat right with me. It works, but it's asking too much of the regalloc to prove why its moves are correct. We should rely less on the regalloc and on complex built-just-for-the-checker plumbing; we should instead improve the checker so that it can prove on its own that the result is correct. This PR modifies the checker so that its basic abstraction for an alloc's value is a *set* of virtual register labels, rather than just one. The transfer function is a little more complex, but manageable: a move keeps the old label(s) and adds a new one; redefining a vreg into one alloc needs to remove that vreg label from all other alloc's sets. This completely removes the need for metadata from the regalloc (!); all we need is the original program (pre-alloc, with vregs), the set of allocations, and the set of inserted moves, and we can validate the result. This should mean that we trust our checker-validated allocation results more, and should result in less complexity and maintenance going forward if we improve the allocator further.
regalloc2: another register allocator
This is a register allocator that started life as, and is about 50% still, a port of IonMonkey's backtracking register allocator to Rust. In many regards, it has been generalized, optimized, and improved since the initial port, and now supports both SSA and non-SSA use-cases.
In addition, it contains substantial amounts of testing infrastructure (fuzzing harnesses and checkers) that does not exist in the original IonMonkey allocator.
See the design overview for (much!) more detail on how the allocator works.
License
This crate is licensed under the Apache 2.0 License with LLVM
Exception. This license text can be found in the file LICENSE.
Parts of the code are derived from regalloc.rs: in particular,
src/checker.rs and src/domtree.rs. This crate has the same license
as regalloc.rs, so the license on these files does not differ.