Note [Worker/wrapper for Strictness and Absence]
The worker/wrapper transformation, mkWWstr_one, takes concrete action
based on the 'UnboxingDecision' returned by 'canUnboxArg'.
The latter takes into account several possibilities to decide if the
function is worthy for splitting:
1. If an argument is absent, it would be silly to pass it to
the worker. Hence the DropAbsent case. This case must come
first because the bottom demand B is also strict.
E.g. B comes from a function like
f x = error "urk"
and the absent demand A can come from Note [Unboxing evaluated arguments]
in GHC.Core.Opt.DmdAnal.
2. If the argument is evaluated strictly (or known to be eval'd),
we can take a view into the product demand ('viewProd'). In accordance
with Note [Boxity analysis], 'canUnboxArg' will say 'DoUnbox'.
'mkWWstr_one' then follows suit it and recurses into the fields of the
product demand. For example
f :: (Int, Int) -> Int
f p = (case p of (a,b) -> a) + 1
is split to
f :: (Int, Int) -> Int
f p = case p of (a,b) -> $wf a
$wf :: Int -> Int
$wf a = a + 1
and
g :: Bool -> (Int, Int) -> Int
g c p = case p of (a,b) ->
if c then a else b
is split to
g c p = case p of (a,b) -> $gw c a b
$gw c a b = if c then a else b
2a But do /not/ unbox if Boxity Analysis said "Boxed".
In this case, 'canUnboxArg' returns 'DontUnbox'.
Otherwise we risk decomposing and reboxing a massive
tuple which is barely used. Example:
f :: ((Int,Int) -> String) -> (Int,Int) -> a
f g pr = error (g pr)
main = print (f fst (1, error "no"))
Here, f does not take 'pr' apart, and it's stupid to do so.
Imagine that it had millions of fields. This actually happened
in GHC itself where the tuple was DynFlags
2b But if e.g. a large tuple or product type is always demanded we might
decide to "unlift" it. That is tighten the calling convention for that
argument to require it to be passed as a pointer to the value itself.
See Note [WW for calling convention].
3. In all other cases (e.g., lazy, used demand and not eval'd),
'finaliseArgBoxities' will have cleared the Boxity flag to 'Boxed'
(see Note [Finalising boxity for demand signatures] in GHC.Core.Opt.DmdAnal)
and 'canUnboxArg' returns 'DontUnbox' so that 'mkWWstr_one'
stops unboxing. References 4
- Finalising boxity for demand signatures GHC.Core.Opt.DmdAnal
- Unboxing evaluated arguments GHC.Core.Opt.DmdAnal
- WW for calling convention GHC.Core.Opt.WorkWrap.Utils
- Boxity analysis GHC.Types.Demand
Referenced by 1
- GHC.Core.Opt.WorkWrap.Utils call site