New core transformation: promote case[One] into case[Many]
Motivation
Since !852 (closed) was merged, the case
expression in the Core definition of constructor wrappers are linear cases.
data T = MkT !Int
Will have a wrapper along the lines of
$WT n = case n of n' # 1
_ -> MkT n'
Now, as explained in the wiki, having a case[One]
prevents binder-swap from happening. And, as it happens, we have seen examples of Core getting less optimised because of it. I don't remember the precise example, unfortunately, but it concerned a cascade of such workers inlined into one-another, and some case-of-case not happening (probably unsurprisingly as this is very much the sort of things that binder-swap is here to detect).
It doesn't really show in any tests, but it does make some non-linear code a bit less optimised. And that's rather unfortunate.
Proposal
My suggestion is to add, as part of occurrence analysis, a new transformation. This transformation would detect cases where the scrutinee is really unrestricted, and change the case[One]
into a case[Many]
.
The point is that: if case[Many]
is still well typed, then we have strictly more freedom for optimisation.
The question remains of how we can detect that case[One]
can be promoted to case[Many]
. My proposal is to do so if and only if the scrutinee is a variable and this variable is bound with multiplicity Many
.