This ticket tracks the design and implementation of a Nested CPR, e.g. extending CPR analysis to unbox constructed products nested inside constructed products.
Various places in GHC/base where we currently unbox IO manually, like GHC.Utils.Encoding or UniqSM
A simple rapid-termination analysis (higher-order exprIsCheap/exprOkForSpeculation) #8655
Effective sum CPR needs to be nested and hence the terminaion analysis machinery
Many heuristics of our current CPR analysis (i.e. Note [CPR for binders that will be unboxed]) are an artifact of not being able to express and propagate nested CPRs in case scrutinees to field binders.
Edited
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information
But that potentially allocates an additional lambda in the wrapper f that might not cancel away in higher order scenarios (e.g. when we call map g where g is the returned lambda). Not sure if we have the analysis info available that could make this process conservative. It's not simple demand info as I was hoping for in the reply to the above mail. But maybe we just shouldn't care for the higher-order scenario, not sure.
Another insight: I think Alexis was on point when suggesting to make Nested CPR "higher-order": In order not to allocate an additional lambda for call sites like
We have to see that mapdoes not unpack the Int returned by its higher-order argument. That's exactly the boxity information we encode in a product demand! In the example above, main puts demand C1(U) on g. NB: It is notC1(P(U)), e.g. a product use on g's result, which would allow us to unbox the result of g without remorse. So we wouldn't w/w for the lambda in the example above, because the demand says "we use the box", ergo the lambda (which is really the wrapper for the lambda in f) won't cancel away.
Here's another example where it could cancel away:
Having another look at #18174 (comment 318048), I think we could also just let bind the lambda before DmdAnal/CprAnal. Then we only have to realise that gs wrapper can inline after WW, thus
Currently, Nested CPR only considers things of arity 0 for WW, but this shows that we also want to transform fields of arity > 0, like g. Although it's not so clear if that's always a win, because we allocate $wg's closure in addition to g's. But the difference is merely in the closure for the wrapper, which will only close over $wg. Maybe the cases where the wrapper doesn't inline are rare.
This reminds me a bit of KaCC-sytyle WW for higher-order function arguments, only "the other way round", e.g. for results rather than arguments.