GHC rewrite rules and constructor wrappers?

Simon Peyton Jones simonpj at
Tue May 6 12:06:54 UTC 2014

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)....
            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


From: ghc-devs [mailto:ghc-devs-bounces at] On Behalf Of Conal Elliott
Sent: 29 April 2014 23:03
To: glasgow-haskell-users at<mailto:glasgow-haskell-users at>; ghc-devs at<mailto:ghc-devs at>
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

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the Glasgow-haskell-users mailing list