From 985a94902e4c26fe740faefc8a66349f05b5c22c Mon Sep 17 00:00:00 2001 From: "simonpj@microsoft.com" Date: Fri, 5 Dec 2008 17:00:15 +0000 Subject: [PATCH] Update INLINE pragmas for new INLINE story - (.) and foldr should inline when applied to only two arguments - Make unpackCString# NOINLINE; it inlines too much (with little gain) --- GHC/Base.lhs | 41 +++++++++++++++++++++++++++++++---------- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/GHC/Base.lhs b/GHC/Base.lhs index 9951b5a..3f811fa 100644 --- a/GHC/Base.lhs +++ b/GHC/Base.lhs @@ -255,6 +255,21 @@ The rest of the prelude list functions are in GHC.List. ---------------------------------------------- -- foldr/build/augment ---------------------------------------------- + +Note [Inlining for foldr] +~~~~~~~~~~~~~~~~~~~~~~~~~ +Inline foldr only in the final stage (0), after the foldr rules +have had a chance + +Notice that we write foldr with just *two* arguments so that it'll inline +when given just those two arguments. Those are the ones that allow it to +be specialised for its argument functions. If you give it *three* args +then a definition like + unpack = foldr unpk_fn unpk_arg +does not get foldr inlined. But now 'unpack' will probably be inlined at +every call site (being small and arity 1), and *that* will make foldr inline! +So we get a copy of foldr at every call of unpack. This is particularly +bad for literal strings. \begin{code} -- | 'foldr', applied to a binary operator, a starting value (typically @@ -266,10 +281,9 @@ The rest of the prelude list functions are in GHC.List. foldr :: (a -> b -> b) -> b -> [a] -> b -- foldr _ z [] = z -- foldr f z (x:xs) = f x (foldr f z xs) -{-# INLINE [0] foldr #-} --- Inline only in the final stage, after the foldr/cons rule has had a chance -foldr k z xs = go xs - where +{-# INLINE [0] foldr #-} -- See Note [Inlining for foldr] +foldr k z = go + where go [] = z go (y:ys) = y `k` go ys @@ -668,7 +682,7 @@ const x _ = x -- | Function composition. {-# INLINE (.) #-} (.) :: (b -> c) -> (a -> b) -> a -> c -(.) f g x = f (g x) +(.) f g = \x -> f (g x) -- | @'flip' f@ takes its (first) two arguments in the reverse order of @f@. flip :: (a -> b -> c) -> b -> a -> c @@ -915,9 +929,16 @@ a `iShiftRL#` b | b >=# WORD_SIZE_IN_BITS# = 0# This code is needed for virtually all programs, since it's used for unpacking the strings of error messages. +Note [Inlining for unpacking C strings] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We use NOINLINE on unpackCString# and unpackFoldrCString# because +there is little or no gain from inlining them -- and there may be a +lot of calls (one for each literal string). + \begin{code} unpackCString# :: Addr# -> [Char] -{-# NOINLINE [1] unpackCString# #-} +{-# NOINLINE unpackCString# #-} +-- See Note [Inlining for unpacking C strings] unpackCString# addr = unpack 0# where @@ -938,9 +959,9 @@ unpackAppendCString# addr rest ch = indexCharOffAddr# addr nh unpackFoldrCString# :: Addr# -> (Char -> a -> a) -> a -> a -{-# NOINLINE [0] unpackFoldrCString# #-} --- Don't inline till right at the end; --- usually the unpack-list rule turns it into unpackCStringList +{-# NOINLINE unpackFoldrCString# #-} +-- See Note [Inlining for unpacking C strings] +-- Usually the unpack-list rule turns it into unpackCString# -- It also has a BuiltInRule in PrelRules.lhs: -- unpackFoldrCString# "foo" c (unpackFoldrCString# "baz" c n) -- = unpackFoldrCString# "foobaz" c n @@ -989,7 +1010,7 @@ unpackNBytes# addr len# = unpack [] (len# -# 1#) ch -> unpack (C# ch : acc) (i# -# 1#) {-# RULES -"unpack" [~1] forall a . unpackCString# a = build (unpackFoldrCString# a) +"unpack" [~1] forall a . unpackCString# a = build (unpackFoldrCString# a) "unpack-list" [1] forall a . unpackFoldrCString# a (:) [] = unpackCString# a "unpack-append" forall a n . unpackFoldrCString# a (:) n = unpackAppendCString# a n -- 1.7.10.4