[GHC] #15840: Inline data constructor wrappers very late

GHC ghc-devs at haskell.org
Wed Oct 31 15:28:38 UTC 2018


#15840: Inline data constructor wrappers very late
-------------------------------------+-------------------------------------
           Reporter:  aspiwack       |             Owner:  (none)
               Type:  feature        |            Status:  new
  request                            |
           Priority:  normal         |         Milestone:
          Component:  Compiler       |           Version:  8.7
           Keywords:                 |  Operating System:  Unknown/Multiple
       Architecture:                 |   Type of failure:  None/Unknown
  Unknown/Multiple                   |
          Test Case:                 |        Blocked By:
           Blocking:                 |   Related Tickets:
Differential Rev(s):                 |         Wiki Page:
-------------------------------------+-------------------------------------
 This came up in the context of the implementation of linear types, where
 more data constructors have wrapper. But this should be of more general
 use. I want to share this in case someone can find an objection to this
 approach.

 Currently, writing a RULE involving a data constructor with a wrapper is
 perilous: the wrapper will be inlined in phase 2, probably before the RULE
 is even triggered (necessarily if the RULE only runs in phase 1).

 I want to remedy this situation. This proposal is mainly from Simon Peyton
 Jones, any misrepresentation is, of course, my own.

 The proposal is to inline all data constructor wrappers in phase 0. After
 all the RULE business has been dealt with. If we do that, we need to be
 quite careful about case-of-know-constructor:

 In
 {{{#!hs
 case $WK u of { K x -> e; … }
 }}}

 `$WK` wouldn't unfold until very late. But we don't want the `case`
 expression to be blocked! Otherwise we may, for instance, prevent the
 function's size to be small enough to be inlined. Hence a maybe some rules
 will not trigger. That would not be acceptable.

 Fortunately, in order to decide whether case-of-known-constructor can
 perform, the simplifier calls `exprIsConApp_maybe`. Also fortunate is that
 in the situation above, we really don't care about any RULE stuff (at
 least not in relation with `K`). So what we can do is make
 `exprIsConApp_maybe` a bit smarter and teach it to see through data
 constructor wrappers.

 Let's take an unpacking wrapper as an example:

 {{{#!hs
 data T = MkT {-# UNPACK #-} !(Int, Bool)

 $WMkT p = case p of (i,b) -> MkT i b
 }}}

 We have to see that `$WMkT u` is a constructor application. Hence we need
 to be able to peek through cases. We also need to be able to witness that
 we have done so. So the type of `exprIsConApp_maybe` would change from

 {{{#!hs
 exprIsConApp_maybe :: InScopeEnv -> CoreExpr -> Maybe (DataCon, [Type],
 [CoreExpr])
 }}}

 to

 {{{#!hs
 exprIsConApp_maybe :: InScopeEnv -> CoreExpr -> Maybe ([Float],DataCon,
 [Type], [CoreExpr])
 }}}

 Where `Float`-s are lets or cases with a single alternative (much like in
 the FloatOut pass).

 We then need to change case-of-known-constructor to also perform case-of-
 lets and case-of-cases when such floats are found.

 In summary: data constructor wrappers would be inlined in phase 0, except
 when they can trigger a case-of-known constructor, in which case they
 would be inlined immediately.

 Does anyone sees something which could go wrong with this plan?

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


More information about the ghc-tickets mailing list