[GHC] #8598: IO hack in demand analyzer gets in the way of CPR
GHC
ghc-devs at haskell.org
Fri Dec 6 14:40:09 UTC 2013
#8598: IO hack in demand analyzer gets in the way of CPR
-------------------------------------+------------------------------------
Reporter: nomeata | Owner:
Type: task | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 7.6.3
Resolution: | Keywords:
Operating System: Unknown/Multiple | Architecture: Unknown/Multiple
Type of failure: None/Unknown | Difficulty: Unknown
Test Case: | Blocked By:
Blocking: | Related Tickets:
-------------------------------------+------------------------------------
Comment (by nomeata):
Mail from SPJ:
Well spotted. I'm on a train, hence email response. Maybe you can paste
this into the ticket?
There are two different issues here.
'''First''', `isDoubleFinite` is declared as non-side-effecting:
{{{
foreign import ccall unsafe "isDoubleFinite" isDoubleFinite :: Double ->
Int
}}}
But (as you can see from the code you give) we currently desugar it into
something that looks (to Core) as though it might have a side effect, or
raise a (synchronous) exception. That is stupid.
How might we fix that? I can think of two ways.
* Generate a `FCallId` whose type is `Double -> Int` rather than (as now)
`Double -> IO Int`. There would be a few knock-on consequences to make
sure they were correctly code-generated. I like this path best, because
it reflects the truth.
* Currently
{{{
IO a = State# RealWorld# -> (# State# RealWorld#, a #)
}}}
For these non-side-effecting things we could instead generate a
`FCallId` with a type involving `SafeIO` instead of `IO`:
{{{
SafeIO a = State# SafeWorld# -> (# State# SafeWorld#, a #)
}}}
The different "world token" would express the idea that the function
can't throw an exception.
I don't like this as much, but it might in any case be useful for things
that ''do'' have side effects but ''don't'' throw exceptions.
My preference is for the first.
'''Second''', as you point out, consider
{{{
f x = do { when (x>3) exit
; return (True, False) }
}}}
Function `f` might throw an exception or exit rather than returning, but
''if it does return'' it will certainly have the CPR property. So yes,
CPR-ness is quite safe.
It's not quite so obvious for divergence:
{{{
g x = do { when (x>3) exit
; g x }
h 0 y = y
h x y = g x
}}}
Is `h` strict in `y`? You might say (reasonably) that we can ignore the
possible IO exception/exit in `g` when figuring out that `g` is sure to
diverge. If so, we'd say that `h` is strict in `y`. But if `(x>3)` then
really `y` is not evaluated... and spotting that is exactly what the IO
hack in the demand analyser is spotting. So I think it is ''not'' safe to
propagate divergence information.
In short, CPR info yes, guaranteed-divergence no.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/8598#comment:2>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list