Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
The primary idea of the new iteration protocol is that for a function like: ``` function iterate(itr) done(itr) ? nothing : next(itr) end ``` we can fuse the `done` comparison into the loop condition and recover the same loop structure we had before (while retaining the flexibility of not requiring the done function to be separate), i.e. for ``` y = iterate(itr) y === nothing && break ``` we want to have after inlining and early optimization: ``` done(itr) && break y = next(itr) ``` LLVM performs this optimization in jump threading. However, we run into a problem. At the top of the loop we have: ``` y = iterate top: %cond = y === nothing br i1 %cond, %exit, %loop .... ``` We'd want to thread over the `top` block (this makes sense, since by the discussion above, we need to merge our condition into the loop exit condition). However, LLVM (quite sensibly) refuses to thread over loop headers and since `top` is both a loop header and a loop exit, we fail to perform the appropriate transformation. However, there's a simple fix. Instead of emitting a foor loop as ``` y = iterate(itr) while y !== nothing x, state = y ... y = iterate(itr, state) end ``` we can emit it as ``` y = iterate(itr) if y !== nothing while true x, state = y ... y = iterate(itr, state) y === nothing && break end end ``` This transformation is known as `loop inversion` (or a special case of `loop rotation`. In our case the primary benefit is that we can fuse the condition contained in the initial `iterate` call into the bypass if, which then lets LLVM understand our loop structure. Co-authored-by: Jeff Bezanson <jeff@juliacomputing.com>
- Loading branch information