Add a note about about W/W for unlifting strict arguments
Simon requests we add a Note:
Indeed, but the user guide isn't the place for explaining the details of how the compiler works. Here is the Note I'd love to see
Note [Worker/wrapper for strict arguments]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
f x = case x of
[] -> blah
(y:ys) -> f ys
Clearly `f` is strict, but its argument is not a product type, so by default
we don't worker/wrapper it. But it is arguably valuable to do so. We could
do this:
f x = case x of xx { DEFAULT -> $wf xx }
$wf xx = case xx of
[] -> blah
(y:ys) -> f ys
Now the worker `$wf` knows that its argument `xx` will be evaluated
and properly tagged, so the code for the `case xx` does not need to do
an "eval" (see `GHC.StgToCmm.Expr.cgCase`). A call (f (a:as)) will
have the wrapper inlined, and will drop the `case x`, so no eval
happens at all.
The worker `$wf` is a StrictWorkerId (see `Note [Strict Worker Ids]`
in GHC.Types.Id.Info) and the code generator guarantees that every
call to `$wf` has a properly tagged argument (see `GHC.Stg.InferTags.Rewrite`).
Is this a win? Not always:
* It can cause slight codesize increases.
* It will also cause many more functions to get a worker/wrapper split
which can play badly with rules (see Ticket #20364). In particular
if you depend on rules firing on functions marked as NOINLINE
without marking use sites of these functions as INLINE or INLINEABLE
then things will break.
So there is a flag, `-fworker-wrapper-cbv`, to control whether we do
w/w on strict arguments (internally `Opt_WorkerWrapperUnlift`). The
flag is off by default. The choice is made in
GHC.Core.Opt.WorkWrape.Utils.wwForUnlifting
See also `Note [WW for calling convention]` in GHC.Core.Opt.WorkWrap.Utils
We could point to this Note from the first bullet above, and from the bits of code that implement the flag. Thanks!