[GHC] #15578: Honour INLINE pragmas on 0-arity bindings

GHC ghc-devs at haskell.org
Fri Aug 31 08:38:35 UTC 2018


#15578: Honour INLINE pragmas on 0-arity bindings
-------------------------------------+-------------------------------------
        Reporter:  simonpj           |                Owner:  (none)
            Type:  bug               |               Status:  new
        Priority:  normal            |            Milestone:  8.6.1
       Component:  Compiler          |              Version:  8.4.3
      Resolution:                    |             Keywords:
Operating System:  Unknown/Multiple  |         Architecture:
                                     |  Unknown/Multiple
 Type of failure:  None/Unknown      |            Test Case:
      Blocked By:                    |             Blocking:
 Related Tickets:  #15519            |  Differential Rev(s):
       Wiki Page:                    |
-------------------------------------+-------------------------------------

Comment (by simonpj):

 Great!  Here's a Note to add, and refer to from the `boring_ok` change
 {{{
 Note [Honour INLINE on 0-ary bindings]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Consider

    x = <expensive>
    {-# INLINE x #-}

    f y = ...x...

 The semantics of an INLINE pragma is

   inline x at every call site, provided it is saturated;
   that is, applied to at least as many arguments as appear
   on the LHS of the Haskell source definition.

 (This soure-code-derived arity is stored in the `ug_arity` field of
 the `UnfoldingGuidance`.)

 In the example, x's ug_arity is 0, so we should inline it at every use
 site.  It's rare to have such an INLINE pragma (usually INLINE Is on
 functions), but it's occasionally very important (Trac #15578, #15519).
 In #15519 we had something like
    x = case (g a b) of I# r -> T r
    {-# INLINE x #-}
    f y = ...(h x)....

 where h is strict.  So we got
    f y = ...(case g a b of I# r -> h (T r))...

 and that in turn allowed SpecConstr to ramp up performance.

 How do we deliver on this?  By adjusting the ug_boring_ok
 flag in mkInlineUnfoldingWithArity; see
 Note [INLINE pragmas and boring contexts]

 NB: there is a real risk that full laziness will float it right back
 out again. Consider again
   x = factorial 200
   {-# INLINE x #-}
   f y = ...x...

 After inlining we get
   f y = ...(factorial 200)...

 but it's entirely possible that full laziness will do
   lvl23 = factorial 200
   f y = ...lvl23...

 That's a problem for another day.

 Note [INLINE pragmas and boring contexts]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 An INLNE pragma uses mkInlineUnfoldingWithArity to build the
 unfolding.  That sets the ug_boring_ok flag to False if the function
 is not tiny (inlineBorkingOK), so that even INLINE functions are not
 inlined in an utterly boring context.  E.g.
      \x y. Just (f y x)
 Nothing is gained by inlining f here, even if it has an INLINE
 pragma.

 But for 0-ary bindings, we want to inline regardless; see
 Note [Honour INLINE on 0-ary bindings].

 I'm a bit worried that it's possible for the same kind of problem
 to arise for non-0-ary functions too, but let's wait and see.
 }}}

-- 
Ticket URL: <http://ghc.haskell.org/trac/ghc/ticket/15578#comment:8>
GHC <http://www.haskell.org/ghc/>
The Glasgow Haskell Compiler


More information about the ghc-tickets mailing list