Wrappers inlined too late
Consider these two modules
module Foo where
test :: Int -> Bool
test 0 = True
test n = test (n-1)
foo :: Foldable t => Int -> t Int -> Int
foo n xs | test n
= foldr (+) n xs
| otherwise
= n+7
and
module Bar where
import Foo
blam x = foo 3 [1..x]
If we simply inline foo
into blam
, we get foldr/build
fusion. And that is exactly what happens if you compile Foo
with -fno-strictness
.
But what actually happens is
- When compiling
Foo
, strictness analysis does worker/wrapper forfoo
. - The wrapper currently gets an aciviation of "active only in phase 0"; see
Note [Wrapper activation]
inWorkWrap
. - So
foo
is ultimately inlined (actually its worker is inlined too) but too late for fusion to take place.
This is bad: optimising Foo
makes the overall runtime increase.
I have seen other examples of this. The general pattern is:
- Without worker/wrapper, a function
f
may inline, which exposes opportunities for functions in its body to participate in rule rewrites - With worker/wrapper, no inlining happens until phase 0; and that is too late for the rules to fire.
Obvious thought: allow wrappers from strictness analysis to inline earlier. I'll try that.
Trac metadata
Trac field | Value |
---|---|
Version | 8.2.2 |
Type | Bug |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler |
Test case | |
Differential revisions | |
BlockedBy | |
Related | |
Blocking | |
CC | |
Operating system | |
Architecture |