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

#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

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by simonpj): I like this plan. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by aspiwack): Here is an example program which changes behaviour depending on this ticket: {{{#!haskell data T = MkT !Bool f :: T -> Bool f _ = False {-# NOINLINE f #-} {-# RULES "non-det" [1] forall x. f (MkT x) = x #-} main :: IO () main = print (f (MkT True)) }}} Since `MkT` has a strict field, it has a wrapper. The rule triggers only if the wrapper hasn't been inlined, however, wrappers are inlined (current GHC) in phase 2, and the rules is only active in phase 1 (and later). So the rule never fires, and the program prints `False`. With the proposed patch, the wrapper is not inlined before phase 0, so the rule can fire and the program prints `False`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:2 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Phab:D5400 Wiki Page: | -------------------------------------+------------------------------------- Changes (by aspiwack): * differential: => Phab:D5400 -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:3 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: 16288 | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/325/ -------------------------------------+------------------------------------- Changes (by monoidal): * status: new => closed * differential: Phab:D5400 => https://gitlab.haskell.org/ghc/ghc/merge_requests/325/ * resolution: => fixed -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: Blocked By: 16288 | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/325/ -------------------------------------+------------------------------------- Comment (by simonpj): Are there any regression tests? Eg RULEs that match on data constructors that have interesting wrappers? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late -------------------------------------+------------------------------------- Reporter: aspiwack | Owner: (none) Type: feature request | Status: closed Priority: normal | Milestone: Component: Compiler | Version: 8.7 Resolution: fixed | Keywords: Operating System: Unknown/Multiple | Architecture: | Unknown/Multiple Type of failure: None/Unknown | Test Case: | simplCore/should_run/{T15840,T15840a} Blocked By: 16288 | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/325/ -------------------------------------+------------------------------------- Changes (by monoidal): * testcase: => simplCore/should_run/{T15840,T15840a} Comment: There are two tests that use `data T = MkT !Bool`. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/15840#comment:7 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#15840: Inline data constructor wrappers very late
-------------------------------------+-------------------------------------
Reporter: aspiwack | Owner: (none)
Type: feature request | Status: closed
Priority: normal | Milestone:
Component: Compiler | Version: 8.7
Resolution: fixed | Keywords:
Operating System: Unknown/Multiple | Architecture:
| Unknown/Multiple
Type of failure: None/Unknown | Test Case:
| simplCore/should_run/{T15840,T15840a}
Blocked By: 16288 | Blocking:
Related Tickets: | Differential Rev(s):
Wiki Page: | https://gitlab.haskell.org/ghc/ghc/merge_requests/325/
-------------------------------------+-------------------------------------
Comment (by Marge Bot
participants (1)
-
GHC