* cranelift-frontend: Avoid quadratic behavior Fixes #4923. * Improve comments and debug assertions * Improve comments One thing that's especially neat about this PR is that, unlike the `can_optimize_var_lookup` graph traversal, `update_predecessor_cycle` doesn't need to keep track of all the blocks it has visited in order to detect cycles. However, the reasons why are subtle and need careful documentation. Also neat: We've previously tried keeping either a HashSet or a SecondaryMap around to re-use the same heap allocation for the `visited` set, which needs space linear in the number of blocks. After this PR, we're still using space that's linear in the number of blocks to store the `in_predecessor_cycle` flag, but that flag fits inside existing padding in `SSABlockData`, so it's a net savings in memory consumption. * Avoid quadratic behavior in `update_predecessor_cycle` So far I hadn't really eliminated the quadratic behavior from `can_optimize_var_lookup`. I just moved it to happen when the CFG is modified instead, and switched to indexing directly into the vector of blocks instead of going through a HashSet. I suspect the latter change is always a win, but the former is only an improvement assuming that `use_var` is called more often than `declare_block_predecessor`. But @cfallin pointed out that it feels like we should be able to do better by taking advantage of the knowledge that once a block is sealed, its predecessors can't change any more. That's not completely trivial to do because changes to the property we care about propagate toward successors, and we're only keeping pointers to predecessors. Still, as long as frontends follow the existing recommendation to seal blocks as soon as possible, maintaining a conservative approximation using only local information works fine in practice. This significantly limits the situations where this graph traversal could visit a lot of the CFG. * Review comments
This crate provides a straightforward way to create a
Cranelift IR function and fill it with
instructions translated from another language. It contains an SSA construction
module that provides convenient methods for translating non-SSA variables into
SSA Cranelift IR values via use_var and def_var calls.