[GHC] #9434: GHC.List.reverse does not fuse
GHC
ghc-devs at haskell.org
Tue Sep 16 23:07:40 UTC 2014
#9434: GHC.List.reverse does not fuse
-------------------------------------+-------------------------------------
Reporter: dfeuer | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: | Version: 7.9
libraries/base | Keywords:
Resolution: | Architecture: Unknown/Multiple
Operating System: | Difficulty: Easy (less than 1
Unknown/Multiple | hour)
Type of failure: Runtime | Blocked By:
performance bug | Related Tickets:
Test Case: |
Blocking: |
Differential Revisions: |
-------------------------------------+-------------------------------------
Changes (by dfeuer):
* status: patch => new
Comment:
Letting `reverse` fuse with `foldr` generally seems to be causing more
than its fair share of problems, including issues relating to arity
analysis. I've been working today on different implementations of
`dropWhileEnd`. One I think seems particularly pleasant looks like this:
{{{#!hs
dropWhileEnd p xs = build (\c n -> foldr (dweFB p c) (const n) xs [])
{-# INLINE dropWhileEnd #-}
dweFB p c =
\x r trues ->
if p x
then r (x : trues)
else foldr c (x `c` r []) (reverse trues)
}}}
I tested this like so:
{{{#!hs
testDWE = foldl (*) 1 $ dropWhileEnd (>10) [1::Int .. 1000]
}}}
If `reverse` is prevented from fusing with `foldr`, this generates what
looks to me like very good code (note: if you're looking at the Core, that
inner `letrec` becomes a let-no-escape), generating far fewer conses and
boxes than the current implementation, even if that one is made `INLINE`.
If they're allowed to fuse, however, Call Arity fails to work its magic,
and the result is a higher-order mess. So I think for now the answer is
probably to just use something like the Report Prelude version that fuses
with a `build` but not a `foldr`, and add a rule to exchange `map` with
`reverse` in some fashion. I'll come up with a patch to do that shortly.
Of course, if Joachim or someone can figure out a better solution or a
better characterization of the problem, that'd be great.
Side note: for reasons I can't begin to figure out, if the `foldl` above
is replaced with `foldl'`, then it doesn't fuse at all.
--
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/9434#comment:12>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler
More information about the ghc-tickets
mailing list