[GHC] #12689: DataCon wrappers get in the way of rules

#12689: DataCon wrappers get in the way of rules -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 is a spin-off of https://ghc.haskell.org/trac/ghc/ticket/12618#comment:25: Simon writes there: Actually this is already a problem today. It's just rendered more prominent now that even `(:)` has a wrapper. Consider {{{#!hs data T = MkT {-# UNPACK #-} !Int {-# RULES "fT" f MkT = True "gT" forall x. g (MkT x) = x #-} f :: (Int -> T) -> Bool {-# NOINLINE f #-} f x = True g :: T -> Int {-# NOINLINE g #-} g (MkT x) = x+1 }}} yields {{{ Foo.hs:9:1: warning: [-Winline-rule-shadowing] Rule "fT" may never fire because 'Foo.$WMkT' might inline first Probable fix: add an INLINE[n] or NOINLINE[n] pragma for 'Foo.$WMkT' Foo.hs:10:1: warning: [-Winline-rule-shadowing] Rule "gT" may never fire because 'Foo.$WMkT' might inline first Probable fix: add an INLINE[n] or NOINLINE[n] pragma for 'Foo.$WMkT' }}} What to do? If we are to match these rules, we really must delay inlining the wrapper for `MkT` (after inlining we get a mess of unboxing etc). So either we must allow you to add a `NOINLINE` pragma to `MkT`; or we must add one automatically (e.g. `NOINLINE [1]`). Delaying all consructor-wrapper inlining to phase 1 is potentially quite drastic, because case-of-known-constructor wouldn't happen until the wrappers are inlined. Maybe that's ok; I'm not sure. Worth trying I think. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12689 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12689: DataCon wrappers get in the way of rules -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 nomeata): We might want to look at two separate cases: 1. The LHS mentions a data con (wrapper) unsaturated, (`fT` above). 2. The LHS mentions a data con (wrapper) saturated, (`gT` above). In the first case, I think we should simply disable the warning. Because the wrapper is unsaturated, it will not have been inlined in the code. Unsaturation is as good as `NOINLINE`, isn’t it? Only in the latter case it matters that, as you write
after inlining we get a mess of unboxing etc Is really all hope lost that we can match the mess? My gut feeling is that it is more promising to not work against the inliner and simplifier, and rather let it do its jobs (both on the LHS and the code), and try hard to make the matcher smart enough to match the mess.
-- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12689#comment:1 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12689: DataCon wrappers get in the way of rules
-------------------------------------+-------------------------------------
Reporter: nomeata | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
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 Joachim Breitner

#12689: DataCon wrappers get in the way of rules
-------------------------------------+-------------------------------------
Reporter: nomeata | Owner:
Type: bug | Status: new
Priority: normal | Milestone:
Component: Compiler | Version: 8.0.1
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 Joachim Breitner

#12689: DataCon wrappers get in the way of rules -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 can't see any decent way forward here except to delay inlining the wrapper until phase 1. In GHC as-is that may be fine, because it'll only apply to data-cons that have wrappers, which are relatively rarer. It'd need to be documented. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12689#comment:4 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12689: DataCon wrappers get in the way of rules -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 nomeata): Here is an idea that came out of what Iavor said (or at least how I understood him). There are still open questions, but I do like the general approach: Consider a rule (which I write with the wrapper name already, as that is what we desugar to these days) {{{ RULE forall a b. foo ($WMkCon a b) = bar a b }}} and a wrapper {{{ $WMkCon a b = case a of (a1,a2) -> MkCon a1 a2 b }}} We don’t want cases on the LHS of the rule, so we do not just want to inline MkCon into the LHS. But what if we move it to the right hand side, and write the rule like that: {{{ RULE forall a1 a2 b. foo (MkCon a1 a2 b) = let a = (a1,a2) in bar a b }}} The rule is nice because the LHS is a normal form (with regard to the simplifier and the rewrite rules). The necessary transformations could be stored with the unfolding information of `$WMkCon`. At least for a strict `foo`, things might work out. We’d get: {{{ case some expr of (a1,a2) -> … foo (MkCon a1 a2 someB) … → case some expr of (a1,a2) -> … (let a = (a1,a2) in bar a someB) … -- rule fires → case some expr of (a1,a2) -> … bar (a1,a2) a someB … -- inlining }}} and further cleanup may happen due to CSE. Unfortunately it does not work as immediately if `foo` is not strict, as the `case` does not get floated out of the way, and we need to match an expression like {{{ foo (case some expr of (a,b) -> MkCon a1 a2 someB) }}} and it would not be sound if the matcher would simply float the case out of the way. So this idea requires more thought. -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12689#comment:5 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler

#12689: DataCon wrappers get in the way of rules -------------------------------------+------------------------------------- Reporter: nomeata | Owner: Type: bug | Status: new Priority: normal | Milestone: Component: Compiler | Version: 8.0.1 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 nomeata): I just found this comment in `SimplUtils`: {{{ active_unfolding_minimal :: Id -> Bool -- Compuslory unfoldings only -- Ignore SimplGently, because we want to inline regardless; -- the Id has no top-level binding at all -- -- NB: we used to have a second exception, for data con wrappers. -- On the grounds that we use gentle mode for rule LHSs, and -- they match better when data con wrappers are inlined. -- But that only really applies to the trivial wrappers (like (:)), -- and they are now constructed as Compulsory unfoldings (in MkId) -- so they'll happen anyway. active_unfolding_minimal id = isCompulsoryUnfolding (realIdUnfolding id) }}} Was there a time when `(:)` had a wrapper? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/12689#comment:6 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler
participants (1)
-
GHC