Static data and RULES

David Feuer david.feuer at gmail.com
Fri Feb 17 00:30:03 UTC 2017


Let me give an example. Suppose we have

data L = LCon1 Int | LCon2
data S = SCon !Int

{-# RULES
"L" LCon1 0 = LCon2
"S" forall x . f (SCon x) = g x
 #-}

The immediate problem today is with "S". The SCon wrapper could very well
inline before the rule has a chance to fire. We'd like to be able to phase
that inline to give it a chance.

The "L" rule becomes problematic when we try to identify static data the
simplifier shouldn't have to try to optimize. If it identifies LCon 0 as
static, the "L" rule will never fire.

On Feb 16, 2017 7:08 PM, "David Feuer" <david.feuer at gmail.com> wrote:

> Semantically, the proposed scheme is very nearly equivalent to breaking
> *every* data constructor into a worker and a wrapper, and allowing INLINE
> and NOINLINE pragmas on the wrappers. That would allow terms built only
> from constructor workers and literals to be identified as they're
> constructed in any stage and left alone by the simplifier. It would also
> allow people using RULES that match on constructors to make those work
> reliably, by making sure the bindings they match on don't inline away or
> get marked static too early. Of course, we don't actually need to add more
> worker/wrapper pairs to do this; we can fake that.
>
> On Feb 16, 2017 6:53 PM, "Simon Peyton Jones" <simonpj at microsoft.com>
> wrote:
>
>> I’m sorry I still don’t understand the problem.  Can you give an
>> example?  It all works fine today; what will change in the proposed new
>> scheme.  Indeed what IS the proposed new scheme?
>>
>>
>>
>> I’m lost
>>
>>
>>
>> Simon
>>
>>
>>
>> *From:* David Feuer [mailto:david.feuer at gmail.com]
>> *Sent:* 16 February 2017 23:51
>> *To:* Simon Peyton Jones <simonpj at microsoft.com>
>> *Cc:* ghc-devs <ghc-devs at haskell.org>; Reid Barton <rwbarton at gmail.com>;
>> Ben Gamari <bgamari at gmail.com>
>> *Subject:* RE: Static data and RULES
>>
>>
>>
>> Sorry; guess I should have given more background on that. This goes back
>> to the performance problems Ben encountered in Typeable. The goal is to
>> avoid trying to optimize something over and over that's never ever going to
>> change. If we know that a term is made only of static data, we can skip it
>> altogether in simplification. Suppose we have
>>
>>
>>
>> foo = Just (Right [1])
>>
>>
>>
>> Then no amount of optimization will ever be useful. But what about RULES?
>> If the outermost pattern in a rule matches on a data constructor, then it's
>> not static anymore! We may be replacing it with something else. So we need
>> a finer mechanism. We *also* need a finer mechanism for strict constructors
>> in general. We need to avoid inlining those too early if they're mentioned
>> in any position in RULES. Trying to make this work right automagically
>> looks a bit tricky in the face of orphan rules and such.
>>
>>
>>
>> On Feb 16, 2017 6:35 PM, "Simon Peyton Jones" <simonpj at microsoft.com>
>> wrote:
>>
>> I don’t understand any of this.
>>
>>
>>
>> However, RULES are allowed to match on data constructors and it would be
>> nice to let that keep happening.
>>
>>
>>
>> Why won’t it keep happening?  What is the problem you are trying to
>> solve?  Why does the fast-path make it harder?
>>
>>
>>
>> Maybe open a ticket?
>>
>>
>>
>> Simon
>>
>>
>>
>> *From:* ghc-devs [mailto:ghc-devs-bounces at haskell.org] *On Behalf Of *David
>> Feuer
>> *Sent:* 16 February 2017 22:13
>> *To:* Ben Gamari <bgamari at gmail.com>; Reid Barton <rwbarton at gmail.com>
>> *Cc:* ghc-devs <ghc-devs at haskell.org>
>> *Subject:* Static data and RULES
>>
>>
>>
>> Ben Gamari and Reid Barton are interested in making it cheaper for static
>> data to pass through simplification. The basic idea is that if a term is
>> already made entirely of data constructors and literals, then there's
>> nothing left to optimize.
>>
>>
>>
>> However, RULES are allowed to match on data constructors and it would be
>> nice to let that keep happening. But on the other hand, RULES are
>> apparently (according to Duncan Coutts) already broken for strict data
>> constructors, because they have workers and wrappers.
>>
>>
>>
>> My thought: let's allow phased INLINE and NOINLINE pragmas for data
>> constructors. The default would be INLINE. The ~ phase choice would not be
>> available: once inline, always inline.
>>
>>
>>
>> Semantics
>>
>> ~~~~~~~~~~
>>
>>
>>
>> For all constructors:
>>
>>
>>
>> If a constructor is allowed by pragmas to inline in a certain phase, then
>> in that phase terms built from it can be considered static. Once static,
>> always static.
>>
>>
>>
>> If a constructor is not allowed to inline in a certain phase, terms built
>> from it will be considered non-static.
>>
>>
>>
>> After demand analysis and worker/wrapper, all constructors are considered
>> inline.
>>
>>
>>
>> For strict constructors:
>>
>>
>>
>> A strict constructor wrapper prohibited from inlining in a certain phase
>> simply will not.
>>
>>
>>
>> Strict constructor wrappers will all be allowed to inline after demand
>> analysis and worker/wrapper. This matches the way we now handle wrappers
>> actually created in that phase.
>>
>>
>>
>> Syntax:
>>
>>
>>
>> For GADT syntax, this is easy:
>>
>>
>>
>> data Foo ... where
>>
>>   {-# INLINE [1] Bar #-}
>>
>>   Bar :: ...
>>
>>
>>
>> For traditional syntax, I think it's probably best to pull the pragmas to
>> the top:
>>
>>
>>
>> {-# NOINLINE Quux #-}
>>
>> data Baz ... = Quux ... | ...
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/ghc-devs/attachments/20170216/eb005357/attachment-0001.html>


More information about the ghc-devs mailing list