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