Can you give an example?

 

Generally the wrapper does stuff like evaluating arguments for a strict constructor, and unboxing UNPACKed fields.  So if you have

            data T = MkT ! {-# UNPACK #-} Int

 

the wrapper looks something like this

 

            $WMkT x = case x of I# y -> MkT y

 

That is, it evaluates and unboxes the argument.   The source-language reference to MkT gets replaced with a call to the wrapper.

 

In a RULE suppose you write

            f (MkT x) = …blah…

and have a call          

            …f (MkT e)….

 

After replacing MkT by its wrapper call we’d have

            RULE  f ($WMkT x) = ...blah...

and      ....f ($WMkT e)....

 

Now if the wrapper for MkT is inlined, we’ll see (f (case e of …)) which won’t match well! 

 

At the moment, the very first run of the simplifier has almost all inlinings switched off, so the rule will indeed have a chance to fire.  But (a) I want to change the early simplifier run to do more inlining, and (b) in any case it all fails if you had, say

            ...f (h x)....

where

            h x = $WMkT e

Here you want h to inline, exposing the opportunity for the rule to fire.  I don’t know if this is the source of your problem, but it might be.

 

The usual solution to the interaction between RULES and inlining is to delay inlining until the rule has had a chance to fire. But in this case the inlining isn’t under your control: it’s the wrapper for MkT.

 

Something very similar happens for the wrappers after strictness analysis; if an (automatically generated, INLINE) wrapper is inlined too early, a rule might not fire.  The crude but effective solution for strictness wappers is to give them an INLINE[0] pragma; ie don’t inline till phase 0.  Maybe we should do the same for constructor wrappers.

 

 

That was probably more than you wanted to know.  Do send a concrete example.  Thanks

 

 

Simon

 

From: ghc-devs [mailto:ghc-devs-bounces@haskell.org] On Behalf Of Conal Elliott
Sent: 29 April 2014 23:03
To: glasgow-haskell-users@haskell.org; ghc-devs@haskell.org
Subject: GHC rewrite rules and constructor wrappers?

 

I'm trying to sort out the relationship of GHC rewrite rules and constructor wrappers. I have rules like

> "reify/(:<)" reifyEP (:<) = kPrim VecSP

This rule seems to fire for `reifyEP ($W:<)` rather than `reifyEP (:<)`. If I'm tracking (uncertain), `($W:<)` inlines to `(:<)`. Sometimes I'm able to preserve the `$W` form, but sometimes I get the bare form when inlining a definition from another already-compiled module. In those cases, I don't know how to get my rules to fire.

Advice and explanation appreciated, including pointers explanations of the role of these wrappers in GHC.

-- Conal