New core transformation: promote case[One] into case[Many]
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.
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
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