Skip to content

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 for foo.
  • The wrapper currently gets an aciviation of "active only in phase 0"; see Note [Wrapper activation] in WorkWrap.
  • 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
Edited by Sebastian Graf
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information