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 0
is a partial application. - It's still not eligible to be a join point, again because
loop 0
is 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 |