Strictness analyser missing useful strictness
Roman Beslik (beroal@ukr.net) writes: I provide a sample program which causes a strange behavior of strictness analyzer.
variant 1
module StrictUnusedArg (main) where
f2 :: Int -> Int -> Int
f2 x1 = if x1 == 0 then (\x0 -> x0) else let
y = x1 - 1
in f3 y y
f3 :: Int -> Int -> Int -> Int
f3 x2 = if x2 == 0 then f2 else let
y = x2 - 1
in f4 y y
f4 :: Int -> Int -> Int -> Int -> Int
f4 x3 = if x3 == 0 then f3 else let
y = x3 - 1
in \x2 x1 x0 -> f4 y x2 x1 (y + x0)
main = print (f2 100 0)
I expect that all arguments will be unboxed. "-ddump-simpl" reveals that actually types are
f2 :: Int# -> Int -> Int
f3 :: Int# -> Int -> Int -> Int
So when "f3" calls "f2" it unboxes the argument named "x1" and when "f2" calls "f3" it boxes the argument named "x1". "-ddump-stranal" knows strictness only for the "x2" of "f3" and "x1" of "f2".
f2:
[Arity 1
Str: DmdType U(L)]
f3:
[Arity 1
Str: DmdType U(L)]
I also can force the analyzer to think that "x1" and "x0" are strict by eta-expanding "f3": variant 2
f3 x2 x1 x0 = if x2 == 0 then f2 x1 x0 else let
y = x2 - 1
in f4 y y x1 x0
"-ddump-stranal" yields:
f3:
[Arity 3
Str: DmdType U(L)U(L)U(L)m]
f2:
[Arity 2
Str: DmdType U(L)U(L)m]
I even do not use ($!). So, the questions: Is it possible to change the strictness analyzer so it will treat "variant 1" as "variant 2"? Are these changes big?
Compiled with options:
$ ghc --make -fstrictness -fPIC -O3 -fforce-recomp blah-blah-blah
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.12.1
Trac metadata
Trac field | Value |
---|---|
Version | 6.12.1 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |