diff options
author | Joachim Breitner <mail@joachim-breitner.de> | 2014-09-06 22:21:54 +0200 |
---|---|---|
committer | Joachim Breitner <mail@joachim-breitner.de> | 2014-09-06 22:21:54 +0200 |
commit | 78209d70596dcbfcb11ad1de1c961ab8479e531e (patch) | |
tree | 72df2fc3589c3576a4dc139e9ddda5f90f650e7c /libraries/base/Data/List.hs | |
parent | 5a1def9732390b65d51dd0aa2d9d8a6cd7204ed2 (diff) | |
download | haskell-78209d70596dcbfcb11ad1de1c961ab8479e531e.tar.gz |
INLINE unfoldr
Summary:
to allow GHC to maybe remove the Maybe. See the code comment for more
commentary. This fixes #9369.
Test Plan: see what happens on ghcspeed (once it is merged)
Reviewers: austin
Reviewed By: austin
Subscribers: simonmar, ezyang, carter
Differential Revision: https://phabricator.haskell.org/D198
GHC Trac Issues: #9369
Diffstat (limited to 'libraries/base/Data/List.hs')
-rw-r--r-- | libraries/base/Data/List.hs | 37 |
1 files changed, 32 insertions, 5 deletions
diff --git a/libraries/base/Data/List.hs b/libraries/base/Data/List.hs index f8137411fe..f7b58c18b1 100644 --- a/libraries/base/Data/List.hs +++ b/libraries/base/Data/List.hs @@ -995,11 +995,38 @@ sortOn f = -- > unfoldr (\b -> if b == 0 then Nothing else Just (b, b-1)) 10 -- > [10,9,8,7,6,5,4,3,2,1] -- -unfoldr :: (b -> Maybe (a, b)) -> b -> [a] -unfoldr f b = - case f b of - Just (a,new_b) -> a : unfoldr f new_b - Nothing -> [] + +-- Note [INLINE unfoldr] +-- We treat unfoldr a little differently from some other forms for list fusion +-- for two reasons: +-- +-- 1. We don't want to use a rule to rewrite a basic form to a fusible +-- form because this would inline before constant floating. As Simon Peyton- +-- Jones and others have pointed out, this could reduce sharing in some cases +-- where sharing is beneficial. Thus we simply INLINE it, which is, for +-- example, how enumFromTo::Int becomes eftInt. Unfortunately, we don't seem +-- to get enough of an inlining discount to get a version of eftInt based on +-- unfoldr to inline as readily as the usual one. We know that all the Maybe +-- nonsense will go away, but the compiler does not. +-- +-- 2. The benefit of inlining unfoldr is likely to be huge in many common cases, +-- even apart from list fusion. In particular, inlining unfoldr often +-- allows GHC to erase all the Maybes. This appears to be critical if unfoldr +-- is to be used in high-performance code. A small increase in code size +-- in the relatively rare cases when this does not happen looks like a very +-- small price to pay. +-- +-- Doing a back-and-forth dance doesn't seem to accomplish anything if the +-- final form has to be inlined in any case. + +unfoldr :: (b -> Maybe (a, b)) -> b -> [a] + +{-# INLINE unfoldr #-} -- See Note [INLINE unfoldr] +unfoldr f b0 = build (\c n -> + let go b = case f b of + Just (a, new_b) -> a `c` go new_b + Nothing -> n + in go b0) -- ----------------------------------------------------------------------------- |