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 |