You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* Simplify parallel-moves state machine
Using a three-state enum instead of visited/onstack bools makes the
state transitions easier to reason about.
Also note that the behavior was the same for two cases ("there is no
next move", and "the next move has already been emitted"), so I merged
them.
This commit also cuts memory usage in half for the must_come_before
array and for the visited/onstack arrays.
* Simplify cycle-handling in parallel moves
The loop as previously written was guaranteed to run at least once and
the first iteration was quite different than later iterations, so peel
off the first iteration.
That in turn made it clear that scratch_src is always set, which allowed
simplifying emitting the final scratch-register move.
One thing which was tricky is that if the existing implementation was
handed a move of an allocation into itself, then it would previously
emit a move from that allocation to the scratch register followed by a
move from the scratch register back to the allocation. Peeling the first
iteration out of the loop made it a little trickier to ensure that the
loop didn't run at all in that case, but also emitting any moves is a
silly result.
So instead I've filtered out self-moves before starting the depth-first
traversal. Ideally we'd do this before checking whether the sources
overlap the destinations, since if the only overlaps are self-moves then
we can just return the original move list. However it should happen
after the debug assertion that there is at most one writer to each
allocation, since the input is malformed if there's both a self-move and
another move to the same allocation. After #157 lands this can be
re-ordered.
Because I'm filtering out self-moves and then running the depth-first
traversal, if all of the moves were self-moves then we may try to
traverse an empty graph. This was easily fixed by not blindly pushing
indices onto the stack, and instead letting the existing check for
un-visited moves fire because the stack is empty.
* Use more idiomatic while-let loops
0 commit comments