Note [The demand for the RHS of a binding]
Given a binding { f = rhs }, in `dmdAnalRhsSig` we compute a `rhs_sd` in
which to analyse `rhs`.
The demand we use is:
* Ordinary bindings: a call-demand of depth (idArity f).
Why idArity arguments? Because that's a conservative estimate of how many
arguments we must feed a function before it does anything interesting with
them. Also it elegantly subsumes the trivial RHS and PAP case. E.g. for
f = g
we want to use a threshold arity based on g, not 0!
idArity is /at least/ the number of manifest lambdas, but might be higher for
PAPs and trivial RHS (see Note [Demand analysis for trivial right-hand sides]).
* Join points: a call-demand of depth (value-binder subset of JoinArity),
wrapped around the incoming demand for the entire expression; see
Note [Demand analysis for join points]
Note that the idArity of a function varies independently of its cardinality
properties (cf. Note [idArity varies independently of dmdTypeDepth]), so we
implicitly encode the arity for when a demand signature is sound to unleash in
its 'dmdTypeDepth', not in its idArity (cf. Note [Understanding DmdType and
DmdSig] in GHC.Types.Demand). It is unsound to unleash a demand signature when
the incoming number of arguments is less than that. See GHC.Types.Demand
Note [DmdSig: demand signatures, and demand-sig arity].
Note that there might, in principle, be functions for which we might want to
analyse for more incoming arguments than idArity. Example:
f x =
if expensive
then \y -> ... y ...
else \y -> ... y ...
We'd analyse `f` under a unary call demand C(1,L), corresponding to idArity
being 1. That's enough to look under the manifest lambda and find out how a
unary call would use `x`, but not enough to look into the lambdas in the if
branches.
On the other hand, if we analysed for call demand C(1,C(1,L)), we'd get useful
strictness info for `y` (and more precise info on `x`) and possibly CPR
information, but
* We would no longer be able to unleash the signature at unary call sites
* Performing the worker/wrapper split based on this information would be
implicitly eta-expanding `f`, playing fast and loose with divergence and
even being unsound in the presence of newtypes, so we refrain from doing so.
Also see Note [Don't eta expand in w/w] in GHC.Core.Opt.WorkWrap.
Since we only compute one signature, we do so for arity 1. Computing multiple
signatures for different arities (i.e., polyvariance) would be entirely
possible, if it weren't for the additional runtime and implementation
complexity. References 5
- Demand analysis for join points GHC.Core.Opt.DmdAnal
- Demand analysis for trivial right-hand sides GHC.Core.Opt.DmdAnal
- idArity varies independently of dmdTypeDepth GHC.Core.Opt.DmdAnal
- Don't eta expand in w/w GHC.Core.Opt.WorkWrap
- DmdSig: demand signatures, and demand-sig arity GHC.Types.Demand
Referenced by 0
Nothing in the tree points here.