Note [Demand analysis for join points]
Consider
g :: (Int,Int) -> Int
g (p,q) = p+q
f :: T -> Int -> Int
f x p = g (join j y = (p,y)
in case x of
A -> j 3
B -> j 4
C -> (p,7))
If j was a vanilla function definition, we'd analyse its body with evalDmd, and
think that it was lazy in p. But for join points we can do better! We know
that j's body will (if called at all) be evaluated with the demand that consumes
the entire join-binding, in this case the argument demand from g. Whizzo! g
evaluates both components of its argument pair, so p will certainly be evaluated
if j is called.
For f to be strict in p, we need /all/ paths to evaluate p; in this case the C
branch does so too, so we are fine. So, as usual, we need to transport demands
on free variables to the call site(s). Compare Note [Lazy and unleashable free
variables].
The implementation is easy: see `body_sd` in`dmdAnalRhsSig`. When analysing
a join point, we can analyse its body (after stripping off the join binders,
here just 'y') with the demand from the entire join-binding (written `let_sd`
here).
Another win for join points! #13543.
BUT see Note [Worker/wrapper arity and join points].
Note we may analyse the rhs of a join point with a demand that is either
bigger than, or smaller than, the number of lambdas syntactically visible.
* More lambdas than call demands:
join j x = \p q r -> blah in ...
in a context with demand Top.
* More call demands than lambdas:
(join j x = h in ..(j 2)..(j 3)) a b c References 1
- Worker/wrapper arity and join points GHC.Core.Opt.DmdAnal
Referenced by 2
- GHC.Core.Opt.DmdAnal call site
- The demand for the RHS of a binding GHC.Core.Opt.DmdAnal