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
foois 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
fmay 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 |
Edited by Sebastian Graf