Admin message

Due to a large amount of spam we do not allow new users to create repositories, they are "external" users. If you are a new user and want to create a repository, for example for forking GHC, open a new issue on ghc/ghc using the "get-verified" issue template

Unfoldings for lambda-bound variables
Currently GHC has an optimization which creates lambda-bound variables with unfoldings. It is described in Note [Case binders and join points], originally added in 72462499b. In this situation, if we'd like to create a join point: ``` case ... of c { I# c# -> ....c.... } ``` we take both the case binder and the deconstructed fields: ``` letjoin $j = \c# -> \c -> ...c.... in case ... of c { I# c# -> $j c# c } ``` and we add an unfolding to the binder `c`: it is equal to `I# c#`. I propose to remove this transformation. The reasons are: - Unfoldings attached to lambda-bound variables are a rather weird concept. They mean that a function can no longer be called on arbitrary values. Lint does not check whether the calls to the join point are consistent with unfolding. - This leads to bugs and addition of special cases (e.g. 71c7067b7cc2, #13890). - In linear types, this transformation does not preserve linearity unless we complicate Lint significantly (in both function abstraction and function calls). Proposed alternative: - If the case binder is not used, we just pass the arguments: `letjoin $j = \c# -> ...c#...` - If the case binder is used, we recreate it inside the join point: `letjoin $j = \c# -> let c = I# c# in ...c...` There are two performance regressions, but I believe the tradeoff is worthwhile. - There's one perf test failing, T9872d, where compile-time allocation goes up by 1.2%. I think we can just mark it as Metric Increase. - nofib results: https://gist.github.com/facundominguez/3482c11ab2be94492843c843f41c755e. There is one regression in allocations, cichelli +9%. The regression happens because of reboxing in the function `hinsert`. Core before and after can be seen at https://github.com/tweag/ghc/issues/412#issuecomment-559213720. The relevant join point is called `$j_s3No` in the version with the optimization, or `$j_s3Nq` in the version without the optimization. When the optimization is enabled, it gets two parameters, `y :: Int#` and `wild1 :: Int (= I# y)`, and returns a structure containing `wild1`. Without the optimization, `$j` gets only `y` and has to recreate `I# y`. The program wave4main, which was the motivation for this transformation as described in the Note [Case binders and join points], is no longer affected.
issue