diff options
author | simonpj@microsoft.com <unknown> | 2010-09-15 15:42:35 +0000 |
---|---|---|
committer | simonpj@microsoft.com <unknown> | 2010-09-15 15:42:35 +0000 |
commit | 42b8aa9e4a054ae6784e6c90c9adc615a9703b8c (patch) | |
tree | b03b7c4ff2d580b002ce100cdedf90682a6c5e9a /docs/users_guide | |
parent | 2b8358cfe8b6399874090c099e3b96e932c6ccbb (diff) | |
download | haskell-42b8aa9e4a054ae6784e6c90c9adc615a9703b8c.tar.gz |
Documentation for INLINABLE
Diffstat (limited to 'docs/users_guide')
-rw-r--r-- | docs/users_guide/glasgow_exts.xml | 114 |
1 files changed, 104 insertions, 10 deletions
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index aeb9314363..3e8df7b469 100644 --- a/docs/users_guide/glasgow_exts.xml +++ b/docs/users_guide/glasgow_exts.xml @@ -7594,21 +7594,68 @@ key_function :: Int -> String -> (Bool, Double) function "<literal>f</literal>" has a number of other effects: <itemizedlist> <listitem><para> -No functions are inlined into <literal>f</literal>. Otherwise -GHC might inline a big function into <literal>f</literal>'s right hand side, -making <literal>f</literal> big; and then inline <literal>f</literal> blindly. +While GHC is keen to inline the function, it does not do so +blindly. For example, if you write +<programlisting> +map key_function xs +</programlisting> +there really isn't any point in inlining <literal>key_function</literal> to get +<programlisting> +map (\x -> <replaceable>body</replaceable>) xs +</programlisting> +In general, GHC only inlines the function if there is some reason (no matter +how slight) to supose that it is useful to do so. </para></listitem> + <listitem><para> -The float-in, float-out, and common-sub-expression transformations are not -applied to the body of <literal>f</literal>. +Moreover, GHC will only inline the function if it is <emphasis>fully applied</emphasis>, +where "fully applied" +means applied to as many arguments as appear (syntactically) +on the LHS of the function +definition. For example: +<programlisting> +comp1 :: (b -> c) -> (a -> b) -> a -> c +{-# INLINE comp1 #-} +comp1 f g = \x -> f (g x) + +comp2 :: (b -> c) -> (a -> b) -> a -> c +{-# INLINE comp2 #-} +comp2 f g x = f (g x) +</programlisting> +The two functions <literal>comp1</literal> and <literal>comp2</literal> have the +same semantics, but <literal>comp1</literal> will be inlined when applied +to <emphasis>two</emphasis> arguments, while <literal>comp2</literal> requires +<emphasis>three</emphasis>. This might make a big difference if you say +<programlisting> +map (not `comp1` not) xs +</programlisting> +which will optimise better than the corresponding use of `comp2`. +</para></listitem> + +<listitem><para> +It is useful for GHC to optimise the definition of an +INLINE function <literal>f</literal> just like any other non-INLINE function, +in case the non-inlined version of <literal>f</literal> is +ultimately called. But we don't want to inline +the <emphasis>optimised</emphasis> version +of <literal>f</literal>; +a major reason for INLINE pragmas is to expose functions +in <literal>f</literal>'s RHS that have +rewrite rules, and it's no good if those functions have been optimised +away. +</para> +<para> +So <emphasis>GHC guarantees to inline precisely the code that you wrote</emphasis>, no more +and no less. It does this by capturing a copy of the definition of the function to use +for inlining (we call this the "inline-RHS"), which it leaves untouched, +while optimising the ordinarly RHS as usual. For externally-visible functions +the inline-RHS (not the optimised RHS) is recorded in the interface file. </para></listitem> <listitem><para> An INLINE function is not worker/wrappered by strictness analysis. It's going to be inlined wholesale instead. </para></listitem> </itemizedlist> -All of these effects are aimed at ensuring that what gets inlined is -exactly what you asked for, no more and no less. </para> <para>GHC ensures that inlining cannot go on forever: every mutually-recursive group is cut by one or more <emphasis>loop breakers</emphasis> that is never inlined @@ -7636,8 +7683,9 @@ itself, so an INLINE pragma is always ignored.</para> {-# INLINE returnUs #-} </programlisting> - <para>See also the <literal>NOINLINE</literal> pragma (<xref - linkend="noinline-pragma"/>).</para> + <para>See also the <literal>NOINLINE</literal> (<xref linkend="inlinable-pragma"/>) + and <literal>INLINABLE</literal> (<xref linkend="noinline-pragma"/>) + pragmas.</para> <para>Note: the HBC compiler doesn't like <literal>INLINE</literal> pragmas, so if you want your code to be HBC-compatible you'll have to surround @@ -7646,6 +7694,36 @@ itself, so an INLINE pragma is always ignored.</para> </sect3> + <sect3 id="inlinable-pragma"> + <title>INLINABLE pragma</title> + +<para>An INLINABLE pragma works very like an INLINE pragma, except that: +<itemizedlist> +<listitem><para> +INLINE says "please inline me", but INLINABLE says "feel free to inline me; use your +discretion". In other words the choice is left to GHC, which uses the same +rules as for pragma-free functions. Unlike INLINE, That decision is made at +the <emphasis>call site</emphasis>, and +will therefore be affected by the inlining threshold, optimisation level etc. +</para></listitem> +<listitem><para> +Like INLINE, the INLINABLE pragma retains a copy of the original RHS for +inlining purposes, and persists it in the interface file, regardless of +the size of the RHS. +</para></listitem> +<listitem><para> +If you use the special function <literal>inline</literal> (<xref linkend="special-ids"/>) +to force inlining at a +call site, you will get a copy of the the original RHS. +Indeed, if you intend to use <literal>inline f</literal> it +is a good idea to mark the definition of <literal>f</literal> INLINABLE, +so that GHC guarantees to expose an unfolding regardless of how big it is. +</para></listitem> +</itemizedlist> +</para> + + </sect3> + <sect3 id="noinline-pragma"> <title>NOINLINE pragma</title> @@ -8760,7 +8838,23 @@ r) -> <para>GHC has a few built-in functions with special behaviour. These are now described in the module <ulink url="&libraryGhcPrimLocation;/GHC-Prim.html"><literal>GHC.Prim</literal></ulink> -in the library documentation.</para> +in the library documentation. +In particular: +<itemizedlist> +<listitem><para> +<ulink url="&libraryGhcPrimLocation;/GHC-Prim.html#v%3Ainline"><literal>inline</literal></ulink> +allows control over inlining on a per-call-site basis. +</para></listitem> +<listitem><para> +<ulink url="&libraryGhcPrimLocation;/GHC-Prim.html#v%3Alazy"><literal>lazy</literal></ulink> +restrains the strictness analyser. +</para></listitem> +<listitem><para> +<ulink url="&libraryGhcPrimLocation;/GHC-Prim.html#v%3AunsafeCoerce%23"><literal>lazy</literal></ulink> +allows you to fool the type checker. +</para></listitem> +</itemizedlist> +</para> </sect1> |