The general idea is: * Run copy prop initially, save the copy prop state. * Unroll one iteration, substitute all jumps by stores to synthetic control vars, move all instructions after the jumps to checks to those control vars. * Run copy prop on the iteration, using the previous iteration's or the root's state as the parent state. * Probe the copy prop state to check if the "loop_broken" control variable was set, stop unrolling if it true, otherwise continue.
Some stuff I'm less sure about and would love comments on: * The way I deferred bounds checking. * Splitting the iter block from the body. This was needed because otherwise copy prop marks variable that are changed in iter blocks (e.g "i++") as invalidated and does not propagate them to subsequent iterations. * Messing around with copy prop internals. I attempted two other similar solutions that were less invasive: running copy prop on the entire block after each unroll and running copy prop once, after unrolling to `max_iterations`, both were too slow to be viable.