Issues resulting from inlining build

David Feuer david.feuer at gmail.com
Sun Jul 27 19:29:01 UTC 2014


I think I finally figured out the deeper problem behind an issue I was
having getting some things to fuse fully. I'm hoping someone has a
brilliant idea for getting around it. Of course, it may be that someone
else has thoroughly studied the matter and determined that there's no good
solution. Suppose we write

crazy :: T -> [U]
crazy x = some $ long $ fusion $ pipeline

oops f = map f $ crazy x
uhOh c n = foldr c n $ crazy Pig
ohMy = take bignum $ crazy amigo

When GHC compiles crazy, it rewrites the pieces of the pipeline to
build/foldr forms, fuses them, and produces

crazy x = build someBigFunction

In then inlines build, producing

crazy x = anotherBiggy

So far, this looks reasonably sensible, but it's likely bad. The problem is
that GHC will (rightly) conclude that `build someBigFunction` is too big to
inline, and therefore the fusion will break at that boundary and we'll
produce intermediate lists in the functions that use crazy. Now if we were
playing the part of the compiler by hand, we would likely factor out
someBigFunction and then *refrain from inlining build*. That is, we would
get

{-# NOINLINE crazyB #-}
crazyB x = someBigFunction

crazy = nonInliningBuild crazyB

Since we've factored out someBigFunction into crazyB, we can now safely
inline crazy itself, allowing the pipeline to continue beyond it. The
problem, of course, is that when we *don't* fuse beyond, there is some
performance penalty (I have not tried to measure it yet) to passing in (:)
and [] at runtime instead of fixing them at compile time.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://www.haskell.org/pipermail/libraries/attachments/20140727/be87a9d8/attachment.html>


More information about the Libraries mailing list