runRW# ruins join points
Found this while poking around in the example for #12781 (closed). Suppose we have code like this:
let loop :: Int -> State# RealWorld -> (State# RealWorld, Int)
loop n = ... loop (n+1) {- tail call -} ...
in runRW# @ 'PtrRepLifted @ Int (loop 0)
We would love for loop to be a join point, but it can't be because it's invoked in the argument to runRW#. In this situation, we're often rescued by Float In, which we might hope to give us this:
runRW# @ 'PtrRepLifted @ Int (
let loop :: Int -> State# RealWorld -> (State# RealWorld, Int)
loop n s = ... loop (n+1) s' {- tail call -} ...
in loop 0
)
Two problems:
- Float In won't do this to begin with because
loop 0is a partial application. - It's still not eligible to be a join point, again because
loop 0is a partial application.
What we would //like// to see is this:
runRW# @ 'PtrRepLifted @ Int (
\s0 ->
let loop :: Int -> State# RealWorld -> (State# RealWorld, Int)
loop n s = ... loop (n+1) s' {- tail call -} ...
in loop 0 s0
)
Now we're golden. But someone has to have thought to eta-expand the argument to runRW# first. (Float In should then float loop into the lambda because, due to the state hack, the lambda is considered one-shot.)
Perhaps the simplifier should //always// eta-expand the argument to runRW#?
Trac metadata
| Trac field | Value |
|---|---|
| Version | 8.1 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture |