Skip to content

Don't float unlifted join points to top level

Ben Gamari requested to merge wip/T16978 into master

Ticket #16978 (closed) showed that we were floating a recursive, unlifted join point to top level. It's very much a corner case:

joinrec j :: Int#
        j = jump j
in ...

But somehow it showed up in a real program.

For non-recursive bindings in SetLevels.lvlBind we were already (correctly) checking for unlifted bindings, but when I wrote that code I didn't think that a /recursive/ binding could be unlifted but /join-points/ can be!

Actually I don't think that SetLevels should be floating join points at all. SetLevels really floats things to move stuff out of loops and save allocation; but none of that applies to join points. The only reason to float join points is in cases like join j1 x = join j2 y = ... in ... which we might want to swizzle to join j2 x y = ... in join j1 x = ... in ... because now j1 looks small and might be inlined away altogether. But this is a very local float perhaps better done in the simplifier.

Still: this patch fixes the crash, and does so in a way that is harmless if/when we change our strategy for floating join points.

Merge request reports