{-# LANGUAGE CPP #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns   #-}
module GHC.Core.Opt.CSE (cseProgram, cseOneExpr) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Core.Subst
import GHC.Types.Var    ( Var )
import GHC.Types.Var.Env ( mkInScopeSet )
import GHC.Types.Id     ( Id, idType, idHasRules, zapStableUnfolding
                        , idInlineActivation, setInlineActivation
                        , zapIdOccInfo, zapIdUsageInfo, idInlinePragma
                        , isJoinId, isJoinId_maybe )
import GHC.Core.Utils   ( mkAltExpr, eqExpr
                        , exprIsTickedString
                        , stripTicksE, stripTicksT, mkTicks )
import GHC.Core.FVs     ( exprFreeVars )
import GHC.Core.Type    ( tyConAppArgs )
import GHC.Core
import GHC.Utils.Outputable
import GHC.Types.Basic
import GHC.Types.Tickish
import GHC.Core.Map.Expr
import GHC.Utils.Misc   ( filterOut, equalLength, debugIsOn )
import GHC.Utils.Panic
import Data.List        ( mapAccumL )
cseProgram :: CoreProgram -> CoreProgram
cseProgram :: CoreProgram -> CoreProgram
cseProgram CoreProgram
binds = (CSEnv, CoreProgram) -> CoreProgram
forall a b. (a, b) -> b
snd ((CSEnv -> CoreBind -> (CSEnv, CoreBind))
-> CSEnv -> CoreProgram -> (CSEnv, CoreProgram)
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL (TopLevelFlag -> CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind TopLevelFlag
TopLevel) CSEnv
emptyCSEnv CoreProgram
binds)
cseBind :: TopLevelFlag -> CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind :: TopLevelFlag -> CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind TopLevelFlag
toplevel CSEnv
env (NonRec Var
b Expr Var
e)
  = (CSEnv
env2, Var -> Expr Var -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Var
b2 Expr Var
e2)
  where
    (CSEnv
env1, Var
b1)       = CSEnv -> Var -> (CSEnv, Var)
addBinder CSEnv
env Var
b
    (CSEnv
env2, (Var
b2, Expr Var
e2)) = TopLevelFlag
-> CSEnv -> (Var, Expr Var) -> Var -> (CSEnv, (Var, Expr Var))
cse_bind TopLevelFlag
toplevel CSEnv
env1 (Var
b,Expr Var
e) Var
b1
cseBind TopLevelFlag
toplevel CSEnv
env (Rec [(Var
in_id, Expr Var
rhs)])
  | Var -> Bool
noCSE Var
in_id
  = (CSEnv
env1, [(Var, Expr Var)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(Var
out_id, Expr Var
rhs')])
  
  | Just Expr Var
previous <- CSEnv -> Var -> Expr Var -> Maybe (Expr Var)
lookupCSRecEnv CSEnv
env Var
out_id Expr Var
rhs''
  , let previous' :: Expr Var
previous' = [CoreTickish] -> Expr Var -> Expr Var
mkTicks [CoreTickish]
ticks Expr Var
previous
        out_id' :: Var
out_id'   = TopLevelFlag -> Var -> Var
delayInlining TopLevelFlag
toplevel Var
out_id
  = 
    (CSEnv -> Var -> Expr Var -> CSEnv
extendCSSubst CSEnv
env1 Var
in_id Expr Var
previous', Var -> Expr Var -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec Var
out_id' Expr Var
previous')
  | Bool
otherwise
  = (CSEnv -> Var -> Expr Var -> Expr Var -> CSEnv
extendCSRecEnv CSEnv
env1 Var
out_id Expr Var
rhs'' Expr Var
id_expr', [(Var, Expr Var)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(Var
zapped_id, Expr Var
rhs')])
  where
    (CSEnv
env1, [Var
out_id]) = CSEnv -> [Var] -> (CSEnv, [Var])
addRecBinders CSEnv
env [Var
in_id]
    rhs' :: Expr Var
rhs'  = CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env1 Expr Var
rhs
    rhs'' :: Expr Var
rhs'' = (CoreTickish -> Bool) -> Expr Var -> Expr Var
forall b. (CoreTickish -> Bool) -> Expr b -> Expr b
stripTicksE CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Var
rhs'
    ticks :: [CoreTickish]
ticks = (CoreTickish -> Bool) -> Expr Var -> [CoreTickish]
forall b. (CoreTickish -> Bool) -> Expr b -> [CoreTickish]
stripTicksT CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Var
rhs'
    id_expr' :: Expr Var
id_expr'  = Var -> Expr Var
forall b. Var -> Expr b
varToCoreExpr Var
out_id
    zapped_id :: Var
zapped_id = Var -> Var
zapIdUsageInfo Var
out_id
cseBind TopLevelFlag
toplevel CSEnv
env (Rec [(Var, Expr Var)]
pairs)
  = (CSEnv
env2, [(Var, Expr Var)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(Var, Expr Var)]
pairs')
  where
    (CSEnv
env1, [Var]
bndrs1) = CSEnv -> [Var] -> (CSEnv, [Var])
addRecBinders CSEnv
env (((Var, Expr Var) -> Var) -> [(Var, Expr Var)] -> [Var]
forall a b. (a -> b) -> [a] -> [b]
map (Var, Expr Var) -> Var
forall a b. (a, b) -> a
fst [(Var, Expr Var)]
pairs)
    (CSEnv
env2, [(Var, Expr Var)]
pairs') = (CSEnv -> ((Var, Expr Var), Var) -> (CSEnv, (Var, Expr Var)))
-> CSEnv -> [((Var, Expr Var), Var)] -> (CSEnv, [(Var, Expr Var)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
mapAccumL CSEnv -> ((Var, Expr Var), Var) -> (CSEnv, (Var, Expr Var))
do_one CSEnv
env1 ([(Var, Expr Var)] -> [Var] -> [((Var, Expr Var), Var)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(Var, Expr Var)]
pairs [Var]
bndrs1)
    do_one :: CSEnv -> ((Var, Expr Var), Var) -> (CSEnv, (Var, Expr Var))
do_one CSEnv
env ((Var, Expr Var)
pr, Var
b1) = TopLevelFlag
-> CSEnv -> (Var, Expr Var) -> Var -> (CSEnv, (Var, Expr Var))
cse_bind TopLevelFlag
toplevel CSEnv
env (Var, Expr Var)
pr Var
b1
cse_bind :: TopLevelFlag -> CSEnv -> (InId, InExpr) -> OutId -> (CSEnv, (OutId, OutExpr))
cse_bind :: TopLevelFlag
-> CSEnv -> (Var, Expr Var) -> Var -> (CSEnv, (Var, Expr Var))
cse_bind TopLevelFlag
toplevel CSEnv
env (Var
in_id, Expr Var
in_rhs) Var
out_id
  | TopLevelFlag -> Bool
isTopLevel TopLevelFlag
toplevel, Expr Var -> Bool
exprIsTickedString Expr Var
in_rhs
      
  = (CSEnv
env', (Var
out_id', Expr Var
in_rhs))
  | Just JoinArity
arity <- Var -> Maybe JoinArity
isJoinId_maybe Var
in_id
      
  = let ([Var]
params, Expr Var
in_body) = JoinArity -> Expr Var -> ([Var], Expr Var)
forall b. JoinArity -> Expr b -> ([b], Expr b)
collectNBinders JoinArity
arity Expr Var
in_rhs
        (CSEnv
env', [Var]
params') = CSEnv -> [Var] -> (CSEnv, [Var])
addBinders CSEnv
env [Var]
params
        out_body :: Expr Var
out_body = CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
env' Expr Var
in_body
    in (CSEnv
env, (Var
out_id, [Var] -> Expr Var -> Expr Var
forall b. [b] -> Expr b -> Expr b
mkLams [Var]
params' Expr Var
out_body))
  | Bool
otherwise
  = (CSEnv
env', (Var
out_id'', Expr Var
out_rhs))
  where
    (CSEnv
env', Var
out_id') = CSEnv -> Var -> Var -> Expr Var -> Bool -> (CSEnv, Var)
addBinding CSEnv
env Var
in_id Var
out_id Expr Var
out_rhs Bool
cse_done
    (Bool
cse_done, Expr Var
out_rhs)  = CSEnv -> Expr Var -> (Bool, Expr Var)
try_for_cse CSEnv
env Expr Var
in_rhs
    out_id'' :: Var
out_id'' | Bool
cse_done  = Var -> Var
zapStableUnfolding (Var -> Var) -> Var -> Var
forall a b. (a -> b) -> a -> b
$
                           TopLevelFlag -> Var -> Var
delayInlining TopLevelFlag
toplevel Var
out_id'
             | Bool
otherwise = Var
out_id'
delayInlining :: TopLevelFlag -> Id -> Id
delayInlining :: TopLevelFlag -> Var -> Var
delayInlining TopLevelFlag
top_lvl Var
bndr
  | TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
  , Activation -> Bool
isAlwaysActive (Var -> Activation
idInlineActivation Var
bndr)
  , Var -> Bool
idHasRules Var
bndr  
                     
       
       
       
  = Var
bndr Var -> Activation -> Var
`setInlineActivation` Activation
activateAfterInitial
  | Bool
otherwise
  = Var
bndr
addBinding :: CSEnv            
           -> InVar            
           -> OutId -> OutExpr 
           -> Bool             
                               
           -> (CSEnv, OutId)   
addBinding :: CSEnv -> Var -> Var -> Expr Var -> Bool -> (CSEnv, Var)
addBinding CSEnv
env Var
in_id Var
out_id Expr Var
rhs' Bool
cse_done
  | Bool -> Bool
not (Var -> Bool
isId Var
in_id) = (CSEnv -> Var -> Expr Var -> CSEnv
extendCSSubst CSEnv
env Var
in_id Expr Var
rhs',     Var
out_id)
  | Var -> Bool
noCSE Var
in_id      = (CSEnv
env,                              Var
out_id)
  | Bool
use_subst        = (CSEnv -> Var -> Expr Var -> CSEnv
extendCSSubst CSEnv
env Var
in_id Expr Var
rhs',     Var
out_id)
  | Bool
cse_done         = (CSEnv
env,                              Var
out_id)
                       
  | Bool
otherwise        = (CSEnv -> Expr Var -> Expr Var -> CSEnv
extendCSEnv CSEnv
env Expr Var
rhs' Expr Var
id_expr', Var
zapped_id)
  where
    id_expr' :: Expr Var
id_expr'  = Var -> Expr Var
forall b. Var -> Expr b
varToCoreExpr Var
out_id
    zapped_id :: Var
zapped_id = Var -> Var
zapIdUsageInfo Var
out_id
       
       
       
       
       
       
       
       
       
    
    
    use_subst :: Bool
use_subst | Var {} <- Expr Var
rhs' = Bool
True
              | Bool
otherwise      = Bool
False
noCSE :: InId -> Bool
noCSE :: Var -> Bool
noCSE Var
id =  Bool -> Bool
not (Activation -> Bool
isAlwaysActive (Var -> Activation
idInlineActivation Var
id)) Bool -> Bool -> Bool
&&
            Bool -> Bool
not (InlineSpec -> Bool
noUserInlineSpec (InlinePragma -> InlineSpec
inlinePragmaSpec (Var -> InlinePragma
idInlinePragma Var
id)))
             
         Bool -> Bool -> Bool
|| InlinePragma -> Bool
isAnyInlinePragma (Var -> InlinePragma
idInlinePragma Var
id)
             
         Bool -> Bool -> Bool
|| Var -> Bool
isJoinId Var
id
             
tryForCSE :: CSEnv -> InExpr -> OutExpr
tryForCSE :: CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
env Expr Var
expr = (Bool, Expr Var) -> Expr Var
forall a b. (a, b) -> b
snd (CSEnv -> Expr Var -> (Bool, Expr Var)
try_for_cse CSEnv
env Expr Var
expr)
try_for_cse :: CSEnv -> InExpr -> (Bool, OutExpr)
try_for_cse :: CSEnv -> Expr Var -> (Bool, Expr Var)
try_for_cse CSEnv
env Expr Var
expr
  | Just Expr Var
e <- CSEnv -> Expr Var -> Maybe (Expr Var)
lookupCSEnv CSEnv
env Expr Var
expr'' = (Bool
True,  [CoreTickish] -> Expr Var -> Expr Var
mkTicks [CoreTickish]
ticks Expr Var
e)
  | Bool
otherwise                        = (Bool
False, Expr Var
expr')
    
    
    
    
  where
    expr' :: Expr Var
expr'  = CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env Expr Var
expr
    expr'' :: Expr Var
expr'' = (CoreTickish -> Bool) -> Expr Var -> Expr Var
forall b. (CoreTickish -> Bool) -> Expr b -> Expr b
stripTicksE CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Var
expr'
    ticks :: [CoreTickish]
ticks  = (CoreTickish -> Bool) -> Expr Var -> [CoreTickish]
forall b. (CoreTickish -> Bool) -> Expr b -> [CoreTickish]
stripTicksT CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Var
expr'
    
    
    
    
cseOneExpr :: InExpr -> OutExpr
cseOneExpr :: Expr Var -> Expr Var
cseOneExpr Expr Var
e = CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env Expr Var
e
  where env :: CSEnv
env = CSEnv
emptyCSEnv {cs_subst :: Subst
cs_subst = InScopeSet -> Subst
mkEmptySubst (VarSet -> InScopeSet
mkInScopeSet (Expr Var -> VarSet
exprFreeVars Expr Var
e)) }
cseExpr :: CSEnv -> InExpr -> OutExpr
cseExpr :: CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env (Type Type
t)              = Type -> Expr Var
forall b. Type -> Expr b
Type (Subst -> Type -> Type
substTy (CSEnv -> Subst
csEnvSubst CSEnv
env) Type
t)
cseExpr CSEnv
env (Coercion Coercion
c)          = Coercion -> Expr Var
forall b. Coercion -> Expr b
Coercion (HasCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
substCo (CSEnv -> Subst
csEnvSubst CSEnv
env) Coercion
c)
cseExpr CSEnv
_   (Lit Literal
lit)             = Literal -> Expr Var
forall b. Literal -> Expr b
Lit Literal
lit
cseExpr CSEnv
env (Var Var
v)               = CSEnv -> Var -> Expr Var
lookupSubst CSEnv
env Var
v
cseExpr CSEnv
env (App Expr Var
f Expr Var
a)             = Expr Var -> Expr Var -> Expr Var
forall b. Expr b -> Expr b -> Expr b
App (CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env Expr Var
f) (CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
env Expr Var
a)
cseExpr CSEnv
env (Tick CoreTickish
t Expr Var
e)            = CoreTickish -> Expr Var -> Expr Var
forall b. CoreTickish -> Expr b -> Expr b
Tick CoreTickish
t (CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env Expr Var
e)
cseExpr CSEnv
env (Cast Expr Var
e Coercion
co)           = Expr Var -> Coercion -> Expr Var
forall b. Expr b -> Coercion -> Expr b
Cast (CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
env Expr Var
e) (HasCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
substCo (CSEnv -> Subst
csEnvSubst CSEnv
env) Coercion
co)
cseExpr CSEnv
env (Lam Var
b Expr Var
e)             = let (CSEnv
env', Var
b') = CSEnv -> Var -> (CSEnv, Var)
addBinder CSEnv
env Var
b
                                    in Var -> Expr Var -> Expr Var
forall b. b -> Expr b -> Expr b
Lam Var
b' (CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env' Expr Var
e)
cseExpr CSEnv
env (Let CoreBind
bind Expr Var
e)          = let (CSEnv
env', CoreBind
bind') = TopLevelFlag -> CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind TopLevelFlag
NotTopLevel CSEnv
env CoreBind
bind
                                    in CoreBind -> Expr Var -> Expr Var
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind' (CSEnv -> Expr Var -> Expr Var
cseExpr CSEnv
env' Expr Var
e)
cseExpr CSEnv
env (Case Expr Var
e Var
bndr Type
ty [OutAlt]
alts) = CSEnv -> Expr Var -> Var -> Type -> [OutAlt] -> Expr Var
cseCase CSEnv
env Expr Var
e Var
bndr Type
ty [OutAlt]
alts
cseCase :: CSEnv -> InExpr -> InId -> InType -> [InAlt] -> OutExpr
cseCase :: CSEnv -> Expr Var -> Var -> Type -> [OutAlt] -> Expr Var
cseCase CSEnv
env Expr Var
scrut Var
bndr Type
ty [OutAlt]
alts
  = Expr Var -> Var -> Type -> [OutAlt] -> Expr Var
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr Var
scrut1 Var
bndr3 Type
ty' ([OutAlt] -> Expr Var) -> [OutAlt] -> Expr Var
forall a b. (a -> b) -> a -> b
$
    CSEnv -> [OutAlt] -> [OutAlt]
combineAlts CSEnv
alt_env ((OutAlt -> OutAlt) -> [OutAlt] -> [OutAlt]
forall a b. (a -> b) -> [a] -> [b]
map OutAlt -> OutAlt
cse_alt [OutAlt]
alts)
  where
    ty' :: Type
ty' = Subst -> Type -> Type
substTy (CSEnv -> Subst
csEnvSubst CSEnv
env) Type
ty
    (Bool
cse_done, Expr Var
scrut1) = CSEnv -> Expr Var -> (Bool, Expr Var)
try_for_cse CSEnv
env Expr Var
scrut
    bndr1 :: Var
bndr1 = Var -> Var
zapIdOccInfo Var
bndr
      
      
      
    (CSEnv
env1, Var
bndr2)    = CSEnv -> Var -> (CSEnv, Var)
addBinder CSEnv
env Var
bndr1
    (CSEnv
alt_env, Var
bndr3) = CSEnv -> Var -> Var -> Expr Var -> Bool -> (CSEnv, Var)
addBinding CSEnv
env1 Var
bndr Var
bndr2 Expr Var
scrut1 Bool
cse_done
         
    con_target :: OutExpr
    con_target :: Expr Var
con_target = CSEnv -> Var -> Expr Var
lookupSubst CSEnv
alt_env Var
bndr
    arg_tys :: [OutType]
    arg_tys :: [Type]
arg_tys = Type -> [Type]
tyConAppArgs (Var -> Type
idType Var
bndr3)
    
    cse_alt :: OutAlt -> OutAlt
cse_alt (Alt (DataAlt DataCon
con) [Var]
args Expr Var
rhs)
        = AltCon -> [Var] -> Expr Var -> OutAlt
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt (DataCon -> AltCon
DataAlt DataCon
con) [Var]
args' (CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
new_env Expr Var
rhs)
        where
          (CSEnv
env', [Var]
args') = CSEnv -> [Var] -> (CSEnv, [Var])
addBinders CSEnv
alt_env [Var]
args
          new_env :: CSEnv
new_env       = CSEnv -> Expr Var -> Expr Var -> CSEnv
extendCSEnv CSEnv
env' Expr Var
con_expr Expr Var
con_target
          con_expr :: Expr Var
con_expr      = AltCon -> [Var] -> [Type] -> Expr Var
mkAltExpr (DataCon -> AltCon
DataAlt DataCon
con) [Var]
args' [Type]
arg_tys
    cse_alt (Alt AltCon
con [Var]
args Expr Var
rhs)
        = AltCon -> [Var] -> Expr Var -> OutAlt
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
con [Var]
args' (CSEnv -> Expr Var -> Expr Var
tryForCSE CSEnv
env' Expr Var
rhs)
        where
          (CSEnv
env', [Var]
args') = CSEnv -> [Var] -> (CSEnv, [Var])
addBinders CSEnv
alt_env [Var]
args
combineAlts :: CSEnv -> [OutAlt] -> [OutAlt]
combineAlts :: CSEnv -> [OutAlt] -> [OutAlt]
combineAlts CSEnv
env [OutAlt]
alts
  | (Just OutAlt
alt1, [OutAlt]
rest_alts) <- [OutAlt] -> (Maybe OutAlt, [OutAlt])
find_bndr_free_alt [OutAlt]
alts
  , Alt AltCon
_ [Var]
bndrs1 Expr Var
rhs1 <- OutAlt
alt1
  , let filtered_alts :: [OutAlt]
filtered_alts = (OutAlt -> Bool) -> [OutAlt] -> [OutAlt]
forall a. (a -> Bool) -> [a] -> [a]
filterOut (Expr Var -> OutAlt -> Bool
identical_alt Expr Var
rhs1) [OutAlt]
rest_alts
  , Bool -> Bool
not ([OutAlt] -> [OutAlt] -> Bool
forall a b. [a] -> [b] -> Bool
equalLength [OutAlt]
rest_alts [OutAlt]
filtered_alts)
  = ASSERT2( null bndrs1, ppr alts )
    AltCon -> [Var] -> Expr Var -> OutAlt
forall b. AltCon -> [b] -> Expr b -> Alt b
Alt AltCon
DEFAULT [] Expr Var
rhs1 OutAlt -> [OutAlt] -> [OutAlt]
forall a. a -> [a] -> [a]
: [OutAlt]
filtered_alts
  | Bool
otherwise
  = [OutAlt]
alts
  where
    in_scope :: InScopeSet
in_scope = Subst -> InScopeSet
substInScope (CSEnv -> Subst
csEnvSubst CSEnv
env)
    find_bndr_free_alt :: [CoreAlt] -> (Maybe CoreAlt, [CoreAlt])
       
       
    find_bndr_free_alt :: [OutAlt] -> (Maybe OutAlt, [OutAlt])
find_bndr_free_alt []
      = (Maybe OutAlt
forall a. Maybe a
Nothing, [])
    find_bndr_free_alt (alt :: OutAlt
alt@(Alt AltCon
_ [Var]
bndrs Expr Var
_) : [OutAlt]
alts)
      | [Var] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Var]
bndrs = (OutAlt -> Maybe OutAlt
forall a. a -> Maybe a
Just OutAlt
alt, [OutAlt]
alts)
      | Bool
otherwise  = case [OutAlt] -> (Maybe OutAlt, [OutAlt])
find_bndr_free_alt [OutAlt]
alts of
                       (Maybe OutAlt
mb_bf, [OutAlt]
alts) -> (Maybe OutAlt
mb_bf, OutAlt
altOutAlt -> [OutAlt] -> [OutAlt]
forall a. a -> [a] -> [a]
:[OutAlt]
alts)
    identical_alt :: Expr Var -> OutAlt -> Bool
identical_alt Expr Var
rhs1 (Alt AltCon
_ [Var]
_ Expr Var
rhs) = InScopeSet -> Expr Var -> Expr Var -> Bool
eqExpr InScopeSet
in_scope Expr Var
rhs1 Expr Var
rhs
       
       
       
       
data CSEnv
  = CS { CSEnv -> Subst
cs_subst :: Subst  
            
            
       , CSEnv -> CoreMap (Expr Var)
cs_map   :: CoreMap OutExpr   
            
            
       , CSEnv -> CoreMap (Expr Var)
cs_rec_map :: CoreMap OutExpr
            
       }
emptyCSEnv :: CSEnv
emptyCSEnv :: CSEnv
emptyCSEnv = CS { cs_map :: CoreMap (Expr Var)
cs_map = CoreMap (Expr Var)
forall a. CoreMap a
emptyCoreMap, cs_rec_map :: CoreMap (Expr Var)
cs_rec_map = CoreMap (Expr Var)
forall a. CoreMap a
emptyCoreMap
                , cs_subst :: Subst
cs_subst = Subst
emptySubst }
lookupCSEnv :: CSEnv -> OutExpr -> Maybe OutExpr
lookupCSEnv :: CSEnv -> Expr Var -> Maybe (Expr Var)
lookupCSEnv (CS { cs_map :: CSEnv -> CoreMap (Expr Var)
cs_map = CoreMap (Expr Var)
csmap }) Expr Var
expr
  = CoreMap (Expr Var) -> Expr Var -> Maybe (Expr Var)
forall a. CoreMap a -> Expr Var -> Maybe a
lookupCoreMap CoreMap (Expr Var)
csmap Expr Var
expr
extendCSEnv :: CSEnv -> OutExpr -> OutExpr -> CSEnv
extendCSEnv :: CSEnv -> Expr Var -> Expr Var -> CSEnv
extendCSEnv CSEnv
cse Expr Var
expr Expr Var
triv_expr
  = CSEnv
cse { cs_map :: CoreMap (Expr Var)
cs_map = CoreMap (Expr Var) -> Expr Var -> Expr Var -> CoreMap (Expr Var)
forall a. CoreMap a -> Expr Var -> a -> CoreMap a
extendCoreMap (CSEnv -> CoreMap (Expr Var)
cs_map CSEnv
cse) Expr Var
sexpr Expr Var
triv_expr }
  where
    sexpr :: Expr Var
sexpr = (CoreTickish -> Bool) -> Expr Var -> Expr Var
forall b. (CoreTickish -> Bool) -> Expr b -> Expr b
stripTicksE CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable Expr Var
expr
extendCSRecEnv :: CSEnv -> OutId -> OutExpr -> OutExpr -> CSEnv
extendCSRecEnv :: CSEnv -> Var -> Expr Var -> Expr Var -> CSEnv
extendCSRecEnv CSEnv
cse Var
bndr Expr Var
expr Expr Var
triv_expr
  = CSEnv
cse { cs_rec_map :: CoreMap (Expr Var)
cs_rec_map = CoreMap (Expr Var) -> Expr Var -> Expr Var -> CoreMap (Expr Var)
forall a. CoreMap a -> Expr Var -> a -> CoreMap a
extendCoreMap (CSEnv -> CoreMap (Expr Var)
cs_rec_map CSEnv
cse) (Var -> Expr Var -> Expr Var
forall b. b -> Expr b -> Expr b
Lam Var
bndr Expr Var
expr) Expr Var
triv_expr }
lookupCSRecEnv :: CSEnv -> OutId -> OutExpr -> Maybe OutExpr
lookupCSRecEnv :: CSEnv -> Var -> Expr Var -> Maybe (Expr Var)
lookupCSRecEnv (CS { cs_rec_map :: CSEnv -> CoreMap (Expr Var)
cs_rec_map = CoreMap (Expr Var)
csmap }) Var
bndr Expr Var
expr
  = CoreMap (Expr Var) -> Expr Var -> Maybe (Expr Var)
forall a. CoreMap a -> Expr Var -> Maybe a
lookupCoreMap CoreMap (Expr Var)
csmap (Var -> Expr Var -> Expr Var
forall b. b -> Expr b -> Expr b
Lam Var
bndr Expr Var
expr)
csEnvSubst :: CSEnv -> Subst
csEnvSubst :: CSEnv -> Subst
csEnvSubst = CSEnv -> Subst
cs_subst
lookupSubst :: CSEnv -> Id -> OutExpr
lookupSubst :: CSEnv -> Var -> Expr Var
lookupSubst (CS { cs_subst :: CSEnv -> Subst
cs_subst = Subst
sub}) Var
x = HasDebugCallStack => Subst -> Var -> Expr Var
Subst -> Var -> Expr Var
lookupIdSubst Subst
sub Var
x
extendCSSubst :: CSEnv -> Id  -> CoreExpr -> CSEnv
extendCSSubst :: CSEnv -> Var -> Expr Var -> CSEnv
extendCSSubst CSEnv
cse Var
x Expr Var
rhs = CSEnv
cse { cs_subst :: Subst
cs_subst = Subst -> Var -> Expr Var -> Subst
extendSubst (CSEnv -> Subst
cs_subst CSEnv
cse) Var
x Expr Var
rhs }
addBinder :: CSEnv -> Var -> (CSEnv, Var)
addBinder :: CSEnv -> Var -> (CSEnv, Var)
addBinder CSEnv
cse Var
v = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, Var
v')
                where
                  (Subst
sub', Var
v') = Subst -> Var -> (Subst, Var)
substBndr (CSEnv -> Subst
cs_subst CSEnv
cse) Var
v
addBinders :: CSEnv -> [Var] -> (CSEnv, [Var])
addBinders :: CSEnv -> [Var] -> (CSEnv, [Var])
addBinders CSEnv
cse [Var]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [Var]
vs')
                where
                  (Subst
sub', [Var]
vs') = Subst -> [Var] -> (Subst, [Var])
substBndrs (CSEnv -> Subst
cs_subst CSEnv
cse) [Var]
vs
addRecBinders :: CSEnv -> [Id] -> (CSEnv, [Id])
addRecBinders :: CSEnv -> [Var] -> (CSEnv, [Var])
addRecBinders CSEnv
cse [Var]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [Var]
vs')
                where
                  (Subst
sub', [Var]
vs') = Subst -> [Var] -> (Subst, [Var])
substRecBndrs (CSEnv -> Subst
cs_subst CSEnv
cse) [Var]
vs