{-
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998

************************************************************************
*                                                                      *
\section[OccurAnal]{Occurrence analysis pass}
*                                                                      *
************************************************************************

The occurrence analyser re-typechecks a core expression, returning a new
core expression with (hopefully) improved usage information.
-}

{-# LANGUAGE CPP, BangPatterns, MultiWayIf, ViewPatterns  #-}

{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
module GHC.Core.Opt.OccurAnal ( occurAnalysePgm, occurAnalyseExpr ) where

#include "HsVersions.h"

import GHC.Prelude

import GHC.Core
import GHC.Core.FVs
import GHC.Core.Utils   ( exprIsTrivial, isDefaultAlt, isExpandableApp,
                          stripTicksTopE, mkTicks )
import GHC.Core.Opt.Arity   ( joinRhsArity )
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Basic
import GHC.Unit.Module( Module )
import GHC.Core.Coercion
import GHC.Core.Type
import GHC.Core.TyCo.FVs( tyCoVarsOfMCo )

import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Types.Var
import GHC.Types.Demand ( argOneShots, argsOneShots )
import GHC.Data.Graph.Directed ( SCC(..), Node(..)
                               , stronglyConnCompFromEdgedVerticesUniq
                               , stronglyConnCompFromEdgedVerticesUniqR )
import GHC.Builtin.Names( runRWKey )
import GHC.Types.Unique
import GHC.Types.Unique.FM
import GHC.Types.Unique.Set
import GHC.Utils.Misc
import GHC.Data.Maybe( isJust )
import GHC.Utils.Outputable
import Data.List

{-
************************************************************************
*                                                                      *
    occurAnalysePgm, occurAnalyseExpr
*                                                                      *
************************************************************************

Here's the externally-callable interface:
-}

occurAnalysePgm :: Module         -- Used only in debug output
                -> (Id -> Bool)         -- Active unfoldings
                -> (Activation -> Bool) -- Active rules
                -> [CoreRule]
                -> CoreProgram -> CoreProgram
occurAnalysePgm :: Module
-> (CoreBndr -> Bool)
-> (Activation -> Bool)
-> [CoreRule]
-> CoreProgram
-> CoreProgram
occurAnalysePgm Module
this_mod CoreBndr -> Bool
active_unf Activation -> Bool
active_rule [CoreRule]
imp_rules CoreProgram
binds
  | UsageDetails -> Bool
isEmptyDetails UsageDetails
final_usage
  = CoreProgram
occ_anald_binds

  | Bool
otherwise   -- See Note [Glomming]
  = WARN( True, hang (text "Glomming in" <+> ppr this_mod <> colon)
                   2 (ppr final_usage ) )
    CoreProgram
occ_anald_glommed_binds
  where
    init_env :: OccEnv
init_env = OccEnv
initOccEnv { occ_rule_act :: Activation -> Bool
occ_rule_act = Activation -> Bool
active_rule
                          , occ_unf_act :: CoreBndr -> Bool
occ_unf_act  = CoreBndr -> Bool
active_unf }

    (UsageDetails
final_usage, CoreProgram
occ_anald_binds) = OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go OccEnv
init_env CoreProgram
binds
    (UsageDetails
_, CoreProgram
occ_anald_glommed_binds)   = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(CoreBndr, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind OccEnv
init_env TopLevelFlag
TopLevel
                                                    ImpRuleEdges
imp_rule_edges
                                                    (CoreProgram -> [(CoreBndr, CoreExpr)]
forall b. [Bind b] -> [(b, Expr b)]
flattenBinds CoreProgram
binds)
                                                    UsageDetails
initial_uds
          -- It's crucial to re-analyse the glommed-together bindings
          -- so that we establish the right loop breakers. Otherwise
          -- we can easily create an infinite loop (#9583 is an example)
          --
          -- Also crucial to re-analyse the /original/ bindings
          -- in case the first pass accidentally discarded as dead code
          -- a binding that was actually needed (albeit before its
          -- definition site).  #17724 threw this up.

    initial_uds :: UsageDetails
initial_uds = UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
emptyDetails ([CoreRule] -> VarSet
rulesFreeVars [CoreRule]
imp_rules)
    -- The RULES declarations keep things alive!

    -- Note [Preventing loops due to imported functions rules]
    imp_rule_edges :: ImpRuleEdges
imp_rule_edges = (ImpRuleEdges -> ImpRuleEdges -> ImpRuleEdges)
-> ImpRuleEdges -> [ImpRuleEdges] -> ImpRuleEdges
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr ((VarSet -> VarSet -> VarSet)
-> ImpRuleEdges -> ImpRuleEdges -> ImpRuleEdges
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C VarSet -> VarSet -> VarSet
unionVarSet) ImpRuleEdges
forall a. VarEnv a
emptyVarEnv
                            [ (CoreBndr -> VarSet) -> VarEnv CoreBndr -> ImpRuleEdges
forall a b. (a -> b) -> VarEnv a -> VarEnv b
mapVarEnv (VarSet -> CoreBndr -> VarSet
forall a b. a -> b -> a
const VarSet
maps_to) (VarEnv CoreBndr -> ImpRuleEdges)
-> VarEnv CoreBndr -> ImpRuleEdges
forall a b. (a -> b) -> a -> b
$
                                VarSet -> VarEnv CoreBndr
forall a. UniqSet a -> UniqFM a a
getUniqSet (CoreExpr -> VarSet
exprFreeIds CoreExpr
arg VarSet -> [CoreBndr] -> VarSet
`delVarSetList` CoreRule -> [CoreBndr]
ru_bndrs CoreRule
imp_rule)
                            | CoreRule
imp_rule <- [CoreRule]
imp_rules
                            , Bool -> Bool
not (CoreRule -> Bool
isBuiltinRule CoreRule
imp_rule)  -- See Note [Plugin rules]
                            , let maps_to :: VarSet
maps_to = CoreExpr -> VarSet
exprFreeIds (CoreRule -> CoreExpr
ru_rhs CoreRule
imp_rule)
                                             VarSet -> [CoreBndr] -> VarSet
`delVarSetList` CoreRule -> [CoreBndr]
ru_bndrs CoreRule
imp_rule
                            , CoreExpr
arg <- CoreRule -> [CoreExpr]
ru_args CoreRule
imp_rule ]

    go :: OccEnv -> [CoreBind] -> (UsageDetails, [CoreBind])
    go :: OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go OccEnv
_ []
        = (UsageDetails
initial_uds, [])
    go OccEnv
env (CoreBind
bind:CoreProgram
binds)
        = (UsageDetails
final_usage, CoreProgram
bind' CoreProgram -> CoreProgram -> CoreProgram
forall a. [a] -> [a] -> [a]
++ CoreProgram
binds')
        where
           (UsageDetails
bs_usage, CoreProgram
binds')   = OccEnv -> CoreProgram -> (UsageDetails, CoreProgram)
go OccEnv
env CoreProgram
binds
           (UsageDetails
final_usage, CoreProgram
bind') = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind OccEnv
env TopLevelFlag
TopLevel ImpRuleEdges
imp_rule_edges CoreBind
bind
                                              UsageDetails
bs_usage

occurAnalyseExpr :: CoreExpr -> CoreExpr
-- Do occurrence analysis, and discard occurrence info returned
occurAnalyseExpr :: CoreExpr -> CoreExpr
occurAnalyseExpr CoreExpr
expr
  = (UsageDetails, CoreExpr) -> CoreExpr
forall a b. (a, b) -> b
snd (OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
initOccEnv CoreExpr
expr)

{- Note [Plugin rules]
~~~~~~~~~~~~~~~~~~~~~~
Conal Elliott (#11651) built a GHC plugin that added some
BuiltinRules (for imported Ids) to the mg_rules field of ModGuts, to
do some domain-specific transformations that could not be expressed
with an ordinary pattern-matching CoreRule.  But then we can't extract
the dependencies (in imp_rule_edges) from ru_rhs etc, because a
BuiltinRule doesn't have any of that stuff.

So we simply assume that BuiltinRules have no dependencies, and filter
them out from the imp_rule_edges comprehension.
-}

{-
************************************************************************
*                                                                      *
                Bindings
*                                                                      *
************************************************************************

Note [Recursive bindings: the grand plan]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When we come across a binding group
  Rec { x1 = r1; ...; xn = rn }
we treat it like this (occAnalRecBind):

1. Occurrence-analyse each right hand side, and build a
   "Details" for each binding to capture the results.

   Wrap the details in a Node (details, node-id, dep-node-ids),
   where node-id is just the unique of the binder, and
   dep-node-ids lists all binders on which this binding depends.
   We'll call these the "scope edges".
   See Note [Forming the Rec groups].

   All this is done by makeNode.

2. Do SCC-analysis on these Nodes.  Each SCC will become a new Rec or
   NonRec.  The key property is that every free variable of a binding
   is accounted for by the scope edges, so that when we are done
   everything is still in scope.

3. For each Cyclic SCC of the scope-edge SCC-analysis in (2), we
   identify suitable loop-breakers to ensure that inlining terminates.
   This is done by occAnalRec.

4. To do so we form a new set of Nodes, with the same details, but
   different edges, the "loop-breaker nodes". The loop-breaker nodes
   have both more and fewer dependencies than the scope edges
   (see Note [Choosing loop breakers])

   More edges: if f calls g, and g has an active rule that mentions h
               then we add an edge from f -> h

   Fewer edges: we only include dependencies on active rules, on rule
                RHSs (not LHSs) and if there is an INLINE pragma only
                on the stable unfolding (and vice versa).  The scope
                edges must be much more inclusive.

5.  The "weak fvs" of a node are, by definition:
       the scope fvs - the loop-breaker fvs
    See Note [Weak loop breakers], and the nd_weak field of Details

6.  Having formed the loop-breaker nodes

Note [Dead code]
~~~~~~~~~~~~~~~~
Dropping dead code for a cyclic Strongly Connected Component is done
in a very simple way:

        the entire SCC is dropped if none of its binders are mentioned
        in the body; otherwise the whole thing is kept.

The key observation is that dead code elimination happens after
dependency analysis: so 'occAnalBind' processes SCCs instead of the
original term's binding groups.

Thus 'occAnalBind' does indeed drop 'f' in an example like

        letrec f = ...g...
               g = ...(...g...)...
        in
           ...g...

when 'g' no longer uses 'f' at all (eg 'f' does not occur in a RULE in
'g'). 'occAnalBind' first consumes 'CyclicSCC g' and then it consumes
'AcyclicSCC f', where 'body_usage' won't contain 'f'.

------------------------------------------------------------
Note [Forming Rec groups]
~~~~~~~~~~~~~~~~~~~~~~~~~
We put bindings {f = ef; g = eg } in a Rec group if "f uses g"
and "g uses f", no matter how indirectly.  We do a SCC analysis
with an edge f -> g if "f uses g".

More precisely, "f uses g" iff g should be in scope wherever f is.
That is, g is free in:
  a) the rhs 'ef'
  b) or the RHS of a rule for f (Note [Rules are extra RHSs])
  c) or the LHS or a rule for f (Note [Rule dependency info])

These conditions apply regardless of the activation of the RULE (eg it might be
inactive in this phase but become active later).  Once a Rec is broken up
it can never be put back together, so we must be conservative.

The principle is that, regardless of rule firings, every variable is
always in scope.

  * Note [Rules are extra RHSs]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    A RULE for 'f' is like an extra RHS for 'f'. That way the "parent"
    keeps the specialised "children" alive.  If the parent dies
    (because it isn't referenced any more), then the children will die
    too (unless they are already referenced directly).

    To that end, we build a Rec group for each cyclic strongly
    connected component,
        *treating f's rules as extra RHSs for 'f'*.
    More concretely, the SCC analysis runs on a graph with an edge
    from f -> g iff g is mentioned in
        (a) f's rhs
        (b) f's RULES
    These are rec_edges.

    Under (b) we include variables free in *either* LHS *or* RHS of
    the rule.  The former might seems silly, but see Note [Rule
    dependency info].  So in Example [eftInt], eftInt and eftIntFB
    will be put in the same Rec, even though their 'main' RHSs are
    both non-recursive.

  * Note [Rule dependency info]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The VarSet in a RuleInfo is used for dependency analysis in the
    occurrence analyser.  We must track free vars in *both* lhs and rhs.
    Hence use of idRuleVars, rather than idRuleRhsVars in occAnalBind.
    Why both? Consider
        x = y
        RULE f x = v+4
    Then if we substitute y for x, we'd better do so in the
    rule's LHS too, so we'd better ensure the RULE appears to mention 'x'
    as well as 'v'

  * Note [Rules are visible in their own rec group]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    We want the rules for 'f' to be visible in f's right-hand side.
    And we'd like them to be visible in other functions in f's Rec
    group.  E.g. in Note [Specialisation rules] we want f' rule
    to be visible in both f's RHS, and fs's RHS.

    This means that we must simplify the RULEs first, before looking
    at any of the definitions.  This is done by Simplify.simplRecBind,
    when it calls addLetIdInfo.

------------------------------------------------------------
Note [Choosing loop breakers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Loop breaking is surprisingly subtle.  First read the section 4 of
"Secrets of the GHC inliner".  This describes our basic plan.
We avoid infinite inlinings by choosing loop breakers, and
ensuring that a loop breaker cuts each loop.

See also Note [Inlining and hs-boot files] in GHC.Core.ToIface, which
deals with a closely related source of infinite loops.

Fundamentally, we do SCC analysis on a graph.  For each recursive
group we choose a loop breaker, delete all edges to that node,
re-analyse the SCC, and iterate.

But what is the graph?  NOT the same graph as was used for Note
[Forming Rec groups]!  In particular, a RULE is like an equation for
'f' that is *always* inlined if it is applicable.  We do *not* disable
rules for loop-breakers.  It's up to whoever makes the rules to make
sure that the rules themselves always terminate.  See Note [Rules for
recursive functions] in GHC.Core.Opt.Simplify

Hence, if
    f's RHS (or its INLINE template if it has one) mentions g, and
    g has a RULE that mentions h, and
    h has a RULE that mentions f

then we *must* choose f to be a loop breaker.  Example: see Note
[Specialisation rules].

In general, take the free variables of f's RHS, and augment it with
all the variables reachable by RULES from those starting points.  That
is the whole reason for computing rule_fv_env in occAnalBind.  (Of
course we only consider free vars that are also binders in this Rec
group.)  See also Note [Finding rule RHS free vars]

Note that when we compute this rule_fv_env, we only consider variables
free in the *RHS* of the rule, in contrast to the way we build the
Rec group in the first place (Note [Rule dependency info])

Note that if 'g' has RHS that mentions 'w', we should add w to
g's loop-breaker edges.  More concretely there is an edge from f -> g
iff
        (a) g is mentioned in f's RHS `xor` f's INLINE rhs
            (see Note [Inline rules])
        (b) or h is mentioned in f's RHS, and
            g appears in the RHS of an active RULE of h
            or a transitive sequence of active rules starting with h

Why "active rules"?  See Note [Finding rule RHS free vars]

Note that in Example [eftInt], *neither* eftInt *nor* eftIntFB is
chosen as a loop breaker, because their RHSs don't mention each other.
And indeed both can be inlined safely.

Note again that the edges of the graph we use for computing loop breakers
are not the same as the edges we use for computing the Rec blocks.
That's why we compute

- rec_edges          for the Rec block analysis
- loop_breaker_nodes for the loop breaker analysis

  * Note [Finding rule RHS free vars]
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    Consider this real example from Data Parallel Haskell
         tagZero :: Array Int -> Array Tag
         {-# INLINE [1] tagZeroes #-}
         tagZero xs = pmap (\x -> fromBool (x==0)) xs

         {-# RULES "tagZero" [~1] forall xs n.
             pmap fromBool <blah blah> = tagZero xs #-}
    So tagZero's RHS mentions pmap, and pmap's RULE mentions tagZero.
    However, tagZero can only be inlined in phase 1 and later, while
    the RULE is only active *before* phase 1.  So there's no problem.

    To make this work, we look for the RHS free vars only for
    *active* rules. That's the reason for the occ_rule_act field
    of the OccEnv.

  * Note [Weak loop breakers]
    ~~~~~~~~~~~~~~~~~~~~~~~~~
    There is a last nasty wrinkle.  Suppose we have

        Rec { f = f_rhs
              RULE f [] = g

              h = h_rhs
              g = h
              ...more...
        }

    Remember that we simplify the RULES before any RHS (see Note
    [Rules are visible in their own rec group] above).

    So we must *not* postInlineUnconditionally 'g', even though
    its RHS turns out to be trivial.  (I'm assuming that 'g' is
    not chosen as a loop breaker.)  Why not?  Because then we
    drop the binding for 'g', which leaves it out of scope in the
    RULE!

    Here's a somewhat different example of the same thing
        Rec { g = h
            ; h = ...f...
            ; f = f_rhs
              RULE f [] = g }
    Here the RULE is "below" g, but we *still* can't postInlineUnconditionally
    g, because the RULE for f is active throughout.  So the RHS of h
    might rewrite to     h = ...g...
    So g must remain in scope in the output program!

    We "solve" this by:

        Make g a "weak" loop breaker (OccInfo = IAmLoopBreaker True)
        iff g is a "missing free variable" of the Rec group

    A "missing free variable" x is one that is mentioned in an RHS or
    INLINE or RULE of a binding in the Rec group, but where the
    dependency on x may not show up in the loop_breaker_nodes (see
    note [Choosing loop breakers} above).

    A normal "strong" loop breaker has IAmLoopBreaker False.  So

                                    Inline  postInlineUnconditionally
   strong   IAmLoopBreaker False    no      no
   weak     IAmLoopBreaker True     yes     no
            other                   yes     yes

    The **sole** reason for this kind of loop breaker is so that
    postInlineUnconditionally does not fire.  Ugh.  (Typically it'll
    inline via the usual callSiteInline stuff, so it'll be dead in the
    next pass, so the main Ugh is the tiresome complication.)

Note [Rules for imported functions]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this
   f = /\a. B.g a
   RULE B.g Int = 1 + f Int
Note that
  * The RULE is for an imported function.
  * f is non-recursive
Now we
can get
   f Int --> B.g Int      Inlining f
         --> 1 + f Int    Firing RULE
and so the simplifier goes into an infinite loop. This
would not happen if the RULE was for a local function,
because we keep track of dependencies through rules.  But
that is pretty much impossible to do for imported Ids.  Suppose
f's definition had been
   f = /\a. C.h a
where (by some long and devious process), C.h eventually inlines to
B.g.  We could only spot such loops by exhaustively following
unfoldings of C.h etc, in case we reach B.g, and hence (via the RULE)
f.

Note that RULES for imported functions are important in practice; they
occur a lot in the libraries.

We regard this potential infinite loop as a *programmer* error.
It's up the programmer not to write silly rules like
     RULE f x = f x
and the example above is just a more complicated version.

Note [Preventing loops due to imported functions rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider:
  import GHC.Base (foldr)

  {-# RULES "filterList" forall p. foldr (filterFB (:) p) [] = filter p #-}
  filter p xs = build (\c n -> foldr (filterFB c p) n xs)
  filterFB c p = ...

  f = filter p xs

Note that filter is not a loop-breaker, so what happens is:
  f =          filter p xs
    = {inline} build (\c n -> foldr (filterFB c p) n xs)
    = {inline} foldr (filterFB (:) p) [] xs
    = {RULE}   filter p xs

We are in an infinite loop.

A more elaborate example (that I actually saw in practice when I went to
mark GHC.List.filter as INLINABLE) is as follows. Say I have this module:
  {-# LANGUAGE RankNTypes #-}
  module GHCList where

  import Prelude hiding (filter)
  import GHC.Base (build)

  {-# INLINABLE filter #-}
  filter :: (a -> Bool) -> [a] -> [a]
  filter p [] = []
  filter p (x:xs) = if p x then x : filter p xs else filter p xs

  {-# NOINLINE [0] filterFB #-}
  filterFB :: (a -> b -> b) -> (a -> Bool) -> a -> b -> b
  filterFB c p x r | p x       = x `c` r
                   | otherwise = r

  {-# RULES
  "filter"     [~1] forall p xs.  filter p xs = build (\c n -> foldr
  (filterFB c p) n xs)
  "filterList" [1]  forall p.     foldr (filterFB (:) p) [] = filter p
   #-}

Then (because RULES are applied inside INLINABLE unfoldings, but inlinings
are not), the unfolding given to "filter" in the interface file will be:
  filter p []     = []
  filter p (x:xs) = if p x then x : build (\c n -> foldr (filterFB c p) n xs)
                           else     build (\c n -> foldr (filterFB c p) n xs

Note that because this unfolding does not mention "filter", filter is not
marked as a strong loop breaker. Therefore at a use site in another module:
  filter p xs
    = {inline}
      case xs of []     -> []
                 (x:xs) -> if p x then x : build (\c n -> foldr (filterFB c p) n xs)
                                  else     build (\c n -> foldr (filterFB c p) n xs)

  build (\c n -> foldr (filterFB c p) n xs)
    = {inline} foldr (filterFB (:) p) [] xs
    = {RULE}   filter p xs

And we are in an infinite loop again, except that this time the loop is producing an
infinitely large *term* (an unrolling of filter) and so the simplifier finally
dies with "ticks exhausted"

Because of this problem, we make a small change in the occurrence analyser
designed to mark functions like "filter" as strong loop breakers on the basis that:
  1. The RHS of filter mentions the local function "filterFB"
  2. We have a rule which mentions "filterFB" on the LHS and "filter" on the RHS

So for each RULE for an *imported* function we are going to add
dependency edges between the *local* FVS of the rule LHS and the
*local* FVS of the rule RHS. We don't do anything special for RULES on
local functions because the standard occurrence analysis stuff is
pretty good at getting loop-breakerness correct there.

It is important to note that even with this extra hack we aren't always going to get
things right. For example, it might be that the rule LHS mentions an imported Id,
and another module has a RULE that can rewrite that imported Id to one of our local
Ids.

Note [Specialising imported functions] (referred to from Specialise)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
BUT for *automatically-generated* rules, the programmer can't be
responsible for the "programmer error" in Note [Rules for imported
functions].  In particular, consider specialising a recursive function
defined in another module.  If we specialise a recursive function B.g,
we get
         g_spec = .....(B.g Int).....
         RULE B.g Int = g_spec
Here, g_spec doesn't look recursive, but when the rule fires, it
becomes so.  And if B.g was mutually recursive, the loop might
not be as obvious as it is here.

To avoid this,
 * When specialising a function that is a loop breaker,
   give a NOINLINE pragma to the specialised function

Note [Glomming]
~~~~~~~~~~~~~~~
RULES for imported Ids can make something at the top refer to something at the bottom:
        f = \x -> B.g (q x)
        h = \y -> 3

        RULE:  B.g (q x) = h x

Applying this rule makes f refer to h, although f doesn't appear to
depend on h.  (And, as in Note [Rules for imported functions], the
dependency might be more indirect. For example, f might mention C.t
rather than B.g, where C.t eventually inlines to B.g.)

NOTICE that this cannot happen for rules whose head is a
locally-defined function, because we accurately track dependencies
through RULES.  It only happens for rules whose head is an imported
function (B.g in the example above).

Solution:
  - When simplifying, bring all top level identifiers into
    scope at the start, ignoring the Rec/NonRec structure, so
    that when 'h' pops up in f's rhs, we find it in the in-scope set
    (as the simplifier generally expects). This happens in simplTopBinds.

  - In the occurrence analyser, if there are any out-of-scope
    occurrences that pop out of the top, which will happen after
    firing the rule:      f = \x -> h x
                          h = \y -> 3
    then just glom all the bindings into a single Rec, so that
    the *next* iteration of the occurrence analyser will sort
    them all out.   This part happens in occurAnalysePgm.

------------------------------------------------------------
Note [Inline rules]
~~~~~~~~~~~~~~~~~~~
None of the above stuff about RULES applies to Inline Rules,
stored in a CoreUnfolding.  The unfolding, if any, is simplified
at the same time as the regular RHS of the function (ie *not* like
Note [Rules are visible in their own rec group]), so it should be
treated *exactly* like an extra RHS.

Or, rather, when computing loop-breaker edges,
  * If f has an INLINE pragma, and it is active, we treat the
    INLINE rhs as f's rhs
  * If it's inactive, we treat f as having no rhs
  * If it has no INLINE pragma, we look at f's actual rhs


There is a danger that we'll be sub-optimal if we see this
     f = ...f...
     [INLINE f = ..no f...]
where f is recursive, but the INLINE is not. This can just about
happen with a sufficiently odd set of rules; eg

        foo :: Int -> Int
        {-# INLINE [1] foo #-}
        foo x = x+1

        bar :: Int -> Int
        {-# INLINE [1] bar #-}
        bar x = foo x + 1

        {-# RULES "foo" [~1] forall x. foo x = bar x #-}

Here the RULE makes bar recursive; but it's INLINE pragma remains
non-recursive. It's tempting to then say that 'bar' should not be
a loop breaker, but an attempt to do so goes wrong in two ways:
   a) We may get
         $df = ...$cfoo...
         $cfoo = ...$df....
         [INLINE $cfoo = ...no-$df...]
      But we want $cfoo to depend on $df explicitly so that we
      put the bindings in the right order to inline $df in $cfoo
      and perhaps break the loop altogether.  (Maybe this
   b)


Example [eftInt]
~~~~~~~~~~~~~~~
Example (from GHC.Enum):

  eftInt :: Int# -> Int# -> [Int]
  eftInt x y = ...(non-recursive)...

  {-# INLINE [0] eftIntFB #-}
  eftIntFB :: (Int -> r -> r) -> r -> Int# -> Int# -> r
  eftIntFB c n x y = ...(non-recursive)...

  {-# RULES
  "eftInt"  [~1] forall x y. eftInt x y = build (\ c n -> eftIntFB c n x y)
  "eftIntList"  [1] eftIntFB  (:) [] = eftInt
   #-}

Note [Specialisation rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider this group, which is typical of what SpecConstr builds:

   fs a = ....f (C a)....
   f  x = ....f (C a)....
   {-# RULE f (C a) = fs a #-}

So 'f' and 'fs' are in the same Rec group (since f refers to fs via its RULE).

But watch out!  If 'fs' is not chosen as a loop breaker, we may get an infinite loop:
  - the RULE is applied in f's RHS (see Note [Self-recursive rules] in GHC.Core.Opt.Simplify
  - fs is inlined (say it's small)
  - now there's another opportunity to apply the RULE

This showed up when compiling Control.Concurrent.Chan.getChanContents.

------------------------------------------------------------
Note [Finding join points]
~~~~~~~~~~~~~~~~~~~~~~~~~~
It's the occurrence analyser's job to find bindings that we can turn into join
points, but it doesn't perform that transformation right away. Rather, it marks
the eligible bindings as part of their occurrence data, leaving it to the
simplifier (or to simpleOptPgm) to actually change the binder's 'IdDetails'.
The simplifier then eta-expands the RHS if needed and then updates the
occurrence sites. Dividing the work this way means that the occurrence analyser
still only takes one pass, yet one can always tell the difference between a
function call and a jump by looking at the occurrence (because the same pass
changes the 'IdDetails' and propagates the binders to their occurrence sites).

To track potential join points, we use the 'occ_tail' field of OccInfo. A value
of `AlwaysTailCalled n` indicates that every occurrence of the variable is a
tail call with `n` arguments (counting both value and type arguments). Otherwise
'occ_tail' will be 'NoTailCallInfo'. The tail call info flows bottom-up with the
rest of 'OccInfo' until it goes on the binder.

Note [Join points and unfoldings/rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
   let j2 y = blah
   let j x = j2 (x+x)
       {-# INLINE [2] j #-}
   in case e of { A -> j 1; B -> ...; C -> j 2 }

Before j is inlined, we'll have occurrences of j2 in
both j's RHS and in its stable unfolding.  We want to discover
j2 as a join point.  So we must do the adjustRhsUsage thing
on j's RHS.  That's why we pass mb_join_arity to calcUnfolding.

Aame with rules. Suppose we have:

  let j :: Int -> Int
      j y = 2 * y
  let k :: Int -> Int -> Int
      {-# RULES "SPEC k 0" k 0 y = j y #-}
      k x y = x + 2 * y
  in case e of { A -> k 1 2; B -> k 3 5; C -> blah }

We identify k as a join point, and we want j to be a join point too.
Without the RULE it would be, and we don't want the RULE to mess it
up.  So provided the join-point arity of k matches the args of the
rule we can allow the tail-cal info from the RHS of the rule to
propagate.

* Wrinkle for Rec case. In the recursive case we don't know the
  join-point arity in advance, when calling occAnalUnfolding and
  occAnalRules.  (See makeNode.)  We don't want to pass Nothing,
  because then a recursive joinrec might lose its join-poin-hood
  when SpecConstr adds a RULE.  So we just make do with the
  *current* join-poin-hood, stored in the Id.

  In the non-recursive case things are simple: see occAnalNonRecBind

* Wrinkle for RULES.  Suppose the example was a bit different:
      let j :: Int -> Int
          j y = 2 * y
          k :: Int -> Int -> Int
          {-# RULES "SPEC k 0" k 0 = j #-}
          k x y = x + 2 * y
      in ...
  If we eta-expanded the rule all woudl be well, but as it stands the
  one arg of the rule don't match the join-point arity of 2.

  Conceivably we could notice that a potential join point would have
  an "undersaturated" rule and account for it. This would mean we
  could make something that's been specialised a join point, for
  instance. But local bindings are rarely specialised, and being
  overly cautious about rules only costs us anything when, for some `j`:

  * Before specialisation, `j` has non-tail calls, so it can't be a join point.
  * During specialisation, `j` gets specialised and thus acquires rules.
  * Sometime afterward, the non-tail calls to `j` disappear (as dead code, say),
    and so now `j` *could* become a join point.

  This appears to be very rare in practice. TODO Perhaps we should gather
  statistics to be sure.

------------------------------------------------------------
Note [Adjusting right-hand sides]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
There's a bit of a dance we need to do after analysing a lambda expression or
a right-hand side. In particular, we need to

  a) call 'markAllInsideLam' *unless* the binding is for a thunk, a one-shot
     lambda, or a non-recursive join point; and
  b) call 'markAllNonTail' *unless* the binding is for a join point.

Some examples, with how the free occurrences in e (assumed not to be a value
lambda) get marked:

                             inside lam    non-tail-called
  ------------------------------------------------------------
  let x = e                  No            Yes
  let f = \x -> e            Yes           Yes
  let f = \x{OneShot} -> e   No            Yes
  \x -> e                    Yes           Yes
  join j x = e               No            No
  joinrec j x = e            Yes           No

There are a few other caveats; most importantly, if we're marking a binding as
'AlwaysTailCalled', it's *going* to be a join point, so we treat it as one so
that the effect cascades properly. Consequently, at the time the RHS is
analysed, we won't know what adjustments to make; thus 'occAnalLamOrRhs' must
return the unadjusted 'UsageDetails', to be adjusted by 'adjustRhsUsage' once
join-point-hood has been decided.

Thus the overall sequence taking place in 'occAnalNonRecBind' and
'occAnalRecBind' is as follows:

  1. Call 'occAnalLamOrRhs' to find usage information for the RHS.
  2. Call 'tagNonRecBinder' or 'tagRecBinders', which decides whether to make
     the binding a join point.
  3. Call 'adjustRhsUsage' accordingly. (Done as part of 'tagRecBinders' when
     recursive.)

(In the recursive case, this logic is spread between 'makeNode' and
'occAnalRec'.)
-}

------------------------------------------------------------------
--                 occAnalBind
------------------------------------------------------------------

occAnalBind :: OccEnv           -- The incoming OccEnv
            -> TopLevelFlag
            -> ImpRuleEdges
            -> CoreBind
            -> UsageDetails             -- Usage details of scope
            -> (UsageDetails,           -- Of the whole let(rec)
                [CoreBind])

occAnalBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env (NonRec CoreBndr
binder CoreExpr
rhs) UsageDetails
body_usage
  = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBndr
-> CoreExpr
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalNonRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env CoreBndr
binder CoreExpr
rhs UsageDetails
body_usage
occAnalBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env (Rec [(CoreBndr, CoreExpr)]
pairs) UsageDetails
body_usage
  = OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(CoreBndr, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
top_env [(CoreBndr, CoreExpr)]
pairs UsageDetails
body_usage

-----------------
occAnalNonRecBind :: OccEnv -> TopLevelFlag -> ImpRuleEdges -> Var -> CoreExpr
                  -> UsageDetails -> (UsageDetails, [CoreBind])
occAnalNonRecBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBndr
-> CoreExpr
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalNonRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
imp_rule_edges CoreBndr
bndr CoreExpr
rhs UsageDetails
body_usage
  | CoreBndr -> Bool
isTyVar CoreBndr
bndr      -- A type let; we don't gather usage info
  = (UsageDetails
body_usage, [CoreBndr -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
bndr CoreExpr
rhs])

  | Bool -> Bool
not (CoreBndr
bndr CoreBndr -> UsageDetails -> Bool
`usedIn` UsageDetails
body_usage)    -- It's not mentioned
  = (UsageDetails
body_usage, [])

  | Bool
otherwise                   -- It's mentioned in the body
  = (UsageDetails
body_usage' UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
rhs_usage4, [CoreBndr -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
final_bndr CoreExpr
rhs'])
  where
    (UsageDetails
body_usage', CoreBndr
tagged_bndr) = TopLevelFlag
-> UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagNonRecBinder TopLevelFlag
lvl UsageDetails
body_usage CoreBndr
bndr
    occ :: OccInfo
occ                        = CoreBndr -> OccInfo
idOccInfo CoreBndr
tagged_bndr

    -- Get the join info from the *new* decision
    -- See Note [Join points and unfoldings/rules]
    mb_join_arity :: Maybe JoinArity
mb_join_arity = CoreBndr -> Maybe JoinArity
willBeJoinId_maybe CoreBndr
tagged_bndr
    is_join_point :: Bool
is_join_point = Maybe JoinArity -> Bool
forall a. Maybe a -> Bool
isJust Maybe JoinArity
mb_join_arity

    final_bndr :: CoreBndr
final_bndr = CoreBndr
tagged_bndr CoreBndr -> Unfolding -> CoreBndr
`setIdUnfolding` Unfolding
unf'
                             CoreBndr -> RuleInfo -> CoreBndr
`setIdSpecialisation` [CoreRule] -> RuleInfo
mkRuleInfo [CoreRule]
rules'

    env1 :: OccEnv
env1 | Bool
is_join_point    = OccEnv
env  -- See Note [Join point RHSs]
         | Bool
certainly_inline = OccEnv
env  -- See Note [Cascading inlines]
         | Bool
otherwise        = OccEnv -> OccEnv
rhsCtxt OccEnv
env

    -- See Note [Sources of one-shot information]
    rhs_env :: OccEnv
rhs_env = OccEnv
env1 { occ_one_shots :: OneShots
occ_one_shots = Demand -> OneShots
argOneShots Demand
dmd }

    (UsageDetails
rhs_usage1, CoreExpr
rhs') = OccEnv -> Maybe JoinArity -> CoreExpr -> (UsageDetails, CoreExpr)
occAnalRhs OccEnv
rhs_env Maybe JoinArity
mb_join_arity CoreExpr
rhs

    -- Unfoldings
    -- See Note [Unfoldings and join points]
    unf :: Unfolding
unf = CoreBndr -> Unfolding
idUnfolding CoreBndr
bndr
    (UsageDetails
unf_usage, Unfolding
unf') = OccEnv -> Maybe JoinArity -> Unfolding -> (UsageDetails, Unfolding)
occAnalUnfolding OccEnv
rhs_env Maybe JoinArity
mb_join_arity Unfolding
unf
    rhs_usage2 :: UsageDetails
rhs_usage2 = UsageDetails
rhs_usage1 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
unf_usage

    -- Rules
    -- See Note [Rules are extra RHSs] and Note [Rule dependency info]
    rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds = OccEnv
-> Maybe JoinArity
-> CoreBndr
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules OccEnv
rhs_env Maybe JoinArity
mb_join_arity CoreBndr
bndr
    rule_uds :: [UsageDetails]
rule_uds    = ((CoreRule, UsageDetails, UsageDetails) -> UsageDetails)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (\(CoreRule
_, UsageDetails
l, UsageDetails
r) -> UsageDetails
l UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
r) [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds
    rules' :: [CoreRule]
rules'      = ((CoreRule, UsageDetails, UsageDetails) -> CoreRule)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [CoreRule]
forall a b. (a -> b) -> [a] -> [b]
map (CoreRule, UsageDetails, UsageDetails) -> CoreRule
forall a b c. (a, b, c) -> a
fstOf3 [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds
    rhs_usage3 :: UsageDetails
rhs_usage3 = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
rhs_usage2 [UsageDetails]
rule_uds
    rhs_usage4 :: UsageDetails
rhs_usage4 = case ImpRuleEdges -> CoreBndr -> Maybe VarSet
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv ImpRuleEdges
imp_rule_edges CoreBndr
bndr of
                   Maybe VarSet
Nothing -> UsageDetails
rhs_usage3
                   Just VarSet
vs -> UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
rhs_usage3 VarSet
vs
       -- See Note [Preventing loops due to imported functions rules]

    certainly_inline :: Bool
certainly_inline -- See Note [Cascading inlines]
      = case OccInfo
occ of
          OneOcc { occ_in_lam :: OccInfo -> InsideLam
occ_in_lam = InsideLam
NotInsideLam, occ_n_br :: OccInfo -> JoinArity
occ_n_br = JoinArity
1 }
            -> Bool
active Bool -> Bool -> Bool
&& Bool
not_stable
          OccInfo
_ -> Bool
False

    dmd :: Demand
dmd        = CoreBndr -> Demand
idDemandInfo CoreBndr
bndr
    active :: Bool
active     = Activation -> Bool
isAlwaysActive (CoreBndr -> Activation
idInlineActivation CoreBndr
bndr)
    not_stable :: Bool
not_stable = Bool -> Bool
not (Unfolding -> Bool
isStableUnfolding (CoreBndr -> Unfolding
idUnfolding CoreBndr
bndr))

-----------------
occAnalRecBind :: OccEnv -> TopLevelFlag -> ImpRuleEdges -> [(Var,CoreExpr)]
               -> UsageDetails -> (UsageDetails, [CoreBind])
occAnalRecBind :: OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> [(CoreBndr, CoreExpr)]
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalRecBind OccEnv
env TopLevelFlag
lvl ImpRuleEdges
imp_rule_edges [(CoreBndr, CoreExpr)]
pairs UsageDetails
body_usage
  = (SCC Details
 -> (UsageDetails, CoreProgram) -> (UsageDetails, CoreProgram))
-> (UsageDetails, CoreProgram)
-> [SCC Details]
-> (UsageDetails, CoreProgram)
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr (OccEnv
-> TopLevelFlag
-> SCC Details
-> (UsageDetails, CoreProgram)
-> (UsageDetails, CoreProgram)
occAnalRec OccEnv
rhs_env TopLevelFlag
lvl) (UsageDetails
body_usage, []) [SCC Details]
sccs
        -- For a recursive group, we
        --      * occ-analyse all the RHSs
        --      * compute strongly-connected components
        --      * feed those components to occAnalRec
        -- See Note [Recursive bindings: the grand plan]
  where
    sccs :: [SCC Details]
    sccs :: [SCC Details]
sccs = {-# SCC "occAnalBind.scc" #-}
           [Node Unique Details] -> [SCC Details]
forall key payload.
Uniquable key =>
[Node key payload] -> [SCC payload]
stronglyConnCompFromEdgedVerticesUniq [Node Unique Details]
nodes

    nodes :: [LetrecNode]
    nodes :: [Node Unique Details]
nodes = {-# SCC "occAnalBind.assoc" #-}
            ((CoreBndr, CoreExpr) -> Node Unique Details)
-> [(CoreBndr, CoreExpr)] -> [Node Unique Details]
forall a b. (a -> b) -> [a] -> [b]
map (OccEnv
-> ImpRuleEdges
-> VarSet
-> (CoreBndr, CoreExpr)
-> Node Unique Details
makeNode OccEnv
rhs_env ImpRuleEdges
imp_rule_edges VarSet
bndr_set) [(CoreBndr, CoreExpr)]
pairs

    bndrs :: [CoreBndr]
bndrs    = ((CoreBndr, CoreExpr) -> CoreBndr)
-> [(CoreBndr, CoreExpr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, CoreExpr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, CoreExpr)]
pairs
    bndr_set :: VarSet
bndr_set = [CoreBndr] -> VarSet
mkVarSet [CoreBndr]
bndrs
    rhs_env :: OccEnv
rhs_env  = OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr]
bndrs

{-
Note [Unfoldings and join points]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

We assume that anything in an unfolding occurs multiple times, since unfoldings
are often copied (that's the whole point!). But we still need to track tail
calls for the purpose of finding join points.
-}

-----------------------------
occAnalRec :: OccEnv -> TopLevelFlag
           -> SCC Details
           -> (UsageDetails, [CoreBind])
           -> (UsageDetails, [CoreBind])

        -- The NonRec case is just like a Let (NonRec ...) above
occAnalRec :: OccEnv
-> TopLevelFlag
-> SCC Details
-> (UsageDetails, CoreProgram)
-> (UsageDetails, CoreProgram)
occAnalRec OccEnv
_ TopLevelFlag
lvl (AcyclicSCC (ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs
                                 , nd_uds :: Details -> UsageDetails
nd_uds = UsageDetails
rhs_uds, nd_rhs_bndrs :: Details -> [CoreBndr]
nd_rhs_bndrs = [CoreBndr]
rhs_bndrs }))
           (UsageDetails
body_uds, CoreProgram
binds)
  | Bool -> Bool
not (CoreBndr
bndr CoreBndr -> UsageDetails -> Bool
`usedIn` UsageDetails
body_uds)
  = (UsageDetails
body_uds, CoreProgram
binds)           -- See Note [Dead code]

  | Bool
otherwise                   -- It's mentioned in the body
  = (UsageDetails
body_uds' UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
rhs_uds',
     CoreBndr -> CoreExpr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
tagged_bndr CoreExpr
rhs CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
binds)
  where
    (UsageDetails
body_uds', CoreBndr
tagged_bndr) = TopLevelFlag
-> UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagNonRecBinder TopLevelFlag
lvl UsageDetails
body_uds CoreBndr
bndr
    rhs_uds' :: UsageDetails
rhs_uds' = Maybe JoinArity
-> RecFlag -> [CoreBndr] -> UsageDetails -> UsageDetails
adjustRhsUsage (CoreBndr -> Maybe JoinArity
willBeJoinId_maybe CoreBndr
tagged_bndr) RecFlag
NonRecursive
                              [CoreBndr]
rhs_bndrs UsageDetails
rhs_uds

        -- The Rec case is the interesting one
        -- See Note [Recursive bindings: the grand plan]
        -- See Note [Loop breaking]
occAnalRec OccEnv
env TopLevelFlag
lvl (CyclicSCC [Details]
details_s) (UsageDetails
body_uds, CoreProgram
binds)
  | Bool -> Bool
not ((CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CoreBndr -> UsageDetails -> Bool
`usedIn` UsageDetails
body_uds) [CoreBndr]
bndrs) -- NB: look at body_uds, not total_uds
  = (UsageDetails
body_uds, CoreProgram
binds)                   -- See Note [Dead code]

  | Bool
otherwise   -- At this point we always build a single Rec
  = -- pprTrace "occAnalRec" (vcat
    --   [ text "weak_fvs" <+> ppr weak_fvs
    --   , text "lb nodes" <+> ppr loop_breaker_nodes])
    (UsageDetails
final_uds, [(CoreBndr, CoreExpr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, CoreExpr)]
pairs CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
binds)

  where
    bndrs :: [CoreBndr]
bndrs    = (Details -> CoreBndr) -> [Details] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map Details -> CoreBndr
nd_bndr [Details]
details_s
    bndr_set :: VarSet
bndr_set = [CoreBndr] -> VarSet
mkVarSet [CoreBndr]
bndrs

    ------------------------------
        -- See Note [Choosing loop breakers] for loop_breaker_nodes
    final_uds :: UsageDetails
    loop_breaker_nodes :: [LetrecNode]
    (UsageDetails
final_uds, [Node Unique Details]
loop_breaker_nodes)
      = OccEnv
-> TopLevelFlag
-> VarSet
-> UsageDetails
-> [Details]
-> (UsageDetails, [Node Unique Details])
mkLoopBreakerNodes OccEnv
env TopLevelFlag
lvl VarSet
bndr_set UsageDetails
body_uds [Details]
details_s

    ------------------------------
    weak_fvs :: VarSet
    weak_fvs :: VarSet
weak_fvs = (Details -> VarSet) -> [Details] -> VarSet
forall a. (a -> VarSet) -> [a] -> VarSet
mapUnionVarSet Details -> VarSet
nd_weak [Details]
details_s

    ---------------------------
    -- Now reconstruct the cycle
    pairs :: [(Id,CoreExpr)]
    pairs :: [(CoreBndr, CoreExpr)]
pairs | VarSet -> Bool
isEmptyVarSet VarSet
weak_fvs = JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
reOrderNodes   JoinArity
0 VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
loop_breaker_nodes []
          | Bool
otherwise              = JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
loopBreakNodes JoinArity
0 VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
loop_breaker_nodes []
          -- If weak_fvs is empty, the loop_breaker_nodes will include
          -- all the edges in the original scope edges [remember,
          -- weak_fvs is the difference between scope edges and
          -- lb-edges], so a fresh SCC computation would yield a
          -- single CyclicSCC result; and reOrderNodes deals with
          -- exactly that case


------------------------------------------------------------------
--                 Loop breaking
------------------------------------------------------------------

type Binding = (Id,CoreExpr)

loopBreakNodes :: Int
               -> VarSet        -- All binders
               -> VarSet        -- Binders whose dependencies may be "missing"
                                -- See Note [Weak loop breakers]
               -> [LetrecNode]
               -> [Binding]             -- Append these to the end
               -> [Binding]
{-
loopBreakNodes is applied to the list of nodes for a cyclic strongly
connected component (there's guaranteed to be a cycle).  It returns
the same nodes, but
        a) in a better order,
        b) with some of the Ids having a IAmALoopBreaker pragma

The "loop-breaker" Ids are sufficient to break all cycles in the SCC.  This means
that the simplifier can guarantee not to loop provided it never records an inlining
for these no-inline guys.

Furthermore, the order of the binds is such that if we neglect dependencies
on the no-inline Ids then the binds are topologically sorted.  This means
that the simplifier will generally do a good job if it works from top bottom,
recording inlinings for any Ids which aren't marked as "no-inline" as it goes.
-}

-- Return the bindings sorted into a plausible order, and marked with loop breakers.
loopBreakNodes :: JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
loopBreakNodes JoinArity
depth VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
nodes [(CoreBndr, CoreExpr)]
binds
  = -- pprTrace "loopBreakNodes" (ppr nodes) $
    [SCC (Node Unique Details)] -> [(CoreBndr, CoreExpr)]
go ([Node Unique Details] -> [SCC (Node Unique Details)]
forall key payload.
Uniquable key =>
[Node key payload] -> [SCC (Node key payload)]
stronglyConnCompFromEdgedVerticesUniqR [Node Unique Details]
nodes)
  where
    go :: [SCC (Node Unique Details)] -> [(CoreBndr, CoreExpr)]
go []         = [(CoreBndr, CoreExpr)]
binds
    go (SCC (Node Unique Details)
scc:[SCC (Node Unique Details)]
sccs) = SCC (Node Unique Details)
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
loop_break_scc SCC (Node Unique Details)
scc ([SCC (Node Unique Details)] -> [(CoreBndr, CoreExpr)]
go [SCC (Node Unique Details)]
sccs)

    loop_break_scc :: SCC (Node Unique Details)
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
loop_break_scc SCC (Node Unique Details)
scc [(CoreBndr, CoreExpr)]
binds
      = case SCC (Node Unique Details)
scc of
          AcyclicSCC Node Unique Details
node  -> VarSet -> Node Unique Details -> (CoreBndr, CoreExpr)
mk_non_loop_breaker VarSet
weak_fvs Node Unique Details
node (CoreBndr, CoreExpr)
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
forall a. a -> [a] -> [a]
: [(CoreBndr, CoreExpr)]
binds
          CyclicSCC [Node Unique Details]
nodes  -> JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
reOrderNodes JoinArity
depth VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
nodes [(CoreBndr, CoreExpr)]
binds

----------------------------------
reOrderNodes :: Int -> VarSet -> VarSet -> [LetrecNode] -> [Binding] -> [Binding]
    -- Choose a loop breaker, mark it no-inline,
    -- and call loopBreakNodes on the rest
reOrderNodes :: JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
reOrderNodes JoinArity
_ VarSet
_ VarSet
_ []     [(CoreBndr, CoreExpr)]
_     = String -> [(CoreBndr, CoreExpr)]
forall a. String -> a
panic String
"reOrderNodes"
reOrderNodes JoinArity
_ VarSet
_ VarSet
_ [Node Unique Details
node] [(CoreBndr, CoreExpr)]
binds = Node Unique Details -> (CoreBndr, CoreExpr)
mk_loop_breaker Node Unique Details
node (CoreBndr, CoreExpr)
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
forall a. a -> [a] -> [a]
: [(CoreBndr, CoreExpr)]
binds
reOrderNodes JoinArity
depth VarSet
bndr_set VarSet
weak_fvs (Node Unique Details
node : [Node Unique Details]
nodes) [(CoreBndr, CoreExpr)]
binds
  = -- pprTrace "reOrderNodes" (vcat [ text "unchosen" <+> ppr unchosen
    --                               , text "chosen" <+> ppr chosen_nodes ]) $
    JoinArity
-> VarSet
-> VarSet
-> [Node Unique Details]
-> [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)]
loopBreakNodes JoinArity
new_depth VarSet
bndr_set VarSet
weak_fvs [Node Unique Details]
unchosen ([(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)])
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
forall a b. (a -> b) -> a -> b
$
    ((Node Unique Details -> (CoreBndr, CoreExpr))
-> [Node Unique Details] -> [(CoreBndr, CoreExpr)]
forall a b. (a -> b) -> [a] -> [b]
map Node Unique Details -> (CoreBndr, CoreExpr)
mk_loop_breaker [Node Unique Details]
chosen_nodes [(CoreBndr, CoreExpr)]
-> [(CoreBndr, CoreExpr)] -> [(CoreBndr, CoreExpr)]
forall a. [a] -> [a] -> [a]
++ [(CoreBndr, CoreExpr)]
binds)
  where
    ([Node Unique Details]
chosen_nodes, [Node Unique Details]
unchosen) = Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approximate_lb
                                                 (Details -> NodeScore
nd_score (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload Node Unique Details
node))
                                                 [Node Unique Details
node] [] [Node Unique Details]
nodes

    approximate_lb :: Bool
approximate_lb = JoinArity
depth JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
>= JoinArity
2
    new_depth :: JoinArity
new_depth | Bool
approximate_lb = JoinArity
0
              | Bool
otherwise      = JoinArity
depthJoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+JoinArity
1
        -- After two iterations (d=0, d=1) give up
        -- and approximate, returning to d=0

mk_loop_breaker :: LetrecNode -> Binding
mk_loop_breaker :: Node Unique Details -> (CoreBndr, CoreExpr)
mk_loop_breaker (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload -> ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs})
  = (CoreBndr
bndr CoreBndr -> OccInfo -> CoreBndr
`setIdOccInfo` OccInfo
strongLoopBreaker { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
tail_info }, CoreExpr
rhs)
  where
    tail_info :: TailCallInfo
tail_info = OccInfo -> TailCallInfo
tailCallInfo (CoreBndr -> OccInfo
idOccInfo CoreBndr
bndr)

mk_non_loop_breaker :: VarSet -> LetrecNode -> Binding
-- See Note [Weak loop breakers]
mk_non_loop_breaker :: VarSet -> Node Unique Details -> (CoreBndr, CoreExpr)
mk_non_loop_breaker VarSet
weak_fvs (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload -> ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
bndr
                                                 , nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
rhs})
  | CoreBndr
bndr CoreBndr -> VarSet -> Bool
`elemVarSet` VarSet
weak_fvs = (CoreBndr -> OccInfo -> CoreBndr
setIdOccInfo CoreBndr
bndr OccInfo
occ', CoreExpr
rhs)
  | Bool
otherwise                  = (CoreBndr
bndr, CoreExpr
rhs)
  where
    occ' :: OccInfo
occ' = OccInfo
weakLoopBreaker { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
tail_info }
    tail_info :: TailCallInfo
tail_info = OccInfo -> TailCallInfo
tailCallInfo (CoreBndr -> OccInfo
idOccInfo CoreBndr
bndr)

----------------------------------
chooseLoopBreaker :: Bool             -- True <=> Too many iterations,
                                      --          so approximate
                  -> NodeScore            -- Best score so far
                  -> [LetrecNode]       -- Nodes with this score
                  -> [LetrecNode]       -- Nodes with higher scores
                  -> [LetrecNode]       -- Unprocessed nodes
                  -> ([LetrecNode], [LetrecNode])
    -- This loop looks for the bind with the lowest score
    -- to pick as the loop  breaker.  The rest accumulate in
chooseLoopBreaker :: Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
_ NodeScore
_ [Node Unique Details]
loop_nodes [Node Unique Details]
acc []
  = ([Node Unique Details]
loop_nodes, [Node Unique Details]
acc)        -- Done

    -- If approximate_loop_breaker is True, we pick *all*
    -- nodes with lowest score, else just one
    -- See Note [Complexity of loop breaking]
chooseLoopBreaker Bool
approx_lb NodeScore
loop_sc [Node Unique Details]
loop_nodes [Node Unique Details]
acc (Node Unique Details
node : [Node Unique Details]
nodes)
  | Bool
approx_lb
  , NodeScore -> JoinArity
rank NodeScore
sc JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
== NodeScore -> JoinArity
rank NodeScore
loop_sc
  = Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
loop_sc (Node Unique Details
node Node Unique Details
-> [Node Unique Details] -> [Node Unique Details]
forall a. a -> [a] -> [a]
: [Node Unique Details]
loop_nodes) [Node Unique Details]
acc [Node Unique Details]
nodes

  | NodeScore
sc NodeScore -> NodeScore -> Bool
`betterLB` NodeScore
loop_sc  -- Better score so pick this new one
  = Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
sc [Node Unique Details
node] ([Node Unique Details]
loop_nodes [Node Unique Details]
-> [Node Unique Details] -> [Node Unique Details]
forall a. [a] -> [a] -> [a]
++ [Node Unique Details]
acc) [Node Unique Details]
nodes

  | Bool
otherwise              -- Worse score so don't pick it
  = Bool
-> NodeScore
-> [Node Unique Details]
-> [Node Unique Details]
-> [Node Unique Details]
-> ([Node Unique Details], [Node Unique Details])
chooseLoopBreaker Bool
approx_lb NodeScore
loop_sc [Node Unique Details]
loop_nodes (Node Unique Details
node Node Unique Details
-> [Node Unique Details] -> [Node Unique Details]
forall a. a -> [a] -> [a]
: [Node Unique Details]
acc) [Node Unique Details]
nodes
  where
    sc :: NodeScore
sc = Details -> NodeScore
nd_score (Node Unique Details -> Details
forall key payload. Node key payload -> payload
node_payload Node Unique Details
node)

{-
Note [Complexity of loop breaking]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The loop-breaking algorithm knocks out one binder at a time, and
performs a new SCC analysis on the remaining binders.  That can
behave very badly in tightly-coupled groups of bindings; in the
worst case it can be (N**2)*log N, because it does a full SCC
on N, then N-1, then N-2 and so on.

To avoid this, we switch plans after 2 (or whatever) attempts:
  Plan A: pick one binder with the lowest score, make it
          a loop breaker, and try again
  Plan B: pick *all* binders with the lowest score, make them
          all loop breakers, and try again
Since there are only a small finite number of scores, this will
terminate in a constant number of iterations, rather than O(N)
iterations.

You might thing that it's very unlikely, but RULES make it much
more likely.  Here's a real example from #1969:
  Rec { $dm = \d.\x. op d
        {-# RULES forall d. $dm Int d  = $s$dm1
                  forall d. $dm Bool d = $s$dm2 #-}

        dInt = MkD .... opInt ...
        dInt = MkD .... opBool ...
        opInt  = $dm dInt
        opBool = $dm dBool

        $s$dm1 = \x. op dInt
        $s$dm2 = \x. op dBool }
The RULES stuff means that we can't choose $dm as a loop breaker
(Note [Choosing loop breakers]), so we must choose at least (say)
opInt *and* opBool, and so on.  The number of loop breakders is
linear in the number of instance declarations.

Note [Loop breakers and INLINE/INLINABLE pragmas]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Avoid choosing a function with an INLINE pramga as the loop breaker!
If such a function is mutually-recursive with a non-INLINE thing,
then the latter should be the loop-breaker.

It's vital to distinguish between INLINE and INLINABLE (the
Bool returned by hasStableCoreUnfolding_maybe).  If we start with
   Rec { {-# INLINABLE f #-}
         f x = ...f... }
and then worker/wrapper it through strictness analysis, we'll get
   Rec { {-# INLINABLE $wf #-}
         $wf p q = let x = (p,q) in ...f...

         {-# INLINE f #-}
         f x = case x of (p,q) -> $wf p q }

Now it is vital that we choose $wf as the loop breaker, so we can
inline 'f' in '$wf'.

Note [DFuns should not be loop breakers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's particularly bad to make a DFun into a loop breaker.  See
Note [How instance declarations are translated] in GHC.Tc.TyCl.Instance

We give DFuns a higher score than ordinary CONLIKE things because
if there's a choice we want the DFun to be the non-loop breaker. Eg

rec { sc = /\ a \$dC. $fBWrap (T a) ($fCT @ a $dC)

      $fCT :: forall a_afE. (Roman.C a_afE) => Roman.C (Roman.T a_afE)
      {-# DFUN #-}
      $fCT = /\a \$dC. MkD (T a) ((sc @ a $dC) |> blah) ($ctoF @ a $dC)
    }

Here 'sc' (the superclass) looks CONLIKE, but we'll never get to it
if we can't unravel the DFun first.

Note [Constructor applications]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's really really important to inline dictionaries.  Real
example (the Enum Ordering instance from GHC.Base):

     rec     f = \ x -> case d of (p,q,r) -> p x
             g = \ x -> case d of (p,q,r) -> q x
             d = (v, f, g)

Here, f and g occur just once; but we can't inline them into d.
On the other hand we *could* simplify those case expressions if
we didn't stupidly choose d as the loop breaker.
But we won't because constructor args are marked "Many".
Inlining dictionaries is really essential to unravelling
the loops in static numeric dictionaries, see GHC.Float.

Note [Closure conversion]
~~~~~~~~~~~~~~~~~~~~~~~~~
We treat (\x. C p q) as a high-score candidate in the letrec scoring algorithm.
The immediate motivation came from the result of a closure-conversion transformation
which generated code like this:

    data Clo a b = forall c. Clo (c -> a -> b) c

    ($:) :: Clo a b -> a -> b
    Clo f env $: x = f env x

    rec { plus = Clo plus1 ()

        ; plus1 _ n = Clo plus2 n

        ; plus2 Zero     n = n
        ; plus2 (Succ m) n = Succ (plus $: m $: n) }

If we inline 'plus' and 'plus1', everything unravels nicely.  But if
we choose 'plus1' as the loop breaker (which is entirely possible
otherwise), the loop does not unravel nicely.


@occAnalUnfolding@ deals with the question of bindings where the Id is marked
by an INLINE pragma.  For these we record that anything which occurs
in its RHS occurs many times.  This pessimistically assumes that this
inlined binder also occurs many times in its scope, but if it doesn't
we'll catch it next time round.  At worst this costs an extra simplifier pass.
ToDo: try using the occurrence info for the inline'd binder.

[March 97] We do the same for atomic RHSs.  Reason: see notes with loopBreakSCC.
[June 98, SLPJ]  I've undone this change; I don't understand it.  See notes with loopBreakSCC.


************************************************************************
*                                                                      *
                   Making nodes
*                                                                      *
************************************************************************
-}

type ImpRuleEdges = IdEnv IdSet     -- Mapping from FVs of imported RULE LHSs to RHS FVs

noImpRuleEdges :: ImpRuleEdges
noImpRuleEdges :: ImpRuleEdges
noImpRuleEdges = ImpRuleEdges
forall a. VarEnv a
emptyVarEnv

type LetrecNode = Node Unique Details  -- Node comes from Digraph
                                       -- The Unique key is gotten from the Id
data Details
  = ND { Details -> CoreBndr
nd_bndr :: Id          -- Binder

       , Details -> CoreExpr
nd_rhs  :: CoreExpr    -- RHS, already occ-analysed

       , Details -> [CoreBndr]
nd_rhs_bndrs :: [CoreBndr] -- Outer lambdas of RHS
                                    -- INVARIANT: (nd_rhs_bndrs nd, _) ==
                                    --              collectBinders (nd_rhs nd)

       , Details -> UsageDetails
nd_uds  :: UsageDetails  -- Usage from RHS, and RULES, and stable unfoldings
                                  -- ignoring phase (ie assuming all are active)
                                  -- See Note [Forming Rec groups]

       , Details -> VarSet
nd_inl  :: IdSet       -- Free variables of
                                --   the stable unfolding (if present and active)
                                --   or the RHS (if not)
                                -- but excluding any RULES
                                -- This is the IdSet that may be used if the Id is inlined

       , Details -> VarSet
nd_weak :: IdSet       -- Binders of this Rec that are mentioned in nd_uds
                                -- but are *not* in nd_inl.  These are the ones whose
                                -- dependencies might not be respected by loop_breaker_nodes
                                -- See Note [Weak loop breakers]

       , Details -> VarSet
nd_active_rule_fvs :: IdSet   -- Free variables of the RHS of active RULES

       , Details -> NodeScore
nd_score :: NodeScore
  }

instance Outputable Details where
   ppr :: Details -> SDoc
ppr Details
nd = String -> SDoc
text String
"ND" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
braces
             ([SDoc] -> SDoc
sep [ String -> SDoc
text String
"bndr =" SDoc -> SDoc -> SDoc
<+> CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> CoreBndr
nd_bndr Details
nd)
                  , String -> SDoc
text String
"uds =" SDoc -> SDoc -> SDoc
<+> UsageDetails -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> UsageDetails
nd_uds Details
nd)
                  , String -> SDoc
text String
"inl =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_inl Details
nd)
                  , String -> SDoc
text String
"weak =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_weak Details
nd)
                  , String -> SDoc
text String
"rule =" SDoc -> SDoc -> SDoc
<+> VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> VarSet
nd_active_rule_fvs Details
nd)
                  , String -> SDoc
text String
"score =" SDoc -> SDoc -> SDoc
<+> NodeScore -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Details -> NodeScore
nd_score Details
nd)
             ])

-- The NodeScore is compared lexicographically;
--      e.g. lower rank wins regardless of size
type NodeScore = ( Int     -- Rank: lower => more likely to be picked as loop breaker
                 , Int     -- Size of rhs: higher => more likely to be picked as LB
                           -- Maxes out at maxExprSize; we just use it to prioritise
                           -- small functions
                 , Bool )  -- Was it a loop breaker before?
                           -- True => more likely to be picked
                           -- Note [Loop breakers, node scoring, and stability]

rank :: NodeScore -> Int
rank :: NodeScore -> JoinArity
rank (JoinArity
r, JoinArity
_, Bool
_) = JoinArity
r

makeNode :: OccEnv -> ImpRuleEdges -> VarSet
         -> (Var, CoreExpr) -> LetrecNode
-- See Note [Recursive bindings: the grand plan]
makeNode :: OccEnv
-> ImpRuleEdges
-> VarSet
-> (CoreBndr, CoreExpr)
-> Node Unique Details
makeNode OccEnv
env ImpRuleEdges
imp_rule_edges VarSet
bndr_set (CoreBndr
bndr, CoreExpr
rhs)
  = Details -> Unique -> [Unique] -> Node Unique Details
forall key payload. payload -> key -> [key] -> Node key payload
DigraphNode Details
details (CoreBndr -> Unique
varUnique CoreBndr
bndr) (VarSet -> [Unique]
forall elt. UniqSet elt -> [Unique]
nonDetKeysUniqSet VarSet
node_fvs)
    -- It's OK to use nonDetKeysUniqSet here as stronglyConnCompFromEdgedVerticesR
    -- is still deterministic with edges in nondeterministic order as
    -- explained in Note [Deterministic SCC] in GHC.Data.Graph.Directed.
  where
    details :: Details
details = ND :: CoreBndr
-> CoreExpr
-> [CoreBndr]
-> UsageDetails
-> VarSet
-> VarSet
-> VarSet
-> NodeScore
-> Details
ND { nd_bndr :: CoreBndr
nd_bndr            = CoreBndr
bndr'
                 , nd_rhs :: CoreExpr
nd_rhs             = CoreExpr
rhs'
                 , nd_rhs_bndrs :: [CoreBndr]
nd_rhs_bndrs       = [CoreBndr]
bndrs'
                 , nd_uds :: UsageDetails
nd_uds             = UsageDetails
rhs_usage3
                 , nd_inl :: VarSet
nd_inl             = VarSet
inl_fvs
                 , nd_weak :: VarSet
nd_weak            = VarSet
node_fvs VarSet -> VarSet -> VarSet
`minusVarSet` VarSet
inl_fvs
                 , nd_active_rule_fvs :: VarSet
nd_active_rule_fvs = VarSet
active_rule_fvs
                 , nd_score :: NodeScore
nd_score           = String -> SDoc -> NodeScore
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"makeNodeDetails" (CoreBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBndr
bndr) }

    bndr' :: CoreBndr
bndr' = CoreBndr
bndr CoreBndr -> Unfolding -> CoreBndr
`setIdUnfolding`      Unfolding
unf'
                 CoreBndr -> RuleInfo -> CoreBndr
`setIdSpecialisation` [CoreRule] -> RuleInfo
mkRuleInfo [CoreRule]
rules'

    -- Get join point info from the *current* decision
    -- We don't know what the new decision will be!
    -- Using the old decision at least allows us to
    -- preserve existing join point, even RULEs are added
    -- See Note [Join points and unfoldings/rules]
    mb_join_arity :: Maybe JoinArity
mb_join_arity = CoreBndr -> Maybe JoinArity
isJoinId_maybe CoreBndr
bndr

    -- Constructing the edges for the main Rec computation
    -- See Note [Forming Rec groups]
    ([CoreBndr]
bndrs, CoreExpr
body) = CoreExpr -> ([CoreBndr], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs
    rhs_env :: OccEnv
rhs_env       = OccEnv -> OccEnv
rhsCtxt OccEnv
env
    (UsageDetails
rhs_usage1, [CoreBndr]
bndrs', CoreExpr
body') = OccEnv
-> [CoreBndr] -> CoreExpr -> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs OccEnv
rhs_env [CoreBndr]
bndrs CoreExpr
body
    rhs' :: CoreExpr
rhs'       = [CoreBndr] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
bndrs' CoreExpr
body'
    rhs_usage3 :: UsageDetails
rhs_usage3 = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
rhs_usage1 [UsageDetails]
rule_uds
                 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
unf_uds
                   -- Note [Rules are extra RHSs]
                   -- Note [Rule dependency info]
    node_fvs :: VarSet
node_fvs   = VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_usage3

    -- Finding the free variables of the rules
    is_active :: Activation -> Bool
is_active = OccEnv -> Activation -> Bool
occ_rule_act OccEnv
env :: Activation -> Bool

    rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
    rules_w_uds :: [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds = OccEnv
-> Maybe JoinArity
-> CoreBndr
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules OccEnv
rhs_env Maybe JoinArity
mb_join_arity CoreBndr
bndr

    rules' :: [CoreRule]
rules' = ((CoreRule, UsageDetails, UsageDetails) -> CoreRule)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [CoreRule]
forall a b. (a -> b) -> [a] -> [b]
map (CoreRule, UsageDetails, UsageDetails) -> CoreRule
forall a b c. (a, b, c) -> a
fstOf3 [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds

    rules_w_rhs_fvs :: [(Activation, VarSet)]    -- Find the RHS fvs
    rules_w_rhs_fvs :: [(Activation, VarSet)]
rules_w_rhs_fvs = ([(Activation, VarSet)] -> [(Activation, VarSet)])
-> (VarSet -> [(Activation, VarSet)] -> [(Activation, VarSet)])
-> Maybe VarSet
-> [(Activation, VarSet)]
-> [(Activation, VarSet)]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [(Activation, VarSet)] -> [(Activation, VarSet)]
forall a. a -> a
id (\VarSet
ids -> ((Activation
AlwaysActive, VarSet
ids)(Activation, VarSet)
-> [(Activation, VarSet)] -> [(Activation, VarSet)]
forall a. a -> [a] -> [a]
:))
                               (ImpRuleEdges -> CoreBndr -> Maybe VarSet
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv ImpRuleEdges
imp_rule_edges CoreBndr
bndr)
      -- See Note [Preventing loops due to imported functions rules]
                      [ (CoreRule -> Activation
ru_act CoreRule
rule, VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_uds)
                      | (CoreRule
rule, UsageDetails
_, UsageDetails
rhs_uds) <- [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds ]
    rule_uds :: [UsageDetails]
rule_uds = ((CoreRule, UsageDetails, UsageDetails) -> UsageDetails)
-> [(CoreRule, UsageDetails, UsageDetails)] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (\(CoreRule
_, UsageDetails
l, UsageDetails
r) -> UsageDetails
l UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
r) [(CoreRule, UsageDetails, UsageDetails)]
rules_w_uds
    active_rule_fvs :: VarSet
active_rule_fvs = [VarSet] -> VarSet
unionVarSets [VarSet
fvs | (Activation
a,VarSet
fvs) <- [(Activation, VarSet)]
rules_w_rhs_fvs
                                        , Activation -> Bool
is_active Activation
a]

    -- Finding the usage details of the INLINE pragma (if any)
    unf :: Unfolding
unf = CoreBndr -> Unfolding
realIdUnfolding CoreBndr
bndr -- realIdUnfolding: Ignore loop-breaker-ness
                               -- here because that is what we are setting!
    (UsageDetails
unf_uds, Unfolding
unf') = OccEnv -> Maybe JoinArity -> Unfolding -> (UsageDetails, Unfolding)
occAnalUnfolding OccEnv
rhs_env Maybe JoinArity
mb_join_arity Unfolding
unf

    -- Find the "nd_inl" free vars; for the loop-breaker phase
    -- These are the vars that would become free if the function
    -- was inlinined; usually that means the RHS, unless the
    -- unfolding is a stable one.
    -- Note: We could do this only for functions with an *active* unfolding
    --       (returning emptyVarSet for an inactive one), but is_active
    --       isn't the right thing (it tells about RULE activation),
    --       so we'd need more plumbing
    inl_fvs :: VarSet
inl_fvs | Unfolding -> Bool
isStableUnfolding Unfolding
unf = VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
unf_uds
            | Bool
otherwise             = VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndr_set UsageDetails
rhs_usage1

mkLoopBreakerNodes :: OccEnv -> TopLevelFlag
                   -> VarSet
                   -> UsageDetails   -- for BODY of let
                   -> [Details]
                   -> (UsageDetails, -- adjusted
                       [LetrecNode])
-- Does four things
--   a) tag each binder with its occurrence info
--   b) add a NodeScore to each node
--   c) make a Node with the right dependency edges for
--      the loop-breaker SCC analysis
--   d) adjust each RHS's usage details according to
--      the binder's (new) shotness and join-point-hood
mkLoopBreakerNodes :: OccEnv
-> TopLevelFlag
-> VarSet
-> UsageDetails
-> [Details]
-> (UsageDetails, [Node Unique Details])
mkLoopBreakerNodes OccEnv
env TopLevelFlag
lvl VarSet
bndr_set UsageDetails
body_uds [Details]
details_s
  = (UsageDetails
final_uds, String
-> (Details -> CoreBndr -> Node Unique Details)
-> [Details]
-> [CoreBndr]
-> [Node Unique Details]
forall a b c. String -> (a -> b -> c) -> [a] -> [b] -> [c]
zipWithEqual String
"mkLoopBreakerNodes" Details -> CoreBndr -> Node Unique Details
mk_lb_node [Details]
details_s [CoreBndr]
bndrs')
  where
    (UsageDetails
final_uds, [CoreBndr]
bndrs')
       = TopLevelFlag
-> UsageDetails
-> [(CoreBndr, UsageDetails, [CoreBndr])]
-> (UsageDetails, [CoreBndr])
tagRecBinders TopLevelFlag
lvl UsageDetails
body_uds
            [ (CoreBndr
bndr, UsageDetails
uds, [CoreBndr]
rhs_bndrs)
            | ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
bndr, nd_uds :: Details -> UsageDetails
nd_uds = UsageDetails
uds, nd_rhs_bndrs :: Details -> [CoreBndr]
nd_rhs_bndrs = [CoreBndr]
rhs_bndrs }
                 <- [Details]
details_s ]

    mk_lb_node :: Details -> CoreBndr -> Node Unique Details
mk_lb_node nd :: Details
nd@(ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
old_bndr, nd_inl :: Details -> VarSet
nd_inl = VarSet
inl_fvs }) CoreBndr
new_bndr
      = Details -> Unique -> [Unique] -> Node Unique Details
forall key payload. payload -> key -> [key] -> Node key payload
DigraphNode Details
nd' (CoreBndr -> Unique
varUnique CoreBndr
old_bndr) (VarSet -> [Unique]
forall elt. UniqSet elt -> [Unique]
nonDetKeysUniqSet VarSet
lb_deps)
              -- It's OK to use nonDetKeysUniqSet here as
              -- stronglyConnCompFromEdgedVerticesR is still deterministic with edges
              -- in nondeterministic order as explained in
              -- Note [Deterministic SCC] in GHC.Data.Graph.Directed.
      where
        nd' :: Details
nd'     = Details
nd { nd_bndr :: CoreBndr
nd_bndr = CoreBndr
new_bndr, nd_score :: NodeScore
nd_score = NodeScore
score }
        score :: NodeScore
score   = OccEnv -> CoreBndr -> VarSet -> Details -> NodeScore
nodeScore OccEnv
env CoreBndr
new_bndr VarSet
lb_deps Details
nd
        lb_deps :: VarSet
lb_deps = ImpRuleEdges -> VarSet -> VarSet
extendFvs_ ImpRuleEdges
rule_fv_env VarSet
inl_fvs


    rule_fv_env :: IdEnv IdSet
        -- Maps a variable f to the variables from this group
        --      mentioned in RHS of active rules for f
        -- Domain is *subset* of bound vars (others have no rule fvs)
    rule_fv_env :: ImpRuleEdges
rule_fv_env = ImpRuleEdges -> ImpRuleEdges
transClosureFV ([(CoreBndr, VarSet)] -> ImpRuleEdges
forall a. [(CoreBndr, a)] -> VarEnv a
mkVarEnv [(CoreBndr, VarSet)]
init_rule_fvs)
    init_rule_fvs :: [(CoreBndr, VarSet)]
init_rule_fvs   -- See Note [Finding rule RHS free vars]
      = [ (CoreBndr
b, VarSet
trimmed_rule_fvs)
        | ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
b, nd_active_rule_fvs :: Details -> VarSet
nd_active_rule_fvs = VarSet
rule_fvs } <- [Details]
details_s
        , let trimmed_rule_fvs :: VarSet
trimmed_rule_fvs = VarSet
rule_fvs VarSet -> VarSet -> VarSet
`intersectVarSet` VarSet
bndr_set
        , Bool -> Bool
not (VarSet -> Bool
isEmptyVarSet VarSet
trimmed_rule_fvs) ]


------------------------------------------
nodeScore :: OccEnv
          -> Id        -- Binder with new occ-info
          -> VarSet    -- Loop-breaker dependencies
          -> Details
          -> NodeScore
nodeScore :: OccEnv -> CoreBndr -> VarSet -> Details -> NodeScore
nodeScore OccEnv
env CoreBndr
new_bndr VarSet
lb_deps
          (ND { nd_bndr :: Details -> CoreBndr
nd_bndr = CoreBndr
old_bndr, nd_rhs :: Details -> CoreExpr
nd_rhs = CoreExpr
bind_rhs })

  | Bool -> Bool
not (CoreBndr -> Bool
isId CoreBndr
old_bndr)     -- A type or coercion variable is never a loop breaker
  = (JoinArity
100, JoinArity
0, Bool
False)

  | CoreBndr
old_bndr CoreBndr -> VarSet -> Bool
`elemVarSet` VarSet
lb_deps  -- Self-recursive things are great loop breakers
  = (JoinArity
0, JoinArity
0, Bool
True)                   -- See Note [Self-recursion and loop breakers]

  | Bool -> Bool
not (OccEnv -> CoreBndr -> Bool
occ_unf_act OccEnv
env CoreBndr
old_bndr) -- A binder whose inlining is inactive (e.g. has
  = (JoinArity
0, JoinArity
0, Bool
True)                   -- a NOINLINE pragma) makes a great loop breaker

  | CoreExpr -> Bool
exprIsTrivial CoreExpr
rhs
  = JoinArity -> NodeScore
mk_score JoinArity
10  -- Practically certain to be inlined
    -- Used to have also: && not (isExportedId bndr)
    -- But I found this sometimes cost an extra iteration when we have
    --      rec { d = (a,b); a = ...df...; b = ...df...; df = d }
    -- where df is the exported dictionary. Then df makes a really
    -- bad choice for loop breaker

  | DFunUnfolding { df_args :: Unfolding -> [CoreExpr]
df_args = [CoreExpr]
args } <- Unfolding
old_unf
    -- Never choose a DFun as a loop breaker
    -- Note [DFuns should not be loop breakers]
  = (JoinArity
9, [CoreExpr] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [CoreExpr]
args, Bool
is_lb)

    -- Data structures are more important than INLINE pragmas
    -- so that dictionary/method recursion unravels

  | CoreUnfolding { uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfWhen {} } <- Unfolding
old_unf
  = JoinArity -> NodeScore
mk_score JoinArity
6

  | CoreExpr -> Bool
forall {b}. Expr b -> Bool
is_con_app CoreExpr
rhs   -- Data types help with cases:
  = JoinArity -> NodeScore
mk_score JoinArity
5       -- Note [Constructor applications]

  | Unfolding -> Bool
isStableUnfolding Unfolding
old_unf
  , Bool
can_unfold
  = JoinArity -> NodeScore
mk_score JoinArity
3

  | OccInfo -> Bool
isOneOcc (CoreBndr -> OccInfo
idOccInfo CoreBndr
new_bndr)
  = JoinArity -> NodeScore
mk_score JoinArity
2  -- Likely to be inlined

  | Bool
can_unfold  -- The Id has some kind of unfolding
  = JoinArity -> NodeScore
mk_score JoinArity
1

  | Bool
otherwise
  = (JoinArity
0, JoinArity
0, Bool
is_lb)

  where
    mk_score :: Int -> NodeScore
    mk_score :: JoinArity -> NodeScore
mk_score JoinArity
rank = (JoinArity
rank, JoinArity
rhs_size, Bool
is_lb)

    -- is_lb: see Note [Loop breakers, node scoring, and stability]
    is_lb :: Bool
is_lb = OccInfo -> Bool
isStrongLoopBreaker (CoreBndr -> OccInfo
idOccInfo CoreBndr
old_bndr)

    old_unf :: Unfolding
old_unf = CoreBndr -> Unfolding
realIdUnfolding CoreBndr
old_bndr
    can_unfold :: Bool
can_unfold = Unfolding -> Bool
canUnfold Unfolding
old_unf
    rhs :: CoreExpr
rhs        = case Unfolding
old_unf of
                   CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
unf_rhs }
                     | UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
                     -> CoreExpr
unf_rhs
                   Unfolding
_ -> CoreExpr
bind_rhs
       -- 'bind_rhs' is irrelevant for inlining things with a stable unfolding
    rhs_size :: JoinArity
rhs_size = case Unfolding
old_unf of
                 CoreUnfolding { uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guidance }
                    | UnfIfGoodArgs { ug_size :: UnfoldingGuidance -> JoinArity
ug_size = JoinArity
size } <- UnfoldingGuidance
guidance
                    -> JoinArity
size
                 Unfolding
_  -> CoreExpr -> JoinArity
cheapExprSize CoreExpr
rhs


        -- Checking for a constructor application
        -- Cheap and cheerful; the simplifier moves casts out of the way
        -- The lambda case is important to spot x = /\a. C (f a)
        -- which comes up when C is a dictionary constructor and
        -- f is a default method.
        -- Example: the instance for Show (ST s a) in GHC.ST
        --
        -- However we *also* treat (\x. C p q) as a con-app-like thing,
        --      Note [Closure conversion]
    is_con_app :: Expr b -> Bool
is_con_app (Var CoreBndr
v)    = CoreBndr -> Bool
isConLikeId CoreBndr
v
    is_con_app (App Expr b
f Expr b
_)  = Expr b -> Bool
is_con_app Expr b
f
    is_con_app (Lam b
_ Expr b
e)  = Expr b -> Bool
is_con_app Expr b
e
    is_con_app (Tick Tickish CoreBndr
_ Expr b
e) = Expr b -> Bool
is_con_app Expr b
e
    is_con_app Expr b
_          = Bool
False

maxExprSize :: Int
maxExprSize :: JoinArity
maxExprSize = JoinArity
20  -- Rather arbitrary

cheapExprSize :: CoreExpr -> Int
-- Maxes out at maxExprSize
cheapExprSize :: CoreExpr -> JoinArity
cheapExprSize CoreExpr
e
  = JoinArity -> CoreExpr -> JoinArity
go JoinArity
0 CoreExpr
e
  where
    go :: JoinArity -> CoreExpr -> JoinArity
go JoinArity
n CoreExpr
e | JoinArity
n JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
>= JoinArity
maxExprSize = JoinArity
n
           | Bool
otherwise        = JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e

    go1 :: JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n (Var {})        = JoinArity
nJoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+JoinArity
1
    go1 JoinArity
n (Lit {})        = JoinArity
nJoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+JoinArity
1
    go1 JoinArity
n (Type {})       = JoinArity
n
    go1 JoinArity
n (Coercion {})   = JoinArity
n
    go1 JoinArity
n (Tick Tickish CoreBndr
_ CoreExpr
e)      = JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e
    go1 JoinArity
n (Cast CoreExpr
e CoercionR
_)      = JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e
    go1 JoinArity
n (App CoreExpr
f CoreExpr
a)       = JoinArity -> CoreExpr -> JoinArity
go (JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
f) CoreExpr
a
    go1 JoinArity
n (Lam CoreBndr
b CoreExpr
e)
      | CoreBndr -> Bool
isTyVar CoreBndr
b         = JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e
      | Bool
otherwise         = JoinArity -> CoreExpr -> JoinArity
go (JoinArity
nJoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+JoinArity
1) CoreExpr
e
    go1 JoinArity
n (Let CoreBind
b CoreExpr
e)       = JoinArity -> [CoreExpr] -> JoinArity
gos (JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e) (CoreBind -> [CoreExpr]
forall b. Bind b -> [Expr b]
rhssOfBind CoreBind
b)
    go1 JoinArity
n (Case CoreExpr
e CoreBndr
_ Type
_ [Alt CoreBndr]
as) = JoinArity -> [CoreExpr] -> JoinArity
gos (JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e) ([Alt CoreBndr] -> [CoreExpr]
forall b. [Alt b] -> [Expr b]
rhssOfAlts [Alt CoreBndr]
as)

    gos :: JoinArity -> [CoreExpr] -> JoinArity
gos JoinArity
n [] = JoinArity
n
    gos JoinArity
n (CoreExpr
e:[CoreExpr]
es) | JoinArity
n JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
>= JoinArity
maxExprSize = JoinArity
n
                 | Bool
otherwise        = JoinArity -> [CoreExpr] -> JoinArity
gos (JoinArity -> CoreExpr -> JoinArity
go1 JoinArity
n CoreExpr
e) [CoreExpr]
es

betterLB :: NodeScore -> NodeScore -> Bool
-- If  n1 `betterLB` n2  then choose n1 as the loop breaker
betterLB :: NodeScore -> NodeScore -> Bool
betterLB (JoinArity
rank1, JoinArity
size1, Bool
lb1) (JoinArity
rank2, JoinArity
size2, Bool
_)
  | JoinArity
rank1 JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
< JoinArity
rank2 = Bool
True
  | JoinArity
rank1 JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
> JoinArity
rank2 = Bool
False
  | JoinArity
size1 JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
< JoinArity
size2 = Bool
False   -- Make the bigger n2 into the loop breaker
  | JoinArity
size1 JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
> JoinArity
size2 = Bool
True
  | Bool
lb1           = Bool
True    -- Tie-break: if n1 was a loop breaker before, choose it
  | Bool
otherwise     = Bool
False   -- See Note [Loop breakers, node scoring, and stability]

{- Note [Self-recursion and loop breakers]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
If we have
   rec { f = ...f...g...
       ; g = .....f...   }
then 'f' has to be a loop breaker anyway, so we may as well choose it
right away, so that g can inline freely.

This is really just a cheap hack. Consider
   rec { f = ...g...
       ; g = ..f..h...
      ;  h = ...f....}
Here f or g are better loop breakers than h; but we might accidentally
choose h.  Finding the minimal set of loop breakers is hard.

Note [Loop breakers, node scoring, and stability]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
To choose a loop breaker, we give a NodeScore to each node in the SCC,
and pick the one with the best score (according to 'betterLB').

We need to be jolly careful (#12425, #12234) about the stability
of this choice. Suppose we have

    let rec { f = ...g...g...
            ; g = ...f...f... }
    in
    case x of
      True  -> ...f..
      False -> ..f...

In each iteration of the simplifier the occurrence analyser OccAnal
chooses a loop breaker. Suppose in iteration 1 it choose g as the loop
breaker. That means it is free to inline f.

Suppose that GHC decides to inline f in the branches of the case, but
(for some reason; eg it is not saturated) in the rhs of g. So we get

    let rec { f = ...g...g...
            ; g = ...f...f... }
    in
    case x of
      True  -> ...g...g.....
      False -> ..g..g....

Now suppose that, for some reason, in the next iteration the occurrence
analyser chooses f as the loop breaker, so it can freely inline g. And
again for some reason the simplifier inlines g at its calls in the case
branches, but not in the RHS of f. Then we get

    let rec { f = ...g...g...
            ; g = ...f...f... }
    in
    case x of
      True  -> ...(...f...f...)...(...f..f..).....
      False -> ..(...f...f...)...(..f..f...)....

You can see where this is going! Each iteration of the simplifier
doubles the number of calls to f or g. No wonder GHC is slow!

(In the particular example in comment:3 of #12425, f and g are the two
mutually recursive fmap instances for CondT and Result. They are both
marked INLINE which, oddly, is why they don't inline in each other's
RHS, because the call there is not saturated.)

The root cause is that we flip-flop on our choice of loop breaker. I
always thought it didn't matter, and indeed for any single iteration
to terminate, it doesn't matter. But when we iterate, it matters a
lot!!

So The Plan is this:
   If there is a tie, choose the node that
   was a loop breaker last time round

Hence the is_lb field of NodeScore

************************************************************************
*                                                                      *
                   Right hand sides
*                                                                      *
************************************************************************
-}

occAnalRhs :: OccEnv -> Maybe JoinArity
           -> CoreExpr   -- RHS
           -> (UsageDetails, CoreExpr)
occAnalRhs :: OccEnv -> Maybe JoinArity -> CoreExpr -> (UsageDetails, CoreExpr)
occAnalRhs OccEnv
env Maybe JoinArity
mb_join_arity CoreExpr
rhs
  = case OccEnv
-> [CoreBndr] -> CoreExpr -> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs OccEnv
env [CoreBndr]
bndrs CoreExpr
body of { (UsageDetails
body_usage, [CoreBndr]
bndrs', CoreExpr
body') ->
    let rhs' :: CoreExpr
rhs' = [CoreBndr] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams (Maybe JoinArity -> [CoreBndr] -> [CoreBndr]
markJoinOneShots Maybe JoinArity
mb_join_arity [CoreBndr]
bndrs') CoreExpr
body'
               -- For a /non-recursive/ join point we can mark all
               -- its join-lambda as one-shot; and it's a good idea to do so

        -- Final adjustment
        rhs_usage :: UsageDetails
rhs_usage = Maybe JoinArity
-> RecFlag -> [CoreBndr] -> UsageDetails -> UsageDetails
adjustRhsUsage Maybe JoinArity
mb_join_arity RecFlag
NonRecursive [CoreBndr]
bndrs' UsageDetails
body_usage

    in (UsageDetails
rhs_usage, CoreExpr
rhs') }
  where
    ([CoreBndr]
bndrs, CoreExpr
body) = CoreExpr -> ([CoreBndr], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
rhs

occAnalUnfolding :: OccEnv
                 -> Maybe JoinArity   -- See Note [Join points and unfoldings/rules]
                 -> Unfolding
                 -> (UsageDetails, Unfolding)
-- Occurrence-analyse a stable unfolding;
-- discard a non-stable one altogether.
occAnalUnfolding :: OccEnv -> Maybe JoinArity -> Unfolding -> (UsageDetails, Unfolding)
occAnalUnfolding OccEnv
env Maybe JoinArity
mb_join_arity Unfolding
unf
  = case Unfolding
unf of
      unf :: Unfolding
unf@(CoreUnfolding { uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
rhs, uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src })
        | UnfoldingSource -> Bool
isStableSource UnfoldingSource
src -> (UsageDetails
usage,        Unfolding
unf')
        | Bool
otherwise          -> (UsageDetails
emptyDetails, Unfolding
unf)
        where -- For non-Stable unfoldings we leave them undisturbed, but
              -- don't count their usage because the simplifier will discard them.
              -- We leave them undisturbed because nodeScore uses their size info
              -- to guide its decisions.  It's ok to leave un-substituted
              -- expressions in the tree because all the variables that were in
              -- scope remain in scope; there is no cloning etc.
          (UsageDetails
usage, CoreExpr
rhs') = OccEnv -> Maybe JoinArity -> CoreExpr -> (UsageDetails, CoreExpr)
occAnalRhs OccEnv
env Maybe JoinArity
mb_join_arity CoreExpr
rhs

          unf' :: Unfolding
unf' | OccEnv -> Bool
noBinderSwaps OccEnv
env = Unfolding
unf -- Note [Unfoldings and rules]
               | Bool
otherwise         = Unfolding
unf { uf_tmpl :: CoreExpr
uf_tmpl = CoreExpr
rhs' }

      unf :: Unfolding
unf@(DFunUnfolding { df_bndrs :: Unfolding -> [CoreBndr]
df_bndrs = [CoreBndr]
bndrs, df_args :: Unfolding -> [CoreExpr]
df_args = [CoreExpr]
args })
        -> ( UsageDetails
final_usage, Unfolding
unf { df_args :: [CoreExpr]
df_args = [CoreExpr]
args' } )
        where
          env' :: OccEnv
env'            = OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr]
bndrs
          (UsageDetails
usage, [CoreExpr]
args')  = OccEnv -> [CoreExpr] -> (UsageDetails, [CoreExpr])
occAnalList OccEnv
env' [CoreExpr]
args
          final_usage :: UsageDetails
final_usage     = UsageDetails -> UsageDetails
markAllManyNonTail (UsageDetails -> [CoreBndr] -> UsageDetails
delDetailsList UsageDetails
usage [CoreBndr]
bndrs)

      Unfolding
unf -> (UsageDetails
emptyDetails, Unfolding
unf)

occAnalRules :: OccEnv
             -> Maybe JoinArity  -- See Note [Join points and unfoldings/rules]
             -> Id               -- Get rules from here
             -> [(CoreRule,      -- Each (non-built-in) rule
                  UsageDetails,  -- Usage details for LHS
                  UsageDetails)] -- Usage details for RHS
occAnalRules :: OccEnv
-> Maybe JoinArity
-> CoreBndr
-> [(CoreRule, UsageDetails, UsageDetails)]
occAnalRules OccEnv
env Maybe JoinArity
mb_join_arity CoreBndr
bndr
  = (CoreRule -> (CoreRule, UsageDetails, UsageDetails))
-> [CoreRule] -> [(CoreRule, UsageDetails, UsageDetails)]
forall a b. (a -> b) -> [a] -> [b]
map CoreRule -> (CoreRule, UsageDetails, UsageDetails)
occ_anal_rule (CoreBndr -> [CoreRule]
idCoreRules CoreBndr
bndr)
  where
    occ_anal_rule :: CoreRule -> (CoreRule, UsageDetails, UsageDetails)
occ_anal_rule rule :: CoreRule
rule@(Rule { ru_bndrs :: CoreRule -> [CoreBndr]
ru_bndrs = [CoreBndr]
bndrs, ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args, ru_rhs :: CoreRule -> CoreExpr
ru_rhs = CoreExpr
rhs })
      = (CoreRule
rule', UsageDetails
lhs_uds', UsageDetails
rhs_uds')
      where
        env' :: OccEnv
env' = OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr]
bndrs
        rule' :: CoreRule
rule' | OccEnv -> Bool
noBinderSwaps OccEnv
env = CoreRule
rule  -- Note [Unfoldings and rules]
              | Bool
otherwise         = CoreRule
rule { ru_args :: [CoreExpr]
ru_args = [CoreExpr]
args', ru_rhs :: CoreExpr
ru_rhs = CoreExpr
rhs' }

        (UsageDetails
lhs_uds, [CoreExpr]
args') = OccEnv -> [CoreExpr] -> (UsageDetails, [CoreExpr])
occAnalList OccEnv
env' [CoreExpr]
args
        lhs_uds' :: UsageDetails
lhs_uds'         = UsageDetails -> UsageDetails
markAllManyNonTail (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
                           UsageDetails
lhs_uds UsageDetails -> [CoreBndr] -> UsageDetails
`delDetailsList` [CoreBndr]
bndrs

        (UsageDetails
rhs_uds, CoreExpr
rhs') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env' CoreExpr
rhs
                            -- Note [Rules are extra RHSs]
                            -- Note [Rule dependency info]
        rhs_uds' :: UsageDetails
rhs_uds' = Bool -> UsageDetails -> UsageDetails
markAllNonTailIf (Bool -> Bool
not Bool
exact_join) (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
                   UsageDetails -> UsageDetails
markAllMany                             (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
                   UsageDetails
rhs_uds UsageDetails -> [CoreBndr] -> UsageDetails
`delDetailsList` [CoreBndr]
bndrs

        exact_join :: Bool
exact_join = Maybe JoinArity -> [CoreExpr] -> Bool
forall a. Maybe JoinArity -> [a] -> Bool
exactJoin Maybe JoinArity
mb_join_arity [CoreExpr]
args
                     -- See Note [Join points and unfoldings/rules]

    occ_anal_rule CoreRule
other_rule = (CoreRule
other_rule, UsageDetails
emptyDetails, UsageDetails
emptyDetails)

{- Note [Join point RHSs]
~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
   x = e
   join j = Just x

We want to inline x into j right away, so we don't want to give
the join point a RhsCtxt (#14137).  It's not a huge deal, because
the FloatIn pass knows to float into join point RHSs; and the simplifier
does not float things out of join point RHSs.  But it's a simple, cheap
thing to do.  See #14137.

Note [Unfoldings and rules]
~~~~~~~~~~~~~~~~~~~~~~~~~~~
Generally unfoldings and rules are already occurrence-analysed, so we
don't want to reconstruct their trees; we just want to analyse them to
find how they use their free variables.

EXCEPT if there is a binder-swap going on, in which case we do want to
produce a new tree.

So we have a fast-path that keeps the old tree if the occ_bs_env is
empty.   This just saves a bit of allocation and reconstruction; not
a big deal.

Note [Cascading inlines]
~~~~~~~~~~~~~~~~~~~~~~~~
By default we use an rhsCtxt for the RHS of a binding.  This tells the
occ anal n that it's looking at an RHS, which has an effect in
occAnalApp.  In particular, for constructor applications, it makes
the arguments appear to have NoOccInfo, so that we don't inline into
them. Thus    x = f y
              k = Just x
we do not want to inline x.

But there's a problem.  Consider
     x1 = a0 : []
     x2 = a1 : x1
     x3 = a2 : x2
     g  = f x3
First time round, it looks as if x1 and x2 occur as an arg of a
let-bound constructor ==> give them a many-occurrence.
But then x3 is inlined (unconditionally as it happens) and
next time round, x2 will be, and the next time round x1 will be
Result: multiple simplifier iterations.  Sigh.

So, when analysing the RHS of x3 we notice that x3 will itself
definitely inline the next time round, and so we analyse x3's rhs in
an ordinary context, not rhsCtxt.  Hence the "certainly_inline" stuff.

Annoyingly, we have to approximate GHC.Core.Opt.Simplify.Utils.preInlineUnconditionally.
If (a) the RHS is expandable (see isExpandableApp in occAnalApp), and
   (b) certainly_inline says "yes" when preInlineUnconditionally says "no"
then the simplifier iterates indefinitely:
        x = f y
        k = Just x   -- We decide that k is 'certainly_inline'
        v = ...k...  -- but preInlineUnconditionally doesn't inline it
inline ==>
        k = Just (f y)
        v = ...k...
float ==>
        x1 = f y
        k = Just x1
        v = ...k...

This is worse than the slow cascade, so we only want to say "certainly_inline"
if it really is certain.  Look at the note with preInlineUnconditionally
for the various clauses.


************************************************************************
*                                                                      *
                Expressions
*                                                                      *
************************************************************************
-}

occAnalList :: OccEnv -> [CoreExpr] -> (UsageDetails, [CoreExpr])
occAnalList :: OccEnv -> [CoreExpr] -> (UsageDetails, [CoreExpr])
occAnalList OccEnv
_   []     = (UsageDetails
emptyDetails, [])
occAnalList OccEnv
env (CoreExpr
e:[CoreExpr]
es) = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
e      of { (UsageDetails
uds1, CoreExpr
e')  ->
                         case OccEnv -> [CoreExpr] -> (UsageDetails, [CoreExpr])
occAnalList OccEnv
env [CoreExpr]
es of { (UsageDetails
uds2, [CoreExpr]
es') ->
                         (UsageDetails
uds1 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
uds2, CoreExpr
e' CoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
: [CoreExpr]
es') } }

occAnal :: OccEnv
        -> CoreExpr
        -> (UsageDetails,       -- Gives info only about the "interesting" Ids
            CoreExpr)

occAnal :: OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
_   expr :: CoreExpr
expr@(Type Type
_) = (UsageDetails
emptyDetails,         CoreExpr
expr)
occAnal OccEnv
_   expr :: CoreExpr
expr@(Lit Literal
_)  = (UsageDetails
emptyDetails,         CoreExpr
expr)
occAnal OccEnv
env expr :: CoreExpr
expr@(Var CoreBndr
_)  = OccEnv
-> (CoreExpr, [CoreExpr], [Tickish CoreBndr])
-> (UsageDetails, CoreExpr)
occAnalApp OccEnv
env (CoreExpr
expr, [], [])
    -- At one stage, I gathered the idRuleVars for the variable here too,
    -- which in a way is the right thing to do.
    -- But that went wrong right after specialisation, when
    -- the *occurrences* of the overloaded function didn't have any
    -- rules in them, so the *specialised* versions looked as if they
    -- weren't used at all.

occAnal OccEnv
_ (Coercion CoercionR
co)
  = (UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
emptyDetails (CoercionR -> VarSet
coVarsOfCo CoercionR
co), CoercionR -> CoreExpr
forall b. CoercionR -> Expr b
Coercion CoercionR
co)
        -- See Note [Gather occurrences of coercion variables]

{-
Note [Gather occurrences of coercion variables]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We need to gather info about what coercion variables appear, so that
we can sort them into the right place when doing dependency analysis.
-}

occAnal OccEnv
env (Tick Tickish CoreBndr
tickish CoreExpr
body)
  | SourceNote{} <- Tickish CoreBndr
tickish
  = (UsageDetails
usage, Tickish CoreBndr -> CoreExpr -> CoreExpr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish CoreExpr
body')
                  -- SourceNotes are best-effort; so we just proceed as usual.
                  -- If we drop a tick due to the issues described below it's
                  -- not the end of the world.

  | Tickish CoreBndr
tickish Tickish CoreBndr -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
  = (UsageDetails -> UsageDetails
markAllNonTail UsageDetails
usage, Tickish CoreBndr -> CoreExpr -> CoreExpr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish CoreExpr
body')

  | Breakpoint JoinArity
_ [CoreBndr]
ids <- Tickish CoreBndr
tickish
  = (UsageDetails
usage_lam UsageDetails -> UsageDetails -> UsageDetails
`andUDs` (CoreBndr -> UsageDetails -> UsageDetails)
-> UsageDetails -> [CoreBndr] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreBndr -> UsageDetails -> UsageDetails
addManyOcc UsageDetails
emptyDetails [CoreBndr]
ids, Tickish CoreBndr -> CoreExpr -> CoreExpr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish CoreExpr
body')
    -- never substitute for any of the Ids in a Breakpoint

  | Bool
otherwise
  = (UsageDetails
usage_lam, Tickish CoreBndr -> CoreExpr -> CoreExpr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
tickish CoreExpr
body')
  where
    !(UsageDetails
usage,CoreExpr
body') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body
    -- for a non-soft tick scope, we can inline lambdas only
    usage_lam :: UsageDetails
usage_lam = UsageDetails -> UsageDetails
markAllNonTail (UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
usage)
                  -- TODO There may be ways to make ticks and join points play
                  -- nicer together, but right now there are problems:
                  --   let j x = ... in tick<t> (j 1)
                  -- Making j a join point may cause the simplifier to drop t
                  -- (if the tick is put into the continuation). So we don't
                  -- count j 1 as a tail call.
                  -- See #14242.

occAnal OccEnv
env (Cast CoreExpr
expr CoercionR
co)
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
expr of { (UsageDetails
usage, CoreExpr
expr') ->
    let usage1 :: UsageDetails
usage1 = Bool -> UsageDetails -> UsageDetails
markAllManyNonTailIf (OccEnv -> Bool
isRhsEnv OccEnv
env) UsageDetails
usage
          -- usage1: if we see let x = y `cast` co
          -- then mark y as 'Many' so that we don't
          -- immediately inline y again.
        usage2 :: UsageDetails
usage2 = UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
usage1 (CoercionR -> VarSet
coVarsOfCo CoercionR
co)
          -- usage2: see Note [Gather occurrences of coercion variables]
    in (UsageDetails -> UsageDetails
markAllNonTail UsageDetails
usage2, CoreExpr -> CoercionR -> CoreExpr
forall b. Expr b -> CoercionR -> Expr b
Cast CoreExpr
expr' CoercionR
co)
    }

occAnal OccEnv
env app :: CoreExpr
app@(App CoreExpr
_ CoreExpr
_)
  = OccEnv
-> (CoreExpr, [CoreExpr], [Tickish CoreBndr])
-> (UsageDetails, CoreExpr)
occAnalApp OccEnv
env ((Tickish CoreBndr -> Bool)
-> CoreExpr -> (CoreExpr, [CoreExpr], [Tickish CoreBndr])
forall b.
(Tickish CoreBndr -> Bool)
-> Expr b -> (Expr b, [Expr b], [Tickish CoreBndr])
collectArgsTicks Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable CoreExpr
app)

-- Ignore type variables altogether
--   (a) occurrences inside type lambdas only not marked as InsideLam
--   (b) type variables not in environment

occAnal OccEnv
env (Lam CoreBndr
x CoreExpr
body)
  | CoreBndr -> Bool
isTyVar CoreBndr
x
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body of { (UsageDetails
body_usage, CoreExpr
body') ->
    (UsageDetails -> UsageDetails
markAllNonTail UsageDetails
body_usage, CoreBndr -> CoreExpr -> CoreExpr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
x CoreExpr
body')
    }

-- For value lambdas we do a special hack.  Consider
--      (\x. \y. ...x...)
-- If we did nothing, x is used inside the \y, so would be marked
-- as dangerous to dup.  But in the common case where the abstraction
-- is applied to two arguments this is over-pessimistic.
-- So instead, we just mark each binder with its occurrence
-- info in the *body* of the multiple lambda.
-- Then, the simplifier is careful when partially applying lambdas.

occAnal OccEnv
env expr :: CoreExpr
expr@(Lam CoreBndr
_ CoreExpr
_)
  = case OccEnv
-> [CoreBndr] -> CoreExpr -> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs OccEnv
env [CoreBndr]
bndrs CoreExpr
body of { (UsageDetails
usage, [CoreBndr]
tagged_bndrs, CoreExpr
body') ->
    let
        expr' :: CoreExpr
expr'       = [CoreBndr] -> CoreExpr -> CoreExpr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
tagged_bndrs CoreExpr
body'
        usage1 :: UsageDetails
usage1      = UsageDetails -> UsageDetails
markAllNonTail UsageDetails
usage
        one_shot_gp :: Bool
one_shot_gp = (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
isOneShotBndr [CoreBndr]
tagged_bndrs
        final_usage :: UsageDetails
final_usage = Bool -> UsageDetails -> UsageDetails
markAllInsideLamIf (Bool -> Bool
not Bool
one_shot_gp) UsageDetails
usage1
    in
    (UsageDetails
final_usage, CoreExpr
expr') }
  where
    ([CoreBndr]
bndrs, CoreExpr
body) = CoreExpr -> ([CoreBndr], CoreExpr)
forall b. Expr b -> ([b], Expr b)
collectBinders CoreExpr
expr

occAnal OccEnv
env (Case CoreExpr
scrut CoreBndr
bndr Type
ty [Alt CoreBndr]
alts)
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv -> [Alt CoreBndr] -> OccEnv
scrutCtxt OccEnv
env [Alt CoreBndr]
alts) CoreExpr
scrut of { (UsageDetails
scrut_usage, CoreExpr
scrut') ->
    let alt_env :: OccEnv
alt_env = CoreExpr -> CoreBndr -> OccEnv -> OccEnv
addBndrSwap CoreExpr
scrut' CoreBndr
bndr (OccEnv -> OccEnv) -> OccEnv -> OccEnv
forall a b. (a -> b) -> a -> b
$
                  OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla } OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr
bndr]
    in
    case (Alt CoreBndr -> (UsageDetails, Alt CoreBndr))
-> [Alt CoreBndr] -> ([UsageDetails], [Alt CoreBndr])
forall a b c. (a -> (b, c)) -> [a] -> ([b], [c])
mapAndUnzip (OccEnv -> Alt CoreBndr -> (UsageDetails, Alt CoreBndr)
occAnalAlt OccEnv
alt_env) [Alt CoreBndr]
alts of { ([UsageDetails]
alts_usage_s, [Alt CoreBndr]
alts')   ->
    let
        alts_usage :: UsageDetails
alts_usage  = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
orUDs UsageDetails
emptyDetails [UsageDetails]
alts_usage_s
        (UsageDetails
alts_usage1, CoreBndr
tagged_bndr) = UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagLamBinder UsageDetails
alts_usage CoreBndr
bndr
        total_usage :: UsageDetails
total_usage = UsageDetails -> UsageDetails
markAllNonTail UsageDetails
scrut_usage UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
alts_usage1
                        -- Alts can have tail calls, but the scrutinee can't
    in
    UsageDetails
total_usage UsageDetails
-> (UsageDetails, CoreExpr) -> (UsageDetails, CoreExpr)
`seq` (UsageDetails
total_usage, CoreExpr -> CoreBndr -> Type -> [Alt CoreBndr] -> CoreExpr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case CoreExpr
scrut' CoreBndr
tagged_bndr Type
ty [Alt CoreBndr]
alts') }}

occAnal OccEnv
env (Let CoreBind
bind CoreExpr
body)
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` CoreBind -> [CoreBndr]
forall b. Bind b -> [b]
bindersOf CoreBind
bind)
                 CoreExpr
body                    of { (UsageDetails
body_usage, CoreExpr
body') ->
    case OccEnv
-> TopLevelFlag
-> ImpRuleEdges
-> CoreBind
-> UsageDetails
-> (UsageDetails, CoreProgram)
occAnalBind OccEnv
env TopLevelFlag
NotTopLevel
                     ImpRuleEdges
noImpRuleEdges CoreBind
bind
                     UsageDetails
body_usage          of { (UsageDetails
final_usage, CoreProgram
new_binds) ->
       (UsageDetails
final_usage, CoreProgram -> CoreExpr -> CoreExpr
forall b. [Bind b] -> Expr b -> Expr b
mkLets CoreProgram
new_binds CoreExpr
body') }}

occAnalArgs :: OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs :: OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
_ [] [OneShots]
_
  = (UsageDetails
emptyDetails, [])

occAnalArgs OccEnv
env (CoreExpr
arg:[CoreExpr]
args) [OneShots]
one_shots
  | CoreExpr -> Bool
forall {b}. Expr b -> Bool
isTypeArg CoreExpr
arg
  = case OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots of { (UsageDetails
uds, [CoreExpr]
args') ->
    (UsageDetails
uds, CoreExpr
argCoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args') }

  | Bool
otherwise
  = case OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt OccEnv
env [OneShots]
one_shots           of { (OccEnv
arg_env, [OneShots]
one_shots') ->
    case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
arg_env CoreExpr
arg             of { (UsageDetails
uds1, CoreExpr
arg') ->
    case OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots' of { (UsageDetails
uds2, [CoreExpr]
args') ->
    (UsageDetails
uds1 UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
uds2, CoreExpr
arg'CoreExpr -> [CoreExpr] -> [CoreExpr]
forall a. a -> [a] -> [a]
:[CoreExpr]
args') }}}

{-
Applications are dealt with specially because we want
the "build hack" to work.

Note [Arguments of let-bound constructors]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
    f x = let y = expensive x in
          let z = (True,y) in
          (case z of {(p,q)->q}, case z of {(p,q)->q})
We feel free to duplicate the WHNF (True,y), but that means
that y may be duplicated thereby.

If we aren't careful we duplicate the (expensive x) call!
Constructors are rather like lambdas in this way.
-}

occAnalApp :: OccEnv
           -> (Expr CoreBndr, [Arg CoreBndr], [Tickish Id])
           -> (UsageDetails, Expr CoreBndr)
-- Naked variables (not applied) end up here too
occAnalApp :: OccEnv
-> (CoreExpr, [CoreExpr], [Tickish CoreBndr])
-> (UsageDetails, CoreExpr)
occAnalApp OccEnv
env (Var CoreBndr
fun, [CoreExpr]
args, [Tickish CoreBndr]
ticks)
  -- Account for join arity of runRW# continuation
  -- See Note [Simplification of runRW#]
  --
  -- NB: Do not be tempted to make the next (Var fun, args, tick)
  --     equation into an 'otherwise' clause for this equation
  --     The former has a bang-pattern to occ-anal the args, and
  --     we don't want to occ-anal them twice in the runRW# case!
  --     This caused #18296
  | CoreBndr
fun CoreBndr -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
runRWKey
  , [CoreExpr
t1, CoreExpr
t2, CoreExpr
arg]  <- [CoreExpr]
args
  , let (UsageDetails
usage, CoreExpr
arg') = OccEnv -> Maybe JoinArity -> CoreExpr -> (UsageDetails, CoreExpr)
occAnalRhs OccEnv
env (JoinArity -> Maybe JoinArity
forall a. a -> Maybe a
Just JoinArity
1) CoreExpr
arg
  = (UsageDetails
usage, [Tickish CoreBndr] -> CoreExpr -> CoreExpr
mkTicks [Tickish CoreBndr]
ticks (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps (CoreBndr -> CoreExpr
forall b. CoreBndr -> Expr b
Var CoreBndr
fun) [CoreExpr
t1, CoreExpr
t2, CoreExpr
arg'])

occAnalApp OccEnv
env (Var CoreBndr
fun_id, [CoreExpr]
args, [Tickish CoreBndr]
ticks)
  = (UsageDetails
all_uds, [Tickish CoreBndr] -> CoreExpr -> CoreExpr
mkTicks [Tickish CoreBndr]
ticks (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps CoreExpr
fun' [CoreExpr]
args')
  where
    (CoreExpr
fun', CoreBndr
fun_id') = OccEnv -> CoreBndr -> (CoreExpr, CoreBndr)
lookupBndrSwap OccEnv
env CoreBndr
fun_id

    fun_uds :: UsageDetails
fun_uds = CoreBndr -> InterestingCxt -> JoinArity -> UsageDetails
mkOneOcc CoreBndr
fun_id' InterestingCxt
int_cxt JoinArity
n_args
       -- NB: fun_uds is computed for fun_id', not fun_id
       -- See (BS1) in Note [The binder-swap substitution]

    all_uds :: UsageDetails
all_uds = UsageDetails
fun_uds UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
final_args_uds

    !(UsageDetails
args_uds, [CoreExpr]
args') = OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args [OneShots]
one_shots
    !final_args_uds :: UsageDetails
final_args_uds = UsageDetails -> UsageDetails
markAllNonTail                        (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
                      Bool -> UsageDetails -> UsageDetails
markAllInsideLamIf (OccEnv -> Bool
isRhsEnv OccEnv
env Bool -> Bool -> Bool
&& Bool
is_exp) (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
                      UsageDetails
args_uds
       -- We mark the free vars of the argument of a constructor or PAP
       -- as "inside-lambda", if it is the RHS of a let(rec).
       -- This means that nothing gets inlined into a constructor or PAP
       -- argument position, which is what we want.  Typically those
       -- constructor arguments are just variables, or trivial expressions.
       -- We use inside-lam because it's like eta-expanding the PAP.
       --
       -- This is the *whole point* of the isRhsEnv predicate
       -- See Note [Arguments of let-bound constructors]

    n_val_args :: JoinArity
n_val_args = [CoreExpr] -> JoinArity
forall b. [Arg b] -> JoinArity
valArgCount [CoreExpr]
args
    n_args :: JoinArity
n_args     = [CoreExpr] -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length [CoreExpr]
args
    int_cxt :: InterestingCxt
int_cxt    = case OccEnv -> OccEncl
occ_encl OccEnv
env of
                   OccEncl
OccScrut -> InterestingCxt
IsInteresting
                   OccEncl
_other   | JoinArity
n_val_args JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
> JoinArity
0 -> InterestingCxt
IsInteresting
                            | Bool
otherwise      -> InterestingCxt
NotInteresting

    is_exp :: Bool
is_exp     = CheapAppFun
isExpandableApp CoreBndr
fun_id JoinArity
n_val_args
        -- See Note [CONLIKE pragma] in GHC.Types.Basic
        -- The definition of is_exp should match that in GHC.Core.Opt.Simplify.prepareRhs

    one_shots :: [OneShots]
one_shots  = StrictSig -> JoinArity -> [OneShots]
argsOneShots (CoreBndr -> StrictSig
idStrictness CoreBndr
fun_id) JoinArity
guaranteed_val_args
    guaranteed_val_args :: JoinArity
guaranteed_val_args = JoinArity
n_val_args JoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+ OneShots -> JoinArity
forall (t :: * -> *) a. Foldable t => t a -> JoinArity
length ((OneShotInfo -> Bool) -> OneShots -> OneShots
forall a. (a -> Bool) -> [a] -> [a]
takeWhile OneShotInfo -> Bool
isOneShotInfo
                                                         (OccEnv -> OneShots
occ_one_shots OccEnv
env))
        -- See Note [Sources of one-shot information], bullet point A']

occAnalApp OccEnv
env (CoreExpr
fun, [CoreExpr]
args, [Tickish CoreBndr]
ticks)
  = (UsageDetails -> UsageDetails
markAllNonTail (UsageDetails
fun_uds UsageDetails -> UsageDetails -> UsageDetails
`andUDs` UsageDetails
args_uds),
     [Tickish CoreBndr] -> CoreExpr -> CoreExpr
mkTicks [Tickish CoreBndr]
ticks (CoreExpr -> CoreExpr) -> CoreExpr -> CoreExpr
forall a b. (a -> b) -> a -> b
$ CoreExpr -> [CoreExpr] -> CoreExpr
forall b. Expr b -> [Expr b] -> Expr b
mkApps CoreExpr
fun' [CoreExpr]
args')
  where
    !(UsageDetails
fun_uds, CoreExpr
fun') = OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv -> [CoreExpr] -> OccEnv
addAppCtxt OccEnv
env [CoreExpr]
args) CoreExpr
fun
        -- The addAppCtxt is a bit cunning.  One iteration of the simplifier
        -- often leaves behind beta redexs like
        --      (\x y -> e) a1 a2
        -- Here we would like to mark x,y as one-shot, and treat the whole
        -- thing much like a let.  We do this by pushing some True items
        -- onto the context stack.
    !(UsageDetails
args_uds, [CoreExpr]
args') = OccEnv -> [CoreExpr] -> [OneShots] -> (UsageDetails, [CoreExpr])
occAnalArgs OccEnv
env [CoreExpr]
args []


{-
Note [Sources of one-shot information]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The occurrence analyser obtains one-shot-lambda information from two sources:

A:  Saturated applications:  eg   f e1 .. en

    In general, given a call (f e1 .. en) we can propagate one-shot info from
    f's strictness signature into e1 .. en, but /only/ if n is enough to
    saturate the strictness signature. A strictness signature like

          f :: C1(C1(L))LS

    means that *if f is applied to three arguments* then it will guarantee to
    call its first argument at most once, and to call the result of that at
    most once. But if f has fewer than three arguments, all bets are off; e.g.

          map (f (\x y. expensive) e2) xs

    Here the \x y abstraction may be called many times (once for each element of
    xs) so we should not mark x and y as one-shot. But if it was

          map (f (\x y. expensive) 3 2) xs

    then the first argument of f will be called at most once.

    The one-shot info, derived from f's strictness signature, is
    computed by 'argsOneShots', called in occAnalApp.

A': Non-obviously saturated applications: eg    build (f (\x y -> expensive))
    where f is as above.

    In this case, f is only manifestly applied to one argument, so it does not
    look saturated. So by the previous point, we should not use its strictness
    signature to learn about the one-shotness of \x y. But in this case we can:
    build is fully applied, so we may use its strictness signature; and from
    that we learn that build calls its argument with two arguments *at most once*.

    So there is really only one call to f, and it will have three arguments. In
    that sense, f is saturated, and we may proceed as described above.

    Hence the computation of 'guaranteed_val_args' in occAnalApp, using
    '(occ_one_shots env)'.  See also #13227, comment:9

B:  Let-bindings:  eg   let f = \c. let ... in \n -> blah
                        in (build f, build f)

    Propagate one-shot info from the demanand-info on 'f' to the
    lambdas in its RHS (which may not be syntactically at the top)

    This information must have come from a previous run of the demanand
    analyser.

Previously, the demand analyser would *also* set the one-shot information, but
that code was buggy (see #11770), so doing it only in on place, namely here, is
saner.

Note [OneShots]
~~~~~~~~~~~~~~~
When analysing an expression, the occ_one_shots argument contains information
about how the function is being used. The length of the list indicates
how many arguments will eventually be passed to the analysed expression,
and the OneShotInfo indicates whether this application is once or multiple times.

Example:

 Context of f                occ_one_shots when analysing f

 f 1 2                       [OneShot, OneShot]
 map (f 1)                   [OneShot, NoOneShotInfo]
 build f                     [OneShot, OneShot]
 f 1 2 `seq` f 2 1           [NoOneShotInfo, OneShot]

Note [Binders in case alternatives]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
    case x of y { (a,b) -> f y }
We treat 'a', 'b' as dead, because they don't physically occur in the
case alternative.  (Indeed, a variable is dead iff it doesn't occur in
its scope in the output of OccAnal.)  It really helps to know when
binders are unused.  See esp the call to isDeadBinder in
Simplify.mkDupableAlt

In this example, though, the Simplifier will bring 'a' and 'b' back to
life, because it binds 'y' to (a,b) (imagine got inlined and
scrutinised y).
-}

occAnalLamOrRhs :: OccEnv -> [CoreBndr] -> CoreExpr
                -> (UsageDetails, [CoreBndr], CoreExpr)
-- Tags the returned binders with their OccInfo, but does
-- not do any markInsideLam to the returned usage details
occAnalLamOrRhs :: OccEnv
-> [CoreBndr] -> CoreExpr -> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs OccEnv
env [] CoreExpr
body
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env CoreExpr
body of (UsageDetails
body_usage, CoreExpr
body') -> (UsageDetails
body_usage, [], CoreExpr
body')
      -- RHS of thunk or nullary join point

occAnalLamOrRhs OccEnv
env (CoreBndr
bndr:[CoreBndr]
bndrs) CoreExpr
body
  | CoreBndr -> Bool
isTyVar CoreBndr
bndr
  = -- Important: Keep the environment so that we don't inline into an RHS like
    --   \(@ x) -> C @x (f @x)
    -- (see the beginning of Note [Cascading inlines]).
    case OccEnv
-> [CoreBndr] -> CoreExpr -> (UsageDetails, [CoreBndr], CoreExpr)
occAnalLamOrRhs OccEnv
env [CoreBndr]
bndrs CoreExpr
body of
      (UsageDetails
body_usage, [CoreBndr]
bndrs', CoreExpr
body') -> (UsageDetails
body_usage, CoreBndr
bndrCoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
:[CoreBndr]
bndrs', CoreExpr
body')

occAnalLamOrRhs OccEnv
env [CoreBndr]
binders CoreExpr
body
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal OccEnv
env_body CoreExpr
body of { (UsageDetails
body_usage, CoreExpr
body') ->
    let
        (UsageDetails
final_usage, [CoreBndr]
tagged_binders) = UsageDetails -> [CoreBndr] -> (UsageDetails, [CoreBndr])
tagLamBinders UsageDetails
body_usage [CoreBndr]
binders'
                      -- Use binders' to put one-shot info on the lambdas
    in
    (UsageDetails
final_usage, [CoreBndr]
tagged_binders, CoreExpr
body') }
  where
    env1 :: OccEnv
env1 = OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr]
binders
    (OccEnv
env_body, [CoreBndr]
binders') = OccEnv -> [CoreBndr] -> (OccEnv, [CoreBndr])
oneShotGroup OccEnv
env1 [CoreBndr]
binders

occAnalAlt :: OccEnv
           -> CoreAlt -> (UsageDetails, Alt IdWithOccInfo)
occAnalAlt :: OccEnv -> Alt CoreBndr -> (UsageDetails, Alt CoreBndr)
occAnalAlt OccEnv
env (AltCon
con, [CoreBndr]
bndrs, CoreExpr
rhs)
  = case OccEnv -> CoreExpr -> (UsageDetails, CoreExpr)
occAnal (OccEnv
env OccEnv -> [CoreBndr] -> OccEnv
`addInScope` [CoreBndr]
bndrs) CoreExpr
rhs of { (UsageDetails
rhs_usage1, CoreExpr
rhs1) ->
    let
      (UsageDetails
alt_usg, [CoreBndr]
tagged_bndrs) = UsageDetails -> [CoreBndr] -> (UsageDetails, [CoreBndr])
tagLamBinders UsageDetails
rhs_usage1 [CoreBndr]
bndrs
    in                          -- See Note [Binders in case alternatives]
    (UsageDetails
alt_usg, (AltCon
con, [CoreBndr]
tagged_bndrs, CoreExpr
rhs1)) }

{-
************************************************************************
*                                                                      *
                    OccEnv
*                                                                      *
************************************************************************
-}

data OccEnv
  = OccEnv { OccEnv -> OccEncl
occ_encl       :: !OccEncl      -- Enclosing context information
           , OccEnv -> OneShots
occ_one_shots  :: !OneShots     -- See Note [OneShots]
           , OccEnv -> CoreBndr -> Bool
occ_unf_act    :: Id -> Bool          -- Which Id unfoldings are active
           , OccEnv -> Activation -> Bool
occ_rule_act   :: Activation -> Bool  -- Which rules are active
             -- See Note [Finding rule RHS free vars]

           -- See Note [The binder-swap substitution]
           -- If  x :-> (y, co)  is in the env,
           -- then please replace x by (y |> sym mco)
           -- Invariant of course: idType x = exprType (y |> sym mco)
           , OccEnv -> VarEnv (CoreBndr, MCoercion)
occ_bs_env  :: VarEnv (OutId, MCoercion)
           , OccEnv -> VarSet
occ_bs_rng  :: VarSet   -- Vars free in the range of occ_bs_env
                   -- Domain is Global and Local Ids
                   -- Range is just Local Ids
    }


-----------------------------
-- OccEncl is used to control whether to inline into constructor arguments
-- For example:
--      x = (p,q)               -- Don't inline p or q
--      y = /\a -> (p a, q a)   -- Still don't inline p or q
--      z = f (p,q)             -- Do inline p,q; it may make a rule fire
-- So OccEncl tells enough about the context to know what to do when
-- we encounter a constructor application or PAP.
--
-- OccScrut is used to set the "interesting context" field of OncOcc

data OccEncl
  = OccRhs         -- RHS of let(rec), albeit perhaps inside a type lambda
                   -- Don't inline into constructor args here

  | OccScrut       -- Scrutintee of a case
                   -- Can inline into constructor args

  | OccVanilla     -- Argument of function, body of lambda, etc
                   -- Do inline into constructor args here

instance Outputable OccEncl where
  ppr :: OccEncl -> SDoc
ppr OccEncl
OccRhs     = String -> SDoc
text String
"occRhs"
  ppr OccEncl
OccScrut   = String -> SDoc
text String
"occScrut"
  ppr OccEncl
OccVanilla = String -> SDoc
text String
"occVanilla"

-- See note [OneShots]
type OneShots = [OneShotInfo]

initOccEnv :: OccEnv
initOccEnv :: OccEnv
initOccEnv
  = OccEnv :: OccEncl
-> OneShots
-> (CoreBndr -> Bool)
-> (Activation -> Bool)
-> VarEnv (CoreBndr, MCoercion)
-> VarSet
-> OccEnv
OccEnv { occ_encl :: OccEncl
occ_encl      = OccEncl
OccVanilla
           , occ_one_shots :: OneShots
occ_one_shots = []

                 -- To be conservative, we say that all
                 -- inlines and rules are active
           , occ_unf_act :: CoreBndr -> Bool
occ_unf_act   = \CoreBndr
_ -> Bool
True
           , occ_rule_act :: Activation -> Bool
occ_rule_act  = \Activation
_ -> Bool
True

           , occ_bs_env :: VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
forall a. VarEnv a
emptyVarEnv
           , occ_bs_rng :: VarSet
occ_bs_rng = VarSet
emptyVarSet }

noBinderSwaps :: OccEnv -> Bool
noBinderSwaps :: OccEnv -> Bool
noBinderSwaps (OccEnv { occ_bs_env :: OccEnv -> VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
bs_env }) = VarEnv (CoreBndr, MCoercion) -> Bool
forall a. VarEnv a -> Bool
isEmptyVarEnv VarEnv (CoreBndr, MCoercion)
bs_env

scrutCtxt :: OccEnv -> [CoreAlt] -> OccEnv
scrutCtxt :: OccEnv -> [Alt CoreBndr] -> OccEnv
scrutCtxt OccEnv
env [Alt CoreBndr]
alts
  | Bool
interesting_alts =  OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccScrut,   occ_one_shots :: OneShots
occ_one_shots = [] }
  | Bool
otherwise        =  OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = [] }
  where
    interesting_alts :: Bool
interesting_alts = case [Alt CoreBndr]
alts of
                         []    -> Bool
False
                         [Alt CoreBndr
alt] -> Bool -> Bool
not (Alt CoreBndr -> Bool
forall a b. (AltCon, a, b) -> Bool
isDefaultAlt Alt CoreBndr
alt)
                         [Alt CoreBndr]
_     -> Bool
True
     -- 'interesting_alts' is True if the case has at least one
     -- non-default alternative.  That in turn influences
     -- pre/postInlineUnconditionally.  Grep for "occ_int_cxt"!

rhsCtxt :: OccEnv -> OccEnv
rhsCtxt :: OccEnv -> OccEnv
rhsCtxt OccEnv
env = OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccRhs, occ_one_shots :: OneShots
occ_one_shots = [] }

argCtxt :: OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt :: OccEnv -> [OneShots] -> (OccEnv, [OneShots])
argCtxt OccEnv
env []
  = (OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = [] }, [])
argCtxt OccEnv
env (OneShots
one_shots:[OneShots]
one_shots_s)
  = (OccEnv
env { occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla, occ_one_shots :: OneShots
occ_one_shots = OneShots
one_shots }, [OneShots]
one_shots_s)

isRhsEnv :: OccEnv -> Bool
isRhsEnv :: OccEnv -> Bool
isRhsEnv (OccEnv { occ_encl :: OccEnv -> OccEncl
occ_encl = OccEncl
cxt }) = case OccEncl
cxt of
                                          OccEncl
OccRhs -> Bool
True
                                          OccEncl
_      -> Bool
False

addInScope :: OccEnv -> [Var] -> OccEnv
-- See Note [The binder-swap substitution]
addInScope :: OccEnv -> [CoreBndr] -> OccEnv
addInScope env :: OccEnv
env@(OccEnv { occ_bs_env :: OccEnv -> VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
swap_env, occ_bs_rng :: OccEnv -> VarSet
occ_bs_rng = VarSet
rng_vars }) [CoreBndr]
bndrs
  | (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (CoreBndr -> VarSet -> Bool
`elemVarSet` VarSet
rng_vars) [CoreBndr]
bndrs = OccEnv
env { occ_bs_env :: VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
forall a. VarEnv a
emptyVarEnv, occ_bs_rng :: VarSet
occ_bs_rng = VarSet
emptyVarSet }
  | Bool
otherwise                         = OccEnv
env { occ_bs_env :: VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
swap_env VarEnv (CoreBndr, MCoercion)
-> [CoreBndr] -> VarEnv (CoreBndr, MCoercion)
forall a. VarEnv a -> [CoreBndr] -> VarEnv a
`delVarEnvList` [CoreBndr]
bndrs }

oneShotGroup :: OccEnv -> [CoreBndr]
             -> ( OccEnv
                , [CoreBndr] )
        -- The result binders have one-shot-ness set that they might not have had originally.
        -- This happens in (build (\c n -> e)).  Here the occurrence analyser
        -- linearity context knows that c,n are one-shot, and it records that fact in
        -- the binder. This is useful to guide subsequent float-in/float-out transformations

oneShotGroup :: OccEnv -> [CoreBndr] -> (OccEnv, [CoreBndr])
oneShotGroup env :: OccEnv
env@(OccEnv { occ_one_shots :: OccEnv -> OneShots
occ_one_shots = OneShots
ctxt }) [CoreBndr]
bndrs
  = OneShots -> [CoreBndr] -> [CoreBndr] -> (OccEnv, [CoreBndr])
go OneShots
ctxt [CoreBndr]
bndrs []
  where
    go :: OneShots -> [CoreBndr] -> [CoreBndr] -> (OccEnv, [CoreBndr])
go OneShots
ctxt [] [CoreBndr]
rev_bndrs
      = ( OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = OneShots
ctxt, occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla }
        , [CoreBndr] -> [CoreBndr]
forall a. [a] -> [a]
reverse [CoreBndr]
rev_bndrs )

    go [] [CoreBndr]
bndrs [CoreBndr]
rev_bndrs
      = ( OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = [], occ_encl :: OccEncl
occ_encl = OccEncl
OccVanilla }
        , [CoreBndr] -> [CoreBndr]
forall a. [a] -> [a]
reverse [CoreBndr]
rev_bndrs [CoreBndr] -> [CoreBndr] -> [CoreBndr]
forall a. [a] -> [a] -> [a]
++ [CoreBndr]
bndrs )

    go ctxt :: OneShots
ctxt@(OneShotInfo
one_shot : OneShots
ctxt') (CoreBndr
bndr : [CoreBndr]
bndrs) [CoreBndr]
rev_bndrs
      | CoreBndr -> Bool
isId CoreBndr
bndr = OneShots -> [CoreBndr] -> [CoreBndr] -> (OccEnv, [CoreBndr])
go OneShots
ctxt' [CoreBndr]
bndrs (CoreBndr
bndr'CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
rev_bndrs)
      | Bool
otherwise = OneShots -> [CoreBndr] -> [CoreBndr] -> (OccEnv, [CoreBndr])
go OneShots
ctxt  [CoreBndr]
bndrs (CoreBndr
bndr CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: [CoreBndr]
rev_bndrs)
      where
        bndr' :: CoreBndr
bndr' = CoreBndr -> OneShotInfo -> CoreBndr
updOneShotInfo CoreBndr
bndr OneShotInfo
one_shot
               -- Use updOneShotInfo, not setOneShotInfo, as pre-existing
               -- one-shot info might be better than what we can infer, e.g.
               -- due to explicit use of the magic 'oneShot' function.
               -- See Note [The oneShot function]


markJoinOneShots :: Maybe JoinArity -> [Var] -> [Var]
-- Mark the lambdas of a non-recursive join point as one-shot.
-- This is good to prevent gratuitous float-out etc
markJoinOneShots :: Maybe JoinArity -> [CoreBndr] -> [CoreBndr]
markJoinOneShots Maybe JoinArity
mb_join_arity [CoreBndr]
bndrs
  = case Maybe JoinArity
mb_join_arity of
      Maybe JoinArity
Nothing -> [CoreBndr]
bndrs
      Just JoinArity
n  -> JoinArity -> [CoreBndr] -> [CoreBndr]
forall {t}. (Eq t, Num t) => t -> [CoreBndr] -> [CoreBndr]
go JoinArity
n [CoreBndr]
bndrs
 where
   go :: t -> [CoreBndr] -> [CoreBndr]
go t
0 [CoreBndr]
bndrs  = [CoreBndr]
bndrs
   go t
_ []     = [] -- This can legitimately happen.
                    -- e.g.    let j = case ... in j True
                    -- This will become an arity-1 join point after the
                    -- simplifier has eta-expanded it; but it may not have
                    -- enough lambdas /yet/. (Lint checks that JoinIds do
                    -- have enough lambdas.)
   go t
n (CoreBndr
b:[CoreBndr]
bs) = CoreBndr
b' CoreBndr -> [CoreBndr] -> [CoreBndr]
forall a. a -> [a] -> [a]
: t -> [CoreBndr] -> [CoreBndr]
go (t
nt -> t -> t
forall a. Num a => a -> a -> a
-t
1) [CoreBndr]
bs
     where
       b' :: CoreBndr
b' | CoreBndr -> Bool
isId CoreBndr
b    = CoreBndr -> CoreBndr
setOneShotLambda CoreBndr
b
          | Bool
otherwise = CoreBndr
b

addAppCtxt :: OccEnv -> [Arg CoreBndr] -> OccEnv
addAppCtxt :: OccEnv -> [CoreExpr] -> OccEnv
addAppCtxt env :: OccEnv
env@(OccEnv { occ_one_shots :: OccEnv -> OneShots
occ_one_shots = OneShots
ctxt }) [CoreExpr]
args
  = OccEnv
env { occ_one_shots :: OneShots
occ_one_shots = JoinArity -> OneShotInfo -> OneShots
forall a. JoinArity -> a -> [a]
replicate ([CoreExpr] -> JoinArity
forall b. [Arg b] -> JoinArity
valArgCount [CoreExpr]
args) OneShotInfo
OneShotLam OneShots -> OneShots -> OneShots
forall a. [a] -> [a] -> [a]
++ OneShots
ctxt }

transClosureFV :: VarEnv VarSet -> VarEnv VarSet
-- If (f,g), (g,h) are in the input, then (f,h) is in the output
--                                   as well as (f,g), (g,h)
transClosureFV :: ImpRuleEdges -> ImpRuleEdges
transClosureFV ImpRuleEdges
env
  | Bool
no_change = ImpRuleEdges
env
  | Bool
otherwise = ImpRuleEdges -> ImpRuleEdges
transClosureFV ([(Unique, VarSet)] -> ImpRuleEdges
forall elt key. [(Unique, elt)] -> UniqFM key elt
listToUFM_Directly [(Unique, VarSet)]
new_fv_list)
  where
    (Bool
no_change, [(Unique, VarSet)]
new_fv_list) = (Bool -> (Unique, VarSet) -> (Bool, (Unique, VarSet)))
-> Bool -> [(Unique, VarSet)] -> (Bool, [(Unique, VarSet)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL Bool -> (Unique, VarSet) -> (Bool, (Unique, VarSet))
forall {a}. Bool -> (a, VarSet) -> (Bool, (a, VarSet))
bump Bool
True (ImpRuleEdges -> [(Unique, VarSet)]
forall key elt. UniqFM key elt -> [(Unique, elt)]
nonDetUFMToList ImpRuleEdges
env)
      -- It's OK to use nonDetUFMToList here because we'll forget the
      -- ordering by creating a new set with listToUFM
    bump :: Bool -> (a, VarSet) -> (Bool, (a, VarSet))
bump Bool
no_change (a
b,VarSet
fvs)
      | Bool
no_change_here = (Bool
no_change, (a
b,VarSet
fvs))
      | Bool
otherwise      = (Bool
False,     (a
b,VarSet
new_fvs))
      where
        (VarSet
new_fvs, Bool
no_change_here) = ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs ImpRuleEdges
env VarSet
fvs

-------------
extendFvs_ :: VarEnv VarSet -> VarSet -> VarSet
extendFvs_ :: ImpRuleEdges -> VarSet -> VarSet
extendFvs_ ImpRuleEdges
env VarSet
s = (VarSet, Bool) -> VarSet
forall a b. (a, b) -> a
fst (ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs ImpRuleEdges
env VarSet
s)   -- Discard the Bool flag

extendFvs :: VarEnv VarSet -> VarSet -> (VarSet, Bool)
-- (extendFVs env s) returns
--     (s `union` env(s), env(s) `subset` s)
extendFvs :: ImpRuleEdges -> VarSet -> (VarSet, Bool)
extendFvs ImpRuleEdges
env VarSet
s
  | ImpRuleEdges -> Bool
forall key elt. UniqFM key elt -> Bool
isNullUFM ImpRuleEdges
env
  = (VarSet
s, Bool
True)
  | Bool
otherwise
  = (VarSet
s VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
extras, VarSet
extras VarSet -> VarSet -> Bool
`subVarSet` VarSet
s)
  where
    extras :: VarSet    -- env(s)
    extras :: VarSet
extras = (VarSet -> VarSet -> VarSet) -> VarSet -> ImpRuleEdges -> VarSet
forall elt a key. (elt -> a -> a) -> a -> UniqFM key elt -> a
nonDetStrictFoldUFM VarSet -> VarSet -> VarSet
unionVarSet VarSet
emptyVarSet (ImpRuleEdges -> VarSet) -> ImpRuleEdges -> VarSet
forall a b. (a -> b) -> a -> b
$
      -- It's OK to use nonDetStrictFoldUFM here because unionVarSet commutes
             (VarSet -> CoreBndr -> VarSet)
-> ImpRuleEdges -> VarEnv CoreBndr -> ImpRuleEdges
forall elt1 elt2 elt3 key.
(elt1 -> elt2 -> elt3)
-> UniqFM key elt1 -> UniqFM key elt2 -> UniqFM key elt3
intersectUFM_C (\VarSet
x CoreBndr
_ -> VarSet
x) ImpRuleEdges
env (VarSet -> VarEnv CoreBndr
forall a. UniqSet a -> UniqFM a a
getUniqSet VarSet
s)

{-
************************************************************************
*                                                                      *
                    Binder swap
*                                                                      *
************************************************************************

Note [Binder swap]
~~~~~~~~~~~~~~~~~~
The "binder swap" transformation swaps occurrence of the
scrutinee of a case for occurrences of the case-binder:

 (1)  case x of b { pi -> ri }
         ==>
      case x of b { pi -> ri[b/x] }

 (2)  case (x |> co) of b { pi -> ri }
        ==>
      case (x |> co) of b { pi -> ri[b |> sym co/x] }

The substitution ri[b/x] etc is done by the occurrence analyser.
See Note [The binder-swap substitution].

There are two reasons for making this swap:

(A) It reduces the number of occurrences of the scrutinee, x.
    That in turn might reduce its occurrences to one, so we
    can inline it and save an allocation.  E.g.
      let x = factorial y in case x of b { I# v -> ...x... }
    If we replace 'x' by 'b' in the alternative we get
      let x = factorial y in case x of b { I# v -> ...b... }
    and now we can inline 'x', thus
      case (factorial y) of b { I# v -> ...b... }

(B) The case-binder b has unfolding information; in the
    example above we know that b = I# v. That in turn allows
    nested cases to simplify.  Consider
       case x of b { I# v ->
       ...(case x of b2 { I# v2 -> rhs })...
    If we replace 'x' by 'b' in the alternative we get
       case x of b { I# v ->
       ...(case b of b2 { I# v2 -> rhs })...
    and now it is trivial to simplify the inner case:
       case x of b { I# v ->
       ...(let b2 = b in rhs)...

    The same can happen even if the scrutinee is a variable
    with a cast: see Note [Case of cast]

The reason for doing these transformations /here in the occurrence
analyser/ is because it allows us to adjust the OccInfo for 'x' and
'b' as we go.

  * Suppose the only occurrences of 'x' are the scrutinee and in the
    ri; then this transformation makes it occur just once, and hence
    get inlined right away.

  * If instead the Simplifier replaces occurrences of x with
    occurrences of b, that will mess up b's occurrence info. That in
    turn might have consequences.

There is a danger though.  Consider
      let v = x +# y
      in case (f v) of w -> ...v...v...
And suppose that (f v) expands to just v.  Then we'd like to
use 'w' instead of 'v' in the alternative.  But it may be too
late; we may have substituted the (cheap) x+#y for v in the
same simplifier pass that reduced (f v) to v.

I think this is just too bad.  CSE will recover some of it.

Note [The binder-swap substitution]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The binder-swap is implemented by the occ_bs_env field of OccEnv.
There are two main pieces:

* Given    case x |> co of b { alts }
  we add [x :-> (b, co)] to the occ_bs_env environment; this is
  done by addBndrSwap.

* Then, at an occurrence of a variable, we look up in the occ_bs_env
  to perform the swap. This is done by lookupBndrSwap.

Some tricky corners:

(BS1) We do the substitution before gathering occurrence info. So in
      the above example, an occurrence of x turns into an occurrence
      of b, and that's what we gather in the UsageDetails.  It's as
      if the binder-swap occurred before occurrence analysis. See
      the computation of fun_uds in occAnalApp.

(BS2) When doing a lookup in occ_bs_env, we may need to iterate,
      as you can see implemented in lookupBndrSwap.  Why?
      Consider   case x of a { 1# -> e1; DEFAULT ->
                 case x of b { 2# -> e2; DEFAULT ->
                 case x of c { 3# -> e3; DEFAULT -> ..x..a..b.. }}}
      At the first case addBndrSwap will extend occ_bs_env with
          [x :-> a]
      At the second case we occ-anal the scrutinee 'x', which looks up
        'x in occ_bs_env, returning 'a', as it should.
      Then addBndrSwap will add [a :-> b] to occ_bs_env, yielding
         occ_bs_env = [x :-> a, a :-> b]
      At the third case we'll again look up 'x' which returns 'a'.
      But we don't want to stop the lookup there, else we'll end up with
                 case x of a { 1# -> e1; DEFAULT ->
                 case a of b { 2# -> e2; DEFAULT ->
                 case a of c { 3# -> e3; DEFAULT -> ..a..b..c.. }}}
      Instead, we want iterate the lookup in addBndrSwap, to give
                 case x of a { 1# -> e1; DEFAULT ->
                 case a of b { 2# -> e2; DEFAULT ->
                 case b of c { 3# -> e3; DEFAULT -> ..c..c..c.. }}}
      This makes a particular difference for case-merge, which works
      only if the scrutinee is the case-binder of the immediately enclosing
      case (Note [Merge Nested Cases] in GHC.Core.Opt.Simplify.Utils
      See #19581 for the bug report that showed this up.

(BS3) We need care when shadowing.  Suppose [x :-> b] is in occ_bs_env,
      and we encounter:
         - \x. blah
           Here we want to delete the x-binding from occ_bs_env

         - \b. blah
           This is harder: we really want to delete all bindings that
           have 'b' free in the range.  That is a bit tiresome to implement,
           so we compromise.  We keep occ_bs_rng, which is the set of
           free vars of rng(occc_bs_env).  If a binder shadows any of these
           variables, we discard all of occ_bs_env.  Safe, if a bit
           brutal.  NB, however: the simplifer de-shadows the code, so the
           next time around this won't happen.

      These checks are implemented in addInScope.

      The occurrence analyser itself does /not/ do cloning. It could, in
      principle, but it'd make it a bit more complicated and there is no
      great benefit. The simplifer uses cloning to get a no-shadowing
      situation, the care-when-shadowing behaviour above isn't needed for
      long.

(BS4) The domain of occ_bs_env can include GlobaIds.  Eg
         case M.foo of b { alts }
      We extend occ_bs_env with [M.foo :-> b].  That's fine.

(BS5) We have to apply the occ_bs_env substitution uniformly,
      including to (local) rules and unfoldings.

Historical note
---------------
We used to do the binder-swap transformation by introducing
a proxy let-binding, thus;

   case x of b { pi -> ri }
      ==>
   case x of b { pi -> let x = b in ri }

But that had two problems:

1. If 'x' is an imported GlobalId, we'd end up with a GlobalId
   on the LHS of a let-binding which isn't allowed.  We worked
   around this for a while by "localising" x, but it turned
   out to be very painful #16296,

2. In CorePrep we use the occurrence analyser to do dead-code
   elimination (see Note [Dead code in CorePrep]).  But that
   occasionally led to an unlifted let-binding
       case x of b { DEFAULT -> let x::Int# = b in ... }
   which disobeys one of CorePrep's output invariants (no unlifted
   let-bindings) -- see #5433.

Doing a substitution (via occ_bs_env) is much better.

Note [Case of cast]
~~~~~~~~~~~~~~~~~~~
Consider        case (x `cast` co) of b { I# ->
                ... (case (x `cast` co) of {...}) ...
We'd like to eliminate the inner case.  That is the motivation for
equation (2) in Note [Binder swap].  When we get to the inner case, we
inline x, cancel the casts, and away we go.

Note [Zap case binders in proxy bindings]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
From the original
     case x of cb(dead) { p -> ...x... }
we will get
     case x of cb(live) { p -> ...cb... }

Core Lint never expects to find an *occurrence* of an Id marked
as Dead, so we must zap the OccInfo on cb before making the
binding x = cb.  See #5028.

NB: the OccInfo on /occurrences/ really doesn't matter much; the simplifier
doesn't use it. So this is only to satisfy the perhaps-over-picky Lint.

Historical note [no-case-of-case]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
We *used* to suppress the binder-swap in case expressions when
-fno-case-of-case is on.  Old remarks:
    "This happens in the first simplifier pass,
    and enhances full laziness.  Here's the bad case:
            f = \ y -> ...(case x of I# v -> ...(case x of ...) ... )
    If we eliminate the inner case, we trap it inside the I# v -> arm,
    which might prevent some full laziness happening.  I've seen this
    in action in spectral/cichelli/Prog.hs:
             [(m,n) | m <- [1..max], n <- [1..max]]
    Hence the check for NoCaseOfCase."
However, now the full-laziness pass itself reverses the binder-swap, so this
check is no longer necessary.

Historical note [Suppressing the case binder-swap]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This old note describes a problem that is also fixed by doing the
binder-swap in OccAnal:

    There is another situation when it might make sense to suppress the
    case-expression binde-swap. If we have

        case x of w1 { DEFAULT -> case x of w2 { A -> e1; B -> e2 }
                       ...other cases .... }

    We'll perform the binder-swap for the outer case, giving

        case x of w1 { DEFAULT -> case w1 of w2 { A -> e1; B -> e2 }
                       ...other cases .... }

    But there is no point in doing it for the inner case, because w1 can't
    be inlined anyway.  Furthermore, doing the case-swapping involves
    zapping w2's occurrence info (see paragraphs that follow), and that
    forces us to bind w2 when doing case merging.  So we get

        case x of w1 { A -> let w2 = w1 in e1
                       B -> let w2 = w1 in e2
                       ...other cases .... }

    This is plain silly in the common case where w2 is dead.

    Even so, I can't see a good way to implement this idea.  I tried
    not doing the binder-swap if the scrutinee was already evaluated
    but that failed big-time:

            data T = MkT !Int

            case v of w  { MkT x ->
            case x of x1 { I# y1 ->
            case x of x2 { I# y2 -> ...

    Notice that because MkT is strict, x is marked "evaluated".  But to
    eliminate the last case, we must either make sure that x (as well as
    x1) has unfolding MkT y1.  The straightforward thing to do is to do
    the binder-swap.  So this whole note is a no-op.

It's fixed by doing the binder-swap in OccAnal because we can do the
binder-swap unconditionally and still get occurrence analysis
information right.
-}

addBndrSwap :: OutExpr -> Id -> OccEnv -> OccEnv
-- See Note [The binder-swap substitution]
addBndrSwap :: CoreExpr -> CoreBndr -> OccEnv -> OccEnv
addBndrSwap CoreExpr
scrut CoreBndr
case_bndr
            env :: OccEnv
env@(OccEnv { occ_bs_env :: OccEnv -> VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
swap_env, occ_bs_rng :: OccEnv -> VarSet
occ_bs_rng = VarSet
rng_vars })
  | Just (CoreBndr
scrut_var, MCoercion
mco) <- CoreExpr -> Maybe (CoreBndr, MCoercion)
get_scrut_var ((Tickish CoreBndr -> Bool) -> CoreExpr -> CoreExpr
forall b. (Tickish CoreBndr -> Bool) -> Expr b -> Expr b
stripTicksTopE (Bool -> Tickish CoreBndr -> Bool
forall a b. a -> b -> a
const Bool
True) CoreExpr
scrut)
  , CoreBndr
scrut_var CoreBndr -> CoreBndr -> Bool
forall a. Eq a => a -> a -> Bool
/= CoreBndr
case_bndr
      -- Consider: case x of x { ... }
      -- Do not add [x :-> x] to occ_bs_env, else lookupBndrSwap will loop
  = OccEnv
env { occ_bs_env :: VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
-> CoreBndr
-> (CoreBndr, MCoercion)
-> VarEnv (CoreBndr, MCoercion)
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv VarEnv (CoreBndr, MCoercion)
swap_env CoreBndr
scrut_var (CoreBndr
case_bndr', MCoercion
mco)
        , occ_bs_rng :: VarSet
occ_bs_rng = VarSet
rng_vars VarSet -> CoreBndr -> VarSet
`extendVarSet` CoreBndr
case_bndr'
                       VarSet -> VarSet -> VarSet
`unionVarSet` MCoercion -> VarSet
tyCoVarsOfMCo MCoercion
mco }

  | Bool
otherwise
  = OccEnv
env
  where
    get_scrut_var :: OutExpr -> Maybe (OutVar, MCoercion)
    get_scrut_var :: CoreExpr -> Maybe (CoreBndr, MCoercion)
get_scrut_var (Var CoreBndr
v)           = (CoreBndr, MCoercion) -> Maybe (CoreBndr, MCoercion)
forall a. a -> Maybe a
Just (CoreBndr
v, MCoercion
MRefl)
    get_scrut_var (Cast (Var CoreBndr
v) CoercionR
co) = (CoreBndr, MCoercion) -> Maybe (CoreBndr, MCoercion)
forall a. a -> Maybe a
Just (CoreBndr
v, CoercionR -> MCoercion
MCo CoercionR
co) -- See Note [Case of cast]
    get_scrut_var CoreExpr
_                 = Maybe (CoreBndr, MCoercion)
forall a. Maybe a
Nothing

    case_bndr' :: CoreBndr
case_bndr' = CoreBndr -> CoreBndr
zapIdOccInfo CoreBndr
case_bndr
                 -- See Note [Zap case binders in proxy bindings]

lookupBndrSwap :: OccEnv -> Id -> (CoreExpr, Id)
-- See Note [The binder-swap substitution]
-- Returns an expression of the same type as Id
lookupBndrSwap :: OccEnv -> CoreBndr -> (CoreExpr, CoreBndr)
lookupBndrSwap env :: OccEnv
env@(OccEnv { occ_bs_env :: OccEnv -> VarEnv (CoreBndr, MCoercion)
occ_bs_env = VarEnv (CoreBndr, MCoercion)
bs_env })  CoreBndr
bndr
  = case VarEnv (CoreBndr, MCoercion)
-> CoreBndr -> Maybe (CoreBndr, MCoercion)
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv VarEnv (CoreBndr, MCoercion)
bs_env CoreBndr
bndr of {
       Maybe (CoreBndr, MCoercion)
Nothing           -> (CoreBndr -> CoreExpr
forall b. CoreBndr -> Expr b
Var CoreBndr
bndr, CoreBndr
bndr) ;
       Just (CoreBndr
bndr1, MCoercion
mco) ->

    -- Why do we iterate here?
    -- See (BS2) in Note [The binder-swap substitution]
    case OccEnv -> CoreBndr -> (CoreExpr, CoreBndr)
lookupBndrSwap OccEnv
env CoreBndr
bndr1 of
      (CoreExpr
fun, CoreBndr
fun_id) -> (CoreExpr -> MCoercion -> CoreExpr
forall {b}. Expr b -> MCoercion -> Expr b
add_cast CoreExpr
fun MCoercion
mco, CoreBndr
fun_id) }

  where
    add_cast :: Expr b -> MCoercion -> Expr b
add_cast Expr b
fun MCoercion
MRefl    = Expr b
fun
    add_cast Expr b
fun (MCo CoercionR
co) = Expr b -> CoercionR -> Expr b
forall b. Expr b -> CoercionR -> Expr b
Cast Expr b
fun (CoercionR -> CoercionR
mkSymCo CoercionR
co)
    -- We must switch that 'co' to 'sym co';
    -- see the comment with occ_bs_env
    -- No need to test for isReflCo, because 'co' came from
    -- a (Cast e co) and hence is unlikely to be Refl

{-
************************************************************************
*                                                                      *
\subsection[OccurAnal-types]{OccEnv}
*                                                                      *
************************************************************************

Note [UsageDetails and zapping]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
On many occasions, we must modify all gathered occurrence data at once. For
instance, all occurrences underneath a (non-one-shot) lambda set the
'occ_in_lam' flag to become 'True'. We could use 'mapVarEnv' to do this, but
that takes O(n) time and we will do this often---in particular, there are many
places where tail calls are not allowed, and each of these causes all variables
to get marked with 'NoTailCallInfo'.

Instead of relying on `mapVarEnv`, then, we carry three 'IdEnv's around along
with the 'OccInfoEnv'. Each of these extra environments is a "zapped set"
recording which variables have been zapped in some way. Zapping all occurrence
info then simply means setting the corresponding zapped set to the whole
'OccInfoEnv', a fast O(1) operation.
-}

type OccInfoEnv = IdEnv OccInfo -- A finite map from ids to their usage
                -- INVARIANT: never IAmDead
                -- (Deadness is signalled by not being in the map at all)

type ZappedSet = OccInfoEnv -- Values are ignored

data UsageDetails
  = UD { UsageDetails -> OccInfoEnv
ud_env       :: !OccInfoEnv
       , UsageDetails -> OccInfoEnv
ud_z_many    :: ZappedSet   -- apply 'markMany' to these
       , UsageDetails -> OccInfoEnv
ud_z_in_lam  :: ZappedSet   -- apply 'markInsideLam' to these
       , UsageDetails -> OccInfoEnv
ud_z_no_tail :: ZappedSet } -- apply 'markNonTail' to these
  -- INVARIANT: All three zapped sets are subsets of the OccInfoEnv

instance Outputable UsageDetails where
  ppr :: UsageDetails -> SDoc
ppr UsageDetails
ud = OccInfoEnv -> SDoc
forall a. Outputable a => a -> SDoc
ppr (UsageDetails -> OccInfoEnv
ud_env (UsageDetails -> UsageDetails
flattenUsageDetails UsageDetails
ud))

-------------------
-- UsageDetails API

andUDs, orUDs
        :: UsageDetails -> UsageDetails -> UsageDetails
andUDs :: UsageDetails -> UsageDetails -> UsageDetails
andUDs = (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith OccInfo -> OccInfo -> OccInfo
addOccInfo
orUDs :: UsageDetails -> UsageDetails -> UsageDetails
orUDs  = (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith OccInfo -> OccInfo -> OccInfo
orOccInfo

mkOneOcc ::Id -> InterestingCxt -> JoinArity -> UsageDetails
mkOneOcc :: CoreBndr -> InterestingCxt -> JoinArity -> UsageDetails
mkOneOcc CoreBndr
id InterestingCxt
int_cxt JoinArity
arity
  | CoreBndr -> Bool
isLocalId CoreBndr
id
  = UsageDetails
emptyDetails { ud_env :: OccInfoEnv
ud_env = CoreBndr -> OccInfo -> OccInfoEnv
forall a. CoreBndr -> a -> VarEnv a
unitVarEnv CoreBndr
id OccInfo
occ_info }
  | Bool
otherwise
  = UsageDetails
emptyDetails
  where
    occ_info :: OccInfo
occ_info = OneOcc :: InsideLam -> JoinArity -> InterestingCxt -> TailCallInfo -> OccInfo
OneOcc { occ_in_lam :: InsideLam
occ_in_lam  = InsideLam
NotInsideLam
                      , occ_n_br :: JoinArity
occ_n_br    = JoinArity
oneBranch
                      , occ_int_cxt :: InterestingCxt
occ_int_cxt = InterestingCxt
int_cxt
                      , occ_tail :: TailCallInfo
occ_tail    = JoinArity -> TailCallInfo
AlwaysTailCalled JoinArity
arity }

addManyOccId :: UsageDetails -> Id -> UsageDetails
-- Add the non-committal (id :-> noOccInfo) to the usage details
addManyOccId :: UsageDetails -> CoreBndr -> UsageDetails
addManyOccId UsageDetails
ud CoreBndr
id = UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = OccInfoEnv -> CoreBndr -> OccInfo -> OccInfoEnv
forall a. VarEnv a -> CoreBndr -> a -> VarEnv a
extendVarEnv (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) CoreBndr
id OccInfo
noOccInfo }

-- Add several occurrences, assumed not to be tail calls
addManyOcc :: Var -> UsageDetails -> UsageDetails
addManyOcc :: CoreBndr -> UsageDetails -> UsageDetails
addManyOcc CoreBndr
v UsageDetails
u | CoreBndr -> Bool
isId CoreBndr
v    = UsageDetails -> CoreBndr -> UsageDetails
addManyOccId UsageDetails
u CoreBndr
v
               | Bool
otherwise = UsageDetails
u
        -- Give a non-committal binder info (i.e noOccInfo) because
        --   a) Many copies of the specialised thing can appear
        --   b) We don't want to substitute a BIG expression inside a RULE
        --      even if that's the only occurrence of the thing
        --      (Same goes for INLINE.)

addManyOccs :: UsageDetails -> VarSet -> UsageDetails
addManyOccs :: UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
usage VarSet
id_set = (CoreBndr -> UsageDetails -> UsageDetails)
-> UsageDetails -> VarSet -> UsageDetails
forall elt a. (elt -> a -> a) -> a -> UniqSet elt -> a
nonDetStrictFoldUniqSet CoreBndr -> UsageDetails -> UsageDetails
addManyOcc UsageDetails
usage VarSet
id_set
  -- It's OK to use nonDetStrictFoldUniqSet here because addManyOcc commutes

delDetails :: UsageDetails -> Id -> UsageDetails
delDetails :: UsageDetails -> CoreBndr -> UsageDetails
delDetails UsageDetails
ud CoreBndr
bndr
  = UsageDetails
ud UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterUsageDetails` (OccInfoEnv -> CoreBndr -> OccInfoEnv
forall a. VarEnv a -> CoreBndr -> VarEnv a
`delVarEnv` CoreBndr
bndr)

delDetailsList :: UsageDetails -> [Id] -> UsageDetails
delDetailsList :: UsageDetails -> [CoreBndr] -> UsageDetails
delDetailsList UsageDetails
ud [CoreBndr]
bndrs
  = UsageDetails
ud UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterUsageDetails` (OccInfoEnv -> [CoreBndr] -> OccInfoEnv
forall a. VarEnv a -> [CoreBndr] -> VarEnv a
`delVarEnvList` [CoreBndr]
bndrs)

emptyDetails :: UsageDetails
emptyDetails :: UsageDetails
emptyDetails = UD :: OccInfoEnv
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv -> UsageDetails
UD { ud_env :: OccInfoEnv
ud_env       = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
                  , ud_z_many :: OccInfoEnv
ud_z_many    = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
                  , ud_z_in_lam :: OccInfoEnv
ud_z_in_lam  = OccInfoEnv
forall a. VarEnv a
emptyVarEnv
                  , ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv
forall a. VarEnv a
emptyVarEnv }

isEmptyDetails :: UsageDetails -> Bool
isEmptyDetails :: UsageDetails -> Bool
isEmptyDetails = OccInfoEnv -> Bool
forall a. VarEnv a -> Bool
isEmptyVarEnv (OccInfoEnv -> Bool)
-> (UsageDetails -> OccInfoEnv) -> UsageDetails -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsageDetails -> OccInfoEnv
ud_env

markAllMany, markAllInsideLam, markAllNonTail, markAllManyNonTail
  :: UsageDetails -> UsageDetails
markAllMany :: UsageDetails -> UsageDetails
markAllMany          UsageDetails
ud = UsageDetails
ud { ud_z_many :: OccInfoEnv
ud_z_many    = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }
markAllInsideLam :: UsageDetails -> UsageDetails
markAllInsideLam     UsageDetails
ud = UsageDetails
ud { ud_z_in_lam :: OccInfoEnv
ud_z_in_lam  = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }
markAllNonTail :: UsageDetails -> UsageDetails
markAllNonTail UsageDetails
ud = UsageDetails
ud { ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud }

markAllInsideLamIf, markAllNonTailIf :: Bool -> UsageDetails -> UsageDetails

markAllInsideLamIf :: Bool -> UsageDetails -> UsageDetails
markAllInsideLamIf  Bool
True  UsageDetails
ud = UsageDetails -> UsageDetails
markAllInsideLam UsageDetails
ud
markAllInsideLamIf  Bool
False UsageDetails
ud = UsageDetails
ud

markAllNonTailIf :: Bool -> UsageDetails -> UsageDetails
markAllNonTailIf Bool
True  UsageDetails
ud = UsageDetails -> UsageDetails
markAllNonTail UsageDetails
ud
markAllNonTailIf Bool
False UsageDetails
ud = UsageDetails
ud


markAllManyNonTail :: UsageDetails -> UsageDetails
markAllManyNonTail = UsageDetails -> UsageDetails
markAllMany (UsageDetails -> UsageDetails)
-> (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall b c a. (b -> c) -> (a -> b) -> a -> c
. UsageDetails -> UsageDetails
markAllNonTail -- effectively sets to noOccInfo

markAllManyNonTailIf :: Bool              -- If this is true
             -> UsageDetails      -- Then do markAllManyNonTail on this
             -> UsageDetails
markAllManyNonTailIf :: Bool -> UsageDetails -> UsageDetails
markAllManyNonTailIf Bool
True  UsageDetails
uds = UsageDetails -> UsageDetails
markAllManyNonTail UsageDetails
uds
markAllManyNonTailIf Bool
False UsageDetails
uds = UsageDetails
uds

lookupDetails :: UsageDetails -> Id -> OccInfo
lookupDetails :: UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
ud CoreBndr
id
  | CoreBndr -> Bool
isCoVar CoreBndr
id  -- We do not currently gather occurrence info (from types)
  = OccInfo
noOccInfo   -- for CoVars, so we must conservatively mark them as used
                -- See Note [DoO not mark CoVars as dead]
  | Bool
otherwise
  = case OccInfoEnv -> CoreBndr -> Maybe OccInfo
forall a. VarEnv a -> CoreBndr -> Maybe a
lookupVarEnv (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) CoreBndr
id of
      Just OccInfo
occ -> UsageDetails -> CoreBndr -> OccInfo -> OccInfo
doZapping UsageDetails
ud CoreBndr
id OccInfo
occ
      Maybe OccInfo
Nothing  -> OccInfo
IAmDead

usedIn :: Id -> UsageDetails -> Bool
CoreBndr
v usedIn :: CoreBndr -> UsageDetails -> Bool
`usedIn` UsageDetails
ud = CoreBndr -> Bool
isExportedId CoreBndr
v Bool -> Bool -> Bool
|| CoreBndr
v CoreBndr -> OccInfoEnv -> Bool
forall a. CoreBndr -> VarEnv a -> Bool
`elemVarEnv` UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud

udFreeVars :: VarSet -> UsageDetails -> VarSet
-- Find the subset of bndrs that are mentioned in uds
udFreeVars :: VarSet -> UsageDetails -> VarSet
udFreeVars VarSet
bndrs UsageDetails
ud = VarSet -> OccInfoEnv -> VarSet
forall key b. UniqSet key -> UniqFM key b -> UniqSet key
restrictUniqSetToUFM VarSet
bndrs (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud)

{- Note [Do not mark CoVars as dead]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's obviously wrong to mark CoVars as dead if they are used.
Currently we don't traverse types to gather usase info for CoVars,
so we had better treat them as having noOccInfo.

This showed up in #15696 we had something like
  case eq_sel d of co -> ...(typeError @(...co...) "urk")...

Then 'd' was substituted by a dictionary, so the expression
simpified to
  case (Coercion <blah>) of co -> ...(typeError @(...co...) "urk")...

But then the "drop the case altogether" equation of rebuildCase
thought that 'co' was dead, and discarded the entire case. Urk!

I have no idea how we managed to avoid this pitfall for so long!
-}

-------------------
-- Auxiliary functions for UsageDetails implementation

combineUsageDetailsWith :: (OccInfo -> OccInfo -> OccInfo)
                        -> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith :: (OccInfo -> OccInfo -> OccInfo)
-> UsageDetails -> UsageDetails -> UsageDetails
combineUsageDetailsWith OccInfo -> OccInfo -> OccInfo
plus_occ_info UsageDetails
ud1 UsageDetails
ud2
  | UsageDetails -> Bool
isEmptyDetails UsageDetails
ud1 = UsageDetails
ud2
  | UsageDetails -> Bool
isEmptyDetails UsageDetails
ud2 = UsageDetails
ud1
  | Bool
otherwise
  = UD :: OccInfoEnv
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv -> UsageDetails
UD { ud_env :: OccInfoEnv
ud_env       = (OccInfo -> OccInfo -> OccInfo)
-> OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_C OccInfo -> OccInfo -> OccInfo
plus_occ_info (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud2)
       , ud_z_many :: OccInfoEnv
ud_z_many    = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_many    UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_many    UsageDetails
ud2)
       , ud_z_in_lam :: OccInfoEnv
ud_z_in_lam  = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_in_lam  UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_in_lam  UsageDetails
ud2)
       , ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a. VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud1) (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud2) }

doZapping :: UsageDetails -> Var -> OccInfo -> OccInfo
doZapping :: UsageDetails -> CoreBndr -> OccInfo -> OccInfo
doZapping UsageDetails
ud CoreBndr
var OccInfo
occ
  = UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique UsageDetails
ud (CoreBndr -> Unique
varUnique CoreBndr
var) OccInfo
occ

doZappingByUnique :: UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique :: UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique (UD { ud_z_many :: UsageDetails -> OccInfoEnv
ud_z_many = OccInfoEnv
many
                      , ud_z_in_lam :: UsageDetails -> OccInfoEnv
ud_z_in_lam = OccInfoEnv
in_lam
                      , ud_z_no_tail :: UsageDetails -> OccInfoEnv
ud_z_no_tail = OccInfoEnv
no_tail })
                  Unique
uniq OccInfo
occ
  = OccInfo
occ2
  where
    occ1 :: OccInfo
occ1 | Unique
uniq Unique -> OccInfoEnv -> Bool
forall a. Unique -> VarEnv a -> Bool
`elemVarEnvByKey` OccInfoEnv
many    = OccInfo -> OccInfo
markMany OccInfo
occ
         | Unique
uniq Unique -> OccInfoEnv -> Bool
forall a. Unique -> VarEnv a -> Bool
`elemVarEnvByKey` OccInfoEnv
in_lam  = OccInfo -> OccInfo
markInsideLam OccInfo
occ
         | Bool
otherwise                      = OccInfo
occ
    occ2 :: OccInfo
occ2 | Unique
uniq Unique -> OccInfoEnv -> Bool
forall a. Unique -> VarEnv a -> Bool
`elemVarEnvByKey` OccInfoEnv
no_tail = OccInfo -> OccInfo
markNonTail OccInfo
occ1
         | Bool
otherwise                      = OccInfo
occ1

alterZappedSets :: UsageDetails -> (ZappedSet -> ZappedSet) -> UsageDetails
alterZappedSets :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterZappedSets UsageDetails
ud OccInfoEnv -> OccInfoEnv
f
  = UsageDetails
ud { ud_z_many :: OccInfoEnv
ud_z_many    = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_many    UsageDetails
ud)
       , ud_z_in_lam :: OccInfoEnv
ud_z_in_lam  = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_in_lam  UsageDetails
ud)
       , ud_z_no_tail :: OccInfoEnv
ud_z_no_tail = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_z_no_tail UsageDetails
ud) }

alterUsageDetails :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterUsageDetails :: UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
alterUsageDetails UsageDetails
ud OccInfoEnv -> OccInfoEnv
f
  = UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = OccInfoEnv -> OccInfoEnv
f (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) } UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterZappedSets` OccInfoEnv -> OccInfoEnv
f

flattenUsageDetails :: UsageDetails -> UsageDetails
flattenUsageDetails :: UsageDetails -> UsageDetails
flattenUsageDetails UsageDetails
ud
  = UsageDetails
ud { ud_env :: OccInfoEnv
ud_env = (Unique -> OccInfo -> OccInfo) -> OccInfoEnv -> OccInfoEnv
forall elt1 elt2 key.
(Unique -> elt1 -> elt2) -> UniqFM key elt1 -> UniqFM key elt2
mapUFM_Directly (UsageDetails -> Unique -> OccInfo -> OccInfo
doZappingByUnique UsageDetails
ud) (UsageDetails -> OccInfoEnv
ud_env UsageDetails
ud) }
      UsageDetails -> (OccInfoEnv -> OccInfoEnv) -> UsageDetails
`alterZappedSets` OccInfoEnv -> OccInfoEnv -> OccInfoEnv
forall a b. a -> b -> a
const OccInfoEnv
forall a. VarEnv a
emptyVarEnv

-------------------
-- See Note [Adjusting right-hand sides]
adjustRhsUsage :: Maybe JoinArity -> RecFlag
               -> [CoreBndr]     -- Outer lambdas, AFTER occ anal
               -> UsageDetails   -- From body of lambda
               -> UsageDetails
adjustRhsUsage :: Maybe JoinArity
-> RecFlag -> [CoreBndr] -> UsageDetails -> UsageDetails
adjustRhsUsage Maybe JoinArity
mb_join_arity RecFlag
rec_flag [CoreBndr]
bndrs UsageDetails
usage
  = Bool -> UsageDetails -> UsageDetails
markAllInsideLamIf     (Bool -> Bool
not Bool
one_shot)   (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
    Bool -> UsageDetails -> UsageDetails
markAllNonTailIf (Bool -> Bool
not Bool
exact_join) (UsageDetails -> UsageDetails) -> UsageDetails -> UsageDetails
forall a b. (a -> b) -> a -> b
$
    UsageDetails
usage
  where
    one_shot :: Bool
one_shot = case Maybe JoinArity
mb_join_arity of
                 Just JoinArity
join_arity
                   | RecFlag -> Bool
isRec RecFlag
rec_flag -> Bool
False
                   | Bool
otherwise      -> (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
isOneShotBndr (JoinArity -> [CoreBndr] -> [CoreBndr]
forall a. JoinArity -> [a] -> [a]
drop JoinArity
join_arity [CoreBndr]
bndrs)
                 Maybe JoinArity
Nothing            -> (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
isOneShotBndr [CoreBndr]
bndrs

    exact_join :: Bool
exact_join = Maybe JoinArity -> [CoreBndr] -> Bool
forall a. Maybe JoinArity -> [a] -> Bool
exactJoin Maybe JoinArity
mb_join_arity [CoreBndr]
bndrs

exactJoin :: Maybe JoinArity -> [a] -> Bool
exactJoin :: forall a. Maybe JoinArity -> [a] -> Bool
exactJoin Maybe JoinArity
Nothing           [a]
_    = Bool
False
exactJoin (Just JoinArity
join_arity) [a]
args = [a]
args [a] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthIs` JoinArity
join_arity
  -- Remember join_arity includes type binders

type IdWithOccInfo = Id

tagLamBinders :: UsageDetails          -- Of scope
              -> [Id]                  -- Binders
              -> (UsageDetails,        -- Details with binders removed
                 [IdWithOccInfo])    -- Tagged binders
tagLamBinders :: UsageDetails -> [CoreBndr] -> (UsageDetails, [CoreBndr])
tagLamBinders UsageDetails
usage [CoreBndr]
binders
  = UsageDetails
usage' UsageDetails
-> (UsageDetails, [CoreBndr]) -> (UsageDetails, [CoreBndr])
`seq` (UsageDetails
usage', [CoreBndr]
bndrs')
  where
    (UsageDetails
usage', [CoreBndr]
bndrs') = (UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr))
-> UsageDetails -> [CoreBndr] -> (UsageDetails, [CoreBndr])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumR UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagLamBinder UsageDetails
usage [CoreBndr]
binders

tagLamBinder :: UsageDetails       -- Of scope
             -> Id                 -- Binder
             -> (UsageDetails,     -- Details with binder removed
                 IdWithOccInfo)    -- Tagged binders
-- Used for lambda and case binders
-- It copes with the fact that lambda bindings can have a
-- stable unfolding, used for join points
tagLamBinder :: UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagLamBinder UsageDetails
usage CoreBndr
bndr
  = (UsageDetails
usage2, CoreBndr
bndr')
  where
        occ :: OccInfo
occ    = UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
usage CoreBndr
bndr
        bndr' :: CoreBndr
bndr'  = OccInfo -> CoreBndr -> CoreBndr
setBinderOcc (OccInfo -> OccInfo
markNonTail OccInfo
occ) CoreBndr
bndr
                   -- Don't try to make an argument into a join point
        usage1 :: UsageDetails
usage1 = UsageDetails
usage UsageDetails -> CoreBndr -> UsageDetails
`delDetails` CoreBndr
bndr
        usage2 :: UsageDetails
usage2 | CoreBndr -> Bool
isId CoreBndr
bndr = UsageDetails -> VarSet -> UsageDetails
addManyOccs UsageDetails
usage1 (CoreBndr -> VarSet
idUnfoldingVars CoreBndr
bndr)
                               -- This is effectively the RHS of a
                               -- non-join-point binding, so it's okay to use
                               -- addManyOccsSet, which assumes no tail calls
               | Bool
otherwise = UsageDetails
usage1

tagNonRecBinder :: TopLevelFlag           -- At top level?
                -> UsageDetails           -- Of scope
                -> CoreBndr               -- Binder
                -> (UsageDetails,         -- Details with binder removed
                    IdWithOccInfo)        -- Tagged binder

tagNonRecBinder :: TopLevelFlag
-> UsageDetails -> CoreBndr -> (UsageDetails, CoreBndr)
tagNonRecBinder TopLevelFlag
lvl UsageDetails
usage CoreBndr
binder
 = let
     occ :: OccInfo
occ     = UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
usage CoreBndr
binder
     will_be_join :: Bool
will_be_join = TopLevelFlag -> UsageDetails -> [CoreBndr] -> Bool
decideJoinPointHood TopLevelFlag
lvl UsageDetails
usage [CoreBndr
binder]
     occ' :: OccInfo
occ'    | Bool
will_be_join = -- must already be marked AlwaysTailCalled
                              ASSERT(isAlwaysTailCalled occ) occ
             | Bool
otherwise    = OccInfo -> OccInfo
markNonTail OccInfo
occ
     binder' :: CoreBndr
binder' = OccInfo -> CoreBndr -> CoreBndr
setBinderOcc OccInfo
occ' CoreBndr
binder
     usage' :: UsageDetails
usage'  = UsageDetails
usage UsageDetails -> CoreBndr -> UsageDetails
`delDetails` CoreBndr
binder
   in
   UsageDetails
usage' UsageDetails
-> (UsageDetails, CoreBndr) -> (UsageDetails, CoreBndr)
`seq` (UsageDetails
usage', CoreBndr
binder')

tagRecBinders :: TopLevelFlag           -- At top level?
              -> UsageDetails           -- Of body of let ONLY
              -> [(CoreBndr,            -- Binder
                   UsageDetails,        -- RHS usage details
                   [CoreBndr])]         -- Lambdas in new RHS
              -> (UsageDetails,         -- Adjusted details for whole scope,
                                        -- with binders removed
                  [IdWithOccInfo])      -- Tagged binders
-- Substantially more complicated than non-recursive case. Need to adjust RHS
-- details *before* tagging binders (because the tags depend on the RHSes).
tagRecBinders :: TopLevelFlag
-> UsageDetails
-> [(CoreBndr, UsageDetails, [CoreBndr])]
-> (UsageDetails, [CoreBndr])
tagRecBinders TopLevelFlag
lvl UsageDetails
body_uds [(CoreBndr, UsageDetails, [CoreBndr])]
triples
 = let
     ([CoreBndr]
bndrs, [UsageDetails]
rhs_udss, [[CoreBndr]]
_) = [(CoreBndr, UsageDetails, [CoreBndr])]
-> ([CoreBndr], [UsageDetails], [[CoreBndr]])
forall a b c. [(a, b, c)] -> ([a], [b], [c])
unzip3 [(CoreBndr, UsageDetails, [CoreBndr])]
triples

     -- 1. Determine join-point-hood of whole group, as determined by
     --    the *unadjusted* usage details
     unadj_uds :: UsageDetails
unadj_uds     = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
body_uds [UsageDetails]
rhs_udss
     will_be_joins :: Bool
will_be_joins = TopLevelFlag -> UsageDetails -> [CoreBndr] -> Bool
decideJoinPointHood TopLevelFlag
lvl UsageDetails
unadj_uds [CoreBndr]
bndrs

     -- 2. Adjust usage details of each RHS, taking into account the
     --    join-point-hood decision
     rhs_udss' :: [UsageDetails]
rhs_udss' = ((CoreBndr, UsageDetails, [CoreBndr]) -> UsageDetails)
-> [(CoreBndr, UsageDetails, [CoreBndr])] -> [UsageDetails]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, UsageDetails, [CoreBndr]) -> UsageDetails
adjust [(CoreBndr, UsageDetails, [CoreBndr])]
triples
     adjust :: (CoreBndr, UsageDetails, [CoreBndr]) -> UsageDetails
adjust (CoreBndr
bndr, UsageDetails
rhs_uds, [CoreBndr]
rhs_bndrs)
       = Maybe JoinArity
-> RecFlag -> [CoreBndr] -> UsageDetails -> UsageDetails
adjustRhsUsage Maybe JoinArity
mb_join_arity RecFlag
Recursive [CoreBndr]
rhs_bndrs UsageDetails
rhs_uds
       where
         -- Can't use willBeJoinId_maybe here because we haven't tagged the
         -- binder yet (the tag depends on these adjustments!)
         mb_join_arity :: Maybe JoinArity
mb_join_arity
           | Bool
will_be_joins
           , let occ :: OccInfo
occ = UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
unadj_uds CoreBndr
bndr
           , AlwaysTailCalled JoinArity
arity <- OccInfo -> TailCallInfo
tailCallInfo OccInfo
occ
           = JoinArity -> Maybe JoinArity
forall a. a -> Maybe a
Just JoinArity
arity
           | Bool
otherwise
           = ASSERT(not will_be_joins) -- Should be AlwaysTailCalled if
             Maybe JoinArity
forall a. Maybe a
Nothing                   -- we are making join points!

     -- 3. Compute final usage details from adjusted RHS details
     adj_uds :: UsageDetails
adj_uds   = (UsageDetails -> UsageDetails -> UsageDetails)
-> UsageDetails -> [UsageDetails] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr UsageDetails -> UsageDetails -> UsageDetails
andUDs UsageDetails
body_uds [UsageDetails]
rhs_udss'

     -- 4. Tag each binder with its adjusted details
     bndrs' :: [CoreBndr]
bndrs'    = [ OccInfo -> CoreBndr -> CoreBndr
setBinderOcc (UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
adj_uds CoreBndr
bndr) CoreBndr
bndr
                 | CoreBndr
bndr <- [CoreBndr]
bndrs ]

     -- 5. Drop the binders from the adjusted details and return
     usage' :: UsageDetails
usage'    = UsageDetails
adj_uds UsageDetails -> [CoreBndr] -> UsageDetails
`delDetailsList` [CoreBndr]
bndrs
   in
   (UsageDetails
usage', [CoreBndr]
bndrs')

setBinderOcc :: OccInfo -> CoreBndr -> CoreBndr
setBinderOcc :: OccInfo -> CoreBndr -> CoreBndr
setBinderOcc OccInfo
occ_info CoreBndr
bndr
  | CoreBndr -> Bool
isTyVar CoreBndr
bndr      = CoreBndr
bndr
  | CoreBndr -> Bool
isExportedId CoreBndr
bndr = if OccInfo -> Bool
isManyOccs (CoreBndr -> OccInfo
idOccInfo CoreBndr
bndr)
                          then CoreBndr
bndr
                          else CoreBndr -> OccInfo -> CoreBndr
setIdOccInfo CoreBndr
bndr OccInfo
noOccInfo
            -- Don't use local usage info for visible-elsewhere things
            -- BUT *do* erase any IAmALoopBreaker annotation, because we're
            -- about to re-generate it and it shouldn't be "sticky"

  | Bool
otherwise = CoreBndr -> OccInfo -> CoreBndr
setIdOccInfo CoreBndr
bndr OccInfo
occ_info

-- | Decide whether some bindings should be made into join points or not.
-- Returns `False` if they can't be join points. Note that it's an
-- all-or-nothing decision, as if multiple binders are given, they're
-- assumed to be mutually recursive.
--
-- It must, however, be a final decision. If we say "True" for 'f',
-- and then subsequently decide /not/ make 'f' into a join point, then
-- the decision about another binding 'g' might be invalidated if (say)
-- 'f' tail-calls 'g'.
--
-- See Note [Invariants on join points] in "GHC.Core".
decideJoinPointHood :: TopLevelFlag -> UsageDetails
                    -> [CoreBndr]
                    -> Bool
decideJoinPointHood :: TopLevelFlag -> UsageDetails -> [CoreBndr] -> Bool
decideJoinPointHood TopLevelFlag
TopLevel UsageDetails
_ [CoreBndr]
_
  = Bool
False
decideJoinPointHood TopLevelFlag
NotTopLevel UsageDetails
usage [CoreBndr]
bndrs
  | CoreBndr -> Bool
isJoinId ([CoreBndr] -> CoreBndr
forall a. [a] -> a
head [CoreBndr]
bndrs)
  = WARN(not all_ok, text "OccurAnal failed to rediscover join point(s):" <+>
                       ppr bndrs)
    Bool
all_ok
  | Bool
otherwise
  = Bool
all_ok
  where
    -- See Note [Invariants on join points]; invariants cited by number below.
    -- Invariant 2 is always satisfiable by the simplifier by eta expansion.
    all_ok :: Bool
all_ok = -- Invariant 3: Either all are join points or none are
             (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
ok [CoreBndr]
bndrs

    ok :: CoreBndr -> Bool
ok CoreBndr
bndr
      | -- Invariant 1: Only tail calls, all same join arity
        AlwaysTailCalled JoinArity
arity <- OccInfo -> TailCallInfo
tailCallInfo (UsageDetails -> CoreBndr -> OccInfo
lookupDetails UsageDetails
usage CoreBndr
bndr)

      , -- Invariant 1 as applied to LHSes of rules
        (CoreRule -> Bool) -> [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (JoinArity -> CoreRule -> Bool
ok_rule JoinArity
arity) (CoreBndr -> [CoreRule]
idCoreRules CoreBndr
bndr)

        -- Invariant 2a: stable unfoldings
        -- See Note [Join points and INLINE pragmas]
      , JoinArity -> Unfolding -> Bool
ok_unfolding JoinArity
arity (CoreBndr -> Unfolding
realIdUnfolding CoreBndr
bndr)

        -- Invariant 4: Satisfies polymorphism rule
      , JoinArity -> Type -> Bool
isValidJoinPointType JoinArity
arity (CoreBndr -> Type
idType CoreBndr
bndr)
      = Bool
True

      | Bool
otherwise
      = Bool
False

    ok_rule :: JoinArity -> CoreRule -> Bool
ok_rule JoinArity
_ BuiltinRule{} = Bool
False -- only possible with plugin shenanigans
    ok_rule JoinArity
join_arity (Rule { ru_args :: CoreRule -> [CoreExpr]
ru_args = [CoreExpr]
args })
      = [CoreExpr]
args [CoreExpr] -> JoinArity -> Bool
forall a. [a] -> JoinArity -> Bool
`lengthIs` JoinArity
join_arity
        -- Invariant 1 as applied to LHSes of rules

    -- ok_unfolding returns False if we should /not/ convert a non-join-id
    -- into a join-id, even though it is AlwaysTailCalled
    ok_unfolding :: JoinArity -> Unfolding -> Bool
ok_unfolding JoinArity
join_arity (CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_tmpl :: Unfolding -> CoreExpr
uf_tmpl = CoreExpr
rhs })
      = Bool -> Bool
not (UnfoldingSource -> Bool
isStableSource UnfoldingSource
src Bool -> Bool -> Bool
&& JoinArity
join_arity JoinArity -> JoinArity -> Bool
forall a. Ord a => a -> a -> Bool
> CoreExpr -> JoinArity
joinRhsArity CoreExpr
rhs)
    ok_unfolding JoinArity
_ (DFunUnfolding {})
      = Bool
False
    ok_unfolding JoinArity
_ Unfolding
_
      = Bool
True

willBeJoinId_maybe :: CoreBndr -> Maybe JoinArity
willBeJoinId_maybe :: CoreBndr -> Maybe JoinArity
willBeJoinId_maybe CoreBndr
bndr
  = case OccInfo -> TailCallInfo
tailCallInfo (CoreBndr -> OccInfo
idOccInfo CoreBndr
bndr) of
      AlwaysTailCalled JoinArity
arity -> JoinArity -> Maybe JoinArity
forall a. a -> Maybe a
Just JoinArity
arity
      TailCallInfo
_                      -> CoreBndr -> Maybe JoinArity
isJoinId_maybe CoreBndr
bndr


{- Note [Join points and INLINE pragmas]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Consider
   f x = let g = \x. not  -- Arity 1
             {-# INLINE g #-}
         in case x of
              A -> g True True
              B -> g True False
              C -> blah2

Here 'g' is always tail-called applied to 2 args, but the stable
unfolding captured by the INLINE pragma has arity 1.  If we try to
convert g to be a join point, its unfolding will still have arity 1
(since it is stable, and we don't meddle with stable unfoldings), and
Lint will complain (see Note [Invariants on join points], (2a), in
GHC.Core.  #13413.

Moreover, since g is going to be inlined anyway, there is no benefit
from making it a join point.

If it is recursive, and uselessly marked INLINE, this will stop us
making it a join point, which is annoying.  But occasionally
(notably in class methods; see Note [Instances and loop breakers] in
GHC.Tc.TyCl.Instance) we mark recursive things as INLINE but the recursion
unravels; so ignoring INLINE pragmas on recursive things isn't good
either.

See Invariant 2a of Note [Invariants on join points] in GHC.Core


************************************************************************
*                                                                      *
\subsection{Operations over OccInfo}
*                                                                      *
************************************************************************
-}

markMany, markInsideLam, markNonTail :: OccInfo -> OccInfo

markMany :: OccInfo -> OccInfo
markMany OccInfo
IAmDead = OccInfo
IAmDead
markMany OccInfo
occ     = ManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
occ_tail OccInfo
occ }

markInsideLam :: OccInfo -> OccInfo
markInsideLam occ :: OccInfo
occ@(OneOcc {}) = OccInfo
occ { occ_in_lam :: InsideLam
occ_in_lam = InsideLam
IsInsideLam }
markInsideLam OccInfo
occ             = OccInfo
occ

markNonTail :: OccInfo -> OccInfo
markNonTail OccInfo
IAmDead = OccInfo
IAmDead
markNonTail OccInfo
occ     = OccInfo
occ { occ_tail :: TailCallInfo
occ_tail = TailCallInfo
NoTailCallInfo }

addOccInfo, orOccInfo :: OccInfo -> OccInfo -> OccInfo

addOccInfo :: OccInfo -> OccInfo -> OccInfo
addOccInfo OccInfo
a1 OccInfo
a2  = ASSERT( not (isDeadOcc a1 || isDeadOcc a2) )
                    ManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
tailCallInfo OccInfo
a1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo`
                                          OccInfo -> TailCallInfo
tailCallInfo OccInfo
a2 }
                                -- Both branches are at least One
                                -- (Argument is never IAmDead)

-- (orOccInfo orig new) is used
-- when combining occurrence info from branches of a case

orOccInfo :: OccInfo -> OccInfo -> OccInfo
orOccInfo (OneOcc { occ_in_lam :: OccInfo -> InsideLam
occ_in_lam  = InsideLam
in_lam1
                  , occ_n_br :: OccInfo -> JoinArity
occ_n_br    = JoinArity
nbr1
                  , occ_int_cxt :: OccInfo -> InterestingCxt
occ_int_cxt = InterestingCxt
int_cxt1
                  , occ_tail :: OccInfo -> TailCallInfo
occ_tail    = TailCallInfo
tail1 })
          (OneOcc { occ_in_lam :: OccInfo -> InsideLam
occ_in_lam  = InsideLam
in_lam2
                  , occ_n_br :: OccInfo -> JoinArity
occ_n_br    = JoinArity
nbr2
                  , occ_int_cxt :: OccInfo -> InterestingCxt
occ_int_cxt = InterestingCxt
int_cxt2
                  , occ_tail :: OccInfo -> TailCallInfo
occ_tail    = TailCallInfo
tail2 })
  = OneOcc :: InsideLam -> JoinArity -> InterestingCxt -> TailCallInfo -> OccInfo
OneOcc { occ_n_br :: JoinArity
occ_n_br    = JoinArity
nbr1 JoinArity -> JoinArity -> JoinArity
forall a. Num a => a -> a -> a
+ JoinArity
nbr2
           , occ_in_lam :: InsideLam
occ_in_lam  = InsideLam
in_lam1 InsideLam -> InsideLam -> InsideLam
forall a. Monoid a => a -> a -> a
`mappend` InsideLam
in_lam2
           , occ_int_cxt :: InterestingCxt
occ_int_cxt = InterestingCxt
int_cxt1 InterestingCxt -> InterestingCxt -> InterestingCxt
forall a. Monoid a => a -> a -> a
`mappend` InterestingCxt
int_cxt2
           , occ_tail :: TailCallInfo
occ_tail    = TailCallInfo
tail1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo` TailCallInfo
tail2 }

orOccInfo OccInfo
a1 OccInfo
a2 = ASSERT( not (isDeadOcc a1 || isDeadOcc a2) )
                  ManyOccs :: TailCallInfo -> OccInfo
ManyOccs { occ_tail :: TailCallInfo
occ_tail = OccInfo -> TailCallInfo
tailCallInfo OccInfo
a1 TailCallInfo -> TailCallInfo -> TailCallInfo
`andTailCallInfo`
                                        OccInfo -> TailCallInfo
tailCallInfo OccInfo
a2 }

andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
andTailCallInfo :: TailCallInfo -> TailCallInfo -> TailCallInfo
andTailCallInfo info :: TailCallInfo
info@(AlwaysTailCalled JoinArity
arity1) (AlwaysTailCalled JoinArity
arity2)
  | JoinArity
arity1 JoinArity -> JoinArity -> Bool
forall a. Eq a => a -> a -> Bool
== JoinArity
arity2 = TailCallInfo
info
andTailCallInfo TailCallInfo
_ TailCallInfo
_  = TailCallInfo
NoTailCallInfo