CAFs lose sharing due to implicit call stacks
The implicit call stack machinery adds a constraint to CAFs, which loses sharing in some cases. The regression is fixed by -O (actually -ffull-laziness
), but it is surprising nonetheless, and might cause problems for people using GHCi or other places where -O is turned off.
For example:
{-# LANGUAGE NoMonomorphismRestriction #-}
module Main where
import System.Environment
fib :: Integer -> Integer
fib n = if n < 2 then 1 else fib (n-1) + fib (n-2)
x = if fib 3 > 20 then error "x" else fib 30
main = do
[n] <- getArgs
case n of
"a" -> print (x + x)
"b" -> print x
Try it as follows (requires 8.0+):
$ ghc imp.hs -fforce-recomp -O -fno-full-laziness
$ ./imp a +RTS -t
2692538
<<ghc: 430859568 bytes, 822 GCs, 36580/44384 avg/max bytes residency (2 samples), 1M in use, 0.000 INIT (0.000 elapsed), 0.156 MUT (0.203 elapsed), 0.018 GC (0.009 elapsed) :ghc>>
$ ./imp b +RTS -t
1346269
<<ghc: 215456192 bytes, 411 GCs, 36580/44384 avg/max bytes residency (2 samples), 1M in use, 0.000 INIT (0.000 elapsed), 0.073 MUT (0.119 elapsed), 0.008 GC (0.004 elapsed) :ghc>>
With GHC 7.10 and earlier both commands perform the same.
Note that this only uses error
, and doesn't require ImplicitParams
. It does require NoMonomorphismRestriction
, however.
Trac metadata
Trac field | Value |
---|---|
Version | 8.0.1-rc1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | simonpj |
Operating system | |
Architecture |