Update INLINE pragmas for new INLINE story
authorsimonpj@microsoft.com <unknown>
Fri, 5 Dec 2008 17:00:15 +0000 (17:00 +0000)
committersimonpj@microsoft.com <unknown>
Fri, 5 Dec 2008 17:00:15 +0000 (17:00 +0000)
- (.) and foldr should inline when applied to only two arguments
- Make unpackCString# NOINLINE; it inlines too much (with little gain)

GHC/Base.lhs

index 9951b5a..3f811fa 100644 (file)
@@ -255,6 +255,21 @@ The rest of the prelude list functions are in GHC.List.
 ----------------------------------------------
 --      foldr/build/augment
 ----------------------------------------------
 ----------------------------------------------
 --      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
   
 \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)
 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
 
                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
 -- | 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
 
 -- | @'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.
 
 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]
 \begin{code}
 unpackCString# :: Addr# -> [Char]
-{-# NOINLINE [1] unpackCString# #-}
+{-# NOINLINE unpackCString# #-}
+-- See Note [Inlining for unpacking C strings]
 unpackCString# addr 
   = unpack 0#
   where
 unpackCString# addr 
   = unpack 0#
   where
@@ -938,9 +959,9 @@ unpackAppendCString# addr rest
         ch = indexCharOffAddr# addr nh
 
 unpackFoldrCString# :: Addr# -> (Char  -> a -> a) -> a -> a 
         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
 -- 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
             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
 
 "unpack-list"  [1]  forall a   . unpackFoldrCString# a (:) [] = unpackCString# a
 "unpack-append"     forall a n . unpackFoldrCString# a (:) n  = unpackAppendCString# a n