The role of INLINE and INLINABLE on recursive functions

Simon Marlow marlowsd at gmail.com
Thu Jun 9 17:38:48 CEST 2011


On 09/06/2011 12:43, Simon Peyton-Jones wrote:
> INLINE:
> - no effect for a recursive function
> - for a non-recursive function, always inline a call that
> 	(a) is applied to as many args as the LHS of the defn
> 	(b) has some interesting context.  Ie (\y x->  f x y) doesn't
> 		inline f
>
> INLINEABLE
> a) For type-class overloaded functions (including recursive ones)
> 	- makes them auto-specialise at call sites in other modules
> 	- allows SPECIALISE pragmas for them in other modules
>
> b) For non-recursive functions, makes GHC willing, but not super-eager,
>    to inline at call sites.  Ie just use GHC's usual inlining rules.
>    The difference from not having the pragma is that the *original*
>    RHS is inlined (if GHC decides to) rather than the optimised RHS.
>
> Does that help?  The dual role of INLINEABLE is a bit confusing.  And the utility of (b) isn't clear to me.

So there are a couple of reasons to want (b).  First, it shifts the 
decision about whether to inline to the call site, where the user has 
more control (e.g. with -funfolding-use-threshold300).  This came up 
during the work on the containers package, where there was a concern 
that overuse of INLINE was causing code bloat in clients.

Second, (b) is useful in cases like this:

g x = ... large ...

f x = ... g x ...

and you want f to be inlined (but not necessarily everywhere, only if 
it's useful).  If you don't say INLINABLE, then g gets inlined into f's 
rhs (let's assume g is only used once), and f never gets inlined because 
it's too big.  If you say INLINE, then f gets inlined everywhere, which 
might be overkill.  INLINABLE is just right.

Cheers,
	Simon




>
> Simon
>
> | -----Original Message-----
> | From: Johan Tibell [mailto:johan.tibell at gmail.com]
> | Sent: 09 June 2011 12:06
> | To: Simon Peyton-Jones
> | Subject: The role of INLINE and INLINABLE on recursive functions
> |
> | Hi,
> |
> | This comment on Trac got me curious:
> |
> |     "Ok, we looked at this, and it turns out that 6.12.3 desugars `forever`
> |     differently: in 6.12, a local recursive `let` was introduced, which meant
> |     that `forever` could be inlined (and hence specialised) at every call
> |     site, whereas in 7.0 the desugarer leaves the function as a top-level
> |     recursive function which cannot be inlined.
> |
> |     The solution is to add an `INLINABLE` pragma for `forever`, which will
> |     allow it to be specialised at a call site."
> |
> | What's the meaning of INLINE or INLINABLE on a recursive function?
> | Normally we don't inline recursive functions (when would we stop
> | inlining?) so it's unclear to me what the meaning of the pragmas would
> | be in this cases. I know that INLINABLE on a recursive function that
> | takes a type class dictionary leads to call site specialization of
> | that function (but not "inlining").
> |
> | People often use this transformation to get recursive functions inlined:
> |
> |     f = ... f ...
> |
> |     f_transformed = go
> |       where go = ... go ...
> |     {-# INLINE f_transformed #-}
> |
> | Could we get the same result by just adding an INLINE pragma to the original f?
> |
> | Cheers,
> | Johan
>
>
> _______________________________________________
> Glasgow-haskell-users mailing list
> Glasgow-haskell-users at haskell.org
> http://www.haskell.org/mailman/listinfo/glasgow-haskell-users




More information about the Glasgow-haskell-users mailing list