
#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
Keywords: | Operating System: Unknown/Multiple
Architecture: Unknown/Multiple | Type of failure: None/Unknown
Difficulty: Unknown | Test Case:
Blocked By: | Blocking:
Related Tickets: |
------------------------------------+-------------------------------------
After a lot of staring at code and comparing unexpected nofib results I
found the following:
The IO hack in the demand analyzer (see `dmdAnalAlt` in `StrAnal.lhs` and
#1592 for a good discussion) prevents CPR in any function that uses a C
call. This is a small example, reduced from the `scaleFloat` method for
doubles:
{{{
module Float(fun) where
import GHC.Float (Double(..))
import GHC.Integer (decodeDoubleInteger, encodeDoubleInteger)
fun :: Double -> Double
fun x | isFix = x
| otherwise = case x of
(D# x#) -> case decodeDoubleInteger x# of
(# i, j #) -> D# (encodeDoubleInteger i j)
where
isFix = isDoubleFinite x == 0
foreign import ccall unsafe "isDoubleFinite" isDoubleFinite :: Double ->
Int
}}}
Here, `fun` does current not get the CPR property, and the work gets type
`GHC.Prim.Double# -> GHC.Types.Double`. Why? Because in core, there will
be a
{{{
case {__pkg_ccall main isDoubleFinite GHC.Prim.Double#
-> GHC.Prim.State# GHC.Prim.RealWorld
-> (# GHC.Prim.State# GHC.Prim.RealWorld,
GHC.Prim.Int# #)}_dQD
ds_dQA GHC.Prim.realWorld#
of _ [Occ=Dead, Dmd=] #) ->
...
}}}
where the case body has `DmdType m {dQz->