{-# LANGUAGE CPP #-}
module CSE (cseProgram, cseOneExpr) where
#include "HsVersions.h"
import GhcPrelude
import CoreSubst
import Var ( Var )
import VarEnv ( elemInScopeSet, mkInScopeSet )
import Id ( Id, idType, isDeadBinder
, idInlineActivation, setInlineActivation
, zapIdOccInfo, zapIdUsageInfo, idInlinePragma
, isJoinId, isJoinId_maybe )
import CoreUtils ( mkAltExpr, eqExpr
, exprIsTickedString
, stripTicksE, stripTicksT, mkTicks )
import CoreFVs ( exprFreeVars )
import Type ( tyConAppArgs )
import CoreSyn
import Outputable
import BasicTypes
import CoreMap
import Util ( filterOut )
import Data.List ( mapAccumL )
cseProgram :: CoreProgram -> CoreProgram
cseProgram :: CoreProgram -> CoreProgram
cseProgram binds :: CoreProgram
binds = (CSEnv, CoreProgram) -> CoreProgram
forall a b. (a, b) -> b
snd ((CSEnv -> CoreBind -> (CSEnv, CoreBind))
-> CSEnv -> CoreProgram -> (CSEnv, CoreProgram)
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
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 toplevel :: TopLevelFlag
toplevel env :: CSEnv
env (NonRec b :: CoreBndr
b e :: Expr CoreBndr
e)
= (CSEnv
env2, CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
b2 Expr CoreBndr
e2)
where
(env1 :: CSEnv
env1, b1 :: CoreBndr
b1) = CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder CSEnv
env CoreBndr
b
(env2 :: CSEnv
env2, (b2 :: CoreBndr
b2, e2 :: Expr CoreBndr
e2)) = TopLevelFlag
-> CSEnv
-> (CoreBndr, Expr CoreBndr)
-> CoreBndr
-> (CSEnv, (CoreBndr, Expr CoreBndr))
cse_bind TopLevelFlag
toplevel CSEnv
env1 (CoreBndr
b,Expr CoreBndr
e) CoreBndr
b1
cseBind toplevel :: TopLevelFlag
toplevel env :: CSEnv
env (Rec [(in_id :: CoreBndr
in_id, rhs :: Expr CoreBndr
rhs)])
| CoreBndr -> Bool
noCSE CoreBndr
in_id
= (CSEnv
env1, [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr
out_id, Expr CoreBndr
rhs')])
| Just previous :: Expr CoreBndr
previous <- CSEnv -> CoreBndr -> Expr CoreBndr -> Maybe (Expr CoreBndr)
lookupCSRecEnv CSEnv
env CoreBndr
out_id Expr CoreBndr
rhs''
, let previous' :: Expr CoreBndr
previous' = [Tickish CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
mkTicks [Tickish CoreBndr]
ticks Expr CoreBndr
previous
out_id' :: CoreBndr
out_id' = TopLevelFlag -> CoreBndr -> CoreBndr
delayInlining TopLevelFlag
toplevel CoreBndr
out_id
=
(CSEnv -> CoreBndr -> Expr CoreBndr -> CSEnv
extendCSSubst CSEnv
env1 CoreBndr
in_id Expr CoreBndr
previous', CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
out_id' Expr CoreBndr
previous')
| Bool
otherwise
= (CSEnv -> CoreBndr -> Expr CoreBndr -> Expr CoreBndr -> CSEnv
extendCSRecEnv CSEnv
env1 CoreBndr
out_id Expr CoreBndr
rhs'' Expr CoreBndr
forall b. Expr b
id_expr', [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr
zapped_id, Expr CoreBndr
rhs')])
where
(env1 :: CSEnv
env1, [out_id :: CoreBndr
out_id]) = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addRecBinders CSEnv
env [CoreBndr
in_id]
rhs' :: Expr CoreBndr
rhs' = CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env1 Expr CoreBndr
rhs
rhs'' :: Expr CoreBndr
rhs'' = (Tickish CoreBndr -> Bool) -> Expr CoreBndr -> Expr CoreBndr
forall b. (Tickish CoreBndr -> Bool) -> Expr b -> Expr b
stripTicksE Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr CoreBndr
rhs'
ticks :: [Tickish CoreBndr]
ticks = (Tickish CoreBndr -> Bool) -> Expr CoreBndr -> [Tickish CoreBndr]
forall b.
(Tickish CoreBndr -> Bool) -> Expr b -> [Tickish CoreBndr]
stripTicksT Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr CoreBndr
rhs'
id_expr' :: Expr b
id_expr' = CoreBndr -> Expr b
forall b. CoreBndr -> Expr b
varToCoreExpr CoreBndr
out_id
zapped_id :: CoreBndr
zapped_id = CoreBndr -> CoreBndr
zapIdUsageInfo CoreBndr
out_id
cseBind toplevel :: TopLevelFlag
toplevel env :: CSEnv
env (Rec pairs :: [(CoreBndr, Expr CoreBndr)]
pairs)
= (CSEnv
env2, [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, Expr CoreBndr)]
pairs')
where
(env1 :: CSEnv
env1, bndrs1 :: [CoreBndr]
bndrs1) = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addRecBinders CSEnv
env (((CoreBndr, Expr CoreBndr) -> CoreBndr)
-> [(CoreBndr, Expr CoreBndr)] -> [CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map (CoreBndr, Expr CoreBndr) -> CoreBndr
forall a b. (a, b) -> a
fst [(CoreBndr, Expr CoreBndr)]
pairs)
(env2 :: CSEnv
env2, pairs' :: [(CoreBndr, Expr CoreBndr)]
pairs') = (CSEnv
-> ((CoreBndr, Expr CoreBndr), CoreBndr)
-> (CSEnv, (CoreBndr, Expr CoreBndr)))
-> CSEnv
-> [((CoreBndr, Expr CoreBndr), CoreBndr)]
-> (CSEnv, [(CoreBndr, Expr CoreBndr)])
forall (t :: * -> *) a b c.
Traversable t =>
(a -> b -> (a, c)) -> a -> t b -> (a, t c)
mapAccumL CSEnv
-> ((CoreBndr, Expr CoreBndr), CoreBndr)
-> (CSEnv, (CoreBndr, Expr CoreBndr))
do_one CSEnv
env1 ([(CoreBndr, Expr CoreBndr)]
-> [CoreBndr] -> [((CoreBndr, Expr CoreBndr), CoreBndr)]
forall a b. [a] -> [b] -> [(a, b)]
zip [(CoreBndr, Expr CoreBndr)]
pairs [CoreBndr]
bndrs1)
do_one :: CSEnv
-> ((CoreBndr, Expr CoreBndr), CoreBndr)
-> (CSEnv, (CoreBndr, Expr CoreBndr))
do_one env :: CSEnv
env (pr :: (CoreBndr, Expr CoreBndr)
pr, b1 :: CoreBndr
b1) = TopLevelFlag
-> CSEnv
-> (CoreBndr, Expr CoreBndr)
-> CoreBndr
-> (CSEnv, (CoreBndr, Expr CoreBndr))
cse_bind TopLevelFlag
toplevel CSEnv
env (CoreBndr, Expr CoreBndr)
pr CoreBndr
b1
cse_bind :: TopLevelFlag -> CSEnv -> (InId, InExpr) -> OutId -> (CSEnv, (OutId, OutExpr))
cse_bind :: TopLevelFlag
-> CSEnv
-> (CoreBndr, Expr CoreBndr)
-> CoreBndr
-> (CSEnv, (CoreBndr, Expr CoreBndr))
cse_bind toplevel :: TopLevelFlag
toplevel env :: CSEnv
env (in_id :: CoreBndr
in_id, in_rhs :: Expr CoreBndr
in_rhs) out_id :: CoreBndr
out_id
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
toplevel, Expr CoreBndr -> Bool
exprIsTickedString Expr CoreBndr
in_rhs
= (CSEnv
env', (CoreBndr
out_id', Expr CoreBndr
in_rhs))
| Just arity :: JoinArity
arity <- CoreBndr -> Maybe JoinArity
isJoinId_maybe CoreBndr
in_id
= let (params :: [CoreBndr]
params, in_body :: Expr CoreBndr
in_body) = JoinArity -> Expr CoreBndr -> ([CoreBndr], Expr CoreBndr)
forall b. JoinArity -> Expr b -> ([b], Expr b)
collectNBinders JoinArity
arity Expr CoreBndr
in_rhs
(env' :: CSEnv
env', params' :: [CoreBndr]
params') = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addBinders CSEnv
env [CoreBndr]
params
out_body :: Expr CoreBndr
out_body = CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env' Expr CoreBndr
in_body
in (CSEnv
env, (CoreBndr
out_id, [CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
forall b. [b] -> Expr b -> Expr b
mkLams [CoreBndr]
params' Expr CoreBndr
out_body))
| Bool
otherwise
= (CSEnv
env', (CoreBndr
out_id'', Expr CoreBndr
out_rhs))
where
(env' :: CSEnv
env', out_id' :: CoreBndr
out_id') = CSEnv -> CoreBndr -> CoreBndr -> Expr CoreBndr -> (CSEnv, CoreBndr)
addBinding CSEnv
env CoreBndr
in_id CoreBndr
out_id Expr CoreBndr
out_rhs
(cse_done :: Bool
cse_done, out_rhs :: Expr CoreBndr
out_rhs) = CSEnv -> Expr CoreBndr -> (Bool, Expr CoreBndr)
try_for_cse CSEnv
env Expr CoreBndr
in_rhs
out_id'' :: CoreBndr
out_id'' | Bool
cse_done = TopLevelFlag -> CoreBndr -> CoreBndr
delayInlining TopLevelFlag
toplevel CoreBndr
out_id'
| Bool
otherwise = CoreBndr
out_id'
delayInlining :: TopLevelFlag -> Id -> Id
delayInlining :: TopLevelFlag -> CoreBndr -> CoreBndr
delayInlining top_lvl :: TopLevelFlag
top_lvl bndr :: CoreBndr
bndr
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
, Activation -> Bool
isAlwaysActive (CoreBndr -> Activation
idInlineActivation CoreBndr
bndr)
= CoreBndr
bndr CoreBndr -> Activation -> CoreBndr
`setInlineActivation` Activation
activeAfterInitial
| Bool
otherwise
= CoreBndr
bndr
addBinding :: CSEnv
-> InVar
-> OutId -> OutExpr
-> (CSEnv, OutId)
addBinding :: CSEnv -> CoreBndr -> CoreBndr -> Expr CoreBndr -> (CSEnv, CoreBndr)
addBinding env :: CSEnv
env in_id :: CoreBndr
in_id out_id :: CoreBndr
out_id rhs' :: Expr CoreBndr
rhs'
| Bool -> Bool
not (CoreBndr -> Bool
isId CoreBndr
in_id) = (CSEnv -> CoreBndr -> Expr CoreBndr -> CSEnv
extendCSSubst CSEnv
env CoreBndr
in_id Expr CoreBndr
rhs', CoreBndr
out_id)
| CoreBndr -> Bool
noCSE CoreBndr
in_id = (CSEnv
env, CoreBndr
out_id)
| Bool
use_subst = (CSEnv -> CoreBndr -> Expr CoreBndr -> CSEnv
extendCSSubst CSEnv
env CoreBndr
in_id Expr CoreBndr
rhs', CoreBndr
out_id)
| Bool
otherwise = (CSEnv -> Expr CoreBndr -> Expr CoreBndr -> CSEnv
extendCSEnv CSEnv
env Expr CoreBndr
rhs' Expr CoreBndr
forall b. Expr b
id_expr', CoreBndr
zapped_id)
where
id_expr' :: Expr b
id_expr' = CoreBndr -> Expr b
forall b. CoreBndr -> Expr b
varToCoreExpr CoreBndr
out_id
zapped_id :: CoreBndr
zapped_id = CoreBndr -> CoreBndr
zapIdUsageInfo CoreBndr
out_id
use_subst :: Bool
use_subst = case Expr CoreBndr
rhs' of
Var {} -> Bool
True
_ -> Bool
False
noCSE :: InId -> Bool
noCSE :: CoreBndr -> Bool
noCSE id :: CoreBndr
id = Bool -> Bool
not (Activation -> Bool
isAlwaysActive (CoreBndr -> Activation
idInlineActivation CoreBndr
id)) Bool -> Bool -> Bool
&&
Bool -> Bool
not (InlineSpec -> Bool
noUserInlineSpec (InlinePragma -> InlineSpec
inlinePragmaSpec (CoreBndr -> InlinePragma
idInlinePragma CoreBndr
id)))
Bool -> Bool -> Bool
|| InlinePragma -> Bool
isAnyInlinePragma (CoreBndr -> InlinePragma
idInlinePragma CoreBndr
id)
Bool -> Bool -> Bool
|| CoreBndr -> Bool
isJoinId CoreBndr
id
tryForCSE :: CSEnv -> InExpr -> OutExpr
tryForCSE :: CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE env :: CSEnv
env expr :: Expr CoreBndr
expr = (Bool, Expr CoreBndr) -> Expr CoreBndr
forall a b. (a, b) -> b
snd (CSEnv -> Expr CoreBndr -> (Bool, Expr CoreBndr)
try_for_cse CSEnv
env Expr CoreBndr
expr)
try_for_cse :: CSEnv -> InExpr -> (Bool, OutExpr)
try_for_cse :: CSEnv -> Expr CoreBndr -> (Bool, Expr CoreBndr)
try_for_cse env :: CSEnv
env expr :: Expr CoreBndr
expr
| Just e :: Expr CoreBndr
e <- CSEnv -> Expr CoreBndr -> Maybe (Expr CoreBndr)
lookupCSEnv CSEnv
env Expr CoreBndr
expr'' = (Bool
True, [Tickish CoreBndr] -> Expr CoreBndr -> Expr CoreBndr
mkTicks [Tickish CoreBndr]
ticks Expr CoreBndr
e)
| Bool
otherwise = (Bool
False, Expr CoreBndr
expr')
where
expr' :: Expr CoreBndr
expr' = CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env Expr CoreBndr
expr
expr'' :: Expr CoreBndr
expr'' = (Tickish CoreBndr -> Bool) -> Expr CoreBndr -> Expr CoreBndr
forall b. (Tickish CoreBndr -> Bool) -> Expr b -> Expr b
stripTicksE Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr CoreBndr
expr'
ticks :: [Tickish CoreBndr]
ticks = (Tickish CoreBndr -> Bool) -> Expr CoreBndr -> [Tickish CoreBndr]
forall b.
(Tickish CoreBndr -> Bool) -> Expr b -> [Tickish CoreBndr]
stripTicksT Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr CoreBndr
expr'
cseOneExpr :: InExpr -> OutExpr
cseOneExpr :: Expr CoreBndr -> Expr CoreBndr
cseOneExpr e :: Expr CoreBndr
e = CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env Expr CoreBndr
e
where env :: CSEnv
env = CSEnv
emptyCSEnv {cs_subst :: Subst
cs_subst = InScopeSet -> Subst
mkEmptySubst (VarSet -> InScopeSet
mkInScopeSet (Expr CoreBndr -> VarSet
exprFreeVars Expr CoreBndr
e)) }
cseExpr :: CSEnv -> InExpr -> OutExpr
cseExpr :: CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr env :: CSEnv
env (Type t :: Type
t) = Type -> Expr CoreBndr
forall b. Type -> Expr b
Type (Subst -> Type -> Type
substTy (CSEnv -> Subst
csEnvSubst CSEnv
env) Type
t)
cseExpr env :: CSEnv
env (Coercion c :: Coercion
c) = Coercion -> Expr CoreBndr
forall b. Coercion -> Expr b
Coercion (Subst -> Coercion -> Coercion
substCo (CSEnv -> Subst
csEnvSubst CSEnv
env) Coercion
c)
cseExpr _ (Lit lit :: Literal
lit) = Literal -> Expr CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit
cseExpr env :: CSEnv
env (Var v :: CoreBndr
v) = CSEnv -> CoreBndr -> Expr CoreBndr
lookupSubst CSEnv
env CoreBndr
v
cseExpr env :: CSEnv
env (App f :: Expr CoreBndr
f a :: Expr CoreBndr
a) = Expr CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Expr b -> Expr b -> Expr b
App (CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env Expr CoreBndr
f) (CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env Expr CoreBndr
a)
cseExpr env :: CSEnv
env (Tick t :: Tickish CoreBndr
t e :: Expr CoreBndr
e) = Tickish CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. Tickish CoreBndr -> Expr b -> Expr b
Tick Tickish CoreBndr
t (CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env Expr CoreBndr
e)
cseExpr env :: CSEnv
env (Cast e :: Expr CoreBndr
e co :: Coercion
co) = Expr CoreBndr -> Coercion -> Expr CoreBndr
forall b. Expr b -> Coercion -> Expr b
Cast (CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env Expr CoreBndr
e) (Subst -> Coercion -> Coercion
substCo (CSEnv -> Subst
csEnvSubst CSEnv
env) Coercion
co)
cseExpr env :: CSEnv
env (Lam b :: CoreBndr
b e :: Expr CoreBndr
e) = let (env' :: CSEnv
env', b' :: CoreBndr
b') = CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder CSEnv
env CoreBndr
b
in CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
b' (CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env' Expr CoreBndr
e)
cseExpr env :: CSEnv
env (Let bind :: CoreBind
bind e :: Expr CoreBndr
e) = let (env' :: CSEnv
env', bind' :: CoreBind
bind') = TopLevelFlag -> CSEnv -> CoreBind -> (CSEnv, CoreBind)
cseBind TopLevelFlag
NotTopLevel CSEnv
env CoreBind
bind
in CoreBind -> Expr CoreBndr -> Expr CoreBndr
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind' (CSEnv -> Expr CoreBndr -> Expr CoreBndr
cseExpr CSEnv
env' Expr CoreBndr
e)
cseExpr env :: CSEnv
env (Case e :: Expr CoreBndr
e bndr :: CoreBndr
bndr ty :: Type
ty alts :: [Alt CoreBndr]
alts) = CSEnv
-> Expr CoreBndr
-> CoreBndr
-> Type
-> [Alt CoreBndr]
-> Expr CoreBndr
cseCase CSEnv
env Expr CoreBndr
e CoreBndr
bndr Type
ty [Alt CoreBndr]
alts
cseCase :: CSEnv -> InExpr -> InId -> InType -> [InAlt] -> OutExpr
cseCase :: CSEnv
-> Expr CoreBndr
-> CoreBndr
-> Type
-> [Alt CoreBndr]
-> Expr CoreBndr
cseCase env :: CSEnv
env scrut :: Expr CoreBndr
scrut bndr :: CoreBndr
bndr ty :: Type
ty alts :: [Alt CoreBndr]
alts
= Expr CoreBndr
-> CoreBndr -> Type -> [Alt CoreBndr] -> Expr CoreBndr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr CoreBndr
scrut1 CoreBndr
bndr3 Type
ty' ([Alt CoreBndr] -> Expr CoreBndr)
-> [Alt CoreBndr] -> Expr CoreBndr
forall a b. (a -> b) -> a -> b
$
CSEnv -> [Alt CoreBndr] -> [Alt CoreBndr]
combineAlts CSEnv
alt_env ((Alt CoreBndr -> Alt CoreBndr) -> [Alt CoreBndr] -> [Alt CoreBndr]
forall a b. (a -> b) -> [a] -> [b]
map Alt CoreBndr -> Alt CoreBndr
cse_alt [Alt CoreBndr]
alts)
where
ty' :: Type
ty' = Subst -> Type -> Type
substTy (CSEnv -> Subst
csEnvSubst CSEnv
env) Type
ty
scrut1 :: Expr CoreBndr
scrut1 = CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env Expr CoreBndr
scrut
bndr1 :: CoreBndr
bndr1 = CoreBndr -> CoreBndr
zapIdOccInfo CoreBndr
bndr
(env1 :: CSEnv
env1, bndr2 :: CoreBndr
bndr2) = CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder CSEnv
env CoreBndr
bndr1
(alt_env :: CSEnv
alt_env, bndr3 :: CoreBndr
bndr3) = CSEnv -> CoreBndr -> CoreBndr -> Expr CoreBndr -> (CSEnv, CoreBndr)
addBinding CSEnv
env1 CoreBndr
bndr CoreBndr
bndr2 Expr CoreBndr
scrut1
con_target :: OutExpr
con_target :: Expr CoreBndr
con_target = CSEnv -> CoreBndr -> Expr CoreBndr
lookupSubst CSEnv
alt_env CoreBndr
bndr
arg_tys :: [OutType]
arg_tys :: [Type]
arg_tys = Type -> [Type]
tyConAppArgs (CoreBndr -> Type
idType CoreBndr
bndr3)
cse_alt :: Alt CoreBndr -> Alt CoreBndr
cse_alt (DataAlt con :: DataCon
con, args :: [CoreBndr]
args, rhs :: Expr CoreBndr
rhs)
| Bool -> Bool
not ([CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreBndr]
args)
= (DataCon -> AltCon
DataAlt DataCon
con, [CoreBndr]
args', CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
new_env Expr CoreBndr
rhs)
where
(env' :: CSEnv
env', args' :: [CoreBndr]
args') = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addBinders CSEnv
alt_env [CoreBndr]
args
new_env :: CSEnv
new_env = CSEnv -> Expr CoreBndr -> Expr CoreBndr -> CSEnv
extendCSEnv CSEnv
env' Expr CoreBndr
con_expr Expr CoreBndr
con_target
con_expr :: Expr CoreBndr
con_expr = AltCon -> [CoreBndr] -> [Type] -> Expr CoreBndr
mkAltExpr (DataCon -> AltCon
DataAlt DataCon
con) [CoreBndr]
args' [Type]
arg_tys
cse_alt (con :: AltCon
con, args :: [CoreBndr]
args, rhs :: Expr CoreBndr
rhs)
= (AltCon
con, [CoreBndr]
args', CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env' Expr CoreBndr
rhs)
where
(env' :: CSEnv
env', args' :: [CoreBndr]
args') = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addBinders CSEnv
alt_env [CoreBndr]
args
combineAlts :: CSEnv -> [InAlt] -> [InAlt]
combineAlts :: CSEnv -> [Alt CoreBndr] -> [Alt CoreBndr]
combineAlts env :: CSEnv
env ((_,bndrs1 :: [CoreBndr]
bndrs1,rhs1 :: Expr CoreBndr
rhs1) : rest_alts :: [Alt CoreBndr]
rest_alts)
| (CoreBndr -> Bool) -> [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
isDeadBinder [CoreBndr]
bndrs1
= (AltCon
DEFAULT, [], Expr CoreBndr
rhs1) Alt CoreBndr -> [Alt CoreBndr] -> [Alt CoreBndr]
forall a. a -> [a] -> [a]
: [Alt CoreBndr]
filtered_alts
where
in_scope :: InScopeSet
in_scope = Subst -> InScopeSet
substInScope (CSEnv -> Subst
csEnvSubst CSEnv
env)
filtered_alts :: [Alt CoreBndr]
filtered_alts = (Alt CoreBndr -> Bool) -> [Alt CoreBndr] -> [Alt CoreBndr]
forall a. (a -> Bool) -> [a] -> [a]
filterOut Alt CoreBndr -> Bool
forall (t :: * -> *) a.
Foldable t =>
(a, t CoreBndr, Expr CoreBndr) -> Bool
identical [Alt CoreBndr]
rest_alts
identical :: (a, t CoreBndr, Expr CoreBndr) -> Bool
identical (_con :: a
_con, bndrs :: t CoreBndr
bndrs, rhs :: Expr CoreBndr
rhs) = (CoreBndr -> Bool) -> t CoreBndr -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all CoreBndr -> Bool
ok t CoreBndr
bndrs Bool -> Bool -> Bool
&& InScopeSet -> Expr CoreBndr -> Expr CoreBndr -> Bool
eqExpr InScopeSet
in_scope Expr CoreBndr
rhs1 Expr CoreBndr
rhs
ok :: CoreBndr -> Bool
ok bndr :: CoreBndr
bndr = CoreBndr -> Bool
isDeadBinder CoreBndr
bndr Bool -> Bool -> Bool
|| Bool -> Bool
not (CoreBndr
bndr CoreBndr -> InScopeSet -> Bool
`elemInScopeSet` InScopeSet
in_scope)
combineAlts _ alts :: [Alt CoreBndr]
alts = [Alt CoreBndr]
alts
data CSEnv
= CS { CSEnv -> Subst
cs_subst :: Subst
, CSEnv -> CoreMap (Expr CoreBndr)
cs_map :: CoreMap OutExpr
, CSEnv -> CoreMap (Expr CoreBndr)
cs_rec_map :: CoreMap OutExpr
}
emptyCSEnv :: CSEnv
emptyCSEnv :: CSEnv
emptyCSEnv = CS :: Subst
-> CoreMap (Expr CoreBndr) -> CoreMap (Expr CoreBndr) -> CSEnv
CS { cs_map :: CoreMap (Expr CoreBndr)
cs_map = CoreMap (Expr CoreBndr)
forall a. CoreMap a
emptyCoreMap, cs_rec_map :: CoreMap (Expr CoreBndr)
cs_rec_map = CoreMap (Expr CoreBndr)
forall a. CoreMap a
emptyCoreMap
, cs_subst :: Subst
cs_subst = Subst
emptySubst }
lookupCSEnv :: CSEnv -> OutExpr -> Maybe OutExpr
lookupCSEnv :: CSEnv -> Expr CoreBndr -> Maybe (Expr CoreBndr)
lookupCSEnv (CS { cs_map :: CSEnv -> CoreMap (Expr CoreBndr)
cs_map = CoreMap (Expr CoreBndr)
csmap }) expr :: Expr CoreBndr
expr
= CoreMap (Expr CoreBndr) -> Expr CoreBndr -> Maybe (Expr CoreBndr)
forall a. CoreMap a -> Expr CoreBndr -> Maybe a
lookupCoreMap CoreMap (Expr CoreBndr)
csmap Expr CoreBndr
expr
extendCSEnv :: CSEnv -> OutExpr -> OutExpr -> CSEnv
extendCSEnv :: CSEnv -> Expr CoreBndr -> Expr CoreBndr -> CSEnv
extendCSEnv cse :: CSEnv
cse expr :: Expr CoreBndr
expr triv_expr :: Expr CoreBndr
triv_expr
= CSEnv
cse { cs_map :: CoreMap (Expr CoreBndr)
cs_map = CoreMap (Expr CoreBndr)
-> Expr CoreBndr -> Expr CoreBndr -> CoreMap (Expr CoreBndr)
forall a. CoreMap a -> Expr CoreBndr -> a -> CoreMap a
extendCoreMap (CSEnv -> CoreMap (Expr CoreBndr)
cs_map CSEnv
cse) Expr CoreBndr
sexpr Expr CoreBndr
triv_expr }
where
sexpr :: Expr CoreBndr
sexpr = (Tickish CoreBndr -> Bool) -> Expr CoreBndr -> Expr CoreBndr
forall b. (Tickish CoreBndr -> Bool) -> Expr b -> Expr b
stripTicksE Tickish CoreBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Expr CoreBndr
expr
extendCSRecEnv :: CSEnv -> OutId -> OutExpr -> OutExpr -> CSEnv
extendCSRecEnv :: CSEnv -> CoreBndr -> Expr CoreBndr -> Expr CoreBndr -> CSEnv
extendCSRecEnv cse :: CSEnv
cse bndr :: CoreBndr
bndr expr :: Expr CoreBndr
expr triv_expr :: Expr CoreBndr
triv_expr
= CSEnv
cse { cs_rec_map :: CoreMap (Expr CoreBndr)
cs_rec_map = CoreMap (Expr CoreBndr)
-> Expr CoreBndr -> Expr CoreBndr -> CoreMap (Expr CoreBndr)
forall a. CoreMap a -> Expr CoreBndr -> a -> CoreMap a
extendCoreMap (CSEnv -> CoreMap (Expr CoreBndr)
cs_rec_map CSEnv
cse) (CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
bndr Expr CoreBndr
expr) Expr CoreBndr
triv_expr }
lookupCSRecEnv :: CSEnv -> OutId -> OutExpr -> Maybe OutExpr
lookupCSRecEnv :: CSEnv -> CoreBndr -> Expr CoreBndr -> Maybe (Expr CoreBndr)
lookupCSRecEnv (CS { cs_rec_map :: CSEnv -> CoreMap (Expr CoreBndr)
cs_rec_map = CoreMap (Expr CoreBndr)
csmap }) bndr :: CoreBndr
bndr expr :: Expr CoreBndr
expr
= CoreMap (Expr CoreBndr) -> Expr CoreBndr -> Maybe (Expr CoreBndr)
forall a. CoreMap a -> Expr CoreBndr -> Maybe a
lookupCoreMap CoreMap (Expr CoreBndr)
csmap (CoreBndr -> Expr CoreBndr -> Expr CoreBndr
forall b. b -> Expr b -> Expr b
Lam CoreBndr
bndr Expr CoreBndr
expr)
csEnvSubst :: CSEnv -> Subst
csEnvSubst :: CSEnv -> Subst
csEnvSubst = CSEnv -> Subst
cs_subst
lookupSubst :: CSEnv -> Id -> OutExpr
lookupSubst :: CSEnv -> CoreBndr -> Expr CoreBndr
lookupSubst (CS { cs_subst :: CSEnv -> Subst
cs_subst = Subst
sub}) x :: CoreBndr
x = SDoc -> Subst -> CoreBndr -> Expr CoreBndr
lookupIdSubst (String -> SDoc
text "CSE.lookupSubst") Subst
sub CoreBndr
x
extendCSSubst :: CSEnv -> Id -> CoreExpr -> CSEnv
extendCSSubst :: CSEnv -> CoreBndr -> Expr CoreBndr -> CSEnv
extendCSSubst cse :: CSEnv
cse x :: CoreBndr
x rhs :: Expr CoreBndr
rhs = CSEnv
cse { cs_subst :: Subst
cs_subst = Subst -> CoreBndr -> Expr CoreBndr -> Subst
extendSubst (CSEnv -> Subst
cs_subst CSEnv
cse) CoreBndr
x Expr CoreBndr
rhs }
addBinder :: CSEnv -> Var -> (CSEnv, Var)
addBinder :: CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder cse :: CSEnv
cse v :: CoreBndr
v = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, CoreBndr
v')
where
(sub' :: Subst
sub', v' :: CoreBndr
v') = Subst -> CoreBndr -> (Subst, CoreBndr)
substBndr (CSEnv -> Subst
cs_subst CSEnv
cse) CoreBndr
v
addBinders :: CSEnv -> [Var] -> (CSEnv, [Var])
addBinders :: CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addBinders cse :: CSEnv
cse vs :: [CoreBndr]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [CoreBndr]
vs')
where
(sub' :: Subst
sub', vs' :: [CoreBndr]
vs') = Subst -> [CoreBndr] -> (Subst, [CoreBndr])
substBndrs (CSEnv -> Subst
cs_subst CSEnv
cse) [CoreBndr]
vs
addRecBinders :: CSEnv -> [Id] -> (CSEnv, [Id])
addRecBinders :: CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addRecBinders cse :: CSEnv
cse vs :: [CoreBndr]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [CoreBndr]
vs')
where
(sub' :: Subst
sub', vs' :: [CoreBndr]
vs') = Subst -> [CoreBndr] -> (Subst, [CoreBndr])
substRecBndrs (CSEnv -> Subst
cs_subst CSEnv
cse) [CoreBndr]
vs