Note [inlineBoringOk]

GHC/Core/Unfold.hs:222 compiler 3 tickets

See Note [INLINE for small functions]

The function `inlineBoringOk` returns True (boringCxtOk) if the supplied
unfolding, which looks like (\x y z. body), is such that the result of
inlining a saturated call is no bigger than `body`.  Some wrinkles:

(IB1) An important case is
    - \x. (x `cast` co)

(IB2) If `body` looks like a data constructor worker, we become keener
  to inline, by ignoring the number of arguments; we just insist they
  are all trivial.  Reason: in a call like `f (g x y)`, if `g` unfolds
  to a data construtor, we can allocate a data constructor instead of
  a thunk (g x y).

  A case in point where a GADT data constructor failed to inline (#25713)
      $WK = /\a \x. K @a <co> x
  We really want to inline a boring call to $WK so that we allocate
  a data constructor not a thunk ($WK @ty x).

  But not for nullary constructors!  We don't want to turn
     f ($WRefl @ty)
  into
     f (Refl @ty <co>)
   because the latter might allocate, whereas the former shares.
   (You might wonder if (Refl @ty <co>) should allocate, but I think
   that currently it does.)  So for nullary constructors, `inlineBoringOk`
   returns False.

(IB3) Types and coercions do not count towards the expression size.
      They are ultimately erased.

(IB4) If there are no value arguments, `inlineBoringOk` we have to be
  careful (#17182).  If we have
      let y = x @Int in f y y
  there’s no reason not to inline y at both use sites — no work is
  actually duplicated.

  But not so for coercion arguments! Unlike type arguments, which have
  no runtime representation, coercion arguments *do* have a runtime
  representation (albeit the zero-width VoidRep, see Note [Coercion
  tokens] in "GHC.CoreToStg").  For example:
       let y = g @Int <co> in g y y
  Here `co` is a value argument, and calling it twice might duplicate
  work.

  Even if `g` is a data constructor, so no work is duplicated,
  inlining `y` might duplicate allocation of a data constructor object
  (#17787). See also (IB2).

  TL;DR: if `is_fun` is False, so we have no value arguments, we /do/
  count coercion arguments, despite (IB3).

(IB5) You might wonder about an unfolding like  (\x y z -> x (y z)),
  whose body is, in some sense, just as small as (g x y z).
  But `inlineBoringOk` doesn't attempt anything fancy; it just looks
  for a function call with trivial arguments, Keep it simple.

(IB6) If we have an unfolding (K op) where K is a unary-class data constructor,
  we want to inline it!  So that we get calls (f op), which in turn can see (in
  STG land) that `op` is already evaluated and properly tagged. (If `op` isn't
  trivial we will have baled out before we get to the Var case.)  This made
  a big difference in benchmarks for the `effectful` library; details in !10479.

  See Note [Unary class magic] in GHC/Core/TyCon.

References 1

Referenced by 3