Note [Add unfolding for scrutinee]

GHC/Core/Opt/Simplify/Iteration.hs:3646 compiler

In general it's unlikely that a variable scrutinee will appear
in the case alternatives   case x of { ...x unlikely to appear... }
because the binder-swap in OccurAnal has got rid of all such occurrences
See Note [Binder swap] in "GHC.Core.Opt.OccurAnal".

BUT it is still VERY IMPORTANT to add a suitable unfolding for a
variable scrutinee, in simplAlt.  Here's why
   case x of y
     (a,b) -> case b of c
                I# v -> ...(f y)...
There is no occurrence of 'b' in the (...(f y)...).  But y gets
the unfolding (a,b), and *that* mentions b.  If f has a RULE
    RULE f (p, I# q) = ...
we want that rule to match, so we must extend the in-scope env with a
suitable unfolding for 'y'.  It's *essential* for rule matching; but
it's also good for case-elimination -- suppose that 'f' was inlined
and did multi-level case analysis, then we'd solve it in one
simplifier sweep instead of two.

HOWEVER, given
  case x of y { Just a -> r1; Nothing -> r2 }
we do not want to add the unfolding x -> y to 'x', which might seem cool,
since 'y' itself has different unfoldings in r1 and r2.  Reason: if we
did that, we'd have to zap y's deadness info and that is a very useful
piece of information.

So instead we add the unfolding x -> Just a, and x -> Nothing in the
respective RHSs.

Since this transformation is tantamount to a binder swap, we use
GHC.Core.Opt.OccurAnal.scrutOkForBinderSwap to do the check.

Exactly the same issue arises in GHC.Core.Opt.SpecConstr;
see Note [Add scrutinee to ValueEnv too] in GHC.Core.Opt.SpecConstr


************************************************************************
*                                                                      *
\subsection{Known constructor}
*                                                                      *
************************************************************************

We are a bit careful with occurrence info.  Here's an example

        (\x* -> case x of (a*, b) -> f a) (h v, e)

where the * means "occurs once".  This effectively becomes
        case (h v, e) of (a*, b) -> f a)
and then
        let a* = h v; b = e in f a
and then
        f (h v)

All this should happen in one sweep.

References 2

Referenced by 2