wiki:Proposal/SelfExplinatoryInlinePragmas

The problem

Currently, the pragmas used for inlining phase control are rather tricky to remember right:

  Should we inline `f`?       -- Before phase 2     Phase 2 and later

  no inline pragmas (default) --      Maybe              Maybe

  {-# INLINE   [2]  f #-}     --      No                 Yes
  {-# INLINE   [~2] f #-}     --      Yes                No
  {-# NOINLINE [2]  f #-}     --      No                 Maybe
  {-# NOINLINE [~2] f #-}     --      Maybe              No

  {-# INLINE   f #-}          --      Yes                Yes
  {-# NOINLINE f #-}          --      No                 No

Note that there are three possible states per phase (inline, do not inline, maybe inline).

Without this table from the docs, most of us are lost as to the precise semantics of these.

The problems are:

  1. The phase controls [2] and [~2] are not self-explanatory.
  2. NO_INLINE [2] and INLINE [2] are asymmetric. NO_INLINE [2] affects inlining before phase 2 only, whereas INLINE [2] affects inlining for all phases. This assymetry is unfortunate, given the symmetry between NO_INLINE and INLINE (without phase controls).

The proposals

We can probably do a better job by using easier-to-understand pragmas.

Proposal 1

{-#   INLINE[n]  f #-}  becomes  {-#   INLINE_FROM[n]   f #-}
{-#   INLINE[~n] f #-}  becomes  {-#   INLINE_BEFORE[n] f #-}
{-# NOINLINE[n]  f #-}  becomes  {-# NOINLINE_BEFORE[n] f #-}
{-# NOINLINE[~n] f #-}  becomes  {-# NOINLINE_FROM[n]   f #-}

The choice of “from” and “before” over (as was proposed as well) ”after” is that with “after” it is not so clear what should happen in stage n.

Con: INLINE_FROM[n] and NOINLINE_FROM[n] are still asymmetric (don't affect the same phases), as are INLINE_BEFORE[n] and NOINLINE_BEFORE[n].

Proposal 2

{-#   INLINE[n]  f #-}  becomes {-#     INLINE_FROM[n]   f #-} {-# NOINLINE_BEFORE[n] f #-} 
{-#   INLINE[~n] f #-}  becomes {-#     INLINE_BEFORE[n] f #-} {-# NOINLINE_FROM[n]   f #-} 
{-# NOINLINE[n]  f #-}  becomes {-# MAY_INLINE_FROM[n]   f #-} {-# NOINLINE_BEFORE[n] f #-} 
{-# NOINLINE[~n] f #-}  becomes {-# MAY_INLINE_BEFORE[n] f #-} {-# NOINLINE_FROM[n]   f #-}

Con: too verbose?

Proposal 3

{-#   INLINE[n]  f #-}  becomes  {-#     INLINE_FROM[n]   f #-}
{-#   INLINE[~n] f #-}  becomes  {-#     INLINE_BEFORE[n] f #-}
{-# NOINLINE[n]  f #-}  becomes  {-# MAY_INLINE_FROM[n]   f #-}
{-# NOINLINE[~n] f #-}  becomes  {-# MAY_INLINE_BEFORE[n] f #-}

Con: not immediately clear what will happen in the phases that aren't specified (the answer is: 'no inline', as opposed to the default 'maybe inline').

Alternatives

Instead of adding such wordy pragmas, we can maybe make the content of the [..] more helpful, by allowing more complex specification of phase ranges.

Proposal 2b

{-#   INLINE[n]  f #-}  becomes  {-#     INLINE[<= n] f #-} {-# NOINLINE[ > n] f #-}
{-#   INLINE[~n] f #-}  becomes  {-#     INLINE[ > n] f #-} {-# NOINLINE[<= n] f #-}
{-# NOINLINE[n]  f #-}  becomes  {-# MAY_INLINE[<= n] f #-} {-# NOINLINE[ > n] f #-}
{-# NOINLINE[~n] f #-}  becomes  {-# MAY_INLINE[ > n] f #-} {-# NOINLINE[<= n] f #-}

Proposal 3b

{-#   INLINE[n]  f #-}  becomes  {-#     INLINE[<= n] f #-}
{-#   INLINE[~n] f #-}  becomes  {-#     INLINE[ > n] f #-}
{-# NOINLINE[n]  f #-}  becomes  {-# MAY_INLINE[<= n] f #-}
{-# NOINLINE[~n] f #-}  becomes  {-# MAY_INLINE[ > n] f #-}

Questions and possible minor variations

  • With these pragmas, do we still need the brackets [..] as part of the syntax, or can we drop that, as in
{-# INLINE_FROM 2 f #-}
Last modified 2 years ago Last modified on Jul 30, 2015 3:44:20 PM