{-# 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
, 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.Core.Map
import GHC.Utils.Misc ( filterOut, equalLength, debugIsOn )
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 CoreBndr
b Expr CoreBndr
e)
= (CSEnv
env2, CoreBndr -> Expr CoreBndr -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec CoreBndr
b2 Expr CoreBndr
e2)
where
(CSEnv
env1, CoreBndr
b1) = CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder CSEnv
env CoreBndr
b
(CSEnv
env2, (CoreBndr
b2, 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 TopLevelFlag
toplevel CSEnv
env (Rec [(CoreBndr
in_id, 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 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
(CSEnv
env1, [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 TopLevelFlag
toplevel CSEnv
env (Rec [(CoreBndr, Expr CoreBndr)]
pairs)
= (CSEnv
env2, [(CoreBndr, Expr CoreBndr)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(CoreBndr, Expr CoreBndr)]
pairs')
where
(CSEnv
env1, [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)
(CSEnv
env2, [(CoreBndr, Expr CoreBndr)]
pairs') = (CSEnv
-> ((CoreBndr, Expr CoreBndr), CoreBndr)
-> (CSEnv, (CoreBndr, Expr CoreBndr)))
-> CSEnv
-> [((CoreBndr, Expr CoreBndr), CoreBndr)]
-> (CSEnv, [(CoreBndr, Expr CoreBndr)])
forall (t :: * -> *) s a b.
Traversable t =>
(s -> a -> (s, b)) -> s -> t a -> (s, t b)
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 CSEnv
env ((CoreBndr, Expr CoreBndr)
pr, 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 TopLevelFlag
toplevel CSEnv
env (CoreBndr
in_id, Expr CoreBndr
in_rhs) 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 JoinArity
arity <- CoreBndr -> Maybe JoinArity
isJoinId_maybe CoreBndr
in_id
= let ([CoreBndr]
params, 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
(CSEnv
env', [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
(CSEnv
env', CoreBndr
out_id') = CSEnv -> CoreBndr -> CoreBndr -> Expr CoreBndr -> (CSEnv, CoreBndr)
addBinding CSEnv
env CoreBndr
in_id CoreBndr
out_id Expr CoreBndr
out_rhs
(Bool
cse_done, 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 TopLevelFlag
top_lvl CoreBndr
bndr
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
, Activation -> Bool
isAlwaysActive (CoreBndr -> Activation
idInlineActivation CoreBndr
bndr)
, CoreBndr -> Bool
idHasRules CoreBndr
bndr
= CoreBndr
bndr CoreBndr -> Activation -> CoreBndr
`setInlineActivation` Activation
activateAfterInitial
| Bool
otherwise
= CoreBndr
bndr
addBinding :: CSEnv
-> InVar
-> OutId -> OutExpr
-> (CSEnv, OutId)
addBinding :: CSEnv -> CoreBndr -> CoreBndr -> Expr CoreBndr -> (CSEnv, CoreBndr)
addBinding CSEnv
env CoreBndr
in_id CoreBndr
out_id 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
Expr CoreBndr
_ -> Bool
False
noCSE :: InId -> Bool
noCSE :: CoreBndr -> Bool
noCSE 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 CSEnv
env 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 CSEnv
env Expr CoreBndr
expr
| Just 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 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 CSEnv
env (Type Type
t) = Type -> Expr CoreBndr
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 CoreBndr
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 CoreBndr
forall b. Literal -> Expr b
Lit Literal
lit
cseExpr CSEnv
env (Var CoreBndr
v) = CSEnv -> CoreBndr -> Expr CoreBndr
lookupSubst CSEnv
env CoreBndr
v
cseExpr CSEnv
env (App Expr CoreBndr
f 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 CSEnv
env (Tick Tickish CoreBndr
t 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 CSEnv
env (Cast Expr CoreBndr
e 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) (HasCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
substCo (CSEnv -> Subst
csEnvSubst CSEnv
env) Coercion
co)
cseExpr CSEnv
env (Lam CoreBndr
b Expr CoreBndr
e) = let (CSEnv
env', 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 CSEnv
env (Let CoreBind
bind Expr CoreBndr
e) = let (CSEnv
env', 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 CSEnv
env (Case Expr CoreBndr
e CoreBndr
bndr Type
ty [OutAlt]
alts) = CSEnv
-> Expr CoreBndr -> CoreBndr -> Type -> [OutAlt] -> Expr CoreBndr
cseCase CSEnv
env Expr CoreBndr
e CoreBndr
bndr Type
ty [OutAlt]
alts
cseCase :: CSEnv -> InExpr -> InId -> InType -> [InAlt] -> OutExpr
cseCase :: CSEnv
-> Expr CoreBndr -> CoreBndr -> Type -> [OutAlt] -> Expr CoreBndr
cseCase CSEnv
env Expr CoreBndr
scrut CoreBndr
bndr Type
ty [OutAlt]
alts
= Expr CoreBndr -> CoreBndr -> Type -> [OutAlt] -> Expr CoreBndr
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr CoreBndr
scrut1 CoreBndr
bndr3 Type
ty' ([OutAlt] -> Expr CoreBndr) -> [OutAlt] -> Expr CoreBndr
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
scrut1 :: Expr CoreBndr
scrut1 = CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env Expr CoreBndr
scrut
bndr1 :: CoreBndr
bndr1 = CoreBndr -> CoreBndr
zapIdOccInfo CoreBndr
bndr
(CSEnv
env1, CoreBndr
bndr2) = CSEnv -> CoreBndr -> (CSEnv, CoreBndr)
addBinder CSEnv
env CoreBndr
bndr1
(CSEnv
alt_env, 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 :: OutAlt -> OutAlt
cse_alt (DataAlt DataCon
con, [CoreBndr]
args, Expr CoreBndr
rhs)
= (DataCon -> AltCon
DataAlt DataCon
con, [CoreBndr]
args', CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
new_env Expr CoreBndr
rhs)
where
(CSEnv
env', [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 (AltCon
con, [CoreBndr]
args, Expr CoreBndr
rhs)
= (AltCon
con, [CoreBndr]
args', CSEnv -> Expr CoreBndr -> Expr CoreBndr
tryForCSE CSEnv
env' Expr CoreBndr
rhs)
where
(CSEnv
env', [CoreBndr]
args') = CSEnv -> [CoreBndr] -> (CSEnv, [CoreBndr])
addBinders CSEnv
alt_env [CoreBndr]
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
, (AltCon
_,[CoreBndr]
bndrs1,Expr CoreBndr
rhs1) <- OutAlt
alt1
, let filtered_alts :: [OutAlt]
filtered_alts = (OutAlt -> Bool) -> [OutAlt] -> [OutAlt]
forall a. (a -> Bool) -> [a] -> [a]
filterOut (Expr CoreBndr -> OutAlt -> Bool
forall {a} {b}. Expr CoreBndr -> (a, b, Expr CoreBndr) -> Bool
identical_alt Expr CoreBndr
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
DEFAULT, [], Expr CoreBndr
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@(AltCon
_,[CoreBndr]
bndrs,Expr CoreBndr
_) : [OutAlt]
alts)
| [CoreBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreBndr]
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 CoreBndr -> (a, b, Expr CoreBndr) -> Bool
identical_alt Expr CoreBndr
rhs1 (a
_,b
_,Expr CoreBndr
rhs) = InScopeSet -> Expr CoreBndr -> Expr CoreBndr -> Bool
eqExpr InScopeSet
in_scope Expr CoreBndr
rhs1 Expr CoreBndr
rhs
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 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 CSEnv
cse Expr CoreBndr
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 CSEnv
cse CoreBndr
bndr Expr CoreBndr
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 }) CoreBndr
bndr 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}) CoreBndr
x = HasDebugCallStack => Subst -> CoreBndr -> Expr CoreBndr
Subst -> CoreBndr -> Expr CoreBndr
lookupIdSubst Subst
sub CoreBndr
x
extendCSSubst :: CSEnv -> Id -> CoreExpr -> CSEnv
extendCSSubst :: CSEnv -> CoreBndr -> Expr CoreBndr -> CSEnv
extendCSSubst CSEnv
cse CoreBndr
x 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 CSEnv
cse CoreBndr
v = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, CoreBndr
v')
where
(Subst
sub', 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 CSEnv
cse [CoreBndr]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [CoreBndr]
vs')
where
(Subst
sub', [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 CSEnv
cse [CoreBndr]
vs = (CSEnv
cse { cs_subst :: Subst
cs_subst = Subst
sub' }, [CoreBndr]
vs')
where
(Subst
sub', [CoreBndr]
vs') = Subst -> [CoreBndr] -> (Subst, [CoreBndr])
substRecBndrs (CSEnv -> Subst
cs_subst CSEnv
cse) [CoreBndr]
vs